From 6b43e796d9121bc21fe287bc26afd6ed69c76b1a Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Tue, 26 Nov 2024 14:00:38 +0200 Subject: [PATCH] multipeer: implement reverse path filtering After decrypting transport packet, make sure its source address matches peer's address. If address doesn't match or packet is not IP packet, drop the packet. GitHub: https://github.com/OpenVPN/ovpn-dco-win/issues/97 Signed-off-by: Lev Stipakov --- socket.cpp | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/socket.cpp b/socket.cpp index 6cb8dbc..b99c9ac 100644 --- a/socket.cpp +++ b/socket.cpp @@ -273,22 +273,45 @@ VOID OvpnSocketDataPacketReceived(_In_ POVPN_DEVICE device, UCHAR op, UINT32 pee OvpnPeerCtxRelease(peer); - if (NT_SUCCESS(status)) { - // ping packet? - if (OvpnTimerIsKeepaliveMessage(buffer->Data, buffer->Len)) { - LOG_INFO("Ping received", TraceLoggingValue(peerId, "peer-id")); + if (!NT_SUCCESS(status)) { + return; + } - // no need to inject ping packet into OS, return buffer to the pool - OvpnRxBufferPoolPut(buffer); - } - else { - if (OvpnMssIsIPv4(buffer->Data, buffer->Len)) { + // ping packet? + if (OvpnTimerIsKeepaliveMessage(buffer->Data, buffer->Len)) { + LOG_INFO("Ping received", TraceLoggingValue(peerId, "peer-id")); + + // no need to inject ping packet into OS, return buffer to the pool + OvpnRxBufferPoolPut(buffer); + } + else { + BOOLEAN drop = TRUE; + OvpnPeerContext* lookup_peer = NULL; + + if (OvpnMssIsIPv4(buffer->Data, buffer->Len)) { + // perform Reverse Path Filtering + auto addr = ((IPV4_HEADER*)(buffer->Data))->SourceAddress; + lookup_peer = OvpnFindPeerVPN4(device, addr); + if (lookup_peer == peer) { + drop = FALSE; OvpnMssDoIPv4(buffer->Data, buffer->Len, mss); } - else if (OvpnMssIsIPv6(buffer->Data, buffer->Len)) { + } + else if (OvpnMssIsIPv6(buffer->Data, buffer->Len)) { + // perform Reverse Path Filtering + auto addr = ((IPV6_HEADER*)(buffer->Data))->SourceAddress; + lookup_peer = OvpnFindPeerVPN6(device, addr); + if (lookup_peer == peer) { + drop = FALSE; OvpnMssDoIPv6(buffer->Data, buffer->Len, mss); } + } + + if (lookup_peer) { + OvpnPeerCtxRelease(lookup_peer); + } + if (!drop) { // enqueue plaintext buffer, it will be dequeued by NetAdapter RX datapath OvpnBufferQueueEnqueue(device->DataRxBufferQueue, &buffer->QueueListEntry);