From 4d42f450b220ed3bd58d74db869fe69ec28aeb6b Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Tue, 22 Oct 2019 11:14:05 +0900 Subject: [PATCH] Addressing the UDP reflection amplification attack: https://github.com/SoftEtherVPN/SoftEtherVPN/issues/1001 --- src/Cedar/Proto_OpenVPN.c | 29 ++++++++++++++++++++--------- src/Cedar/Proto_OpenVPN.h | 3 +++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/Cedar/Proto_OpenVPN.c b/src/Cedar/Proto_OpenVPN.c index e4d09d12..9fb776f2 100644 --- a/src/Cedar/Proto_OpenVPN.c +++ b/src/Cedar/Proto_OpenVPN.c @@ -821,7 +821,7 @@ void OvsProcessRecvControlPacket(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN case OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2: // New connection (hard reset) - OvsSendControlPacket(c, OPENVPN_P_CONTROL_HARD_RESET_SERVER_V2, NULL, 0); + OvsSendControlPacketEx(c, OPENVPN_P_CONTROL_HARD_RESET_SERVER_V2, NULL, 0, true); c->Status = OPENVPN_CHANNEL_STATUS_TLS_WAIT_CLIENT_KEY; break; @@ -1552,6 +1552,10 @@ void OvsSendControlPacketWithAutoSplit(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR * // Send the control packet void OvsSendControlPacket(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size) +{ + OvsSendControlPacketEx(c, opcode, data, data_size, false); +} +void OvsSendControlPacketEx(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size, bool no_resend) { OPENVPN_CONTROL_PACKET *p; // Validate arguments @@ -1562,6 +1566,8 @@ void OvsSendControlPacket(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT da p = ZeroMalloc(sizeof(OPENVPN_CONTROL_PACKET)); + p->NoResend = no_resend; + p->OpCode = opcode; p->PacketId = c->NextSendPacketId++; @@ -2559,20 +2565,25 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list) if (cp->NextSendTime <= s->Now) { - OPENVPN_PACKET *p; + if (cp->NoResend == false || cp->NumSent == 0) // To address the UDP reflection amplification attack: https://github.com/SoftEtherVPN/SoftEtherVPN/issues/1001 + { + OPENVPN_PACKET *p; - num = OvsGetAckReplyList(c, acks); + cp->NumSent++; - p = OvsNewControlPacket(cp->OpCode, j, se->ServerSessionId, num, acks, - se->ClientSessionId, cp->PacketId, cp->DataSize, cp->Data); + num = OvsGetAckReplyList(c, acks); - OvsSendPacketNow(s, se, p); + p = OvsNewControlPacket(cp->OpCode, j, se->ServerSessionId, num, acks, + se->ClientSessionId, cp->PacketId, cp->DataSize, cp->Data); - OvsFreePacket(p); + OvsSendPacketNow(s, se, p); - cp->NextSendTime = s->Now + (UINT64)OPENVPN_CONTROL_PACKET_RESEND_INTERVAL; + OvsFreePacket(p); - AddInterrupt(s->Interrupt, cp->NextSendTime); + cp->NextSendTime = s->Now + (UINT64)OPENVPN_CONTROL_PACKET_RESEND_INTERVAL; + + AddInterrupt(s->Interrupt, cp->NextSendTime); + } } } diff --git a/src/Cedar/Proto_OpenVPN.h b/src/Cedar/Proto_OpenVPN.h index 02ba2247..8fae45f3 100644 --- a/src/Cedar/Proto_OpenVPN.h +++ b/src/Cedar/Proto_OpenVPN.h @@ -108,6 +108,8 @@ struct OPENVPN_CONTROL_PACKET UINT DataSize; // Data size UCHAR *Data; // Data body UINT64 NextSendTime; // Scheduled next transmission time + bool NoResend; // Disable re-sending + UINT NumSent; // How many times we have sent this packet }; // OpenVPN packet @@ -260,6 +262,7 @@ void OvsSendPacketRawNow(OPENVPN_SERVER *s, OPENVPN_SESSION *se, void *data, UIN void OvsProcessRecvControlPacket(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, OPENVPN_PACKET *p); void OvsSendControlPacket(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size); +void OvsSendControlPacketEx(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size, bool no_resend); void OvsSendControlPacketWithAutoSplit(OPENVPN_CHANNEL *c, UCHAR opcode, UCHAR *data, UINT data_size); void OvsFreeControlPacket(OPENVPN_CONTROL_PACKET *p); void OvsDeleteFromSendingControlPacketList(OPENVPN_CHANNEL *c, UINT num_acks, UINT *acks);