mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-06-09 00:53:53 +02:00
fix: use raw IPv6 socket for DNS responses in macOS intercept mode
macOS rejects sendmsg from [::1] to global unicast IPv6 (EINVAL), and nat on lo0 doesn't fire for route-to'd packets (pf skips translation on the second interface pass). ULA addresses on lo0 also fail (EHOSTUNREACH - kernel segregates lo0 routing). Solution: wrap the [::1] UDP listener's ResponseWriter with rawIPv6Writer that sends responses via SOCK_RAW (IPPROTO_UDP) on lo0, bypassing the kernel's routing validation. pf's rdr state reverses the address translation on the response path. Changes: - Add rawipv6_darwin.go: rawIPv6Writer wraps dns.ResponseWriter, sends UDP responses via raw IPv6 socket with proper checksum calculation - Add rawipv6_other.go: no-op wrapIPv6Handler for non-darwin platforms - Remove nat rules from pf anchor (no longer needed) - Block IPv6 TCP DNS (block return) - falls back to IPv4 (~1s, rare) - Remove IPv6 TCP rdr/route-to/pass rules (only UDP intercepted)
This commit is contained in:
committed by
Cuong Manh Le
parent
95dd871e2d
commit
22a796f673
@@ -211,7 +211,11 @@ func (p *prog) serveDNS(listenerNum string) error {
|
||||
proto := proto
|
||||
if needLocalIPv6Listener(p.cfg.Service.InterceptMode) {
|
||||
g.Go(func() error {
|
||||
s, errCh := runDNSServer(net.JoinHostPort("::1", strconv.Itoa(listenerConfig.Port)), proto, handler)
|
||||
ipv6Handler := handler
|
||||
if proto == "udp" {
|
||||
ipv6Handler = wrapIPv6Handler(handler)
|
||||
}
|
||||
s, errCh := runDNSServer(net.JoinHostPort("::1", strconv.Itoa(listenerConfig.Port)), proto, ipv6Handler)
|
||||
defer s.Shutdown()
|
||||
select {
|
||||
case <-p.stopCh:
|
||||
|
||||
Reference in New Issue
Block a user