Compare commits

...

13 Commits

Author SHA1 Message Date
世界
0cb0451034 Improve iproute2 rules 2024-05-30 22:49:01 +08:00
世界
5bf54dc69a Fix netlink 2024-05-23 14:54:56 +08:00
世界
840f3758f9 Prioritize *_route_address in linux auto-route 2024-05-20 22:19:46 +08:00
XYenon
d923e5d10a Fix darwin routes 2024-05-20 19:07:24 +08:00
世界
779d1c7db2 Fix linux auto-route sequence 2024-05-15 22:22:08 +08:00
世界
3f128a4a6a Fix Remove bad suppress_prefixlength iproute2 rule 2024-05-10 17:50:56 +08:00
世界
fb6e917a2c Add StackOptions.IncludeAllNetworks 2024-05-07 20:20:44 +08:00
世界
e272ff0ad3 Remove bad suppress_prefixlength iproute2 rule
This change gives tun priority over DHCP 121 rules
2024-05-07 19:52:59 +08:00
世界
5584917e52 Update gVisor to 20240422.0 2024-05-07 19:52:59 +08:00
世界
e0ddbbb84f Update gVisor to 20240212.0-65-g71212d503 2024-05-07 19:52:59 +08:00
世界
a9895a7d88 Update gVisor to 20240206.0 2024-05-07 19:52:59 +08:00
世界
9380493c39 Fix bad usage for exec 2024-05-07 19:52:44 +08:00
世界
63f6630a0a Fix darwin monitor 2024-05-03 15:33:14 +08:00
14 changed files with 121 additions and 102 deletions

4
go.mod
View File

