Fix gateway & FIx prefix check

This commit is contained in:
世界 2024-10-26 14:54:08 +08:00
parent 07278fb470
commit 10f73346a0
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
8 changed files with 111 additions and 45 deletions

View file

@ -142,41 +142,47 @@ func (r *autoRedirect) setupIPTablesForFamily(iptablesPath string) error {
}) })
if !dnsServer.IsValid() { if !dnsServer.IsValid() {
if iptablesPath == r.iptablesPath { 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 { } else {
dnsServer = r.tunOptions.Inet6Address[0].Addr().Next() if HasNextAddress(r.tunOptions.Inet6Address[0], 1) {
dnsServer = r.tunOptions.Inet6Address[0].Addr().Next()
}
} }
} }
if len(routeAddress) > 0 { if dnsServer.IsValid() {
for _, address := range routeAddress { if len(routeAddress) > 0 {
err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, for _, address := range routeAddress {
"-d", address.String(), "-p udp --dport 53 -j DNAT --to", dnsServer)
if err != nil {
return err
}
}
} 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
}
}
for _, uidRange := range r.tunOptions.IncludeUID {
for uid := uidRange.Start; uid <= uidRange.End; uid++ {
err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing,
"-m owner --uid-owner", uid, "-p udp --dport 53 -j DNAT --to", dnsServer) "-d", address.String(), "-p udp --dport 53 -j DNAT --to", dnsServer)
if err != nil { if err != nil {
return err return err
} }
} }
} } else if len(r.tunOptions.IncludeInterface) > 0 || len(r.tunOptions.IncludeUID) > 0 {
} else { for _, name := range r.tunOptions.IncludeInterface {
err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing, err = r.runShell(iptablesPath, "-t nat -A", tableNamePreRouteing,
"-p udp --dport 53 -j DNAT --to", dnsServer) "-i", name, "-p udp --dport 53 -j DNAT --to", dnsServer)
if err != nil { if err != nil {
return err 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
}
} }
} }
} }

View file

