From f4f4c999267437c3eb909e8d0e5278fb4596d9a7 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 31 Mar 2026 16:37:57 +0300 Subject: [PATCH] fix: apply S4 transport padding to keepalive packets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keepalive packets were excluded from S4 padding because the padding logic was nested inside the dataSent guard. The receiving side (DeterminePacketTypeAndPadding) expects S4 padding on all transport packets, so unpadded keepalives fail H4 header validation and are silently dropped. This prevents the responder from completing key confirmation — lastHandshakeNano stays 0 until real data flows through the tunnel. --- device/send.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/device/send.go b/device/send.go index 5e5cc1b..0cc57da 100644 --- a/device/send.go +++ b/device/send.go @@ -574,16 +574,15 @@ func (peer *Peer) RoutineSequentialSender(maxBatchSize int) { for _, elem := range elemsContainer.elems { if len(elem.packet) != MessageKeepaliveSize { dataSent = true - - if padding := device.paddings.transport; padding > 0 { - // elem.packet is stored at the start of elem.buffer - // with zero padding - for i := len(elem.packet) - 1; i >= 0; i-- { - elem.buffer[i+padding] = elem.buffer[i] - } - rand.Read(elem.buffer[:padding]) - elem.packet = elem.buffer[:padding+len(elem.packet)] + } + if padding := device.paddings.transport; padding > 0 { + // elem.packet is stored at the start of elem.buffer + // with zero padding + for i := len(elem.packet) - 1; i >= 0; i-- { + elem.buffer[i+padding] = elem.buffer[i] } + rand.Read(elem.buffer[:padding]) + elem.packet = elem.buffer[:padding+len(elem.packet)] } bufs = append(bufs, elem.packet) }