mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-24 23:05:01 +03:00
f55938ba0a
* fix(amneziawg): respect tunnel MTU when writing UDP replies Send replies through gVisor FindRoute/Route.WritePacket instead of WriteRawPacket so the network endpoints apply the tunnel MTU and fragment oversized IPv4/IPv6 datagrams. Preserve UDP checksums including the zero-complement IPv6 case and validate lengths before narrowing to uint16. Regression tests inspect and reassemble actual channel-backed TUN output at and above the MTU, verify checksums and exercise concurrent sources. * docs(review): put the tally before Design and name who can store a trigger
63 lines
1.6 KiB
Go
63 lines
1.6 KiB
Go
package amneziawgnet
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"net/netip"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
|
)
|
|
|
|
func TestWriteUDPReplyConcurrentSources(t *testing.T) {
|
|
tun, gstack, err := createNetTUNWithStack([]netip.Addr{netip.MustParseAddr("10.77.0.1")}, 1280)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer tun.Close()
|
|
enablePromiscuousRouting(gstack)
|
|
const replies = 32
|
|
to := netip.MustParseAddrPort("10.77.0.2:49152")
|
|
var wg sync.WaitGroup
|
|
errs := make(chan error, replies)
|
|
for i := range replies {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
from := netip.AddrPortFrom(netip.MustParseAddr("203.0.113.9"), uint16(10000+i))
|
|
var payload [2]byte
|
|
binary.BigEndian.PutUint16(payload[:], uint16(i))
|
|
errs <- WriteUDPReply(gstack, from, to, payload[:])
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
close(errs)
|
|
for err := range errs {
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
seen := make(map[uint16]bool)
|
|
for range replies {
|
|
select {
|
|
case v := <-tun.(*stackTun).incomingPacket:
|
|
packet := append([]byte(nil), v.AsSlice()...)
|
|
v.Release()
|
|
if len(packet) > 1280 {
|
|
t.Fatalf("packet length %d", len(packet))
|
|
}
|
|
ip := header.IPv4(packet)
|
|
udp := packet[ip.HeaderLength():]
|
|
port := binary.BigEndian.Uint16(udp[0:2])
|
|
index := binary.BigEndian.Uint16(udp[8:10])
|
|
if index >= replies || port != 10000+index || seen[index] || binary.BigEndian.Uint16(udp[2:4]) != to.Port() {
|
|
t.Fatalf("duplicate/corrupt concurrent reply: port %d index %d", port, index)
|
|
}
|
|
seen[index] = true
|
|
case <-time.After(time.Second):
|
|
t.Fatal("concurrent replies missing")
|
|
}
|
|
}
|
|
}
|