From f43daca5b7e6d3680dd4e32f557ebfe73819ddae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 27 Oct 2024 23:42:33 +0800 Subject: [PATCH] Fix gateway address/check --- redirect_iptables.go | 58 +++++++++++++++++++++----------------- redirect_nftables_rules.go | 11 ++++++-- stack.go | 8 ++++++ stack_system.go | 4 +-- tun.go | 12 ++++++-- tun_linux.go | 18 ++++-------- tun_windows.go | 20 +++++++------ 7 files changed, 78 insertions(+), 53 deletions(-) diff --git a/redirect_iptables.go b/redirect_iptables.go index 603ccf3..59c2d1d 100644 --- a/redirect_iptables.go +++ b/redirect_iptables.go @@ -142,41 +142,47 @@ func (r *autoRedirect) setupIPTablesForFamily(iptablesPath string) error { }) if !dnsServer.IsValid() { if iptablesPath == r.iptablesPath { - dnsServer = r.tunOptions.Inet4Address[0].Addr().Next() + if HasNextAddress(r.tunOptions.Inet4Address[0], 1) { + dnsServer = r.tunOptions.Inet4Address[0].Addr().Next() + } } else { - dnsServer = r.tunOptions.Inet6Address[0].Addr().Next() - } - } - if len(routeAddress) > 0 { - for _, address := range routeAddress { - err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, - "-d", address.String(), "-p udp --dport 53 -j DNAT --to", dnsServer) - if err != nil { - return err + if HasNextAddress(r.tunOptions.Inet6Address[0], 1) { + dnsServer = r.tunOptions.Inet6Address[0].Addr().Next() } } - } else if len(r.tunOptions.IncludeInterface) > 0 || len(r.tunOptions.IncludeUID) > 0 { - for _, name := range r.tunOptions.IncludeInterface { - err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, - "-i", name, "-p udp --dport 53 -j DNAT --to", dnsServer) - if err != nil { - return err + } + if dnsServer.IsValid() { + if len(routeAddress) > 0 { + for _, address := range routeAddress { + err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, + "-d", address.String(), "-p udp --dport 53 -j DNAT --to", dnsServer) + if err != nil { + return err + } } - } - for _, uidRange := range r.tunOptions.IncludeUID { - for uid := uidRange.Start; uid <= uidRange.End; uid++ { + } else if len(r.tunOptions.IncludeInterface) > 0 || len(r.tunOptions.IncludeUID) > 0 { + for _, name := range r.tunOptions.IncludeInterface { err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, - "-m owner --uid-owner", uid, "-p udp --dport 53 -j DNAT --to", dnsServer) + "-i", name, "-p udp --dport 53 -j DNAT --to", dnsServer) if err != nil { return err } } - } - } else { - err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, - "-p udp --dport 53 -j DNAT --to", dnsServer) - if err != nil { - return err + for _, uidRange := range r.tunOptions.IncludeUID { + for uid := uidRange.Start; uid <= uidRange.End; uid++ { + err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, + "-m owner --uid-owner", uid, "-p udp --dport 53 -j DNAT --to", dnsServer) + if err != nil { + return err + } + } + } + } else { + err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, + "-p udp --dport 53 -j DNAT --to", dnsServer) + if err != nil { + return err + } } } } diff --git a/redirect_nftables_rules.go b/redirect_nftables_rules.go index 34dda6d..a5840dc 100644 --- a/redirect_nftables_rules.go +++ b/redirect_nftables_rules.go @@ -573,11 +573,18 @@ func (r *autoRedirect) nftablesCreateDNSHijackRulesForFamily( }) if !dnsServer.IsValid() { if family == nftables.TableFamilyIPv4 { - dnsServer = r.tunOptions.Inet4Address[0].Addr().Next() + if HasNextAddress(r.tunOptions.Inet4Address[0], 1) { + dnsServer = r.tunOptions.Inet4Address[0].Addr().Next() + } } else { - dnsServer = r.tunOptions.Inet6Address[0].Addr().Next() + if HasNextAddress(r.tunOptions.Inet6Address[0], 1) { + dnsServer = r.tunOptions.Inet6Address[0].Addr().Next() + } } } + if !dnsServer.IsValid() { + return nil + } exprs := []expr.Any{ &expr.Meta{ Key: expr.MetaKeyNFPROTO, diff --git a/stack.go b/stack.go index 22853d6..4e61f8b 100644 --- a/stack.go +++ b/stack.go @@ -59,6 +59,14 @@ func NewStack( } } +func HasNextAddress(prefix netip.Prefix, count int) bool { + checkAddr := prefix.Addr() + for i := 0; i < count; i++ { + checkAddr = checkAddr.Next() + } + return prefix.Contains(checkAddr) +} + func BroadcastAddr(inet4Address []netip.Prefix) netip.Addr { if len(inet4Address) == 0 { return netip.Addr{} diff --git a/stack_system.go b/stack_system.go index 9f32abc..873b08a 100644 --- a/stack_system.go +++ b/stack_system.go @@ -70,14 +70,14 @@ func NewSystem(options StackOptions) (Stack, error) { interfaceFinder: options.InterfaceFinder, } if len(options.TunOptions.Inet4Address) > 0 { - if options.TunOptions.Inet4Address[0].Bits() == 32 { + if !HasNextAddress(options.TunOptions.Inet4Address[0], 1) { return nil, E.New("need one more IPv4 address in first prefix for system stack") } stack.inet4ServerAddress = options.TunOptions.Inet4Address[0].Addr() stack.inet4Address = stack.inet4ServerAddress.Next() } if len(options.TunOptions.Inet6Address) > 0 { - if options.TunOptions.Inet6Address[0].Bits() == 128 { + if !HasNextAddress(options.TunOptions.Inet6Address[0], 1) { return nil, E.New("need one more IPv6 address in first prefix for system stack") } stack.inet6ServerAddress = options.TunOptions.Inet6Address[0].Addr() diff --git a/tun.go b/tun.go index ed4b0e9..f1688fa 100644 --- a/tun.go +++ b/tun.go @@ -89,7 +89,11 @@ func (o *Options) Inet4GatewayAddr() netip.Addr { return o.Inet4Gateway } if len(o.Inet4Address) > 0 { - return o.Inet4Address[0].Addr() + if HasNextAddress(o.Inet4Address[0], 1) { + return o.Inet4Address[0].Addr().Next() + } else if runtime.GOOS != "linux" { + return o.Inet4Address[0].Addr() + } } return netip.IPv4Unspecified() } @@ -99,7 +103,11 @@ func (o *Options) Inet6GatewayAddr() netip.Addr { return o.Inet6Gateway } if len(o.Inet6Address) > 0 { - return o.Inet6Address[0].Addr() + if HasNextAddress(o.Inet6Address[0], 1) { + return o.Inet6Address[0].Addr().Next() + } else if runtime.GOOS != "linux" { + return o.Inet6Address[0].Addr() + } } return netip.IPv6Unspecified() } diff --git a/tun_linux.go b/tun_linux.go index 84d9110..0c64b15 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -351,20 +351,12 @@ func (t *NativeTun) routes(tunLink netlink.Link) ([]netlink.Route, error) { return nil, err } // Do not create gateway on linux by default - var ( - gateway4, gateway6 netip.Addr - ) - if t.options.Inet4Gateway.IsValid() { - gateway4 = t.options.Inet4Gateway - } - if t.options.Inet6Gateway.IsValid() { - gateway6 = t.options.Inet6Gateway - } + gateway4, gateway6 := t.options.Inet4GatewayAddr(), t.options.Inet6GatewayAddr() return common.Map(routeRanges, func(it netip.Prefix) netlink.Route { var gateway net.IP - if it.Addr().Is4() && gateway4.IsValid() { + if it.Addr().Is4() && !gateway4.IsUnspecified() { gateway = gateway4.AsSlice() - } else if it.Addr().Is6() && gateway6.IsValid() { + } else if it.Addr().Is6() && !gateway6.IsUnspecified() { gateway = gateway6.AsSlice() } return netlink.Route{ @@ -898,10 +890,10 @@ func (t *NativeTun) setSearchDomainForSystemdResolved() { } dnsServer := t.options.DNSServers if len(dnsServer) == 0 { - if len(t.options.Inet4Address) > 0 { + if len(t.options.Inet4Address) > 0 && HasNextAddress(t.options.Inet4Address[0], 1) { dnsServer = append(dnsServer, t.options.Inet4Address[0].Addr().Next()) } - if len(t.options.Inet6Address) > 0 { + if len(t.options.Inet6Address) > 0 && HasNextAddress(t.options.Inet6Address[0], 1) { dnsServer = append(dnsServer, t.options.Inet6Address[0].Addr().Next()) } } diff --git a/tun_windows.go b/tun_windows.go index 36fd8d0..45d5b00 100644 --- a/tun_windows.go +++ b/tun_windows.go @@ -74,12 +74,14 @@ func (t *NativeTun) configure() error { } if !t.options.EXP_DisableDNSHijack { dnsServers := common.Filter(t.options.DNSServers, netip.Addr.Is4) - if len(dnsServers) == 0 { + if len(dnsServers) == 0 && HasNextAddress(t.options.Inet4Address[0], 1) { dnsServers = []netip.Addr{t.options.Inet4Address[0].Addr().Next()} } - err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET), dnsServers, nil) - if err != nil { - return E.Cause(err, "set ipv4 dns") + if len(dnsServers) > 0 { + err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET), dnsServers, nil) + if err != nil { + return E.Cause(err, "set ipv4 dns") + } } } } @@ -90,12 +92,14 @@ func (t *NativeTun) configure() error { } if !t.options.EXP_DisableDNSHijack { dnsServers := common.Filter(t.options.DNSServers, netip.Addr.Is6) - if len(dnsServers) == 0 { + if len(dnsServers) == 0 && HasNextAddress(t.options.Inet6Address[0], 1) { dnsServers = []netip.Addr{t.options.Inet6Address[0].Addr().Next()} } - err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET6), dnsServers, nil) - if err != nil { - return E.Cause(err, "set ipv6 dns") + if len(dnsServers) > 0 { + err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET6), dnsServers, nil) + if err != nil { + return E.Cause(err, "set ipv6 dns") + } } } }