refactor: New tun udpnat

This commit is contained in:
世界
2026-08-30 17:41:43 +08:00
parent a072f21978
commit 1f7d571017
25 changed files with 422 additions and 96 deletions
+17 -11
View File
@@ -6,6 +6,7 @@ import (
"time"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/control"
"github.com/sagernet/sing/common/logger"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/wireguard-go/device"
@@ -22,17 +23,22 @@ type Device interface {
}
type DeviceOptions struct {
Context context.Context
Logger logger.ContextLogger
System bool
Handler tun.Handler
UDPTimeout time.Duration
ICMPTimeout time.Duration
CreateDialer func(interfaceName string) N.Dialer
Name string
MTU uint32
Address []netip.Prefix
AllowedAddress []netip.Prefix
Context context.Context
Logger logger.ContextLogger
System bool
Handler tun.Handler
UDPTimeout time.Duration
ICMPTimeout time.Duration
UDPMapping tun.NATMapping
UDPFiltering tun.NATFiltering
UDPNATMax uint32
NetworkMonitor tun.NetworkUpdateMonitor
InterfaceFinder control.InterfaceFinder
CreateDialer func(interfaceName string) N.Dialer
Name string
MTU uint32
Address []netip.Prefix
AllowedAddress []netip.Prefix
}
func NewDevice(options DeviceOptions) (Device, error) {
+20 -1
View File
@@ -42,6 +42,7 @@ type stackDevice struct {
inet4Address netip.Addr
inet6Address netip.Addr
icmpForwarder *tun.ICMPForwarder
udpForwarder *tun.UDPForwarder
}
func newStackDevice(options DeviceOptions) (*stackDevice, error) {
@@ -79,7 +80,16 @@ func newStackDevice(options DeviceOptions) (*stackDevice, error) {
tunDevice.stack = ipStack
if options.Handler != nil {
ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tun.NewTCPForwarder(options.Context, ipStack, options.Handler).HandlePacket)
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, tun.NewUDPForwarder(options.Context, ipStack, options.Handler, options.UDPTimeout).HandlePacket)
udpForwarder := tun.NewUDPForwarder(options.Context, ipStack, options.Handler, tun.UDPNatOptions{
Timeout: options.UDPTimeout,
Shared: true,
Mapping: options.UDPMapping,
Filtering: options.UDPFiltering,
MaxSize: options.UDPNATMax,
InterfaceFinder: options.InterfaceFinder,
})
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)
tunDevice.udpForwarder = udpForwarder
icmpForwarder := tun.NewICMPForwarder(ipStack, options.Handler, options.Logger)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber4, icmpForwarder.HandlePacket)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber6, icmpForwarder.HandlePacket)
@@ -166,6 +176,12 @@ func (w *stackDevice) SetDevice(device *device.Device) {
}
func (w *stackDevice) Start() error {
if w.udpForwarder != nil {
err := w.udpForwarder.Start()
if err != nil {
return err
}
}
w.events <- wgTun.EventUp
return nil
}
@@ -245,6 +261,9 @@ func (w *stackDevice) Close() error {
if w.icmpForwarder != nil {
w.icmpForwarder.Close()
}
if w.udpForwarder != nil {
_ = w.udpForwarder.Close()
}
w.stack.Close()
for _, endpoint := range w.stack.CleanupEndpoints() {
endpoint.Abort()
+29 -1
View File
@@ -27,6 +27,7 @@ type systemStackDevice struct {
stack *stack.Stack
endpoint *deviceEndpoint
icmpForwarder *tun.ICMPForwarder
udpForwarder *tun.UDPForwarder
writeBufs [][]byte
closeOnce sync.Once
}
@@ -69,7 +70,17 @@ func newSystemStackDevice(options DeviceOptions) (*systemStackDevice, error) {
}
if options.Handler != nil {
ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tun.NewTCPForwarder(options.Context, ipStack, options.Handler).HandlePacket)
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, tun.NewUDPForwarder(options.Context, ipStack, options.Handler, options.UDPTimeout).HandlePacket)
udpForwarder := tun.NewUDPForwarder(options.Context, ipStack, options.Handler, tun.UDPNatOptions{
Timeout: options.UDPTimeout,
Shared: true,
Mapping: options.UDPMapping,
Filtering: options.UDPFiltering,
MaxSize: options.UDPNATMax,
InterfaceFinder: options.InterfaceFinder,
ExcludeInterface: []string{options.Name},
})
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)
stackDevice.udpForwarder = udpForwarder
icmpForwarder := tun.NewICMPForwarder(ipStack, options.Handler, options.Logger)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber4, icmpForwarder.HandlePacket)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber6, icmpForwarder.HandlePacket)
@@ -82,6 +93,20 @@ func (w *systemStackDevice) SetDevice(device *device.Device) {
w.endpoint.device = device
}
func (w *systemStackDevice) Start() error {
if w.udpForwarder != nil {
err := w.udpForwarder.Start()
if err != nil {
return err
}
}
err := w.systemDevice.Start()
if err != nil && w.udpForwarder != nil {
_ = w.udpForwarder.Close()
}
return err
}
func (w *systemStackDevice) Write(bufs [][]byte, offset int) (count int, err error) {
if w.batchDevice != nil {
w.writeBufs = w.writeBufs[:0]
@@ -118,6 +143,9 @@ func (w *systemStackDevice) Close() error {
if w.icmpForwarder != nil {
w.icmpForwarder.Close()
}
if w.udpForwarder != nil {
_ = w.udpForwarder.Close()
}
w.stack.Close()
for _, endpoint := range w.stack.CleanupEndpoints() {
endpoint.Abort()
+17 -12
View File
@@ -101,17 +101,21 @@ func NewEndpoint(options EndpointOptions) (*Endpoint, error) {
options.MTU = 1408
}
deviceOptions := DeviceOptions{
Context: options.Context,
Logger: options.Logger,
System: options.System,
Handler: options.Handler,
UDPTimeout: options.UDPTimeout,
ICMPTimeout: options.ICMPTimeout,
CreateDialer: options.CreateDialer,
Name: options.Name,
MTU: options.MTU,
Address: options.Address,
AllowedAddress: allowedAddresses,
Context: options.Context,
Logger: options.Logger,
System: options.System,
Handler: options.Handler,
UDPTimeout: options.UDPTimeout,
ICMPTimeout: options.ICMPTimeout,
UDPMapping: options.UDPMapping,
UDPFiltering: options.UDPFiltering,
UDPNATMax: options.UDPNATMax,
InterfaceFinder: options.InterfaceFinder,
CreateDialer: options.CreateDialer,
Name: options.Name,
MTU: options.MTU,
Address: options.Address,
AllowedAddress: allowedAddresses,
}
tunDevice, err := NewDevice(deviceOptions)
if err != nil {
@@ -231,8 +235,9 @@ func (e *Endpoint) Close() error {
e.device.Down()
e.device.Close()
e.device = nil
return nil
}
return nil
return e.tunDevice.Close()
}
func (e *Endpoint) Lookup(address netip.Addr) *device.Peer {
+16 -10
View File
@@ -6,6 +6,7 @@ import (
"time"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/control"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
@@ -18,16 +19,21 @@ type EndpointOptions struct {
Handler tun.Handler
UDPTimeout time.Duration
ICMPTimeout time.Duration
Dialer N.Dialer
CreateDialer func(interfaceName string) N.Dialer
Name string
MTU uint32
Address []netip.Prefix
PrivateKey string
ListenPort uint16
ResolvePeer func(domain string) (netip.Addr, error)
Peers []PeerOptions
Workers int
UDPMapping tun.NATMapping
UDPFiltering tun.NATFiltering
UDPNATMax uint32
InterfaceFinder control.InterfaceFinder
Dialer N.Dialer
CreateDialer func(interfaceName string) N.Dialer
Name string
MTU uint32
Address []netip.Prefix
PrivateKey string
ListenPort uint16
ResolvePeer func(domain string) (netip.Addr, error)
Peers []PeerOptions
Workers int
}
type PeerOptions struct {