Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/SagerNet/sing-tun into meta
Browse files Browse the repository at this point in the history
  • Loading branch information
wwqgtxx committed Dec 7, 2023
2 parents 170591e + e9db7e1 commit 1aa1d8c
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 53 deletions.
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ go 1.18
require (
github.com/fsnotify/fsnotify v1.7.0
github.com/go-ole/go-ole v1.3.0
github.com/metacubex/gvisor v0.0.0-20231001104248-0f672c3fb8d8
github.com/metacubex/gvisor v0.0.0-20231206145044-b6960a648d8b
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
github.com/sagernet/sing v0.2.14
github.com/sagernet/sing v0.2.19-0.20231207034108-445cd4f41e3f
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9
go4.org/netipx v0.0.0-20230824141953-6213f710f925
golang.org/x/net v0.17.0
golang.org/x/sys v0.13.0
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/net v0.19.0
golang.org/x/sys v0.15.0
)

require (
github.com/google/btree v1.1.2 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/time v0.4.0 // indirect
)
24 changes: 12 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@ github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
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/metacubex/gvisor v0.0.0-20231001104248-0f672c3fb8d8 h1:npBvaPAT145UY8682AzpUMWpdIxJti/WPLjy7gCiYYs=
github.com/metacubex/gvisor v0.0.0-20231001104248-0f672c3fb8d8/go.mod h1:ZR6Gas7P1GcADCVBc1uOrA0bLQqDDyp70+63fD/BE2c=
github.com/metacubex/gvisor v0.0.0-20231206145044-b6960a648d8b h1:xJHepHYyQ7NOpUkEcz9wC3TnMRFjFQ3KVVqtHC/6G5s=
github.com/metacubex/gvisor v0.0.0-20231206145044-b6960a648d8b/go.mod h1:rhBU9tD5ktoGPBtXUquhWuGJ4u+8ZZzBMi2cAdv9q8Y=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
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/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.2.14 h1:L3AXDh22nsOOYz2nTRU1JvpRsmzViWKI1B8TsQYG1eY=
github.com/sagernet/sing v0.2.14/go.mod h1:AhNEHu0GXrpqkuzvTwvC8+j2cQUU/dh+zLEmq4C99pg=
github.com/sagernet/sing v0.2.19-0.20231207034108-445cd4f41e3f h1:hYkBnmJjVphGc4b02b4jN46ojh05vACYZI3ciD/V3pA=
github.com/sagernet/sing v0.2.19-0.20231207034108-445cd4f41e3f/go.mod h1:Ce5LNojQOgOiWhiD8pPD6E9H7e2KgtOe3Zxx4Ou5u80=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ=
go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
12 changes: 12 additions & 0 deletions stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tun

import (
"context"
"encoding/binary"
"net"
"net/netip"

"github.com/sagernet/sing/common/control"
Expand Down Expand Up @@ -52,3 +54,13 @@ func NewStack(
return nil, E.New("unknown stack: ", stack)
}
}

