launch hardening: TC bit, Dockerfile, platform-aware deploy
- Set TC (truncation) bit when response exceeds 4096-byte buffer instead of dropping the response silently. Clients can retry via TCP. - Log when upstream response is truncated in forward.rs. - Dockerfile: bump to Rust 1.88, include site/service files, use alpine runtime instead of scratch, add cmake/perl for aws-lc-sys. - Makefile deploy: platform-aware — codesign on macOS, systemctl on Linux. - README: trim roadmap to near-term items only. - Verified: Docker build + smoke test passes on Linux (Alpine musl). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
CLAUDE.md
|
CLAUDE.md
|
||||||
|
docs
|
||||||
|
|||||||
14
Dockerfile
14
Dockerfile
@@ -1,15 +1,17 @@
|
|||||||
FROM rust:1.85-alpine AS builder
|
FROM rust:1.88-alpine AS builder
|
||||||
RUN apk add --no-cache musl-dev
|
RUN apk add --no-cache musl-dev cmake make perl
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY Cargo.toml Cargo.lock ./
|
COPY Cargo.toml Cargo.lock ./
|
||||||
RUN mkdir src && echo 'fn main() {}' > src/main.rs && echo '' > src/lib.rs
|
RUN mkdir src && echo 'fn main() {}' > src/main.rs && echo '' > src/lib.rs
|
||||||
RUN cargo build --release 2>/dev/null || true
|
RUN cargo build --release 2>/dev/null || true
|
||||||
RUN rm -rf src
|
RUN rm -rf src
|
||||||
COPY src/ src/
|
COPY src/ src/
|
||||||
|
COPY site/ site/
|
||||||
|
COPY numa.toml com.numa.dns.plist numa.service ./
|
||||||
RUN touch src/main.rs src/lib.rs
|
RUN touch src/main.rs src/lib.rs
|
||||||
RUN cargo build --release
|
RUN cargo build --release
|
||||||
|
|
||||||
FROM scratch
|
FROM alpine:3.20
|
||||||
COPY --from=builder /app/target/release/numa /numa
|
COPY --from=builder /app/target/release/numa /usr/local/bin/numa
|
||||||
EXPOSE 53/udp 5380/tcp
|
EXPOSE 53/udp 80/tcp 443/tcp 5380/tcp
|
||||||
ENTRYPOINT ["/numa"]
|
ENTRYPOINT ["numa"]
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -22,7 +22,11 @@ clean:
|
|||||||
deploy:
|
deploy:
|
||||||
cargo build --release
|
cargo build --release
|
||||||
sudo cp target/release/numa /usr/local/bin/numa
|
sudo cp target/release/numa /usr/local/bin/numa
|
||||||
|
ifeq ($(shell uname -s),Darwin)
|
||||||
sudo codesign -f -s - /usr/local/bin/numa
|
sudo codesign -f -s - /usr/local/bin/numa
|
||||||
sudo kill $$(pgrep -f /usr/local/bin/numa) 2>/dev/null || true
|
sudo kill $$(pgrep -f /usr/local/bin/numa) 2>/dev/null || true
|
||||||
|
else
|
||||||
|
sudo systemctl restart numa 2>/dev/null || sudo kill $$(pgrep -f /usr/local/bin/numa) 2>/dev/null || true
|
||||||
|
endif
|
||||||
@sleep 1
|
@sleep 1
|
||||||
@dig @127.0.0.1 google.com +short +time=3 > /dev/null && echo "Service restarted successfully" || echo "Warning: DNS not responding yet"
|
@dig @127.0.0.1 google.com +short +time=3 > /dev/null && echo "Service restarted successfully" || echo "Warning: DNS not responding yet"
|
||||||
|
|||||||
@@ -230,11 +230,8 @@ Zero external DNS libraries. RFC 1035 wire protocol parsed by hand. Dependencies
|
|||||||
- [x] System DNS auto-discovery — Tailscale, VPN split-DNS
|
- [x] System DNS auto-discovery — Tailscale, VPN split-DNS
|
||||||
- [x] System DNS auto-configuration — `numa install` / `numa uninstall`
|
- [x] System DNS auto-configuration — `numa install` / `numa uninstall`
|
||||||
- [x] Local service proxy — `.numa` domains with HTTP/HTTPS reverse proxy, auto TLS, WebSocket
|
- [x] Local service proxy — `.numa` domains with HTTP/HTTPS reverse proxy, auto TLS, WebSocket
|
||||||
- [ ] pkarr integration — resolve Ed25519 keys via Mainline DHT (15M nodes)
|
- [ ] pkarr integration — self-sovereign DNS via Mainline DHT (15M nodes)
|
||||||
- [ ] Global `.numa` names — self-publish, DHT-backed, first-come-first-served
|
- [ ] Global `.numa` names — self-publish, DHT-backed, first-come-first-served
|
||||||
- [ ] Audit protocol — challenge-based verification of resolver honesty
|
|
||||||
- [ ] Numa Network — proof-of-service consensus, NUMA token, paid `.numa` domains
|
|
||||||
- [ ] `.onion` bridge — human-readable `.numa` names for Tor hidden services
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
13
src/ctx.rs
13
src/ctx.rs
@@ -150,8 +150,17 @@ pub async fn handle_query(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut resp_buffer = BytePacketBuffer::new();
|
let mut resp_buffer = BytePacketBuffer::new();
|
||||||
response.write(&mut resp_buffer)?;
|
if response.write(&mut resp_buffer).is_err() {
|
||||||
ctx.socket.send_to(resp_buffer.filled(), src_addr).await?;
|
// Response too large for UDP — set TC bit and send header + question only
|
||||||
|
debug!("response too large, setting TC bit for {}", qname);
|
||||||
|
let mut tc_response = DnsPacket::response_from(&query, response.header.rescode);
|
||||||
|
tc_response.header.truncated_message = true;
|
||||||
|
let mut tc_buffer = BytePacketBuffer::new();
|
||||||
|
tc_response.write(&mut tc_buffer)?;
|
||||||
|
ctx.socket.send_to(tc_buffer.filled(), src_addr).await?;
|
||||||
|
} else {
|
||||||
|
ctx.socket.send_to(resp_buffer.filled(), src_addr).await?;
|
||||||
|
}
|
||||||
|
|
||||||
// Record stats and query log
|
// Record stats and query log
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ pub async fn forward_query(
|
|||||||
socket.send_to(send_buffer.filled(), upstream).await?;
|
socket.send_to(send_buffer.filled(), upstream).await?;
|
||||||
|
|
||||||
let mut recv_buffer = BytePacketBuffer::new();
|
let mut recv_buffer = BytePacketBuffer::new();
|
||||||
timeout(timeout_duration, socket.recv_from(&mut recv_buffer.buf)).await??;
|
let (size, _) = timeout(timeout_duration, socket.recv_from(&mut recv_buffer.buf)).await??;
|
||||||
|
|
||||||
|
if size >= recv_buffer.buf.len() {
|
||||||
|
log::debug!("upstream response truncated ({} bytes, buffer {})", size, recv_buffer.buf.len());
|
||||||
|
}
|
||||||
|
|
||||||
DnsPacket::from_buffer(&mut recv_buffer)
|
DnsPacket::from_buffer(&mut recv_buffer)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user