From 3839182c85d2dd31b42cf84a34115f965e42b8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 4 Aug 2023 09:12:22 +0800 Subject: [PATCH] feat: add MTU random range --- config/cfg.go | 2 ++ gold/link/link.go | 4 +++- gold/link/peer.go | 12 +++++++----- gold/link/send.go | 24 ++++++++++++++---------- upper/services/wg/wg.go | 33 ++++++++++++++++++++------------- 5 files changed, 46 insertions(+), 29 deletions(-) diff --git a/config/cfg.go b/config/cfg.go index 9c11d8e..ceec970 100644 --- a/config/cfg.go +++ b/config/cfg.go @@ -31,8 +31,10 @@ type Peer struct { QuerySeconds int64 `yaml:"QuerySeconds"` AllowTrans bool `yaml:"AllowTrans"` MTU int64 `yaml:"MTU"` + MTURandomRange int64 `yaml:"MTURandomRange"` } +// Parse 解析配置文件 func Parse(path string) (c Config) { file, err := os.ReadFile(path) if err != nil { diff --git a/gold/link/link.go b/gold/link/link.go index 0a93e62..51a06c3 100644 --- a/gold/link/link.go +++ b/gold/link/link.go @@ -34,11 +34,13 @@ type Link struct { // 本机信息 me *Me // 连接的状态,详见下方 const - status int + status int8 // 是否允许转发 allowtrans bool // udp 数据包的最大大小 mtu uint16 + // 随机放缩 mtu 范围 (只减不增) + mturandomrange uint16 } const ( diff --git a/gold/link/peer.go b/gold/link/peer.go index 9c1fbf3..326a079 100644 --- a/gold/link/peer.go +++ b/gold/link/peer.go @@ -19,6 +19,7 @@ type PeerConfig struct { PresharedKey *[32]byte KeepAliveDur, QueryTick int64 MTU uint16 + MTURandomRange uint16 AllowTrans, NoPipe bool } @@ -34,11 +35,12 @@ func (m *Me) AddPeer(cfg *PeerConfig) (l *Link) { panic("invalid mtu for peer " + cfg.PeerIP) } l = &Link{ - pubk: cfg.PubicKey, - peerip: net.ParseIP(cfg.PeerIP), - allowtrans: cfg.AllowTrans, - me: m, - mtu: uint16(cfg.MTU), + pubk: cfg.PubicKey, + peerip: net.ParseIP(cfg.PeerIP), + allowtrans: cfg.AllowTrans, + me: m, + mtu: uint16(cfg.MTU), + mturandomrange: uint16(cfg.MTURandomRange), } if !cfg.NoPipe { diff --git a/gold/link/send.go b/gold/link/send.go index 397f391..ae256fe 100644 --- a/gold/link/send.go +++ b/gold/link/send.go @@ -15,7 +15,11 @@ func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) { teatype := uint8(rand.Intn(16)) sndcnt := atomic.AddUintptr(&l.sendcount, 1) logrus.Debugln("[send] count:", sndcnt, ", additional data:", uint16(sndcnt)) - if len(p.Data) <= int(l.mtu) { + mtu := l.mtu + if l.mturandomrange > 0 { + mtu -= uint16(rand.Intn(int(l.mturandomrange))) + } + if len(p.Data) <= int(mtu) { if !istransfer { p.FillHash() if l.aead != nil { @@ -24,7 +28,7 @@ func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) { p.Data = l.Encode(teatype, p.Data) } defer p.Put() - return l.write(p, teatype, uint16(sndcnt), uint32(len(p.Data)), 0, istransfer, false) + return l.write(p, teatype, uint16(sndcnt), mtu, uint32(len(p.Data)), 0, istransfer, false) } if !istransfer { p.FillHash() @@ -39,31 +43,31 @@ func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) { i := 0 packet := head.SelectPacket() *packet = *p - for ; int(totl)-i > int(l.mtu); i += int(l.mtu) { - logrus.Debugln("[send] split frag", i, ":", i+int(l.mtu), ", remain:", int(totl)-i-int(l.mtu)) - packet.Data = data[:int(l.mtu)] - cnt, err := l.write(packet, teatype, uint16(sndcnt), totl, uint16(i>>3), istransfer, true) + for ; int(totl)-i > int(mtu); i += int(mtu) { + logrus.Debugln("[send] split frag", i, ":", i+int(mtu), ", remain:", int(totl)-i-int(mtu)) + packet.Data = data[:int(mtu)] + cnt, err := l.write(packet, teatype, uint16(sndcnt), mtu, totl, uint16(i>>3), istransfer, true) n += cnt if err != nil { return n, err } - data = data[int(l.mtu):] + data = data[int(mtu):] packet.TTL = ttl } packet.Put() p.Data = data - cnt, err := l.write(p, teatype, uint16(sndcnt), totl, uint16(i>>3), istransfer, false) + cnt, err := l.write(p, teatype, uint16(sndcnt), mtu, totl, uint16(i>>3), istransfer, false) p.Put() n += cnt return n, err } // write 向 peer 发一个包 -func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz uint32, offset uint16, istransfer, hasmore bool) (n int, err error) { +func (l *Link) write(p *head.Packet, teatype uint8, additional, mtu uint16, datasz uint32, offset uint16, istransfer, hasmore bool) (n int, err error) { var d []byte var cl func() if istransfer { - if p.Flags&0x4000 == 0x4000 && len(p.Data) > int(l.mtu) { + if p.Flags&0x4000 == 0x4000 && len(p.Data) > int(mtu) { return len(p.Data), errors.New("drop dont fragmnet big trans packet") } d, cl = p.Marshal(nil, teatype, additional, 0, 0, false, false) diff --git a/upper/services/wg/wg.go b/upper/services/wg/wg.go index 0836a6e..c842244 100644 --- a/upper/services/wg/wg.go +++ b/upper/services/wg/wg.go @@ -107,7 +107,7 @@ func (wg *WG) init(srcport, dstport uint16) { } n := copy(peerkey[:], base14.Decode(k)) if n != 32 { - panic("peer public key length < 32") + panic("peer " + peer.IP + ": public key length < 32") } var pshk *[32]byte if peer.PresharedKey != "" { @@ -118,21 +118,28 @@ func (wg *WG) init(srcport, dstport uint16) { pshk = &[32]byte{} n := copy(pshk[:], base14.Decode(k)) if n != 32 { - panic("peer preshared key length < 32") + panic("peer " + peer.IP + ": preshared key length < 32") } } + if peer.MTU >= 65535 { + panic("peer " + peer.IP + ": MTU too large") + } + if peer.MTURandomRange >= peer.MTU/2 { + panic("peer " + peer.IP + ": MTURandomRange too large") + } wg.me.AddPeer(&link.PeerConfig{ - PeerIP: peer.IP, - EndPoint: peer.EndPoint, - AllowedIPs: peer.AllowedIPs, - Querys: peer.QueryList, - PubicKey: &peerkey, - PresharedKey: pshk, - KeepAliveDur: peer.KeepAliveSeconds, - QueryTick: peer.QuerySeconds, - MTU: uint16(peer.MTU), - AllowTrans: peer.AllowTrans, - NoPipe: true, + PeerIP: peer.IP, + EndPoint: peer.EndPoint, + AllowedIPs: peer.AllowedIPs, + Querys: peer.QueryList, + PubicKey: &peerkey, + PresharedKey: pshk, + KeepAliveDur: peer.KeepAliveSeconds, + QueryTick: peer.QuerySeconds, + MTU: uint16(peer.MTU), + MTURandomRange: uint16(peer.MTURandomRange), + AllowTrans: peer.AllowTrans, + NoPipe: true, }) } }