1
0
mirror of https://github.com/fumiama/WireGold.git synced 2026-06-21 19:13:20 +08:00

feat: add param DoublePacket

This commit is contained in:
源文雨
2024-07-31 15:21:02 +08:00
parent 574d1ccfc4
commit dd51f9f26f
9 changed files with 43 additions and 15 deletions

View File

@@ -33,6 +33,7 @@ type Peer struct {
QuerySeconds int64 `yaml:"QuerySeconds"` QuerySeconds int64 `yaml:"QuerySeconds"`
AllowTrans bool `yaml:"AllowTrans"` AllowTrans bool `yaml:"AllowTrans"`
UseZstd bool `yaml:"UseZstd"` UseZstd bool `yaml:"UseZstd"`
DoublePacket bool `yaml:"DoublePacket"`
MTU int64 `yaml:"MTU"` MTU int64 `yaml:"MTU"`
MTURandomRange int64 `yaml:"MTURandomRange"` MTURandomRange int64 `yaml:"MTURandomRange"`
} }

View File

@@ -155,14 +155,15 @@ func (p *Packet) Unmarshal(data []byte) (complete bool, err error) {
return return
} }
// DecreaseAndGetTTL TTL 自减后返回
func (p *Packet) DecreaseAndGetTTL() uint8 {
p.TTL--
return p.TTL
}
// Marshal 将自身数据编码为 []byte // Marshal 将自身数据编码为 []byte
// offset 必须为 8 的倍数,表示偏移的 8 位 // offset 必须为 8 的倍数,表示偏移的 8 位
func (p *Packet) Marshal(src net.IP, teatype uint8, additional uint16, datasz uint32, offset uint16, dontfrag, hasmore bool) ([]byte, func()) { func (p *Packet) Marshal(src net.IP, teatype uint8, additional uint16, datasz uint32, offset uint16, dontfrag, hasmore bool) ([]byte, func()) {
p.TTL--
if p.TTL == 0 {
return nil, nil
}
if src != nil { if src != nil {
p.Src = src p.Src = src
p.idxdatsz = (uint32(teatype) << 27) | (uint32(additional&0x07ff) << 16) | datasz&0xffff p.idxdatsz = (uint32(teatype) << 27) | (uint32(additional&0x07ff) << 16) | datasz&0xffff
@@ -175,14 +176,13 @@ func (p *Packet) Marshal(src net.IP, teatype uint8, additional uint16, datasz ui
if hasmore { if hasmore {
offset |= 0x2000 offset |= 0x2000
} }
p.Flags = PacketFlags(offset)
return helper.OpenWriterF(func(w *helper.Writer) { return helper.OpenWriterF(func(w *helper.Writer) {
w.WriteUInt32(p.idxdatsz) w.WriteUInt32(p.idxdatsz)
w.WriteUInt16((uint16(p.TTL) << 8) | uint16(p.Proto)) w.WriteUInt16((uint16(p.TTL) << 8) | uint16(p.Proto))
w.WriteUInt16(p.SrcPort) w.WriteUInt16(p.SrcPort)
w.WriteUInt16(p.DstPort) w.WriteUInt16(p.DstPort)
w.WriteUInt16(uint16(p.Flags)) w.WriteUInt16(uint16(PacketFlags(offset)))
w.Write(p.Src.To4()) w.Write(p.Src.To4())
w.Write(p.Dst.To4()) w.Write(p.Dst.To4())
w.Write(p.Hash[:]) w.Write(p.Hash[:])

View File

@@ -125,25 +125,30 @@ func (m *Me) xorenc(data []byte) []byte {
batchsz := len(data) / 8 batchsz := len(data) / 8
remain := len(data) % 8 remain := len(data) % 8
sum := m.mask sum := m.mask
newdat := helper.MakeBytes(len(data) + 8)
_, _ = rand.Read(newdat[:8])
if remain > 0 { if remain > 0 {
var buf [8]byte var buf [8]byte
p := batchsz * 8 p := batchsz * 8
copy(buf[:], data[p:]) copy(buf[:], data[p:])
sum ^= binary.LittleEndian.Uint64(buf[:]) sum ^= binary.LittleEndian.Uint64(buf[:])
binary.LittleEndian.PutUint64(buf[:], sum) binary.LittleEndian.PutUint64(buf[:], sum)
copy(data[p:], buf[:]) copy(newdat[8+p:], buf[:])
} }
for i := batchsz - 1; i >= 0; i-- { for i := batchsz - 1; i >= 0; i-- {
a := i * 8 a := i * 8
b := (i + 1) * 8 b := (i + 1) * 8
sum ^= binary.LittleEndian.Uint64(data[a:b]) sum ^= binary.LittleEndian.Uint64(data[a:b])
binary.LittleEndian.PutUint64(data[a:b], sum) binary.LittleEndian.PutUint64(newdat[a+8:b+8], sum)
} }
return data return newdat
} }
// xordec 按 8 字节, 以初始 m.mask 循环异或解码 data // xordec 按 8 字节, 以初始 m.mask 循环异或解码 data
func (m *Me) xordec(data []byte) []byte { func (m *Me) xordec(data []byte) []byte {
if len(data) <= 8 {
return nil
}
batchsz := len(data) / 8 batchsz := len(data) / 8
remain := len(data) % 8 remain := len(data) % 8
this := uint64(0) this := uint64(0)
@@ -173,5 +178,5 @@ func (m *Me) xordec(data []byte) []byte {
} else { } else {
binary.LittleEndian.PutUint64(data[len(data)-8:], next^m.mask) binary.LittleEndian.PutUint64(data[len(data)-8:], next^m.mask)
} }
return data return data[8:]
} }

View File

@@ -44,6 +44,8 @@ type Link struct {
allowtrans bool allowtrans bool
// 是否对数据进行 zstd 压缩 // 是否对数据进行 zstd 压缩
usezstd bool usezstd bool
// 是否采用双倍发包对抗强丢包
doublepacket bool
// udp 数据包的最大大小 // udp 数据包的最大大小
mtu uint16 mtu uint16
// 随机放缩 mtu 范围 (只减不增) // 随机放缩 mtu 范围 (只减不增)

View File

@@ -22,6 +22,7 @@ type PeerConfig struct {
MTURandomRange uint16 MTURandomRange uint16
AllowTrans, NoPipe bool AllowTrans, NoPipe bool
UseZstd bool UseZstd bool
DoublePacket bool
} }
// AddPeer 添加一个 peer // AddPeer 添加一个 peer
@@ -41,6 +42,7 @@ func (m *Me) AddPeer(cfg *PeerConfig) (l *Link) {
rawep: cfg.EndPoint, rawep: cfg.EndPoint,
allowtrans: cfg.AllowTrans, allowtrans: cfg.AllowTrans,
usezstd: cfg.UseZstd, usezstd: cfg.UseZstd,
doublepacket: cfg.DoublePacket,
me: m, me: m,
mtu: cfg.MTU, mtu: cfg.MTU,
mturandomrange: cfg.MTURandomRange, mturandomrange: cfg.MTURandomRange,

View File

@@ -34,6 +34,7 @@ func (m *Me) wait(data []byte) *head.Packet {
return nil return nil
} }
crc := binary.LittleEndian.Uint64(data[52:head.PacketHeadLen]) crc := binary.LittleEndian.Uint64(data[52:head.PacketHeadLen])
logrus.Debugf("[recv] packet crc %016x", crc)
if m.recved.Get(crc) { // 是重放攻击 if m.recved.Get(crc) { // 是重放攻击
logrus.Warnln("[recv] ignore duplicated crc packet", strconv.FormatUint(crc, 16)) logrus.Warnln("[recv] ignore duplicated crc packet", strconv.FormatUint(crc, 16))
return nil return nil
@@ -78,5 +79,6 @@ func (m *Me) wait(data []byte) *head.Packet {
return nil return nil
} }
m.recving.Set(hsh, h) m.recving.Set(hsh, h)
m.recved.Set(crc, true)
return nil return nil
} }

View File

@@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"io" "io"
"math/rand" "math/rand"
"time"
"github.com/fumiama/WireGold/gold/head" "github.com/fumiama/WireGold/gold/head"
"github.com/fumiama/WireGold/helper" "github.com/fumiama/WireGold/helper"
@@ -88,8 +89,23 @@ func (l *Link) encrypt(p *head.Packet, sndcnt uint16, teatype uint8) {
logrus.Debugln("[send] data len after xchacha20:", p.BodyLen(), "addt:", sndcnt) logrus.Debugln("[send] data len after xchacha20:", p.BodyLen(), "addt:", sndcnt)
} }
// write 向 peer 发一个 // write 向 peer 发包
func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz uint32, offset uint16, istransfer, hasmore bool) (int, error) { func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz uint32, offset uint16, istransfer, hasmore bool) (int, error) {
if p.DecreaseAndGetTTL() <= 0 {
return 0, ErrTTL
}
if l.doublepacket {
cpp := p.Copy()
time.AfterFunc(time.Millisecond*(10+time.Duration(rand.Intn(10))), func() {
defer cpp.Put()
_, _ = l.writeonce(cpp, teatype, additional, datasz, offset, istransfer, hasmore)
})
}
return l.writeonce(p, teatype, additional, datasz, offset, istransfer, hasmore)
}
// write 向 peer 发一个包
func (l *Link) writeonce(p *head.Packet, teatype uint8, additional uint16, datasz uint32, offset uint16, istransfer, hasmore bool) (int, error) {
peerep := l.endpoint peerep := l.endpoint
if peerep == nil { if peerep == nil {
return 0, errors.New("nil endpoint of " + p.Dst.String()) return 0, errors.New("nil endpoint of " + p.Dst.String())
@@ -103,9 +119,6 @@ func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz ui
} else { } else {
d, cl = p.Marshal(l.me.me, teatype, additional, datasz, offset, false, hasmore) d, cl = p.Marshal(l.me.me, teatype, additional, datasz, offset, false, hasmore)
} }
if d == nil {
return 0, ErrTTL
}
defer cl() defer cl()
bound := 64 bound := 64
@@ -118,5 +131,6 @@ func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz ui
logrus.Debugln("[send] data bytes", hex.EncodeToString(d[:bound]), endl) logrus.Debugln("[send] data bytes", hex.EncodeToString(d[:bound]), endl)
d = l.me.xorenc(d) d = l.me.xorenc(d)
logrus.Debugln("[send] data xored", hex.EncodeToString(d[:bound]), endl) logrus.Debugln("[send] data xored", hex.EncodeToString(d[:bound]), endl)
defer helper.PutBytes(d)
return l.me.conn.WriteToPeer(d, peerep) return l.me.conn.WriteToPeer(d, peerep)
} }

View File

@@ -81,6 +81,7 @@ func testTunnel(t *testing.T, nw string, isplain bool, pshk *[32]byte, mtu uint1
MTU: mtu, MTU: mtu,
MTURandomRange: mtu / 2, MTURandomRange: mtu / 2,
UseZstd: true, UseZstd: true,
DoublePacket: true,
}) })
p.AddPeer(&link.PeerConfig{ p.AddPeer(&link.PeerConfig{
PeerIP: "192.168.1.2", PeerIP: "192.168.1.2",

View File

@@ -154,6 +154,7 @@ func (wg *WG) init(srcport, dstport uint16) {
AllowTrans: peer.AllowTrans, AllowTrans: peer.AllowTrans,
NoPipe: true, NoPipe: true,
UseZstd: peer.UseZstd, UseZstd: peer.UseZstd,
DoublePacket: peer.DoublePacket,
}) })
} }
} }