diff --git a/openvpn-wire-protocol.xml b/openvpn-wire-protocol.xml index 3edf915..1c0dd1b 100644 --- a/openvpn-wire-protocol.xml +++ b/openvpn-wire-protocol.xml @@ -117,50 +117,53 @@
- Since OpenVPN can work both in a traditional server-client setup - as well as a peer-to-peer setup, this document tries to avoid the - concept of server and clients. It will refer to these as - either the local or remote sites. In a peer-to-peer setup only - a single tunnel can be established, while in a server-client setup - several clients can connect to a single server at the same time. - - If the terms server and client are used these are almost always - synonymous with the peer's role as either TLS server or TLS client. + OpenVPN can work both in a traditional client-server topology + and in a peer-to-peer topology. In a peer-to-peer setup only + a single point-to-point tunnel can be established, while in a + client-server setup multiple clients can connect to a single + server in a star configuration. + + + When the terms client and server are used in the context of a + peer-to-peer topology, this reflects the peer's role as + either TLS server or TLS client.
OpenVPN is capable of using both UDP and TCP for transporting SSL/TLS traffic. The SSL/TLS protocol is strictly written for - TCP but OpenVPN makes that possible through encapsulating the - SSL/TLS packets and adding a reliability layer to avoid issues - when packets get resent. + TCP but OpenVPN makes UDP possible by encapsulating the + SSL/TLS concepts in the payload and adding a reliability + layer in the payload to avoid issues when packets get + resent.
-
+ +
- The wire packet identical for both UDP and TCP transport - modes with one exception. For UDP packets the size of a - payload packet is derived from UDP packet length. Since - TCP present a stream of bytes to the application, TCP - payloads carry a 16 bits packet length indicator of the - size of the payload. Splitting too large payload and - combining multiple payload into packets is done by the - TCP/IP stack of the operating system. + The wire payloads are identical for both UDP and TCP transport + modes with one exception: For UDP packets the size of the + payload is derived from the UDP packet length. Since + TCP presents a stream of bytes to the application, TCP + payloads carry a 16 bit payload length. + Splitting large payloads and + combining split payloads is done by the operating system's + TCP/IP stack. - - The basic OpenVPN packet format that is common to both - control and data channel is that the first byte (after the length in - TCP mode) in a packet consists of an opcode (highest 5 bits) - that determines the packet type and a key id (low 3 bit). + After the length in TCP mode, the OpenVPN payload format is + common to both control and data channel. The first byte + consists of an opcode in the high order 5 bits and a key id + in the low 3 bits. The op code dictates the payload type. - The data channel section - and control channel + The control channel + and data channel section sections describe the formats of the packets in details.
+
@@ -276,7 +279,7 @@ operational mode will encrypt the control packet channel payload with a static key. The static keying material is the same which HMAC authentication uses, but the key-direction is fixed according - to the local process' role (server or client). + to the local process' role (server or client). This feature is called tls-crypt, which uses a pre-shared static key (like @@ -322,11 +325,11 @@ output = Header || Tag || Ciph This boils down to the following on-the-wire packet format:
- + -opcode- || -session_id- || -packet_id- || auth_tag || * payload * - +
Where
    @@ -433,23 +436,23 @@ output = Header || Tag || Ciph
    - ``--tls-auth`` and ``tls-crypt`` use a pre-shared group key, + --tls-auth and tls-crypt use a pre-shared group key, which is shared among all clients and servers in an OpenVPN deployment. If any client or server is compromised, the attacker will have access to this shared key, and it will no longer provide any security. To reduce the risk of - losing pre-shared keys, ``tls-crypt-v2`` adds the ability to + losing pre-shared keys, tls-crypt-v2 adds the ability to supply each client with a unique tls-crypt key. This allows large organizations and VPN providers to profit from the same DoS and TLS stack protection that small deployments can already - achieve using ``tls-auth`` or ``tls-crypt``. + achieve using tls-auth or tls-crypt. - Also, for ``tls-crypt``, even if all these peers succeed in + Also, for tls-crypt, even if all these peers succeed in keeping the key secret, the key lifetime is limited to roughly 8000 years, divided by the number of clients (see the - ``--tls-crypt`` section of the man page). + --tls-crypt section of the man page). [FIXME/flichtenheld: either include or remove reference] Using client-specific keys, we lift this lifetime requirement to roughly 8000 years @@ -459,7 +462,7 @@ output = Header || Tag || Ciph
    - ``tls-crypt-v2`` uses an encrypted cookie mechanism to introduce + tls-crypt-v2 uses an encrypted cookie mechanism to introduce client-specific tls-crypt keys without introducing a lot of server-side state. The client-specific key is encrypted using a server key. The server key is the same for all servers in a group. When a client connects, it first sends the @@ -474,16 +477,16 @@ output = Header || Tag || Ciph to abort the connection immediately after receiving the first packet, rather than performing an entire TLS handshake. Aborting the connection this early greatly improves the DoS resilience and reduces attack surface against - malicious clients that have the ``tls-crypt`` or ``tls-auth`` key. This is + malicious clients that have the tls-crypt or tls-auth key. This is particularly relevant for large deployments (think lost key or disgruntled employee) and VPN providers (clients are not trusted). - To allow for a smooth transition, ``tls-crypt-v2`` is designed such that a - server can enable both ``tls-crypt-v2`` and either ``tls-crypt`` or - ``tls-auth``. This is achieved by introducing a CONTROL_HARD_RESET_CLIENT_V3 - opcode, that indicates that the client wants to use ``tls-crypt-v2`` for the + To allow for a smooth transition, tls-crypt-v2 is designed such that a + server can enable both tls-crypt-v2 and either tls-crypt or + tls-auth. This is achieved by introducing a CONTROL_HARD_RESET_CLIENT_V3 + opcode, that indicates that the client wants to use tls-crypt-v2 for the current connection.
    @@ -494,19 +497,19 @@ output = Header || Tag || Ciph
    1. - Generate a tls-crypt-v2 server key using OpenVPN's ``--genkey tls-crypt-v2-server``. + Generate a tls-crypt-v2 server key using OpenVPN's --genkey tls-crypt-v2-server. This key contains 2 512-bit keys, of which we use:
        -
      • the first 256 bits of key 1 as AES-256-CTR encryption key ``Ke``
      • -
      • the first 256 bits of key 2 as HMAC-SHA-256 authentication key ``Ka``
      • +
      • the first 256 bits of key 1 as AES-256-CTR encryption key Ke
      • +
      • the first 256 bits of key 2 as HMAC-SHA-256 authentication key Ka
      - This format is similar to the format for regular ``tls-crypt``/``tls-auth`` + This format is similar to the format for regular tls-crypt/tls-auth and data channel keys, which allows us to reuse code.
    2. Add the tls-crypt-v2 server key to all server configs - (``tls-crypt-v2 /path/to/server.key``) + (tls-crypt-v2 /path/to/server.key)
    @@ -515,7 +518,7 @@ output = Header || Tag || Ciph When provisioning a client, create a client-specific tls-crypt key:
      -
    1. . Generate 2048 bits client-specific key ``Kc`` using OpenVPN's ``--genkey tls-crypt-v2-client``
    2. +
    3. Generate 2048 bits client-specific key Kc using OpenVPN's --genkey tls-crypt-v2-client
    4. Optionally generate metadata. @@ -542,7 +545,7 @@ output = Header || Tag || Ciph
    5. -
    6. Create a wrapped client key ``WKc``, using the same nonce-misuse-resistant +
    7. Create a wrapped client key WKc, using the same nonce-misuse-resistant SIV construction we use for tls-crypt:
      @@ -557,12 +560,12 @@ WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len
      - Note that the length of ``WKc`` can be computed before composing ``WKc``, + Note that the length of WKc can be computed before composing WKc, because the length of each component is known (and AES-256-CTR does not add any padding).
    8. -
    9. Create a tls-crypt-v2 client key: PEM-encode ``Kc || WKc`` and store in a +
    10. Create a tls-crypt-v2 client key: PEM-encode Kc || WKc and store in a file, using the header -----BEGIN OpenVPN tls-crypt-v2 client key----- and the footer -----END OpenVPN tls-crypt-v2 client key-----. (The PEM format is simple, and following PEM allows us to use the crypto library functions @@ -570,7 +573,7 @@ WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len
    11. Add the tls-crypt-v2 client key to the client config - (``tls-crypt-v2 /path/to/client-specific.key``)
    12. + (tls-crypt-v2 /path/to/client-specific.key)
    @@ -581,14 +584,14 @@ WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len
  • The client reads the tls-crypt-v2 key from its config, and:
      -
    1. loads ``Kc`` as its tls-crypt key,
    2. -
    3. stores ``WKc`` in memory for sending to the server.
    4. +
    5. loads Kc as its tls-crypt key,
    6. +
    7. stores WKc in memory for sending to the server.
  • To start the connection, the client creates a P_CONTROL_HARD_RESET_CLIENT_V3 - message, wraps it with tls-crypt using ``Kc`` as the key, and appends - ``WKc``. (``WKc`` must not be encrypted, to prevent a chicken-and-egg + message, wraps it with tls-crypt using Kc as the key, and appends + WKc. (WKc must not be encrypted, to prevent a chicken-and-egg problem.)
  • The server receives the P_CONTROL_HARD_RESET_CLIENT_V3 message, and @@ -596,9 +599,9 @@ WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len
    1. reads the WKc length field from the end of the message, and extracts WKc from the message
    2. -
    3. unwraps ``WKc``
    4. -
    5. uses unwrapped ``Kc`` to verify the remaining - P_CONTROL_HARD_RESET_CLIENT_V3 message's (encryption and) authentication.
    6. +
    7. unwraps WKc
    8. +
    9. uses unwrapped Kc to verify the remaining + P_CONTROL_HARD_RESET_CLIENT_V3 message's (encryption and) authentication.
    The message is dropped and no error response is sent when any of these steps fails (DoS protection). @@ -618,7 +621,7 @@ WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len A server should not send back any error messages if metadata verification fails, to reduce attack surface and maximize DoS resilience.
  • -
  • Client and server use ``Kc`` for (un)wrapping any following control channel +
  • Client and server use Kc for (un)wrapping any following control channel messages.
  • @@ -674,8 +677,8 @@ WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len
    To allow for a smooth transition, the server implementation allows - ``tls-crypt`` or ``tls-auth`` to be used simultaneously with ``tls-crypt-v2``. - This specification does not allow simultaneously using ``tls-crypt-v2`` and + tls-crypt or tls-auth to be used simultaneously with tls-crypt-v2. + This specification does not allow simultaneously using tls-crypt-v2 and connections without any control channel wrapping, because that would break DoS resilience. @@ -685,7 +688,7 @@ WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len indicate low-level protocol features.) - ``tls-crypt-v2`` uses fixed crypto algorithms, because: + tls-crypt-v2 uses fixed crypto algorithms, because:
    • The crypto is used before we can do any negotiation, so the algorithms have @@ -697,10 +700,10 @@ WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len
    - Potential ``tls-crypt-v2`` risks: + Potential tls-crypt-v2 risks:
      -
    • Slightly more work on first connection (``WKc`` unwrap + hard reset unwrap) - than with ``tls-crypt`` (hard reset unwrap) or ``tls-auth`` (hard reset auth).
    • +
    • Slightly more work on first connection (WKc unwrap + hard reset unwrap) + than with tls-crypt (hard reset unwrap) or tls-auth (hard reset auth).
    • Flexible metadata allow mistakes (So we should make it easy to do it right. Provide tooling to create client keys based on cert serial + CA fingerprint, provide script that uses CRL (if @@ -943,7 +946,7 @@ available) to drop revoked keys.)
    • For CFB/OFB based ciphers, the long packet_id format MUST be - used, as the packet_id is part of the cipher's IV. + used, as the packet_id is part of the cipher's IV. [FIXME/syzzer: Elaborate more] [FIXME/schwabe: move to data channel] @@ -1341,7 +1344,7 @@ struct datakeys { The purpose of this feature is to allow a client to float between various client IP addresses and UDP ports. When a client floats it means that the established - encryption and session keys will be reused when the client's source IP + encryption and session keys will be reused when the client's source IP address or source port changes. Reasons for such changes can be NAT firewalls interrupting longer lasting established connections, mobile devices moving from WLAN to a mobile data carrier (such as GPRS, 3G,