feat(net): support host.docker.internal DNS and gateway-to-localhost translation#157
Merged
feat(net): support host.docker.internal DNS and gateway-to-localhost translation#157
Conversation
…translation Containers need to access services running on the host machine via the standard Docker hostname `host.docker.internal`. This was completely missing — DNS returned NXDOMAIN, and even if resolved, TCP/UDP connections to the gateway IP failed because the host OS has no route to 10.0.2.1 (it only exists in user-space smoltcp). Two fixes: 1. Register `host.docker.internal` and `gateway.docker.internal` in the shared DNS LocalHostsTable at daemon startup, resolving to the gateway IP. Queries flow: container → guest DNS → gateway DNS → LocalHostsTable hit → response. 2. Translate gateway-IP-destined connections to 127.0.0.1 in the TCP bridge (gate_syns) and UDP proxy (proxy_udp). The gateway IS the host process, so loopback reaches any service on 0.0.0.0 or 127.0.0.1 — matching Docker Desktop's effective behavior.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds Docker Desktop–compatible host.docker.internal / gateway.docker.internal support by ensuring those names resolve inside the VM and by translating gateway-IP–destined traffic to host loopback so connections actually reach host services.
Changes:
- Register
host.docker.internalandgateway.docker.internalDNS entries at daemon startup, pointing to the VM gateway IP. - Translate outbound TCP gateway-IP connections to
127.0.0.1inTcpBridge::gate_syns. - Translate outbound UDP gateway-IP flows to
127.0.0.1inUdpProxy::proxy_udp.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| virt/arcbox-net/src/darwin/tcp_bridge.rs | Adds gateway-IP→loopback translation for TCP connects; updates constructor/tests accordingly. |
| virt/arcbox-net/src/darwin/socket_proxy.rs | Adds gateway-IP→loopback translation for UDP flow sockets; updates constructor/callers/tests. |
| virt/arcbox-net/src/darwin/datapath_loop.rs | Wires the gateway IP into the TcpBridge constructor. |
| app/arcbox-daemon/src/services.rs | Registers Docker compatibility DNS names (host.docker.internal, gateway.docker.internal) to the gateway IP. |
Address review feedback: - Force proxy_target=None when dst_ip==gateway_ip so the loopback translation is never bypassed by a configured system proxy. - Add TCP test: SYN to GW_IP connects successfully via loopback. - Add UDP test: datagram to GW_IP is delivered to a loopback listener.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
host.docker.internalandgateway.docker.internalin the shared DNSLocalHostsTableat daemon startup, resolving to the gateway IPTcpBridge::gate_syns) and UDP (inUdpProxy::proxy_udp) connections to127.0.0.1so they reach host serviceshost.docker.internalreturned NXDOMAIN and even manually resolved gateway connections failed because10.0.2.1doesn't exist as a real interface on the hostContext
host.docker.internalis a Docker Desktop compatibility feature used by many containerized applications to reach host services (databases, API servers, dev tools). ArcBox had zero support — two independent bugs:TcpStream::connect(10.0.2.1:port)on the host OS, where10.0.2.1only exists in user-space smoltcp. The UDP proxy had the same issue.The fix resolves both: DNS returns the gateway IP, and the bridge/proxy translate gateway IP →
127.0.0.1before connecting. This matches Docker Desktop's effective behavior (vpnkit routes gateway connections to host loopback).Test plan
cargo clippyandcargo testpass (verified locally, 2 pre-existing pool test flakes excluded)docker run --rm alpine wget -qO- http://host.docker.internal:N— should succeedgateway.docker.internalalso resolves correctlyhost.docker.internalworks (e.g. DNS client targeting host DNS)