@ -573,11 +573,18 @@ func (r *autoRedirect) nftablesCreateDNSHijackRulesForFamily(
}) })
if !dnsServer.IsValid() { if !dnsServer.IsValid() {
if family == nftables.TableFamilyIPv4 { 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 { } 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{ exprs := []expr.Any{
&expr.Meta{ &expr.Meta{
Key: expr.MetaKeyNFPROTO, Key: expr.MetaKeyNFPROTO,

View file

@ -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 { func BroadcastAddr(inet4Address []netip.Prefix) netip.Addr {
if len(inet4Address) == 0 { if len(inet4Address) == 0 {
return netip.Addr{} return netip.Addr{}

View file

@ -70,14 +70,14 @@ func NewSystem(options StackOptions) (Stack, error) {
interfaceFinder: options.InterfaceFinder, interfaceFinder: options.InterfaceFinder,
} }
if len(options.TunOptions.Inet4Address) > 0 { 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") return nil, E.New("need one more IPv4 address in first prefix for system stack")
} }
stack.inet4ServerAddress = options.TunOptions.Inet4Address[0].Addr() stack.inet4ServerAddress = options.TunOptions.Inet4Address[0].Addr()
stack.inet4Address = stack.inet4ServerAddress.Next() stack.inet4Address = stack.inet4ServerAddress.Next()
} }
if len(options.TunOptions.Inet6Address) > 0 { 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") return nil, E.New("need one more IPv6 address in first prefix for system stack")
} }
stack.inet6ServerAddress = options.TunOptions.Inet6Address[0].Addr() stack.inet6ServerAddress = options.TunOptions.Inet6Address[0].Addr()

30
tun.go
View file

@ -53,6 +53,8 @@ type Options struct {
MTU uint32 MTU uint32
GSO bool GSO bool
AutoRoute bool AutoRoute bool
Inet4Gateway netip.Addr
Inet6Gateway netip.Addr
DNSServers []netip.Addr DNSServers []netip.Addr
IPRoute2TableIndex int IPRoute2TableIndex int
IPRoute2RuleIndex int IPRoute2RuleIndex int
@ -82,6 +84,34 @@ type Options struct {
EXP_DisableDNSHijack bool EXP_DisableDNSHijack bool
} }
func (o *Options) Inet4GatewayAddr() netip.Addr {
if o.Inet4Gateway.IsValid() {
return o.Inet4Gateway
}
if len(o.Inet4Address) > 0 {
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()
}
func (o *Options) Inet6GatewayAddr() netip.Addr {
if o.Inet6Gateway.IsValid() {
return o.Inet6Gateway
}
if len(o.Inet6Address) > 0 {
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()
}
func CalculateInterfaceName(name string) (tunName string) { func CalculateInterfaceName(name string) (tunName string) {
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
tunName = "utun" tunName = "utun"

View file

@ -245,11 +245,12 @@ func configure(tunFd int, ifIndex int, name string, options Options) error {
if err != nil { if err != nil {
return err return err
} }
gateway4, gateway6 := options.Inet4GatewayAddr(), options.Inet6GatewayAddr()
for _, routeRange := range routeRanges { for _, routeRange := range routeRanges {
if routeRange.Addr().Is4() { if routeRange.Addr().Is4() {
err = addRoute(routeRange, options.Inet4Address[0].Addr()) err = addRoute(routeRange, gateway4)
} else { } else {
err = addRoute(routeRange, options.Inet6Address[0].Addr()) err = addRoute(routeRange, gateway6)
} }
if err != nil { if err != nil {
return E.Cause(err, "add route: ", routeRange) return E.Cause(err, "add route: ", routeRange)

View file

@ -350,9 +350,18 @@ func (t *NativeTun) routes(tunLink netlink.Link) ([]netlink.Route, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Do not create gateway on linux by default
gateway4, gateway6 := t.options.Inet4GatewayAddr(), t.options.Inet6GatewayAddr()
return common.Map(routeRanges, func(it netip.Prefix) netlink.Route { return common.Map(routeRanges, func(it netip.Prefix) netlink.Route {
var gateway net.IP
if it.Addr().Is4() && !gateway4.IsUnspecified() {
gateway = gateway4.AsSlice()
} else if it.Addr().Is6() && !gateway6.IsUnspecified() {
gateway = gateway6.AsSlice()
}
return netlink.Route{ return netlink.Route{
Dst: prefixToIPNet(it), Dst: prefixToIPNet(it),
Gw: gateway,
LinkIndex: tunLink.Attrs().Index, LinkIndex: tunLink.Attrs().Index,
Table: t.options.IPRoute2TableIndex, Table: t.options.IPRoute2TableIndex,
} }
@ -881,10 +890,10 @@ func (t *NativeTun) setSearchDomainForSystemdResolved() {
} }
dnsServer := t.options.DNSServers dnsServer := t.options.DNSServers
if len(dnsServer) == 0 { 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()) 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()) dnsServer = append(dnsServer, t.options.Inet6Address[0].Addr().Next())
} }
} }

View file

@ -74,12 +74,14 @@ func (t *NativeTun) configure() error {
} }
if !t.options.EXP_DisableDNSHijack { if !t.options.EXP_DisableDNSHijack {
dnsServers := common.Filter(t.options.DNSServers, netip.Addr.Is4) 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()} dnsServers = []netip.Addr{t.options.Inet4Address[0].Addr().Next()}
} }
err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET), dnsServers, nil) if len(dnsServers) > 0 {
if err != nil { err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET), dnsServers, nil)
return E.Cause(err, "set ipv4 dns") if err != nil {
return E.Cause(err, "set ipv4 dns")
}
} }
} }
} }
@ -90,12 +92,14 @@ func (t *NativeTun) configure() error {
} }
if !t.options.EXP_DisableDNSHijack { if !t.options.EXP_DisableDNSHijack {
dnsServers := common.Filter(t.options.DNSServers, netip.Addr.Is6) 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()} dnsServers = []netip.Addr{t.options.Inet6Address[0].Addr().Next()}
} }
err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET6), dnsServers, nil) if len(dnsServers) > 0 {
if err != nil { err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET6), dnsServers, nil)
return E.Cause(err, "set ipv6 dns") if err != nil {
return E.Cause(err, "set ipv6 dns")
}
} }
} }
} }
@ -103,15 +107,16 @@ func (t *NativeTun) configure() error {
_ = luid.DisableDNSRegistration() _ = luid.DisableDNSRegistration()
} }
if t.options.AutoRoute { if t.options.AutoRoute {
gateway4, gateway6 := t.options.Inet4GatewayAddr(), t.options.Inet6GatewayAddr()
routeRanges, err := t.options.BuildAutoRouteRanges(false) routeRanges, err := t.options.BuildAutoRouteRanges(false)
if err != nil { if err != nil {
return err return err
} }
for _, routeRange := range routeRanges { for _, routeRange := range routeRanges {
if routeRange.Addr().Is4() { if routeRange.Addr().Is4() {
err = luid.AddRoute(routeRange, netip.IPv4Unspecified(), 0) err = luid.AddRoute(routeRange, gateway4, 0)
} else { } else {
err = luid.AddRoute(routeRange, netip.IPv6Unspecified(), 0) err = luid.AddRoute(routeRange, gateway6, 0)
} }
} }
if err != nil { if err != nil {