mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-14 03:23:58 +00:00
TUN inbound: autoSystemDnsToGateway falls back to an IPv6 gateway on Linux
Without an IPv4 address in gateway, the system DNS now points at the first IPv6 gateway plus one (e.g. fc00::1/64 -> fc00::2) instead of nothing, and the routing check before the takeover accepts IPv6 addresses for it. The README also says what each system does without gateway: Xray assigns no address on Linux, Windows gives the TUN link-local ones itself, and macOS and FreeBSD use 169.254.10.1/30. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
de02da553a
commit
3a6bdb19ba
+18
-12
@@ -53,23 +53,29 @@ var resolvectlRunner = func(name string, args ...string) ([]byte, error) {
|
||||
}
|
||||
|
||||
// systemDNSAddrs derives the addresses used for the system DNS takeover from the
|
||||
// first IPv4 gateway: the gateway address itself is what a query from this
|
||||
// interface appears to come from, and the next address is what the resolver is
|
||||
// pointed at. The latter belongs to the TUN and is answered inside Xray;
|
||||
// handing the configured public resolvers to resolvectl instead would leave the
|
||||
// system querying them directly over the physical link, defeating the point of
|
||||
// the TUN.
|
||||
// first IPv4 gateway, or without one, the first IPv6 gateway: the gateway
|
||||
// address itself is what a query from this interface appears to come from, and
|
||||
// the next address is what the resolver is pointed at. The latter belongs to
|
||||
// the TUN and is answered inside Xray; handing the configured public resolvers
|
||||
// to resolvectl instead would leave the system querying them directly over the
|
||||
// physical link, defeating the point of the TUN.
|
||||
func systemDNSAddrs(gateway []string) (source, dns netip.Addr, ok bool) {
|
||||
var first6 netip.Addr
|
||||
for _, address := range gateway {
|
||||
prefix, err := netip.ParsePrefix(address)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
addr := prefix.Addr()
|
||||
if !addr.Is4() {
|
||||
continue
|
||||
if addr.Is4() {
|
||||
return addr, addr.Next(), true
|
||||
}
|
||||
return addr, addr.Next(), true
|
||||
if !first6.IsValid() {
|
||||
first6 = addr
|
||||
}
|
||||
}
|
||||
if first6.IsValid() {
|
||||
return first6, first6.Next(), true
|
||||
}
|
||||
return netip.Addr{}, netip.Addr{}, false
|
||||
}
|
||||
@@ -115,11 +121,11 @@ const probeSourcePort = 49152
|
||||
// Overridable for tests.
|
||||
var verifyDNSRouting = func(ctx context.Context, inboundTag, source, address string) error {
|
||||
ip, err := netip.ParseAddr(address)
|
||||
if err != nil || !ip.Is4() {
|
||||
if err != nil {
|
||||
return errors.New("invalid DNS address ", address).Base(err)
|
||||
}
|
||||
src, err := netip.ParseAddr(source)
|
||||
if err != nil || !src.Is4() {
|
||||
if err != nil || src.Is4() != ip.Is4() {
|
||||
return errors.New("invalid source address ", source).Base(err)
|
||||
}
|
||||
|
||||
@@ -202,7 +208,7 @@ func (t *LinuxTun) ConfigureSystemDNS(ctx context.Context, inboundTag string) er
|
||||
|
||||
source, address, ok := systemDNSAddrs(t.options.Gateway)
|
||||
if !ok {
|
||||
return errors.New("no IPv4 gateway, cannot derive a system DNS address")
|
||||
return errors.New("no gateway, cannot derive a system DNS address")
|
||||
}
|
||||
|
||||
iface := t.ifaceName()
|
||||
|
||||
Reference in New Issue
Block a user