Skip to content

Commit

Permalink
fix(link): transfer fragmented packet
Browse files Browse the repository at this point in the history
  • Loading branch information
fumiama committed Jul 17, 2024
1 parent 06853c6 commit cb2fe9b
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 40 deletions.
25 changes: 14 additions & 11 deletions gold/head/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/sirupsen/logrus"
)

const PacketHeadLen = 60

var (
ErrBadCRCChecksum = errors.New("bad crc checksum")
ErrDataLenLT60 = errors.New("data len < 60")
Expand Down Expand Up @@ -105,7 +107,7 @@ func (p *Packet) Unmarshal(data []byte) (complete bool, err error) {
err = ErrDataLenLT60
return
}
p.crc64 = binary.LittleEndian.Uint64(data[52:60])
p.crc64 = binary.LittleEndian.Uint64(data[52:PacketHeadLen])
if crc64.Checksum(data[:52], crc64.MakeTable(crc64.ISO)) != p.crc64 {
err = ErrBadCRCChecksum
return
Expand Down Expand Up @@ -144,7 +146,7 @@ func (p *Packet) Unmarshal(data []byte) (complete bool, err error) {
}

if p.rembytes > 0 {
p.rembytes -= copy(p.data[flags.Offset():], data[60:])
p.rembytes -= copy(p.data[flags.Offset():], data[PacketHeadLen:])
logrus.Debugln("[packet] copied frag", hex.EncodeToString(p.Hash[:]), "rembytes:", p.rembytes)
}

Expand All @@ -162,17 +164,18 @@ func (p *Packet) Marshal(src net.IP, teatype uint8, additional uint16, datasz ui
}

if src != nil {
p.idxdatsz = (uint32(teatype) << 27) | (uint32(additional&0x07ff) << 16) | datasz&0xffff
p.Src = src
offset &= 0x1fff
if dontfrag {
offset |= 0x4000
}
if hasmore {
offset |= 0x2000
}
p.Flags = PacketFlags(offset)
p.idxdatsz = (uint32(teatype) << 27) | (uint32(additional&0x07ff) << 16) | datasz&0xffff
}

offset &= 0x1fff
if dontfrag {
offset |= 0x4000
}
if hasmore {
offset |= 0x2000
}
p.Flags = PacketFlags(offset)

return helper.OpenWriterF(func(w *helper.Writer) {
w.WriteUInt32(p.idxdatsz)
Expand Down
2 changes: 1 addition & 1 deletion gold/link/listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (m *Me) dispatch(packet *head.Packet, addr p2p.EndPoint, index int, finish
var err error
data, err := p.Decode(packet.CipherIndex(), addt, packet.Body())
if err != nil {
logrus.Debugln("[listen] @", index, "drop invalid packet", ", key idx:", packet.CipherIndex(), "addt:", addt, "err:", err)
logrus.Debugln("[listen] @", index, "drop invalid packet key idx:", packet.CipherIndex(), "addt:", addt, "err:", err)
packet.Put()
return
}
Expand Down
4 changes: 2 additions & 2 deletions gold/link/recv.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func (l *Link) Read() *head.Packet {
}

func (m *Me) wait(data []byte) *head.Packet {
if len(data) < 60 { // not a valid packet
if len(data) < head.PacketHeadLen { // not a valid packet
return nil
}
bound := 64
Expand All @@ -33,7 +33,7 @@ func (m *Me) wait(data []byte) *head.Packet {
logrus.Debugln("[recv] drop invalid flags packet:", hex.EncodeToString(data[11:12]), hex.EncodeToString(data[10:11]))
return nil
}
crc := binary.LittleEndian.Uint64(data[52:60])
crc := binary.LittleEndian.Uint64(data[52:head.PacketHeadLen])
if m.recved.Get(crc) { // 是重放攻击
logrus.Warnln("[recv] ignore duplicated crc packet", strconv.FormatUint(crc, 16))
return nil
Expand Down
28 changes: 15 additions & 13 deletions gold/link/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
)

var (
ErrDropBigDontFragTransPkt = errors.New("drop big don't fragmnet trans packet")
ErrTTL = errors.New("ttl exceeded")
ErrDropBigDontFragPkt = errors.New("drop big don't fragmnet packet")
ErrTTL = errors.New("ttl exceeded")
)

// WriteAndPut 向 peer 发包并将包放回缓存池
Expand All @@ -32,7 +32,7 @@ func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) {
if !istransfer {
l.encrypt(p, sndcnt, teatype)
}
delta := (int(mtu) - 60) & 0x0000fff8
delta := (int(mtu) - head.PacketHeadLen) & 0x0000fff8
if delta <= 0 {
logrus.Warnln("[send] reset invalid data frag len", delta, "to 8")
delta = 8
Expand All @@ -42,7 +42,7 @@ func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) {
return l.write(p, teatype, sndcnt, uint32(remlen), 0, istransfer, false)
}
if istransfer && p.Flags.DontFrag() && remlen > delta {
return 0, ErrDropBigDontFragTransPkt
return 0, ErrDropBigDontFragPkt
}
ttl := p.TTL
totl := uint32(remlen)
Expand Down Expand Up @@ -89,21 +89,25 @@ func (l *Link) encrypt(p *head.Packet, sndcnt uint16, teatype uint8) {
}

// 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 uint16, datasz uint32, offset uint16, istransfer, hasmore bool) (int, error) {
peerep := l.endpoint
if peerep == nil {
return 0, errors.New("nil endpoint of " + p.Dst.String())
}

var d []byte
var cl func()
// TODO: now all packet allow frag, adapt to DF
if istransfer {
d, cl = p.Marshal(nil, teatype, additional, 0, 0, false, false)
d, cl = p.Marshal(nil, 0, 0, 0, offset, false, hasmore)
} else {
d, cl = p.Marshal(l.me.me, teatype, additional, datasz, offset, false, hasmore)
}
if d == nil {
return 0, ErrTTL
}
peerep := l.endpoint
if peerep == nil {
return 0, errors.New("nil endpoint of " + p.Dst.String())
}
defer cl()

bound := 64
endl := "..."
if len(d) < bound {
Expand All @@ -114,7 +118,5 @@ func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz ui
logrus.Debugln("[send] data bytes", hex.EncodeToString(d[:bound]), endl)
d = l.me.xorenc(d)
logrus.Debugln("[send] data xored", hex.EncodeToString(d[:bound]), endl)
n, err = l.me.conn.WriteToPeer(d, peerep)
cl()
return
return l.me.conn.WriteToPeer(d, peerep)
}
58 changes: 45 additions & 13 deletions upper/services/tunnel/tunnel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/fumiama/WireGold/helper"
)

func testTunnel(t *testing.T, nw string, isplain bool, pshk *[32]byte) {
func testTunnel(t *testing.T, nw string, isplain bool, pshk *[32]byte, mtu uint16) {
selfpk, err := curve.New(nil)
if err != nil {
panic(err)
Expand All @@ -37,7 +37,7 @@ func testTunnel(t *testing.T, nw string, isplain bool, pshk *[32]byte) {
PrivateKey: selfpk.Private(),
SrcPort: 1,
DstPort: 1,
MTU: 4096,
MTU: mtu,
})
defer m.Close()

Expand All @@ -48,7 +48,7 @@ func testTunnel(t *testing.T, nw string, isplain bool, pshk *[32]byte) {
PrivateKey: peerpk.Private(),
SrcPort: 1,
DstPort: 1,
MTU: 4096,
MTU: mtu,
})
defer p.Close()

Expand All @@ -65,8 +65,8 @@ func testTunnel(t *testing.T, nw string, isplain bool, pshk *[32]byte) {
AllowedIPs: []string{"192.168.1.3/32"},
PubicKey: ppp,
PresharedKey: pshk,
MTU: 4096,
MTURandomRange: 1024,
MTU: mtu,
MTURandomRange: mtu / 2,
UseZstd: true,
})
p.AddPeer(&link.PeerConfig{
Expand All @@ -75,8 +75,8 @@ func testTunnel(t *testing.T, nw string, isplain bool, pshk *[32]byte) {
AllowedIPs: []string{"192.168.1.2/32"},
PubicKey: spp,
PresharedKey: pshk,
MTU: 4096,
MTURandomRange: 1024,
MTU: mtu,
MTURandomRange: mtu / 2,
UseZstd: true,
})
tunnme, err := Create(&m, "192.168.1.3")
Expand Down Expand Up @@ -152,32 +152,64 @@ func TestTunnelUDP(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetFormatter(&logFormat{enableColor: false})

testTunnel(t, "udp", true, nil) // test plain text
testTunnel(t, "udp", true, nil, 4096) // test plain text

testTunnel(t, "udp", false, nil) // test normal
testTunnel(t, "udp", false, nil, 4096) // test normal

var buf [32]byte
_, err := rand.Read(buf[:])
if err != nil {
panic(err)
}
testTunnel(t, "udp", false, &buf) // test preshared
testTunnel(t, "udp", false, &buf, 4096) // test preshared
}

func TestTunnelUDPSmallMTU(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetFormatter(&logFormat{enableColor: false})

testTunnel(t, "udp", true, nil, 1024) // test plain text

testTunnel(t, "udp", false, nil, 1024) // test normal

var buf [32]byte
_, err := rand.Read(buf[:])
if err != nil {
panic(err)
}
testTunnel(t, "udp", false, &buf, 1024) // test preshared
}

func TestTunnelTCP(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetFormatter(&logFormat{enableColor: false})

testTunnel(t, "tcp", true, nil) // test plain text
testTunnel(t, "tcp", true, nil, 4096) // test plain text

testTunnel(t, "tcp", false, nil, 4096) // test normal

var buf [32]byte
_, err := rand.Read(buf[:])
if err != nil {
panic(err)
}
testTunnel(t, "tcp", false, &buf, 4096) // test preshared
}

func TestTunnelTCPSmallMTU(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetFormatter(&logFormat{enableColor: false})

testTunnel(t, "tcp", true, nil, 1024) // test plain text

testTunnel(t, "tcp", false, nil) // test normal
testTunnel(t, "tcp", false, nil, 1024) // test normal

var buf [32]byte
_, err := rand.Read(buf[:])
if err != nil {
panic(err)
}
testTunnel(t, "tcp", false, &buf) // test preshared
testTunnel(t, "tcp", false, &buf, 1024) // test preshared
}

// logFormat specialize for go-cqhttp
Expand Down

0 comments on commit cb2fe9b

Please sign in to comment.