parent
4ece508872
commit
feb8ed1e9c
@ -0,0 +1,94 @@ |
||||
# The OpenVPN protocol |
||||
|
||||
## Status |
||||
|
||||
This describes a subset of the protocol as implemented in OpenVPN 2.4.7. The |
||||
original motivation is to document for interoperability of a newly developed |
||||
OpenVPN client with existing servers, reusing existing configuration files. The |
||||
scope for key exchanges is TLS (i.e. key-method 2), the pre-shared secret mode |
||||
is not described in this document. Not all features and configuration options of |
||||
OpenVPN are covered in this document, nor in the implementation itself. |
||||
|
||||
## Terminology |
||||
|
||||
## Protocol overview |
||||
|
||||
OpenVPN establishes a mutually authenticated tunnel between two endpoints. The |
||||
cryptographic properties depend on the concrete configuration. An OpenVPN tunnel |
||||
can be established via UDP or TCP. Two kinds of packets are distinguished: |
||||
control packets that are reliably transfered (acknowledged and retransmitted), |
||||
and data packets. Data packets are only accepted once a tunnel is established. |
||||
|
||||
## Packet wire format |
||||
|
||||
Each OpenVPN packet consists of a one-byte header, which high 5 bits encode the |
||||
operation, and low 3 bits encode the key identifier. This is followed by the |
||||
actual payload, depending on the operation. The header is prefixed by a two-byte |
||||
length field if TCP is used as transport. |
||||
|
||||
The operations are: |
||||
- SOFT_RESET to initialize a rekeying. This is the first packet with a fresh |
||||
key identifier |
||||
- CONTROL which carry a TLS payload |
||||
- ACK for acknowledgement packets |
||||
- HARD_RESET_CLIENT to initiate a new connection |
||||
- HARD_RESET_SERVER to answer to a HARD_RESET_CLIENT |
||||
- DATA carrying actual data |
||||
|
||||
All operations apart from DATA share a common header: |
||||
- local SID - 8 byte |
||||
- hmac - 20 bytes (depending on hash algo, commonly SHA1) |
||||
- packed id - 4 byte |
||||
- timestamp - 4 byte (seconds since Unix epoch) |
||||
- acked length - 1 byte |
||||
- acked IDs - length * 4 byte |
||||
- remote SID - 8 byte (only if acked length > 0) |
||||
- TLS payload (only in control messages) |
||||
|
||||
They consist of: local session ID, HMAC signature, packet ID, timestamp, acked |
||||
packet IDs, remote session ID (only present if acked packet IDs is non-empty), |
||||
message ID, TLS payload. |
||||
|
||||
- hmac - 20 bytes |
||||
- IV - cipher block-size |
||||
- data - padded to block-size |
||||
|
||||
A DATA packet consists of a HMAC signature, its ciphertext IV, and the actual |
||||
ciphertext. |
||||
|
||||
|
||||
## Handshake protocol |
||||
|
||||
Key establishment and configuration synchronization is achieved by a TLS |
||||
handshake over the control channel, over which configuration parameters are |
||||
exchanged. At any time after the tunnel is established, any party may use the |
||||
control channel for tunnel teardown or initiating a key exchange for rekeying |
||||
the tunnel. Multiple keys may be active at the same time, which is especially |
||||
useful for handing over from old keys to new keys without loosing in-flight |
||||
data. |
||||
|
||||
## Encryption / decryption and padding |
||||
|
||||
The purpose of padding is to align data to the cipher block size. The padding |
||||
mechanism is to contain the padding length in each byte, i.e. if the block size |
||||
is 16, and the data 13 bytes, the padding will be 3 bytes containing 0x03 each. |
||||
If the data is already aligned to the block size, an entire block will be |
||||
appended. |
||||
|
||||
## Configuration parameters and their interaction |
||||
|
||||
For initializing a tunnel, first a remote must be selected from the |
||||
configuration. Depending on whether *remote-random* is configured, the list of |
||||
remotes will be randomized or not. A remote consists of a hostname or IP |
||||
address, an optional port (default to 1194) and optional protocol |
||||
(TCP/UDP/TCPv4/UDPv4/TCPv6/UDPv6), defaults to *proto*, filtered depending on |
||||
*force-proto*. If a hostname is configured, this is resolved using DNS, and one |
||||
of the returned IP addresses is used. If *connect-timeout* is reached without an |
||||
initial packet exchange in both directions, the next remote is tried. If |
||||
*hand-window* is exceeded without completing the handshake, the next remote is |
||||
chosen. If the list of remotes is all tried, the client waits for at least |
||||
*connect-retry* seconds (with a backoff factor of 2 after 5 retries, limited to |
||||
the optional max argument, default to 300). If *connect-retry-max* is reached |
||||
(defaults to unlimited) without establishing a connection, the client exits. |
||||
|
||||
TODO: resolv-retry |
Loading…
Reference in new issue