0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 20:13:05 +02:00

ssl/proto: increment packet-id in control retransmit

Control packets are retransmitted if ACK hasn't been
received with certain time. This often happens with PUSH_REQUEST,
since it might take a while for the client to set up tun device and routing.
In this case client doesn't send ACK fast enough and server retransmits.

When using tls-auth (like in case of CloudVPN), most control packets
contain "packet-id" field. On retransmit, openvpn3 doesn't increment
packet-id value, unlike openvpn2. This triggers high verbosity replay
protection warnings in openvpn2 clients. Openvpn3 client also generates
replay errors, but they're only dumped to log at the end of session.

Fix by storing unencapsulated packets in send reliability object and
do encapculation on send and retransmit. This way packet-id will
be incremented on retransmit and no replay errors will occur on the
client side.

Signed-off-by: Lev Stipakov <lev@openvpn.net>
This commit is contained in:
Lev Stipakov 2021-12-02 12:00:29 +02:00 committed by David Sommerseth
parent 7765540e58
commit acdcab8675
No known key found for this signature in database
GPG Key ID: 86CF944C9671FDF2
2 changed files with 34 additions and 5 deletions

View File

@ -1312,6 +1312,15 @@ namespace openvpn {
{
}
// clone packet, including buffer content
Packet clone() const
{
Packet pkt;
pkt.opcode = opcode;
pkt.buf.reset(new BufferAllocated(*buf));
return pkt;
}
void reset()
{
reset_non_buf();

View File

@ -56,6 +56,9 @@ namespace openvpn {
// Constructor for BufferPtr:
// explicit PACKET(const BufferPtr& buf)
//
// Return cloned packet, including cloned buffer content:
// PACKET clone() const
//
// Test if defined:
// operator bool() const
//
@ -196,7 +199,19 @@ namespace openvpn {
typename ReliableSend::Message& m = rel_send.ref_by_id(i);
if (m.ready_retransmit(*now))
{
parent().net_send(m.packet, NET_SEND_RETRANSMIT);
// preserve original packet non-encapsulated
PACKET pkt = m.packet.clone();
// encapsulate packet
try {
parent().encapsulate(m.id(), pkt);
}
catch (...)
{
error(Error::ENCAPSULATION_ERROR);
throw;
}
parent().net_send(pkt, NET_SEND_RETRANSMIT);
m.reset_retransmit(*now, tls_timeout);
}
}
@ -343,9 +358,12 @@ namespace openvpn {
typename ReliableSend::Message& m = rel_send.send(*now, tls_timeout);
m.packet = PACKET(ssl_->read_ciphertext());
// encapsulate and send cloned packet, preserve original one for retransmit
PACKET pkt = m.packet.clone();
// encapsulate packet
try {
parent().encapsulate(m.id(), m.packet);
parent().encapsulate(m.id(), pkt);
}
catch (...)
{
@ -354,7 +372,7 @@ namespace openvpn {
}
// transmit it
parent().net_send(m.packet, NET_SEND_SSL);
parent().net_send(pkt, NET_SEND_SSL);
}
}
}
@ -368,9 +386,11 @@ namespace openvpn {
m.packet = raw_write_queue.front();
raw_write_queue.pop_front();
PACKET pkt = m.packet.clone();
// encapsulate packet
try {
parent().encapsulate(m.id(), m.packet);
parent().encapsulate(m.id(), pkt);
}
catch (...)
{
@ -379,7 +399,7 @@ namespace openvpn {
}
// transmit it
parent().net_send(m.packet, NET_SEND_RAW);
parent().net_send(pkt, NET_SEND_RAW);
}
}