diff --git a/config/cfg.go b/config/cfg.go index c62f61c..c48fac0 100644 --- a/config/cfg.go +++ b/config/cfg.go @@ -8,6 +8,16 @@ import ( "gopkg.in/yaml.v3" ) +// EndPoint 一个终结点的信息 +type EndPoint struct { + Host string `yaml:"Host"` + Port int64 `yaml:"Port"` + Poly uint64 `yaml:"Poly"` // Poly 是 port 随机切换算法的生成多项式, 0 为禁用 + Protocol string `yaml:"Protocol"` // Protocol is udp/tcp + ReconnectSeconds int64 `yaml:"ReconnectSeconds"` // ReconnectSeconds 断开重连间隔, 每次到时即向对端通报并切换到新的端口, 0 为禁用 + FECMethod string `yaml:"FECMethod"` // FECMethod 可选 1/2 2/3 +} + // Config WireGold 配置文件 type Config struct { IP string `yaml:"IP"` @@ -15,6 +25,7 @@ type Config struct { PrivateKey string `yaml:"PrivateKey"` EndPoint string `yaml:"EndPoint"` MTU int64 `yaml:"MTU"` + Mask uint64 `yaml:"Mask"` // Mask 是异或报文所用掩码, 必须保证各端统一 Peers []Peer `yaml:"Peers"` } diff --git a/gold/link/crypto.go b/gold/link/crypto.go index 57aa8fe..d31005d 100644 --- a/gold/link/crypto.go +++ b/gold/link/crypto.go @@ -65,3 +65,24 @@ func (l *Link) DecodePreshared(additional uint16, b []byte) (db []byte) { db, _ = l.aead.Open(nil, nonce, ciphertext, buf[:]) return } + +// xor 按 8 字节, 以初始 m.mask 循环异或 data +func (m *Me) xor(data []byte) []byte { + batchsz := len(data) / 8 + remain := len(data) % 8 + sum := m.mask + for i := 0; i < batchsz; i++ { + a := i * 8 + b := (i + 1) * 8 + sum ^= binary.LittleEndian.Uint64(data[a:b]) + binary.LittleEndian.PutUint64(data[a:b], sum) + } + if remain > 0 { + var buf [8]byte + copy(buf[:], data[remain:]) + sum ^= binary.LittleEndian.Uint64(buf[:]) + binary.LittleEndian.PutUint64(buf[:], sum) + copy(data[remain:], buf[:]) + } + return data +} diff --git a/gold/link/me.go b/gold/link/me.go index ba48a40..5fe9d09 100644 --- a/gold/link/me.go +++ b/gold/link/me.go @@ -49,6 +49,8 @@ type Me struct { recved *ttl.Cache[uint64, uint8] // 本机上层配置 srcport, dstport, mtu uint16 + // 报头掩码 + mask uint64 } type MyConfig struct { @@ -57,6 +59,7 @@ type MyConfig struct { PrivateKey *[32]byte NIC lower.NICIO SrcPort, DstPort, MTU uint16 + Mask uint64 } // NewMe 设置本机参数 @@ -95,6 +98,7 @@ func NewMe(cfg *MyConfig) (m Me) { m.srcport = cfg.SrcPort m.dstport = cfg.DstPort m.mtu = cfg.MTU & 0xfff8 + m.mask = cfg.Mask if m.writer == nil { m.writer = helper.SelectWriter() } diff --git a/gold/link/recv.go b/gold/link/recv.go index 2444f3e..c459b8c 100644 --- a/gold/link/recv.go +++ b/gold/link/recv.go @@ -18,6 +18,7 @@ func (m *Me) wait(data []byte) *head.Packet { if len(data) < 60 { // not a valid packet return nil } + data = m.xor(data) flags := binary.LittleEndian.Uint16(data[10:12]) if flags&0x8000 == 0x8000 { // not a valid packet return nil diff --git a/gold/link/send.go b/gold/link/send.go index a407358..5bfd922 100644 --- a/gold/link/send.go +++ b/gold/link/send.go @@ -99,7 +99,7 @@ func (l *Link) write(p *head.Packet, teatype uint8, additional, mtu uint16, data return 0, errors.New("[send] nil endpoint of " + p.Dst.String()) } logrus.Debugln("[send] write", len(d), "bytes data from ep", l.me.myep.LocalAddr(), "to", peerep, "offset:", fmt.Sprintf("%04x", offset)) - n, err = l.me.myep.WriteToUDP(d, peerep) + n, err = l.me.myep.WriteToUDP(l.me.xor(d), peerep) cl() } return diff --git a/upper/services/wg/wg.go b/upper/services/wg/wg.go index b81ae3b..f873610 100644 --- a/upper/services/wg/wg.go +++ b/upper/services/wg/wg.go @@ -97,6 +97,7 @@ func (wg *WG) init(srcport, dstport uint16) { SrcPort: srcport, DstPort: dstport, MTU: uint16(wg.c.MTU), + Mask: wg.c.Mask, }) for _, peer := range wg.c.Peers {