mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-04 12:27:39 +03:00
Update gVisor to release-20230605.0-21-g457c1c36d
This commit is contained in:
parent
b02f252916
commit
e881f21013
20 changed files with 71 additions and 550 deletions
6
go.mod
6
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 (
|
||||
|
|
12
go.sum
12
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=
|
||||
|
|
102
gvisor.go
102
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# fdbased
|
||||
|
||||
Version: release-20230417.0
|
||||
Version: release-20230605.0-21-g457c1c36d
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
// automatically generated by stateify.
|
||||
|
||||
//go:build (linux && amd64) || (linux && arm64)
|
||||
// +build linux,amd64 linux,arm64
|
||||
|
||||
package stopfd
|
92
route.go
92
route.go
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
119
route_nat.go
119
route_nat.go
|
@ -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()
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
1
stack.go
1
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
|
||||
|
|
96
system.go
96
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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue