WireGuard: Implement UDP FullCone NAT (#5833)

Fixes https://github.com/XTLS/Xray-core/issues/5601

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
LjhAUMEM
2026-03-23 01:42:40 +08:00
committed by GitHub
parent ce66db7032
commit 67a71adad1
9 changed files with 317 additions and 119 deletions
+18 -21
View File
@@ -31,6 +31,7 @@ type netTun struct {
ep *channel.Endpoint
stack *stack.Stack
events chan tun.Event
notifyHandle *channel.NotificationHandle
incomingPacket chan *buffer.View
mtu int
hasV4, hasV6 bool
@@ -48,12 +49,17 @@ func CreateNetTUN(localAddresses []netip.Addr, mtu int, promiscuousMode bool) (t
dev := &netTun{
ep: channel.New(1024, uint32(mtu), ""),
stack: stack.New(opts),
events: make(chan tun.Event, 1),
events: make(chan tun.Event, 10),
incomingPacket: make(chan *buffer.View),
mtu: mtu,
}
dev.ep.AddNotify(dev)
tcpipErr := dev.stack.CreateNIC(1, dev.ep)
sackEnabledOpt := tcpip.TCPSACKEnabled(true) // TCP SACK is disabled by default
tcpipErr := dev.stack.SetTransportProtocolOption(tcp.ProtocolNumber, &sackEnabledOpt)
if tcpipErr != nil {
return nil, nil, dev.stack, fmt.Errorf("could not enable TCP SACK: %v", tcpipErr)
}
dev.notifyHandle = dev.ep.AddNotify(dev)
tcpipErr = dev.stack.CreateNIC(1, dev.ep)
if tcpipErr != nil {
return nil, nil, dev.stack, fmt.Errorf("CreateNIC: %v", tcpipErr)
}
@@ -90,20 +96,10 @@ func CreateNetTUN(localAddresses []netip.Addr, mtu int, promiscuousMode bool) (t
dev.stack.SetSpoofing(1, true)
}
opt := tcpip.CongestionControlOption("cubic")
if err := dev.stack.SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil {
return nil, nil, dev.stack, fmt.Errorf("SetTransportProtocolOption(%d, &%T(%s)): %s", tcp.ProtocolNumber, opt, opt, err)
}
dev.events <- tun.EventUp
return dev, (*Net)(dev), dev.stack, nil
}
// BatchSize implements tun.Device
func (tun *netTun) BatchSize() int {
return 1
}
// Name implements tun.Device
func (tun *netTun) Name() (string, error) {
return "go", nil
@@ -120,7 +116,6 @@ func (tun *netTun) Events() <-chan tun.Event {
}
// Read implements tun.Device
func (tun *netTun) Read(buf [][]byte, sizes []int, offset int) (int, error) {
view, ok := <-tun.incomingPacket
if !ok {
@@ -169,20 +164,16 @@ func (tun *netTun) WriteNotify() {
tun.incomingPacket <- view
}
// Flush implements tun.Device
func (tun *netTun) Flush() error {
return nil
}
// Close implements tun.Device
func (tun *netTun) Close() error {
tun.closeOnce.Do(func() {
tun.stack.RemoveNIC(1)
tun.stack.Close()
tun.ep.RemoveNotify(tun.notifyHandle)
tun.ep.Close()
close(tun.events)
tun.ep.Close()
close(tun.incomingPacket)
})
return nil
@@ -193,6 +184,11 @@ func (tun *netTun) MTU() (int, error) {
return tun.mtu, nil
}
// BatchSize implements tun.Device
func (tun *netTun) BatchSize() int {
return 1
}
func convertToFullAddr(endpoint netip.AddrPort) (tcpip.FullAddress, tcpip.NetworkProtocolNumber) {
var protoNumber tcpip.NetworkProtocolNumber
if endpoint.Addr().Is4() {
@@ -224,6 +220,7 @@ func (net *Net) DialUDPAddrPort(laddr, raddr netip.AddrPort) (*gonet.UDPConn, er
var addr tcpip.FullAddress
addr, pn = convertToFullAddr(raddr)
rfa = &addr
rfa = nil // do not ep connect
}
return gonet.DialUDP(net.stack, lfa, rfa, pn)
}