From e881f21013109dc3c5f82dd61a1179e2faeaa40c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 20 May 2023 12:09:41 +0800 Subject: [PATCH] Update gVisor to release-20230605.0-21-g457c1c36d --- go.mod | 6 +- go.sum | 12 +- gvisor.go | 102 +++------------ gvisor_udp.go | 15 ++- internal/fdbased/README.md | 2 +- internal/fdbased/endpoint.go | 8 +- internal/fdbased/mmap.go | 8 +- internal/fdbased/packet_dispatchers.go | 16 +-- .../fdbased/stopfd/stopfd_state_autogen.go | 6 - route.go | 92 -------------- route_gvisor.go | 16 --- route_mapping.go | 32 ----- route_nat.go | 119 ------------------ route_nat_gvisor.go | 41 ------ route_non_gvisor.go | 11 -- stack.go | 1 - system.go | 96 -------------- tun_darwin.go | 8 +- tun_darwin_gvisor.go | 14 +-- tun_windows_gvisor.go | 16 +-- 20 files changed, 71 insertions(+), 550 deletions(-) delete mode 100644 internal/fdbased/stopfd/stopfd_state_autogen.go delete mode 100644 route.go delete mode 100644 route_gvisor.go delete mode 100644 route_mapping.go delete mode 100644 route_nat.go delete mode 100644 route_nat_gvisor.go delete mode 100644 route_non_gvisor.go diff --git a/go.mod b/go.mod index aeb2ebb..73d22e9 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,9 @@ require ( github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 github.com/sagernet/sing v0.2.4 github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 - golang.org/x/net v0.9.0 - golang.org/x/sys v0.7.0 - gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 + golang.org/x/net v0.10.0 + golang.org/x/sys v0.8.0 + gvisor.dev/gvisor v0.0.0-20230609002524-f143e1baf0bb ) require ( diff --git a/go.sum b/go.sum index d5f1d03..02da0df 100644 --- a/go.sum +++ b/go.sum @@ -15,15 +15,15 @@ github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh 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= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 h1:zUQYeyyPLnSR6yMvLSOmLH37xDWCZ7BqlpE69fE5K3Q= -gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q= +gvisor.dev/gvisor v0.0.0-20230609002524-f143e1baf0bb h1:A5Zr25mHIiXEZUjN92wAopvMv2XL4jTbl2/+9D4ATgE= +gvisor.dev/gvisor v0.0.0-20230609002524-f143e1baf0bb/go.mod h1:sQuqOkxbfJq/GS2uSnqHphtXclHyk/ZrAGhZBxxsq6g= diff --git a/gvisor.go b/gvisor.go index 4a75a02..9a3d8e1 100644 --- a/gvisor.go +++ b/gvisor.go @@ -4,8 +4,7 @@ package tun import ( "context" - "net" - "syscall" + "net/netip" "time" "github.com/sagernet/sing/common/bufio" @@ -36,12 +35,10 @@ type GVisor struct { tunMtu uint32 endpointIndependentNat bool udpTimeout int64 - router Router handler Handler logger logger.Logger stack *stack.Stack endpoint stack.LinkEndpoint - routeMapping *RouteMapping } type GVisorTun interface { @@ -63,13 +60,9 @@ func NewGVisor( tunMtu: options.MTU, endpointIndependentNat: options.EndpointIndependentNat, udpTimeout: options.UDPTimeout, - router: options.Router, handler: options.Handler, logger: options.Logger, } - if gStack.router != nil { - gStack.routeMapping = NewRouteMapping(options.UDPTimeout) - } return gStack, nil } @@ -155,44 +148,7 @@ func (t *GVisor) Start() error { } }() }) - ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, func(id stack.TransportEndpointID, buffer stack.PacketBufferPtr) bool { - if t.router != nil { - var routeSession RouteSession - routeSession.Network = syscall.IPPROTO_TCP - var ipHdr header.Network - if buffer.NetworkProtocolNumber == header.IPv4ProtocolNumber { - routeSession.IPVersion = 4 - ipHdr = header.IPv4(buffer.NetworkHeader().Slice()) - } else { - routeSession.IPVersion = 6 - ipHdr = header.IPv6(buffer.NetworkHeader().Slice()) - } - tcpHdr := header.TCP(buffer.TransportHeader().Slice()) - routeSession.Source = M.AddrPortFrom(net.IP(ipHdr.SourceAddress()), tcpHdr.SourcePort()) - routeSession.Destination = M.AddrPortFrom(net.IP(ipHdr.DestinationAddress()), tcpHdr.DestinationPort()) - action := t.routeMapping.Lookup(routeSession, func() RouteAction { - if routeSession.IPVersion == 4 { - return t.router.RouteConnection(routeSession, &systemTCPDirectPacketWriter4{t.tun, routeSession.Source}) - } else { - return t.router.RouteConnection(routeSession, &systemTCPDirectPacketWriter6{t.tun, routeSession.Source}) - } - }) - switch actionType := action.(type) { - case *ActionBlock: - // TODO: send icmp unreachable - return true - case *ActionDirect: - buffer.IncRef() - err = actionType.WritePacketBuffer(buffer) - if err != nil { - t.logger.Trace("route gvisor tcp packet: ", err) - } - return true - } - } - return tcpForwarder.HandlePacket(id, buffer) - }) - + ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpForwarder.HandlePacket) if !t.endpointIndependentNat { udpForwarder := udp.NewForwarder(ipStack, func(request *udp.ForwarderRequest) { var wq waiter.Queue @@ -218,43 +174,7 @@ func (t *GVisor) Start() error { } }() }) - ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, func(id stack.TransportEndpointID, buffer stack.PacketBufferPtr) bool { - if t.router != nil { - var routeSession RouteSession - routeSession.Network = syscall.IPPROTO_UDP - var ipHdr header.Network - if buffer.NetworkProtocolNumber == header.IPv4ProtocolNumber { - routeSession.IPVersion = 4 - ipHdr = header.IPv4(buffer.NetworkHeader().Slice()) - } else { - routeSession.IPVersion = 6 - ipHdr = header.IPv6(buffer.NetworkHeader().Slice()) - } - udpHdr := header.UDP(buffer.TransportHeader().Slice()) - routeSession.Source = M.AddrPortFrom(net.IP(ipHdr.SourceAddress()), udpHdr.SourcePort()) - routeSession.Destination = M.AddrPortFrom(net.IP(ipHdr.DestinationAddress()), udpHdr.DestinationPort()) - action := t.routeMapping.Lookup(routeSession, func() RouteAction { - if routeSession.IPVersion == 4 { - return t.router.RouteConnection(routeSession, &systemUDPDirectPacketWriter4{t.tun, routeSession.Source}) - } else { - return t.router.RouteConnection(routeSession, &systemUDPDirectPacketWriter6{t.tun, routeSession.Source}) - } - }) - switch actionType := action.(type) { - case *ActionBlock: - // TODO: send icmp unreachable - return true - case *ActionDirect: - buffer.IncRef() - err = actionType.WritePacketBuffer(buffer) - if err != nil { - t.logger.Trace("route gvisor udp packet: ", err) - } - return true - } - } - return udpForwarder.HandlePacket(id, buffer) - }) + ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket) } else { ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUDPForwarder(t.ctx, ipStack, t.handler, t.udpTimeout).HandlePacket) } @@ -272,3 +192,19 @@ func (t *GVisor) Close() error { } return nil } + +func AddressFromAddr(destination netip.Addr) tcpip.Address { + if destination.Is6() { + return tcpip.AddrFrom16(destination.As16()) + } else { + return tcpip.AddrFrom4(destination.As4()) + } +} + +func AddrFromAddress(address tcpip.Address) netip.Addr { + if address.Len() == 16 { + return netip.AddrFrom16(address.As16()) + } else { + return netip.AddrFrom4(address.As4()) + } +} diff --git a/gvisor_udp.go b/gvisor_udp.go index f23bd3a..78b060a 100644 --- a/gvisor_udp.go +++ b/gvisor_udp.go @@ -5,7 +5,6 @@ package tun import ( "context" "math" - "net" "net/netip" "github.com/sagernet/sing/common/buf" @@ -13,7 +12,7 @@ import ( N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/udpnat" - "gvisor.dev/gvisor/pkg/bufferv2" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/checksum" "gvisor.dev/gvisor/pkg/tcpip/header" @@ -36,8 +35,8 @@ func NewUDPForwarder(ctx context.Context, stack *stack.Stack, handler Handler, u func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt stack.PacketBufferPtr) bool { var upstreamMetadata M.Metadata - upstreamMetadata.Source = M.SocksaddrFrom(M.AddrFromIP(net.IP(id.RemoteAddress)), id.RemotePort) - upstreamMetadata.Destination = M.SocksaddrFrom(M.AddrFromIP(net.IP(id.LocalAddress)), id.LocalPort) + upstreamMetadata.Source = M.SocksaddrFrom(AddrFromAddress(id.RemoteAddress), id.RemotePort) + upstreamMetadata.Destination = M.SocksaddrFrom(AddrFromAddress(id.LocalAddress), id.LocalPort) var netProto tcpip.NetworkProtocolNumber if upstreamMetadata.Source.IsIPv4() { netProto = header.IPv4ProtocolNumber @@ -63,12 +62,12 @@ type UDPBackWriter struct { sourceNetwork tcpip.NetworkProtocolNumber } -func (w *UDPBackWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { - defer buffer.Release() +func (w *UDPBackWriter) WritePacket(packetBuffer *buf.Buffer, destination M.Socksaddr) error { + defer packetBuffer.Release() route, err := w.stack.FindRoute( defaultNIC, - tcpip.Address(destination.Addr.AsSlice()), + AddressFromAddr(destination.Addr), w.source, w.sourceNetwork, false, @@ -80,7 +79,7 @@ func (w *UDPBackWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) packet := stack.NewPacketBuffer(stack.PacketBufferOptions{ ReserveHeaderBytes: header.UDPMinimumSize + int(route.MaxHeaderLength()), - Payload: bufferv2.MakeWithData(buffer.Bytes()), + Payload: buffer.MakeWithData(packetBuffer.Bytes()), }) defer packet.DecRef() diff --git a/internal/fdbased/README.md b/internal/fdbased/README.md index 6bb26b5..085db72 100644 --- a/internal/fdbased/README.md +++ b/internal/fdbased/README.md @@ -1,3 +1,3 @@ # fdbased -Version: release-20230417.0 \ No newline at end of file +Version: release-20230605.0-21-g457c1c36d \ No newline at end of file diff --git a/internal/fdbased/endpoint.go b/internal/fdbased/endpoint.go index d2a5bf2..3550855 100644 --- a/internal/fdbased/endpoint.go +++ b/internal/fdbased/endpoint.go @@ -45,7 +45,7 @@ import ( "golang.org/x/sys/unix" "gvisor.dev/gvisor/pkg/atomicbitops" - "gvisor.dev/gvisor/pkg/bufferv2" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" @@ -545,7 +545,7 @@ func (e *endpoint) writePacket(pkt stack.PacketBufferPtr) tcpip.Error { vnetHdr.csumStart = header.EthernetMinimumSize + pkt.GSOOptions.L3HdrLen vnetHdr.csumOffset = pkt.GSOOptions.CsumOffset } - if pkt.GSOOptions.Type != stack.GSONone && uint16(pkt.Data().Size()) > pkt.GSOOptions.MSS { + if uint16(pkt.Data().Size()) > pkt.GSOOptions.MSS { switch pkt.GSOOptions.Type { case stack.GSOTCPv4: vnetHdr.gsoType = _VIRTIO_NET_HDR_GSO_TCPV4 @@ -732,7 +732,7 @@ func (e *endpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error) } // InjectOutbound implements stack.InjectableEndpoint.InjectOutbound. -func (e *endpoint) InjectOutbound(dest tcpip.Address, packet *bufferv2.View) tcpip.Error { +func (e *endpoint) InjectOutbound(dest tcpip.Address, packet *buffer.View) tcpip.Error { return rawfile.NonBlockingWrite(e.fds[0].fd, packet.AsSlice()) } @@ -756,7 +756,7 @@ func (e *endpoint) GSOMaxSize() uint32 { return e.gsoMaxSize } -// SupportsHWGSO implements stack.GSOEndpoint. +// SupportedGSO implements stack.GSOEndpoint. func (e *endpoint) SupportedGSO() stack.SupportedGSO { return e.gsoKind } diff --git a/internal/fdbased/mmap.go b/internal/fdbased/mmap.go index 218057f..04bb761 100644 --- a/internal/fdbased/mmap.go +++ b/internal/fdbased/mmap.go @@ -24,7 +24,7 @@ import ( "github.com/sagernet/sing-tun/internal/fdbased/stopfd" "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/bufferv2" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/link/rawfile" @@ -135,7 +135,7 @@ type packetMMapDispatcher struct { func (*packetMMapDispatcher) release() {} -func (d *packetMMapDispatcher) readMMappedPacket() (*bufferv2.View, bool, tcpip.Error) { +func (d *packetMMapDispatcher) readMMappedPacket() (*buffer.View, bool, tcpip.Error) { hdr := tPacketHdr(d.ringBuffer[d.ringOffset*tpFrameSize:]) for hdr.tpStatus()&tpStatusUser == 0 { stopped, errno := rawfile.BlockingPollUntilStopped(d.EFD, d.fd, unix.POLLIN|unix.POLLERR) @@ -159,7 +159,7 @@ func (d *packetMMapDispatcher) readMMappedPacket() (*bufferv2.View, bool, tcpip. } // Copy out the packet from the mmapped frame to a locally owned buffer. - pkt := bufferv2.NewView(int(hdr.tpSnapLen())) + pkt := buffer.NewView(int(hdr.tpSnapLen())) pkt.Write(hdr.Payload()) // Release packet to kernel. hdr.setTPStatus(tpStatusKernel) @@ -191,7 +191,7 @@ func (d *packetMMapDispatcher) dispatch() (bool, tcpip.Error) { } pbuf := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Payload: bufferv2.MakeWithView(pkt), + Payload: buffer.MakeWithView(pkt), }) defer pbuf.DecRef() if d.e.hdrSize > 0 { diff --git a/internal/fdbased/packet_dispatchers.go b/internal/fdbased/packet_dispatchers.go index 51d5c42..5e35f11 100644 --- a/internal/fdbased/packet_dispatchers.go +++ b/internal/fdbased/packet_dispatchers.go @@ -21,7 +21,7 @@ import ( "github.com/sagernet/sing-tun/internal/fdbased/stopfd" "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/bufferv2" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/link/rawfile" @@ -35,7 +35,7 @@ type iovecBuffer struct { // buffer is the actual buffer that holds the packet contents. Some contents // are reused across calls to pullBuffer if number of requested bytes is // smaller than the number of bytes allocated in the buffer. - views []*bufferv2.View + views []*buffer.View // iovecs are initialized with base pointers/len of the corresponding // entries in the views defined above, except when GSO is enabled @@ -59,7 +59,7 @@ type iovecBuffer struct { func newIovecBuffer(sizes []int, skipsVnetHdr bool) *iovecBuffer { b := &iovecBuffer{ - views: make([]*bufferv2.View, len(sizes)), + views: make([]*buffer.View, len(sizes)), sizes: sizes, skipsVnetHdr: skipsVnetHdr, } @@ -87,7 +87,7 @@ func (b *iovecBuffer) nextIovecs() []unix.Iovec { if b.views[i] != nil { break } - v := bufferv2.NewViewSize(b.sizes[i]) + v := buffer.NewViewSize(b.sizes[i]) b.views[i] = v b.iovecs[i+vnetHdrOff] = unix.Iovec{Base: v.BasePtr()} b.iovecs[i+vnetHdrOff].SetLen(v.Size()) @@ -100,14 +100,14 @@ func (b *iovecBuffer) nextIovecs() []unix.Iovec { // that holds the storage, and updates pulledIndex to indicate which part // of b.buffer's storage must be reallocated during the next call to // nextIovecs. -func (b *iovecBuffer) pullBuffer(n int) bufferv2.Buffer { - var views []*bufferv2.View +func (b *iovecBuffer) pullBuffer(n int) buffer.Buffer { + var views []*buffer.View c := 0 if b.skipsVnetHdr { c += virtioNetHdrSize if c >= n { // Nothing in the packet. - return bufferv2.Buffer{} + return buffer.Buffer{} } } // Remove the used views from the buffer. @@ -126,7 +126,7 @@ func (b *iovecBuffer) pullBuffer(n int) bufferv2.Buffer { // Exclude the size of the vnet header. n -= virtioNetHdrSize } - pulled := bufferv2.Buffer{} + pulled := buffer.Buffer{} for _, v := range views { pulled.Append(v) } diff --git a/internal/fdbased/stopfd/stopfd_state_autogen.go b/internal/fdbased/stopfd/stopfd_state_autogen.go deleted file mode 100644 index c013598..0000000 --- a/internal/fdbased/stopfd/stopfd_state_autogen.go +++ /dev/null @@ -1,6 +0,0 @@ -// automatically generated by stateify. - -//go:build (linux && amd64) || (linux && arm64) -// +build linux,amd64 linux,arm64 - -package stopfd diff --git a/route.go b/route.go deleted file mode 100644 index 0ebf267..0000000 --- a/route.go +++ /dev/null @@ -1,92 +0,0 @@ -package tun - -import ( - "net/netip" - - E "github.com/sagernet/sing/common/exceptions" -) - -type ActionType = uint8 - -const ( - ActionTypeUnknown ActionType = iota - ActionTypeReturn - ActionTypeBlock - ActionTypeDirect -) - -func ParseActionType(action string) (ActionType, error) { - switch action { - case "return": - return ActionTypeReturn, nil - case "block": - return ActionTypeBlock, nil - case "direct": - return ActionTypeDirect, nil - default: - return 0, E.New("unknown action: ", action) - } -} - -func ActionTypeName(actionType ActionType) (string, error) { - switch actionType { - case ActionTypeUnknown: - return "", nil - case ActionTypeReturn: - return "return", nil - case ActionTypeBlock: - return "block", nil - case ActionTypeDirect: - return "direct", nil - default: - return "", E.New("unknown action: ", actionType) - } -} - -type RouteSession struct { - IPVersion uint8 - Network uint8 - Source netip.AddrPort - Destination netip.AddrPort -} - -type RouteContext interface { - WritePacket(packet []byte) error -} - -type Router interface { - RouteConnection(session RouteSession, context RouteContext) RouteAction -} - -type RouteAction interface { - ActionType() ActionType - Timeout() bool -} - -type ActionReturn struct{} - -func (r *ActionReturn) ActionType() ActionType { - return ActionTypeReturn -} - -func (r *ActionReturn) Timeout() bool { - return false -} - -type ActionBlock struct{} - -func (r *ActionBlock) ActionType() ActionType { - return ActionTypeBlock -} - -func (r *ActionBlock) Timeout() bool { - return false -} - -type ActionDirect struct { - DirectDestination -} - -func (r *ActionDirect) ActionType() ActionType { - return ActionTypeDirect -} diff --git a/route_gvisor.go b/route_gvisor.go deleted file mode 100644 index 185a362..0000000 --- a/route_gvisor.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build with_gvisor - -package tun - -import ( - "github.com/sagernet/sing/common/buf" - - "gvisor.dev/gvisor/pkg/tcpip/stack" -) - -type DirectDestination interface { - WritePacket(buffer *buf.Buffer) error - WritePacketBuffer(buffer stack.PacketBufferPtr) error - Close() error - Timeout() bool -} diff --git a/route_mapping.go b/route_mapping.go deleted file mode 100644 index b0ccad8..0000000 --- a/route_mapping.go +++ /dev/null @@ -1,32 +0,0 @@ -package tun - -import ( - "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/cache" -) - -type RouteMapping struct { - status *cache.LruCache[RouteSession, RouteAction] -} - -func NewRouteMapping(maxAge int64) *RouteMapping { - return &RouteMapping{ - status: cache.New( - cache.WithAge[RouteSession, RouteAction](maxAge), - cache.WithUpdateAgeOnGet[RouteSession, RouteAction](), - cache.WithEvict[RouteSession, RouteAction](func(key RouteSession, conn RouteAction) { - common.Close(conn) - }), - ), - } -} - -func (m *RouteMapping) Lookup(session RouteSession, constructor func() RouteAction) RouteAction { - action, _ := m.status.LoadOrStore(session, constructor) - if action.Timeout() { - common.Close(action) - action = constructor() - m.status.Store(session, action) - } - return action -} diff --git a/route_nat.go b/route_nat.go deleted file mode 100644 index 35b1d55..0000000 --- a/route_nat.go +++ /dev/null @@ -1,119 +0,0 @@ -package tun - -import ( - "net/netip" - "sync" - - "github.com/sagernet/sing-tun/internal/clashtcpip" -) - -type NatMapping struct { - access sync.RWMutex - sessions map[RouteSession]RouteContext - ipRewrite bool -} - -func NewNatMapping(ipRewrite bool) *NatMapping { - return &NatMapping{ - sessions: make(map[RouteSession]RouteContext), - ipRewrite: ipRewrite, - } -} - -func (m *NatMapping) CreateSession(session RouteSession, context RouteContext) { - if m.ipRewrite { - session.Source = netip.AddrPort{} - } - m.access.Lock() - m.sessions[session] = context - m.access.Unlock() -} - -func (m *NatMapping) DeleteSession(session RouteSession) { - if m.ipRewrite { - session.Source = netip.AddrPort{} - } - m.access.Lock() - delete(m.sessions, session) - m.access.Unlock() -} - -func (m *NatMapping) WritePacket(packet []byte) (bool, error) { - var routeSession RouteSession - var ipHdr clashtcpip.IP - switch ipVersion := packet[0] >> 4; ipVersion { - case 4: - routeSession.IPVersion = 4 - ipHdr = clashtcpip.IPv4Packet(packet) - case 6: - routeSession.IPVersion = 6 - ipHdr = clashtcpip.IPv6Packet(packet) - default: - return false, nil - } - routeSession.Network = ipHdr.Protocol() - switch routeSession.Network { - case clashtcpip.TCP: - tcpHdr := clashtcpip.TCPPacket(ipHdr.Payload()) - routeSession.Destination = netip.AddrPortFrom(ipHdr.SourceIP(), tcpHdr.SourcePort()) - if !m.ipRewrite { - routeSession.Source = netip.AddrPortFrom(ipHdr.DestinationIP(), tcpHdr.DestinationPort()) - } - case clashtcpip.UDP: - udpHdr := clashtcpip.UDPPacket(ipHdr.Payload()) - routeSession.Destination = netip.AddrPortFrom(ipHdr.SourceIP(), udpHdr.SourcePort()) - if !m.ipRewrite { - routeSession.Source = netip.AddrPortFrom(ipHdr.DestinationIP(), udpHdr.DestinationPort()) - } - default: - routeSession.Destination = netip.AddrPortFrom(ipHdr.SourceIP(), 0) - if !m.ipRewrite { - routeSession.Source = netip.AddrPortFrom(ipHdr.DestinationIP(), 0) - } - } - m.access.RLock() - context, loaded := m.sessions[routeSession] - m.access.RUnlock() - if !loaded { - return false, nil - } - return true, context.WritePacket(packet) -} - -type NatWriter struct { - inet4Address netip.Addr - inet6Address netip.Addr -} - -func NewNatWriter(inet4Address netip.Addr, inet6Address netip.Addr) *NatWriter { - return &NatWriter{ - inet4Address: inet4Address, - inet6Address: inet6Address, - } -} - -func (w *NatWriter) RewritePacket(packet []byte) { - var ipHdr clashtcpip.IP - var bindAddr netip.Addr - switch ipVersion := packet[0] >> 4; ipVersion { - case 4: - ipHdr = clashtcpip.IPv4Packet(packet) - bindAddr = w.inet4Address - case 6: - ipHdr = clashtcpip.IPv6Packet(packet) - bindAddr = w.inet6Address - default: - return - } - ipHdr.SetSourceIP(bindAddr) - switch ipHdr.Protocol() { - case clashtcpip.TCP: - tcpHdr := clashtcpip.TCPPacket(ipHdr.Payload()) - tcpHdr.ResetChecksum(ipHdr.PseudoSum()) - case clashtcpip.UDP: - udpHdr := clashtcpip.UDPPacket(ipHdr.Payload()) - udpHdr.ResetChecksum(ipHdr.PseudoSum()) - default: - } - ipHdr.ResetChecksum() -} diff --git a/route_nat_gvisor.go b/route_nat_gvisor.go deleted file mode 100644 index 1c59335..0000000 --- a/route_nat_gvisor.go +++ /dev/null @@ -1,41 +0,0 @@ -//go:build with_gvisor - -package tun - -import ( - "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/header" - "gvisor.dev/gvisor/pkg/tcpip/stack" -) - -func (w *NatWriter) RewritePacketBuffer(packetBuffer stack.PacketBufferPtr) { - var bindAddr tcpip.Address - if packetBuffer.NetworkProtocolNumber == header.IPv4ProtocolNumber { - bindAddr = tcpip.Address(w.inet4Address.AsSlice()) - } else { - bindAddr = tcpip.Address(w.inet6Address.AsSlice()) - } - var ipHdr header.Network - switch packetBuffer.NetworkProtocolNumber { - case header.IPv4ProtocolNumber: - ipHdr = header.IPv4(packetBuffer.NetworkHeader().Slice()) - case header.IPv6ProtocolNumber: - ipHdr = header.IPv6(packetBuffer.NetworkHeader().Slice()) - default: - return - } - oldAddr := ipHdr.SourceAddress() - if checksumHdr, needChecksum := ipHdr.(header.ChecksummableNetwork); needChecksum { - checksumHdr.SetSourceAddressWithChecksumUpdate(bindAddr) - } else { - ipHdr.SetSourceAddress(bindAddr) - } - switch packetBuffer.TransportProtocolNumber { - case header.TCPProtocolNumber: - tcpHdr := header.TCP(packetBuffer.TransportHeader().Slice()) - tcpHdr.UpdateChecksumPseudoHeaderAddress(oldAddr, bindAddr, true) - case header.UDPProtocolNumber: - udpHdr := header.UDP(packetBuffer.TransportHeader().Slice()) - udpHdr.UpdateChecksumPseudoHeaderAddress(oldAddr, bindAddr, true) - } -} diff --git a/route_non_gvisor.go b/route_non_gvisor.go deleted file mode 100644 index d77d975..0000000 --- a/route_non_gvisor.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !with_gvisor - -package tun - -import "github.com/sagernet/sing/common/buf" - -type DirectDestination interface { - WritePacket(buffer *buf.Buffer) error - Close() error - Timeout() bool -} diff --git a/stack.go b/stack.go index 71a183d..2191187 100644 --- a/stack.go +++ b/stack.go @@ -23,7 +23,6 @@ type StackOptions struct { Inet6Address []netip.Prefix EndpointIndependentNat bool UDPTimeout int64 - Router Router Handler Handler Logger logger.Logger ForwarderBindInterface bool diff --git a/system.go b/system.go index 8ab05f9..5cf2dc5 100644 --- a/system.go +++ b/system.go @@ -23,7 +23,6 @@ type System struct { tun Tun tunName string mtu uint32 - router Router handler Handler logger logger.Logger inet4Prefixes []netip.Prefix @@ -39,7 +38,6 @@ type System struct { tcpPort6 uint16 tcpNat *TCPNat udpNat *udpnat.Service[netip.AddrPort] - routeMapping *RouteMapping bindInterface bool interfaceFinder control.InterfaceFinder } @@ -58,7 +56,6 @@ func NewSystem(options StackOptions) (Stack, error) { tunName: options.Name, mtu: options.MTU, udpTimeout: options.UDPTimeout, - router: options.Router, handler: options.Handler, logger: options.Logger, inet4Prefixes: options.Inet4Address, @@ -66,9 +63,6 @@ func NewSystem(options StackOptions) (Stack, error) { bindInterface: options.ForwarderBindInterface, interfaceFinder: options.InterfaceFinder, } - if stack.router != nil { - stack.routeMapping = NewRouteMapping(options.UDPTimeout) - } if len(options.Inet4Address) > 0 { if options.Inet4Address[0].Bits() == 32 { return nil, E.New("need one more IPv4 address in first prefix for system stack") @@ -275,21 +269,6 @@ func (s *System) processIPv4TCP(packet clashtcpip.IPv4Packet, header clashtcpip. packet.SetDestinationIP(session.Source.Addr()) header.SetDestinationPort(session.Source.Port()) } else { - if s.router != nil { - session := RouteSession{4, syscall.IPPROTO_TCP, source, destination} - action := s.routeMapping.Lookup(session, func() RouteAction { - return s.router.RouteConnection(session, &systemTCPDirectPacketWriter4{s.tun, source}) - }) - switch actionType := action.(type) { - case *ActionBlock: - // TODO: send ICMP unreachable - return nil - case *ActionDirect: - return E.Append(nil, actionType.WritePacket(buf.As(packet).ToOwned()), func(err error) error { - return E.Cause(err, "route ipv4 tcp packet") - }) - } - } natPort := s.tcpNat.Lookup(source, destination) packet.SetSourceIP(s.inet4Address) header.SetSourcePort(natPort) @@ -316,21 +295,6 @@ func (s *System) processIPv6TCP(packet clashtcpip.IPv6Packet, header clashtcpip. packet.SetDestinationIP(session.Source.Addr()) header.SetDestinationPort(session.Source.Port()) } else { - if s.router != nil { - session := RouteSession{6, syscall.IPPROTO_TCP, source, destination} - action := s.routeMapping.Lookup(session, func() RouteAction { - return s.router.RouteConnection(session, &systemTCPDirectPacketWriter6{s.tun, source}) - }) - switch actionType := action.(type) { - case *ActionBlock: - // TODO: send RST - return nil - case *ActionDirect: - return E.Append(nil, actionType.WritePacket(buf.As(packet).ToOwned()), func(err error) error { - return E.Cause(err, "route ipv6 tcp packet") - }) - } - } natPort := s.tcpNat.Lookup(source, destination) packet.SetSourceIP(s.inet6Address) header.SetSourcePort(natPort) @@ -354,21 +318,6 @@ func (s *System) processIPv4UDP(packet clashtcpip.IPv4Packet, header clashtcpip. if !destination.Addr().IsGlobalUnicast() { return common.Error(s.tun.Write(packet)) } - if s.router != nil { - routeSession := RouteSession{4, syscall.IPPROTO_UDP, source, destination} - action := s.routeMapping.Lookup(routeSession, func() RouteAction { - return s.router.RouteConnection(routeSession, &systemUDPDirectPacketWriter4{s.tun, source}) - }) - switch actionType := action.(type) { - case *ActionBlock: - // TODO: send icmp unreachable - return nil - case *ActionDirect: - return E.Append(nil, actionType.WritePacket(buf.As(packet).ToOwned()), func(err error) error { - return E.Cause(err, "route ipv4 udp packet") - }) - } - } data := buf.As(header.Payload()) if data.Len() == 0 { return nil @@ -392,21 +341,6 @@ func (s *System) processIPv6UDP(packet clashtcpip.IPv6Packet, header clashtcpip. if !destination.Addr().IsGlobalUnicast() { return common.Error(s.tun.Write(packet)) } - if s.router != nil { - routeSession := RouteSession{6, syscall.IPPROTO_UDP, source, destination} - action := s.routeMapping.Lookup(routeSession, func() RouteAction { - return s.router.RouteConnection(routeSession, &systemUDPDirectPacketWriter6{s.tun, source}) - }) - switch actionType := action.(type) { - case *ActionBlock: - // TODO: send icmp unreachable - return nil - case *ActionDirect: - return E.Append(nil, actionType.WritePacket(buf.As(packet).ToOwned()), func(err error) error { - return E.Cause(err, "route ipv6 udp packet") - }) - } - } data := buf.As(header.Payload()) if data.Len() == 0 { return nil @@ -425,21 +359,6 @@ func (s *System) processIPv6UDP(packet clashtcpip.IPv6Packet, header clashtcpip. } func (s *System) processIPv4ICMP(packet clashtcpip.IPv4Packet, header clashtcpip.ICMPPacket) error { - if s.router != nil { - routeSession := RouteSession{4, clashtcpip.ICMP, netip.AddrPortFrom(packet.SourceIP(), 0), netip.AddrPortFrom(packet.DestinationIP(), 0)} - action := s.routeMapping.Lookup(routeSession, func() RouteAction { - return s.router.RouteConnection(routeSession, &systemICMPDirectPacketWriter4{s.tun, packet.SourceIP()}) - }) - switch actionType := action.(type) { - case *ActionBlock: - // TODO: send icmp unreachable - return nil - case *ActionDirect: - return E.Append(nil, actionType.WritePacket(buf.As(packet).ToOwned()), func(err error) error { - return E.Cause(err, "route ipv4 icmp packet") - }) - } - } if header.Type() != clashtcpip.ICMPTypePingRequest || header.Code() != 0 { return nil } @@ -453,21 +372,6 @@ func (s *System) processIPv4ICMP(packet clashtcpip.IPv4Packet, header clashtcpip } func (s *System) processIPv6ICMP(packet clashtcpip.IPv6Packet, header clashtcpip.ICMPv6Packet) error { - if s.router != nil { - routeSession := RouteSession{6, clashtcpip.ICMPv6, netip.AddrPortFrom(packet.SourceIP(), 0), netip.AddrPortFrom(packet.DestinationIP(), 0)} - action := s.routeMapping.Lookup(routeSession, func() RouteAction { - return s.router.RouteConnection(routeSession, &systemICMPDirectPacketWriter6{s.tun, packet.SourceIP()}) - }) - switch actionType := action.(type) { - case *ActionBlock: - // TODO: send icmp unreachable - return nil - case *ActionDirect: - return E.Append(nil, actionType.WritePacket(buf.As(packet).ToOwned()), func(err error) error { - return E.Cause(err, "route ipv6 icmp packet") - }) - } - } if header.Type() != clashtcpip.ICMPv6EchoRequest || header.Code() != 0 { return nil } diff --git a/tun_darwin.go b/tun_darwin.go index 8dc8b17..2013e21 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -25,8 +25,8 @@ type NativeTun struct { tunFile *os.File tunWriter N.VectorisedWriter mtu uint32 - inet4Address string - inet6Address string + inet4Address [4]byte + inet6Address [16]byte } func New(options Options) (Tun, error) { @@ -57,10 +57,10 @@ func New(options Options) (Tun, error) { mtu: options.MTU, } if len(options.Inet4Address) > 0 { - nativeTun.inet4Address = string(options.Inet4Address[0].Addr().AsSlice()) + nativeTun.inet4Address = options.Inet4Address[0].Addr().As4() } if len(options.Inet6Address) > 0 { - nativeTun.inet6Address = string(options.Inet6Address[0].Addr().AsSlice()) + nativeTun.inet6Address = options.Inet6Address[0].Addr().As16() } var ok bool nativeTun.tunWriter, ok = bufio.CreateVectorisedWriter(nativeTun.tunFile) diff --git a/tun_darwin_gvisor.go b/tun_darwin_gvisor.go index f0d66bb..19ad033 100644 --- a/tun_darwin_gvisor.go +++ b/tun_darwin_gvisor.go @@ -7,7 +7,7 @@ import ( "github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/bufio" - "gvisor.dev/gvisor/pkg/bufferv2" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/stack" @@ -56,9 +56,9 @@ func (e *DarwinEndpoint) Attach(dispatcher stack.NetworkDispatcher) { func (e *DarwinEndpoint) dispatchLoop() { _buffer := buf.StackNewSize(int(e.tun.mtu) + 4) defer common.KeepAlive(_buffer) - buffer := common.Dup(_buffer) - defer buffer.Release() - data := buffer.FreeBytes() + packetBuffer := common.Dup(_buffer) + defer packetBuffer.Release() + data := packetBuffer.FreeBytes() for { n, err := e.tun.tunFile.Read(data) if err != nil { @@ -69,13 +69,13 @@ func (e *DarwinEndpoint) dispatchLoop() { switch header.IPVersion(packet) { case header.IPv4Version: networkProtocol = header.IPv4ProtocolNumber - if header.IPv4(packet).DestinationAddress() == tcpip.Address(e.tun.inet4Address) { + if header.IPv4(packet).DestinationAddress().As4() == e.tun.inet4Address { e.tun.tunFile.Write(data[:n]) continue } case header.IPv6Version: networkProtocol = header.IPv6ProtocolNumber - if header.IPv6(packet).DestinationAddress() == tcpip.Address(e.tun.inet6Address) { + if header.IPv6(packet).DestinationAddress().As16() == e.tun.inet6Address { e.tun.tunFile.Write(data[:n]) continue } @@ -84,7 +84,7 @@ func (e *DarwinEndpoint) dispatchLoop() { continue } pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Payload: bufferv2.MakeWithData(data[4:n]), + Payload: buffer.MakeWithData(data[4:n]), IsForwardedPacket: true, }) pkt.NetworkProtocolNumber = networkProtocol diff --git a/tun_windows_gvisor.go b/tun_windows_gvisor.go index c8f7aad..0db33fb 100644 --- a/tun_windows_gvisor.go +++ b/tun_windows_gvisor.go @@ -3,7 +3,7 @@ package tun import ( - "gvisor.dev/gvisor/pkg/bufferv2" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/stack" @@ -51,16 +51,16 @@ func (e *WintunEndpoint) Attach(dispatcher stack.NetworkDispatcher) { func (e *WintunEndpoint) dispatchLoop() { for { - var buffer bufferv2.Buffer + var packetBuffer buffer.Buffer err := e.tun.ReadFunc(func(b []byte) { - buffer = bufferv2.MakeWithData(b) + packetBuffer = buffer.MakeWithData(b) }) if err != nil { break } - ihl, ok := buffer.PullUp(0, 1) + ihl, ok := packetBuffer.PullUp(0, 1) if !ok { - buffer.Release() + packetBuffer.Release() continue } var networkProtocol tcpip.NetworkProtocolNumber @@ -70,12 +70,12 @@ func (e *WintunEndpoint) dispatchLoop() { case header.IPv6Version: networkProtocol = header.IPv6ProtocolNumber default: - e.tun.Write(buffer.Flatten()) - buffer.Release() + e.tun.Write(packetBuffer.Flatten()) + packetBuffer.Release() continue } pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Payload: buffer, + Payload: packetBuffer, IsForwardedPacket: true, }) dispatcher := e.dispatcher