func BroadcastAddr(inet4Address []netip.Prefix) netip.Addr {
if len(inet4Address) == 0 {
return netip.Addr{}
}
prefix := inet4Address[0]
var broadcastAddr [4]byte
binary.BigEndian.PutUint32(broadcastAddr[:], binary.BigEndian.Uint32(prefix.Masked().Addr().AsSlice())|^binary.BigEndian.Uint32(net.CIDRMask(prefix.Bits(), 32)))
return netip.AddrFrom4(broadcastAddr)
}
6 changes: 4 additions & 2 deletions stack_gvisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type GVisor struct {
tunMtu uint32
endpointIndependentNat bool
udpTimeout int64
broadcastAddr netip.Addr
handler Handler
logger logger.Logger
stack *stack.Stack
Expand All @@ -60,6 +61,7 @@ func NewGVisor(
tunMtu: options.MTU,
endpointIndependentNat: options.EndpointIndependentNat,
udpTimeout: options.UDPTimeout,
broadcastAddr: BroadcastAddr(options.Inet4Address),
handler: options.Handler,
logger: options.Logger,
}
Expand All @@ -71,7 +73,7 @@ func (t *GVisor) Start() error {
if err != nil {
return err
}
linkEndpoint = &LinkEndpointFilter{linkEndpoint, t.tun.CreateVectorisedWriter()}
linkEndpoint = &LinkEndpointFilter{linkEndpoint, t.broadcastAddr, t.tun.CreateVectorisedWriter()}
ipStack, err := newGVisorStack(linkEndpoint)
if err != nil {
return err
Expand Down Expand Up @@ -135,7 +137,7 @@ func (t *GVisor) Start() error {
var metadata M.Metadata
metadata.Source = M.SocksaddrFromNet(lAddr)
metadata.Destination = M.SocksaddrFromNet(rAddr)
ctx, conn := canceler.NewPacketConn(t.ctx, bufio.NewPacketConn(&bufio.UnbindPacketConn{ExtendedConn: bufio.NewExtendedConn(gConn), Addr: M.SocksaddrFromNet(rAddr)}), time.Duration(t.udpTimeout)*time.Second)
ctx, conn := canceler.NewPacketConn(t.ctx, bufio.NewUnbindPacketConnWithAddr(gConn, metadata.Destination), time.Duration(t.udpTimeout)*time.Second)
hErr := t.handler.NewPacketConnection(ctx, conn, metadata)
if hErr != nil {
endpoint.Abort()
Expand Down
16 changes: 10 additions & 6 deletions stack_gvisor_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package tun

import (
"net/netip"

"github.com/metacubex/gvisor/pkg/tcpip"
"github.com/metacubex/gvisor/pkg/tcpip/header"
"github.com/metacubex/gvisor/pkg/tcpip/stack"
Expand All @@ -14,18 +16,20 @@ var _ stack.LinkEndpoint = (*LinkEndpointFilter)(nil)

type LinkEndpointFilter struct {
stack.LinkEndpoint
Writer N.VectorisedWriter
BroadcastAddress netip.Addr
Writer N.VectorisedWriter
}

func (w *LinkEndpointFilter) Attach(dispatcher stack.NetworkDispatcher) {
w.LinkEndpoint.Attach(&networkDispatcherFilter{dispatcher, w.Writer})
w.LinkEndpoint.Attach(&networkDispatcherFilter{dispatcher, w.BroadcastAddress, w.Writer})
}

var _ stack.NetworkDispatcher = (*networkDispatcherFilter)(nil)

type networkDispatcherFilter struct {
stack.NetworkDispatcher
writer N.VectorisedWriter
broadcastAddress netip.Addr
writer N.VectorisedWriter
}

func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
Expand All @@ -44,9 +48,9 @@ func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkPro
return
}
destination := AddrFromAddress(network.DestinationAddress())
if destination.IsGlobalUnicast() {
w.NetworkDispatcher.DeliverNetworkPacket(protocol, pkt)
if destination == w.broadcastAddress || !destination.IsGlobalUnicast() {
_, _ = bufio.WriteVectorised(w.writer, pkt.AsSlices())
return
}
_, _ = bufio.WriteVectorised(w.writer, pkt.AsSlices())
w.NetworkDispatcher.DeliverNetworkPacket(protocol, pkt)
}
9 changes: 8 additions & 1 deletion stack_mixed.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (m *Mixed) Start() error {
var metadata M.Metadata
metadata.Source = M.SocksaddrFromNet(lAddr)
metadata.Destination = M.SocksaddrFromNet(rAddr)
ctx, conn := canceler.NewPacketConn(m.ctx, bufio.NewPacketConn(&bufio.UnbindPacketConn{ExtendedConn: bufio.NewExtendedConn(gConn), Addr: M.SocksaddrFromNet(rAddr)}), time.Duration(m.udpTimeout)*time.Second)
ctx, conn := canceler.NewPacketConn(m.ctx, bufio.NewUnbindPacketConnWithAddr(gConn, metadata.Destination), time.Duration(m.udpTimeout)*time.Second)
hErr := m.handler.NewPacketConnection(ctx, conn, metadata)
if hErr != nil {
endpoint.Abort()
Expand Down Expand Up @@ -146,6 +146,10 @@ func (m *Mixed) wintunLoop(winTun WinTun) {
}

func (m *Mixed) processIPv4(packet clashtcpip.IPv4Packet) error {
destination := packet.DestinationIP()
if destination == m.broadcastAddr || !destination.IsGlobalUnicast() {
return common.Error(m.tun.Write(packet))
}
switch packet.Protocol() {
case clashtcpip.TCP:
return m.processIPv4TCP(packet, packet.Payload())
Expand All @@ -164,6 +168,9 @@ func (m *Mixed) processIPv4(packet clashtcpip.IPv4Packet) error {
}

func (m *Mixed) processIPv6(packet clashtcpip.IPv6Packet) error {
if !packet.DestinationIP().IsGlobalUnicast() {
return common.Error(m.tun.Write(packet))
}
switch packet.Protocol() {
case clashtcpip.TCP:
return m.processIPv6TCP(packet, packet.Payload())
Expand Down
11 changes: 10 additions & 1 deletion stack_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type System struct {
inet4Address netip.Addr
inet6ServerAddress netip.Addr
inet6Address netip.Addr
broadcastAddr netip.Addr
udpTimeout int64
tcpListener net.Listener
tcpListener6 net.Listener
Expand Down Expand Up @@ -60,6 +61,7 @@ func NewSystem(options StackOptions) (Stack, error) {
logger: options.Logger,
inet4Prefixes: options.Inet4Address,
inet6Prefixes: options.Inet6Address,
broadcastAddr: BroadcastAddr(options.Inet4Address),
bindInterface: options.ForwarderBindInterface,
interfaceFinder: options.InterfaceFinder,
}
Expand Down Expand Up @@ -233,7 +235,8 @@ func (s *System) acceptLoop(listener net.Listener) {
}

func (s *System) processIPv4(packet clashtcpip.IPv4Packet) error {
if !packet.DestinationIP().IsGlobalUnicast() {
destination := packet.DestinationIP()
if destination == s.broadcastAddr || !destination.IsGlobalUnicast() {
return common.Error(s.tun.Write(packet))
}
switch packet.Protocol() {
Expand Down Expand Up @@ -323,6 +326,9 @@ func (s *System) processIPv4UDP(packet clashtcpip.IPv4Packet, header clashtcpip.
if packet.FragmentOffset() != 0 {
return E.New("ipv4: udp: fragment dropped")
}
if !header.Valid() {
return E.New("ipv4: udp: invalid packet")
}
source := netip.AddrPortFrom(packet.SourceIP(), header.SourcePort())
destination := netip.AddrPortFrom(packet.DestinationIP(), header.DestinationPort())
if !destination.Addr().IsGlobalUnicast() {
Expand All @@ -346,6 +352,9 @@ func (s *System) processIPv4UDP(packet clashtcpip.IPv4Packet, header clashtcpip.
}

func (s *System) processIPv6UDP(packet clashtcpip.IPv6Packet, header clashtcpip.UDPPacket) error {
if !header.Valid() {
return E.New("ipv6: udp: invalid packet")
}
source := netip.AddrPortFrom(packet.SourceIP(), header.SourcePort())
destination := netip.AddrPortFrom(packet.DestinationIP(), header.DestinationPort())
if !destination.Addr().IsGlobalUnicast() {
Expand Down
2 changes: 1 addition & 1 deletion tun_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func configure(tunFd int, ifIndex int, name string, options Options) error {
}
if options.AutoRoute {
var routeRanges []netip.Prefix
routeRanges, err = options.BuildAutoRouteRanges()
routeRanges, err = options.BuildAutoRouteRanges(false)
for _, routeRange := range routeRanges {
if routeRange.Addr().Is4() {
err = addRoute(routeRange, options.Inet4Address[0].Addr())
Expand Down
38 changes: 19 additions & 19 deletions tun_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,28 +196,17 @@ func prefixToIPNet(prefix netip.Prefix) *net.IPNet {
}

func (t *NativeTun) routes(tunLink netlink.Link) ([]netlink.Route, error) {
var routes []netlink.Route
for _, address := range t.options.Inet6Address {
routes = append(routes, netlink.Route{
Dst: prefixToIPNet(address),
routeRanges, err := t.options.BuildAutoRouteRanges(false)
if err != nil {
return nil, err
}
return common.Map(routeRanges, func(it netip.Prefix) netlink.Route {
return netlink.Route{
Dst: prefixToIPNet(it),
LinkIndex: tunLink.Attrs().Index,
Table: t.options.TableIndex,
})
}
if t.options.AutoRoute {
routeRanges, err := t.options.BuildAutoRouteRanges()
if err != nil {
return nil, err
}
for _, routeRange := range routeRanges {
routes = append(routes, netlink.Route{
Dst: prefixToIPNet(routeRange),
LinkIndex: tunLink.Attrs().Index,
Table: t.options.TableIndex,
})
}
}
return routes, nil
}), nil
}

const (
Expand Down Expand Up @@ -561,6 +550,17 @@ func (t *NativeTun) rules() []*netlink.Rule {
}
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++

it = netlink.NewRule()
it.Priority = priority6
it.IifName = "lo"
Expand Down
8 changes: 4 additions & 4 deletions tun_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ func buildExcludedRanges(includeRanges []ranges.Range[uint32], excludeRanges []r

const autoRouteUseSubRanges = runtime.GOOS == "darwin"

func (o *Options) BuildAutoRouteRanges() ([]netip.Prefix, error) {
func (o *Options) BuildAutoRouteRanges(underNetworkExtension bool) ([]netip.Prefix, error) {
var routeRanges []netip.Prefix
if len(o.Inet4Address) > 0 {
if o.AutoRoute && len(o.Inet4Address) > 0 {
var inet4Ranges []netip.Prefix
if len(o.Inet4RouteAddress) > 0 {
inet4Ranges = o.Inet4RouteAddress
} else if autoRouteUseSubRanges {
} else if autoRouteUseSubRanges && !underNetworkExtension {
inet4Ranges = []netip.Prefix{
netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 0, 0, 0}), 8),
netip.PrefixFrom(netip.AddrFrom4([4]byte{2, 0, 0, 0}), 7),
Expand Down Expand Up @@ -144,7 +144,7 @@ func (o *Options) BuildAutoRouteRanges() ([]netip.Prefix, error) {
var inet6Ranges []netip.Prefix
if len(o.Inet6RouteAddress) > 0 {
inet6Ranges = o.Inet6RouteAddress
} else if autoRouteUseSubRanges {
} else if autoRouteUseSubRanges && !underNetworkExtension {
inet6Ranges = []netip.Prefix{
netip.PrefixFrom(netip.IPv6Unspecified(), 1),
netip.PrefixFrom(netip.AddrFrom16([16]byte{0: 128}), 1),
Expand Down
2 changes: 1 addition & 1 deletion tun_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (t *NativeTun) configure() error {
_ = luid.DisableDNSRegistration()
}
if t.options.AutoRoute {
routeRanges, err := t.options.BuildAutoRouteRanges()
routeRanges, err := t.options.BuildAutoRouteRanges(false)
if err != nil {
return err
}
Expand Down

0 comments on commit 1aa1d8c

Please sign in to comment.