@@ -5,8 +5,8 @@ go 1.18
require (
github.com/fsnotify/fsnotify v1.7.0
github.com/go-ole/go-ole v1.3.0
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba
github.com/sagernet/sing v0.3.8
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/net v0.24.0

8
go.sum
View File

@@ -6,10 +6,10 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e h1:DOkjByVeAR56dkszjnMZke4wr7yM/1xHaJF3G9olkEE=
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I=
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0=
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk=
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing v0.3.8 h1:gm4JKalPhydMYX2zFOTnnd4TXtM/16WFRqSjMepYQQk=
github.com/sagernet/sing v0.3.8/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=

View File

@@ -57,14 +57,19 @@ func (m *networkUpdateMonitor) loopUpdate0() error {
if err != nil {
return err
}
err = unix.SetNonblock(routeSocket, true)
if err != nil {
unix.Close(routeSocket)
return err
}
routeSocketFile := os.NewFile(uintptr(routeSocket), "route")
defer routeSocketFile.Close()
m.routeSocketFile = routeSocketFile
m.loopUpdate1(routeSocketFile)
return nil
}
func (m *networkUpdateMonitor) loopUpdate1(routeSocketFile *os.File) {
defer routeSocketFile.Close()
buffer := buf.NewPacket()
defer buffer.Release()
done := make(chan struct{})

View File

@@ -25,6 +25,7 @@ type StackOptions struct {
Handler Handler
Logger logger.Logger
ForwarderBindInterface bool
IncludeAllNetworks bool
InterfaceFinder control.InterfaceFinder
}
@@ -34,7 +35,9 @@ func NewStack(
) (Stack, error) {
switch stack {
case "":
if WithGVisor && !options.TunOptions.GSO {
if options.IncludeAllNetworks {
return NewGVisor(options)
} else if WithGVisor && !options.TunOptions.GSO {
return NewMixed(options)
} else {
return NewSystem(options)
@@ -42,8 +45,14 @@ func NewStack(
case "gvisor":
return NewGVisor(options)
case "mixed":
if options.IncludeAllNetworks {
return nil, ErrIncludeAllNetworks
}
return NewMixed(options)
case "system":
if options.IncludeAllNetworks {
return nil, ErrIncludeAllNetworks
}
return NewSystem(options)
default:
return nil, E.New("unknown stack: ", stack)

View File

@@ -122,7 +122,7 @@ func (t *GVisor) Start() error {
if err != nil {
return
}
udpConn := gonet.NewUDPConn(ipStack, &wq, endpoint)
udpConn := gonet.NewUDPConn(&wq, endpoint)
lAddr := udpConn.RemoteAddr()
rAddr := udpConn.LocalAddr()
if lAddr == nil || rAddr == nil {

View File

@@ -32,7 +32,7 @@ type networkDispatcherFilter struct {
writer N.VectorisedWriter
}
func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
var network header.Network
if protocol == header.IPv4ProtocolNumber {
if headerPackets, loaded := pkt.Data().PullUp(header.IPv4MinimumSize); loaded {

View File

@@ -42,7 +42,7 @@ func NewUDPForwarder(ctx context.Context, stack *stack.Stack, handler Handler, u
}
}
func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt stack.PacketBufferPtr) bool {
func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.PacketBuffer) bool {
var upstreamMetadata M.Metadata
upstreamMetadata.Source = M.SocksaddrFrom(AddrFromAddress(id.RemoteAddress), id.RemotePort)
upstreamMetadata.Destination = M.SocksaddrFrom(AddrFromAddress(id.LocalAddress), id.LocalPort)
@@ -174,7 +174,7 @@ func (c *gUDPConn) Close() error {
return c.UDPConn.Close()
}
func gWriteUnreachable(gStack *stack.Stack, packet stack.PacketBufferPtr, err error) (retErr error) {
func gWriteUnreachable(gStack *stack.Stack, packet *stack.PacketBuffer, err error) (retErr error) {
if errors.Is(err, syscall.ENETUNREACH) {
if packet.NetworkProtocolNumber == header.IPv4ProtocolNumber {
return gWriteUnreachable4(gStack, packet, stack.RejectIPv4WithICMPNetUnreachable)
@@ -197,7 +197,7 @@ func gWriteUnreachable(gStack *stack.Stack, packet stack.PacketBufferPtr, err er
return nil
}
func gWriteUnreachable4(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpCode stack.RejectIPv4WithICMPType) error {
func gWriteUnreachable4(gStack *stack.Stack, packet *stack.PacketBuffer, icmpCode stack.RejectIPv4WithICMPType) error {
err := gStack.NetworkProtocolInstance(header.IPv4ProtocolNumber).(stack.RejectIPv4WithHandler).SendRejectionError(packet, icmpCode, true)
if err != nil {
return wrapStackError(err)
@@ -205,7 +205,7 @@ func gWriteUnreachable4(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpC
return nil
}
func gWriteUnreachable6(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpCode stack.RejectIPv6WithICMPType) error {
func gWriteUnreachable6(gStack *stack.Stack, packet *stack.PacketBuffer, icmpCode stack.RejectIPv6WithICMPType) error {
err := gStack.NetworkProtocolInstance(header.IPv6ProtocolNumber).(stack.RejectIPv6WithHandler).SendRejectionError(packet, icmpCode, true)
if err != nil {
return wrapStackError(err)

View File

@@ -56,7 +56,7 @@ func (m *Mixed) Start() error {
if err != nil {
return
}
udpConn := gonet.NewUDPConn(ipStack, &wq, endpoint)
udpConn := gonet.NewUDPConn(&wq, endpoint)
lAddr := udpConn.RemoteAddr()
rAddr := udpConn.LocalAddr()
if lAddr == nil || rAddr == nil {

View File

@@ -18,6 +18,8 @@ import (
"github.com/sagernet/sing/common/udpnat"
)
var ErrIncludeAllNetworks = E.New("`system` and `mixed` stack are not available when `includeAllNetworks` is enabled. See https://github.com/SagerNet/sing-tun/issues/25")
type System struct {
ctx context.Context
tun Tun

2
tun.go
View File

@@ -85,7 +85,7 @@ func CalculateInterfaceName(name string) (tunName string) {
for _, netInterface := range interfaces {
if strings.HasPrefix(netInterface.Name, tunName) {
index, parseErr := strconv.ParseInt(netInterface.Name[len(tunName):], 10, 16)
if parseErr == nil {
if parseErr == nil && int(index) >= tunIndex {
tunIndex = int(index) + 1
}
}

View File

@@ -102,10 +102,10 @@ func (e *DarwinEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
func (e *DarwinEndpoint) AddHeader(buffer stack.PacketBufferPtr) {
func (e *DarwinEndpoint) AddHeader(buffer *stack.PacketBuffer) {
}
func (e *DarwinEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool {
func (e *DarwinEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool {
return true
}

View File

@@ -516,7 +516,7 @@ func (t *NativeTun) rules() []*netlink.Rule {
if runtime.GOOS == "android" && t.options.InterfaceMonitor.AndroidVPNEnabled() {
const protectedFromVPN = 0x20000
if p4 || t.options.StrictRoute {
if p4 {
it = netlink.NewRule()
if t.options.InterfaceMonitor.OverrideAndroidVPN() {
it.Mark = protectedFromVPN
@@ -528,7 +528,7 @@ func (t *NativeTun) rules() []*netlink.Rule {
rules = append(rules, it)
priority++
}
if p6 || t.options.StrictRoute {
if p6 {
it = netlink.NewRule()
if t.options.InterfaceMonitor.OverrideAndroidVPN() {
it.Mark = protectedFromVPN
@@ -572,16 +572,47 @@ func (t *NativeTun) rules() []*netlink.Rule {
rules = append(rules, it)
}
priority++
}
/*if p6 {
it = netlink.NewRule()
it.Priority = priority
it.Dst = t.options.Inet6Address.Masked()
it.Table = tunTableIndex
it.Table = t.options.TableIndex
it.SuppressPrefixlen = 0
it.Family = unix.AF_INET
rules = append(rules, it)
priority++
}
if p6 {
it = netlink.NewRule()
it.Priority = priority6
it.Table = t.options.TableIndex
it.SuppressPrefixlen = 0
it.Family = unix.AF_INET6
rules = append(rules, it)
}*/
priority6++
}
if p4 {
it = netlink.NewRule()
it.Priority = priority
it.Invert = true
it.Dport = netlink.NewRulePortRange(53, 53)
it.Table = unix.RT_TABLE_MAIN
it.SuppressPrefixlen = 0
it.Family = unix.AF_INET
rules = append(rules, it)
priority++
}
if p6 {
it = netlink.NewRule()
it.Priority = priority6
it.Invert = true
it.Dport = netlink.NewRulePortRange(53, 53)
it.Table = unix.RT_TABLE_MAIN
it.SuppressPrefixlen = 0
it.Family = unix.AF_INET6
rules = append(rules, it)
priority6++
}
if p4 && !t.options.StrictRoute {
it = netlink.NewRule()
it.Priority = priority
it.IPProto = syscall.IPPROTO_ICMP
@@ -590,7 +621,7 @@ func (t *NativeTun) rules() []*netlink.Rule {
rules = append(rules, it)
priority++
}
if p6 {
if p6 && !t.options.StrictRoute {
it = netlink.NewRule()
it.Priority = priority6
it.IPProto = syscall.IPPROTO_ICMPV6
@@ -599,101 +630,63 @@ func (t *NativeTun) rules() []*netlink.Rule {
rules = append(rules, it)
priority6++
}
if p4 {
it = netlink.NewRule()
it.Priority = priority
it.Invert = true
it.Dport = netlink.NewRulePortRange(53, 53)
it.Table = unix.RT_TABLE_MAIN
it.SuppressPrefixlen = 0
it.Family = unix.AF_INET
rules = append(rules, it)
}
if p6 {
it = netlink.NewRule()
it.Priority = priority6
it.Invert = true
it.Dport = netlink.NewRulePortRange(53, 53)
it.Table = unix.RT_TABLE_MAIN
it.SuppressPrefixlen = 0
it.Family = unix.AF_INET6
rules = append(rules, it)
}
}
if p4 {
if t.options.StrictRoute {
it = netlink.NewRule()
it.Priority = priority
it.Table = t.options.TableIndex
it.Family = unix.AF_INET
rules = append(rules, it)
} else {
it = netlink.NewRule()
it.Priority = priority
it.Invert = true
it.IifName = "lo"
it.Table = t.options.TableIndex
it.Family = unix.AF_INET
rules = append(rules, it)
it = netlink.NewRule()
it.Priority = priority
it.Invert = true
it.IifName = "lo"
it.Table = t.options.TableIndex
it.Family = unix.AF_INET
rules = append(rules, it)
it = netlink.NewRule()
it.Priority = priority
it.IifName = "lo"
it.Src = netip.PrefixFrom(netip.IPv4Unspecified(), 32)
it.Table = t.options.TableIndex
it.Family = unix.AF_INET
rules = append(rules, it)
for _, address := range t.options.Inet4Address {
it = netlink.NewRule()
it.Priority = priority
it.IifName = "lo"
it.Src = netip.PrefixFrom(netip.IPv4Unspecified(), 32)
it.Src = address.Masked()
it.Table = t.options.TableIndex
it.Family = unix.AF_INET
rules = append(rules, it)
for _, address := range t.options.Inet4Address {
it = netlink.NewRule()
it.Priority = priority
it.IifName = "lo"
it.Src = address.Masked()
it.Table = t.options.TableIndex
it.Family = unix.AF_INET
rules = append(rules, it)
}
}
priority++
}
if p6 {
if !t.options.StrictRoute {
for _, address := range t.options.Inet6Address {
it = netlink.NewRule()
it.Priority = priority6
it.IifName = "lo"
it.Src = address.Masked()
it.Table = t.options.TableIndex
it.Family = unix.AF_INET6
rules = append(rules, it)
}
priority6++
for _, address := range t.options.Inet6Address {
it = netlink.NewRule()
it.Priority = priority6
it.IifName = "lo"
it.Src = netip.PrefixFrom(netip.IPv6Unspecified(), 1)
it.Goto = nopPriority
it.Src = address.Masked()
it.Table = t.options.TableIndex
it.Family = unix.AF_INET6
rules = append(rules, it)
it = netlink.NewRule()
it.Priority = priority6
it.IifName = "lo"
it.Src = netip.PrefixFrom(netip.AddrFrom16([16]byte{0: 128}), 1)
it.Goto = nopPriority
it.Family = unix.AF_INET6
rules = append(rules, it)
priority6++
}
priority6++
it = netlink.NewRule()
it.Priority = priority6
it.Table = t.options.TableIndex
it.IifName = "lo"
it.Src = netip.PrefixFrom(netip.IPv6Unspecified(), 1)
it.Goto = nopPriority
it.Family = unix.AF_INET6
rules = append(rules, it)
it = netlink.NewRule()
it.Priority = priority6
it.IifName = "lo"
it.Src = netip.PrefixFrom(netip.AddrFrom16([16]byte{0: 128}), 1)
it.Goto = nopPriority
it.Family = unix.AF_INET6
rules = append(rules, it)
priority6++
}
if p4 {
@@ -820,9 +813,9 @@ func (t *NativeTun) setSearchDomainForSystemdResolved() {
if len(t.options.Inet6Address) > 0 {
dnsServer = append(dnsServer, t.options.Inet6Address[0].Addr().Next())
}
shell.Exec(ctlPath, "domain", t.options.Name, "~.").Start()
go shell.Exec(ctlPath, "domain", t.options.Name, "~.").Run()
if t.options.AutoRoute {
shell.Exec(ctlPath, "default-route", t.options.Name, "true").Start()
shell.Exec(ctlPath, append([]string{"dns", t.options.Name}, common.Map(dnsServer, netip.Addr.String)...)...).Start()
go shell.Exec(ctlPath, "default-route", t.options.Name, "true").Run()
go shell.Exec(ctlPath, append([]string{"dns", t.options.Name}, common.Map(dnsServer, netip.Addr.String)...)...).Run()
}
}

View File

@@ -109,6 +109,11 @@ func (o *Options) BuildAutoRouteRanges(underNetworkExtension bool) ([]netip.Pref
var inet4Ranges []netip.Prefix
if len(o.Inet4RouteAddress) > 0 {
inet4Ranges = o.Inet4RouteAddress
for _, address := range o.Inet4Address {
if address.Bits() < 32 {
inet4Ranges = append(inet4Ranges, netipx.RangeOfPrefix(address).Prefixes()...)
}
}
} else if autoRouteUseSubRanges && !underNetworkExtension {
inet4Ranges = []netip.Prefix{
netip.PrefixFrom(netip.AddrFrom4([4]byte{0: 1}), 8),
@@ -144,6 +149,11 @@ func (o *Options) BuildAutoRouteRanges(underNetworkExtension bool) ([]netip.Pref
var inet6Ranges []netip.Prefix
if len(o.Inet6RouteAddress) > 0 {
inet6Ranges = o.Inet6RouteAddress
for _, address := range o.Inet6Address {
if address.Bits() < 32 {
inet6Ranges = append(inet6Ranges, netipx.RangeOfPrefix(address).Prefixes()...)
}
}
} else if autoRouteUseSubRanges && !underNetworkExtension {
inet6Ranges = []netip.Prefix{
netip.PrefixFrom(netip.AddrFrom16([16]byte{0: 1}), 8),

View File

@@ -99,10 +99,10 @@ func (e *WintunEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
func (e *WintunEndpoint) AddHeader(buffer stack.PacketBufferPtr) {
func (e *WintunEndpoint) AddHeader(buffer *stack.PacketBuffer) {
}
func (e *WintunEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool {
func (e *WintunEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool {
return true
}