mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-02 19:37:40 +03:00
Fix gateway & FIx prefix check
This commit is contained in:
parent
07278fb470
commit
10f73346a0
8 changed files with 111 additions and 45 deletions
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
8
stack.go
8
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 {
|
func BroadcastAddr(inet4Address []netip.Prefix) netip.Addr {
|
||||||
if len(inet4Address) == 0 {
|
if len(inet4Address) == 0 {
|
||||||
return netip.Addr{}
|
return netip.Addr{}
|
||||||
|
|
|
@ -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
30
tun.go
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
|
|
13
tun_linux.go
13
tun_linux.go
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue