mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-19 19:52:15 +02:00
OpenVPN Protocol extensions update.
1. Added specific details on DATA_V2/peer-id/float support. 2. For AEAD mode, emphasized that the leading 8 bytes (4 bytes for DATA_V2/peer-id and 4 for packet ID) is all included in the AD. 3. Added specific details on protocol negotiation where the client indicates protocol extension availability with IV_x parameters in the peer info string, and the server responds by pushing directives to the client to enable the feature. 4. Added "TCP nonlinear mode" section, a new protocol extension that is needed by multithreaded TCP servers.
This commit is contained in:
parent
a80508ab21
commit
dbd5995d7a
@ -1,7 +1,37 @@
|
||||
OpenVPN Protocol extensions
|
||||
2015-01-06
|
||||
|
||||
1. DATA_V2 opcode with 24-bit peer ID
|
||||
|
||||
* The DATA_V2 opcode is 9.
|
||||
* The DATA_V2 opcode/key_id byte is followed by 3 additional
|
||||
(network endian) bytes indicating the peer ID.
|
||||
* If a 4-byte DATA_V2 header is passed through ntohl,
|
||||
the resulting high 8 bits will be the DATA_V2 opcode/key_id,
|
||||
and the lower 24 bits will be the peer ID.
|
||||
* A disabled peer ID is denoted by 0xFFFFFF.
|
||||
* Server tells the client to use DATA_V2/peer_id by pushing
|
||||
the directive "peer-id ID" where ID is a decimal integer
|
||||
in the range [-1, 16777215]. Setting the peer ID to -1
|
||||
transmits DATA_V2 packets with the peer ID field set to
|
||||
0xFFFFFF. Setting the peer_id to -1 is the same as
|
||||
setting it to 16777215 (i.e. 0xFFFFFF).
|
||||
* Client never transmits DATA_V2 packets unless the server
|
||||
has pushed a "peer-id" directive.
|
||||
* Server never pushes a "peer-id" directive unless the
|
||||
client has indicated its support for DATA_V2 by
|
||||
including "IV_PROTO=2" in the peer info data.
|
||||
* When DATA_V2 is used for "float" functionality, the server
|
||||
must perform the following checks before allowing
|
||||
a client to float, i.e. to assume a new source address.
|
||||
(a) verify integrity (HMAC or GCM auth tag, replay
|
||||
protection, etc.) of the DATA_V2 packet, and
|
||||
(b) ensure that the float doesn't clobber a pre-existing
|
||||
client (i.e. if the address floated to is already
|
||||
owned by another client) unless it can be verified
|
||||
that the pre-existing client is a previous instance
|
||||
of the floating client.
|
||||
|
||||
2. AEAD mode
|
||||
|
||||
To support AEAD crypto modes such as AES-GCM, some protocol
|
||||
@ -33,25 +63,42 @@ OpenVPN Protocol extensions
|
||||
|
||||
[ DATA_V2 opcode ] [ Packet ID ] [ AEAD Auth tag ] [ ciphertext ]
|
||||
[ 4 bytes ] [ 4 bytes ] [ 16 bytes ]
|
||||
[ AEAD additional data (AD) ]
|
||||
|
||||
Static Key wire protocol:
|
||||
|
||||
[ DATA_V2 opcode ] [ Packet ID ] [ Nonce tail (random) ] [ AEAD Auth tag ] [ ciphertext ]
|
||||
[ AEAD nonce ]
|
||||
[ 4 bytes ] [ 8 bytes ] [ 4 bytes ] [ 16 bytes ]
|
||||
[ AEAD additional data (AD) ]
|
||||
|
||||
Note that because the HMAC keying material used to derive the
|
||||
last 8 bytes of the AEAD nonce is negotiated once per key
|
||||
Note that the AEAD additional data (AD) includes all data
|
||||
preceding the AEAD Auth tag including the DATA_V2/peer_id
|
||||
opcode and packet ID.
|
||||
|
||||
Also, note that because the HMAC keying material used to derive
|
||||
the last 8 bytes of the AEAD nonce is negotiated once per key
|
||||
as part of the control channel handshake, we can omit it from the
|
||||
data channel packets, thereby saving 8 bytes per packet. So
|
||||
only the 4-byte Packet ID component of the nonce must be
|
||||
transmitted with every packet.
|
||||
|
||||
Also note that that the TLS wire protocol overhead is only 24
|
||||
bytes, including the new 4 byte DATA_V2 opcode that includes
|
||||
the Peer ID! Compare that with traditional AES-CBC mode and
|
||||
DATA_V1 opcode: 1 (DATA_V1 opcode) + 20 (HMAC-SHA1 hash)
|
||||
+ 8 (IV) + 4 (Packet ID) + 1-8 (PKCS#7 padding) = 34-41 bytes.
|
||||
When negotiating AEAD mode, the client indicates its support
|
||||
of AES-128-GCM, AES-192-GCM, and AES-192-GCM by including:
|
||||
|
||||
IV_NCP=2
|
||||
|
||||
in the peer info string (NCP stands for Negotiable Crypto
|
||||
Parameters).
|
||||
|
||||
When the IV_NCP value is 2 or higher, it indicates that
|
||||
the server may push an AEAD "cipher" directive, e.g.:
|
||||
|
||||
push "cipher AES-128-GCM"
|
||||
|
||||
In the future, the IV_NCP value (2 in the current
|
||||
implementation) may be increased to indicate the
|
||||
availability of additional negotiable ciphers.
|
||||
|
||||
3. Compression V2
|
||||
|
||||
@ -78,7 +125,7 @@ OpenVPN Protocol extensions
|
||||
|
||||
c. Compression occurred (2 bytes of overhead):
|
||||
|
||||
[ 0x50 ] [ compression Alg ID ] [ compressed IP/Ethernet packet ]
|
||||
[ 0x50 ] [ compression Alg ID byte ] [ compressed IP/Ethernet packet ]
|
||||
|
||||
Compression Alg ID is one-byte algorithm identifier
|
||||
for LZ4 (0x1), LZO (0x2), or Snappy (0x3).
|
||||
@ -94,3 +141,58 @@ OpenVPN Protocol extensions
|
||||
3. This technique does not require any byte swapping with
|
||||
the tail of the packet which can potentially incur an
|
||||
expensive cache miss.
|
||||
|
||||
When negotiating Compression V2 mode, the client indicates its
|
||||
support by including the following in the peer info string:
|
||||
|
||||
IV_LZ4v2=1 -> LZ4 compression available in V2 format
|
||||
IV_COMP_STUBv2=1 -> stub compression available in V2 format
|
||||
(i.e. disable compression but still
|
||||
retain compression framing)
|
||||
|
||||
In response, the server can push to the client:
|
||||
|
||||
push "compress lz4-v2" -> enable LZ4 compression in V2 format
|
||||
|
||||
or
|
||||
|
||||
push "compress stub-v2" -> disable compression but retain
|
||||
compression framing in V2 format
|
||||
|
||||
4. TCP nonlinear mode
|
||||
|
||||
The OpenVPN 2.x packet ID and replay protection code, when running
|
||||
in TCP mode, requires that the packet ID follows a linearly
|
||||
incrementing sequence, i.e. 1, 2, 2, 3, ... This was a reasonable
|
||||
requirement, since the reliable nature of TCP guaranteed that a
|
||||
linear sequence of packet IDs transmitted by the sender would be
|
||||
received in the same order by the receiver.
|
||||
|
||||
However, recent work has shown that multithreaded OpenVPN servers
|
||||
may not be able to guarantee TCP packet ID linearity (on the
|
||||
transmit side) without incurring a performance penalty. This
|
||||
is because the packet ID for transmitted packets must be allocated
|
||||
before the packet is encrypted, while a multithreaded OpenVPN server
|
||||
might be concurrently encrypting and transmitting multiple packets
|
||||
using different threads, where the order that the threads complete
|
||||
encryption and transmit the packet is non-deterministic. This
|
||||
non-deterministic ordering of packets over the TCP session means
|
||||
that the client might see out-of-order packets and a non-linear
|
||||
packet ID progression, just as clients now see with UDP.
|
||||
|
||||
My proposed solution to the issue is to relax the Packet ID
|
||||
validation on the receiver side to allow non-linear packet ID
|
||||
sequences, even in TCP mode. This essentially means that the
|
||||
packet ID validation logic is now the same for both UDP and TCP.
|
||||
|
||||
The client indicates its ability to process non-linear packet
|
||||
ID sequences in TCP mode by including the following in the
|
||||
peer info string:
|
||||
|
||||
IV_TCPNL=1 -> TCP non-linear receiver supported
|
||||
|
||||
When the server receives a IV_TCPNL setting of 1 from the
|
||||
client, it may transmit out-of-order packets in TCP mode.
|
||||
Otherwise, servers must use other means (such as using thread
|
||||
synchronization primitives) to ensure strictly linear packet
|
||||
ID ordering in TCP mode.
|
||||
|
Loading…
Reference in New Issue
Block a user