[Openvpn-devel] [PATCH] systemd: Reworked the systemd unit file to handle server and client configs better

2014-11-13 Thread David Sommerseth
From: David Sommerseth 

Systemd can delay starting a service if the network isn't fully available
yet.  This feature is useful in client configurations, where OpenVPN will
not be started before the client can reach the Internet.  It is the network
service manager which tells systemd if the system is "online" or not.

For server configurations, the OpenVPN should be able to be started,
regardless if the system is "online" or not.  This is also the old
behaviour of most of the old init.d script and the last systemd unit file.

This patch splits the previous systemd unit file into to two files.  One
which is aimed at clients (openvpn-client@.service) and one for server
configurations (openvpn-server@.service).  These files will also pick
the configurations from different sub-directories.  The unit file for
openvpn-client@ will use /etc/openvpn/client and the server unit file
will use /etc/openvpn/server.  This also ensures that config files
are not started in the wrong manner.

The arguments given to the openvpn binary have also shifted order,
to ensure that some of them cannot be overridden by the config file,
such as --daemon and --writepid.  For server configurations a
--status file is also added with the status format set to 2.  This
can be overridden by the configuration file.

Signed-off-by: David Sommerseth 
---
 distro/systemd/{openvpn@.service => openvpn-client@.service} | 7 ---
 distro/systemd/{openvpn@.service => openvpn-server@.service} | 6 +++---
 2 files changed, 7 insertions(+), 6 deletions(-)
 copy distro/systemd/{openvpn@.service => openvpn-client@.service} (68%)
 rename distro/systemd/{openvpn@.service => openvpn-server@.service} (65%)

diff --git a/distro/systemd/openvpn@.service 
b/distro/systemd/openvpn-client@.service
similarity index 68%
copy from distro/systemd/openvpn@.service
copy to distro/systemd/openvpn-client@.service
index 7cd36c3..56d93a9 100644
--- a/distro/systemd/openvpn@.service
+++ b/distro/systemd/openvpn-client@.service
@@ -1,6 +1,7 @@
 [Unit]
 Description=OpenVPN tunnel for %I
-After=syslog.target network.target
+After=syslog.target network-online.target
+Wants=network-online.target
 Documentation=man:openvpn(8)
 Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
 Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
@@ -8,8 +9,8 @@ Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
 [Service]
 PrivateTmp=true
 Type=forking
-PIDFile=/var/run/openvpn/%i.pid
-ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/%i.pid --cd 
/etc/openvpn/ --config %i.conf
+PIDFile=/var/run/openvpn/client_%i.pid
+ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/client --config %i.conf --daemon 
--writepid /var/run/openvpn/client_%i.pid
 CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE 
CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH
 LimitNPROC=10
 DeviceAllow=/dev/null rw
diff --git a/distro/systemd/openvpn@.service 
b/distro/systemd/openvpn-server@.service
similarity index 65%
rename from distro/systemd/openvpn@.service
rename to distro/systemd/openvpn-server@.service
index 7cd36c3..c4c9a12 100644
--- a/distro/systemd/openvpn@.service
+++ b/distro/systemd/openvpn-server@.service
@@ -1,5 +1,5 @@
 [Unit]
-Description=OpenVPN tunnel for %I
+Description=OpenVPN service for %I
 After=syslog.target network.target
 Documentation=man:openvpn(8)
 Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
@@ -8,8 +8,8 @@ Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
 [Service]
 PrivateTmp=true
 Type=forking
-PIDFile=/var/run/openvpn/%i.pid
-ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/%i.pid --cd 
/etc/openvpn/ --config %i.conf
+PIDFile=/var/run/openvpn/server_%i.pid
+ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/server --status 
/var/run/openvpn/server_%i-status.log --status-version 2 --config %i.conf 
--daemon --writepid /var/run/openvpn/server_%i.pid
 CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE 
CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH
 LimitNPROC=10
 DeviceAllow=/dev/null rw
-- 
1.8.3.1




[Openvpn-devel] [PATCH] Peer-id patch v4

2014-11-13 Thread Lev Stipakov
Added new packet format P_DATA_V2, which includes peer-id. If server
supports, client sends all data packets in the new format. When data
packet arrives, server identifies peer by peer-id. If peer's ip/port has
changed, server assumes that client has floated, verifies HMAC and
updates ip/port in internal structs.

New in v4:
Handles correctly float to an address which is used by another peer.
This also has fixed crash on assert in multi_client_disconnect.

New in v3:
Bugfix: If float happens after TLS renegotiation and there are no data packets 
between reneg and float, server will not recognize floated client.
---
 src/openvpn/crypto.c |  66 +++--
 src/openvpn/crypto.h |   3 +
 src/openvpn/init.c   |  10 +++-
 src/openvpn/mudp.c   | 150 ++-
 src/openvpn/multi.c  |   6 ++
 src/openvpn/multi.h  |   2 +
 src/openvpn/options.c|   9 ++-
 src/openvpn/options.h|   8 ++-
 src/openvpn/push.c   |  16 -
 src/openvpn/ssl.c|  67 +++--
 src/openvpn/ssl.h|   9 ++-
 src/openvpn/ssl_common.h |   4 ++
 12 files changed, 308 insertions(+), 42 deletions(-)

diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
index ef2bde1..ccea1b8 100644
--- a/src/openvpn/crypto.c
+++ b/src/openvpn/crypto.c
@@ -223,6 +223,30 @@ err:
   return;
 }

+int verify_hmac(struct buffer *buf, struct key_ctx *ctx, int offset)
+{
+  uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed 
locally */
+  int hmac_len = 0;
+
+  hmac_ctx_reset(ctx->hmac);
+  /* Assume the length of the input HMAC */
+  hmac_len = hmac_ctx_size (ctx->hmac);
+
+  /* Authentication fails if insufficient data in packet for HMAC */
+  if (buf->len - offset < hmac_len)
+return 0;
+
+  hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len + offset,
+   BLEN (buf) - hmac_len - offset);
+  hmac_ctx_final (ctx->hmac, local_hmac);
+
+  /* Compare locally computed HMAC with packet HMAC */
+  if (memcmp_constant_time (local_hmac, BPTR (buf) + offset, hmac_len) == 0)
+return hmac_len;
+
+  return 0;
+}
+
 /*
  * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet.
  *
@@ -249,25 +273,9 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
   /* Verify the HMAC */
   if (ctx->hmac)
{
- int hmac_len;
- uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext 
computed locally */
-
- hmac_ctx_reset(ctx->hmac);
-
- /* Assume the length of the input HMAC */
- hmac_len = hmac_ctx_size (ctx->hmac);
-
- /* Authentication fails if insufficient data in packet for HMAC */
- if (buf->len < hmac_len)
-   CRYPT_ERROR ("missing authentication info");
-
- hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len, BLEN (buf) - 
hmac_len);
- hmac_ctx_final (ctx->hmac, local_hmac);
-
- /* Compare locally computed HMAC with packet HMAC */
- if (memcmp_constant_time (local_hmac, BPTR (buf), hmac_len))
+ int hmac_len = verify_hmac(buf, ctx, 0);
+ if (hmac_len == 0)
CRYPT_ERROR ("packet HMAC authentication failed");
-
  ASSERT (buf_advance (buf, hmac_len));
}

@@ -392,6 +400,28 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
 }

 /*
+ * This verifies if a packet and its HMAC fit to a crypto context.
+ *
+ * On success true is returned.
+ */
+bool
+crypto_test_hmac (struct buffer *buf, struct key_ctx_bi *key_ctx_bi)
+{
+  if (buf->len > 0 && key_ctx_bi)
+{
+  struct key_ctx *ctx = _ctx_bi->decrypt;
+
+  /* Verify the HMAC */
+  if (ctx->hmac)
+   {
+ /* sizeof(uint32_t) comes from peer_id (3 bytes) and opcode (1 byte) 
*/
+ return verify_hmac(buf, ctx, sizeof(uint32_t)) != 0;
+   }
+}
+  return false;
+}
+
+/*
  * How many bytes will we add to frame buffer for a given
  * set of crypto options?
  */
diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h
index bf2f802..b8db85c 100644
--- a/src/openvpn/crypto.h
+++ b/src/openvpn/crypto.h
@@ -275,6 +275,9 @@ bool openvpn_decrypt (struct buffer *buf, struct buffer 
work,
  const struct crypto_options *opt,
  const struct frame* frame);

+
+bool crypto_test_hmac (struct buffer *buf, struct key_ctx_bi *key_ctx_bi);
+
 /** @} name Functions for performing security operations on data channel 
packets */

 void crypto_adjust_frame_parameters(struct frame *frame,
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index a673be5..3811e09 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -1718,7 +1718,8 @@ pull_permission_mask (const struct context *c)
 | OPT_P_MESSAGES
 | OPT_P_EXPLICIT_NOTIFY
 | OPT_P_ECHO
-| OPT_P_PULL_MODE;
+| OPT_P_PULL_MODE
+| OPT_P_PEER_ID;

   if (!c->options.route_nopull)
 flags |= (OPT_P_ROUTE | OPT_P_IPWIN32);
@@ -1795,6 +1796,13 @@ do_deferred_options (struct context 

[Openvpn-devel] OpenVPN Protocol extensions

2014-11-13 Thread James Yonan

In addition to the Peer-ID/DATA_V2 protocol change proposal,
here are a couple more proposed extensions for AEAD mode and
Compression V2 that we can discuss at the upcoming Munich
hackathon.

James
OpenVPN Protocol extensions

1. DATA_V2 opcode with 24-bit peer ID

2. AEAD mode

   To support AEAD crypto modes such as AES-GCM, some protocol
   changes are in order.  AES-GCM, for example, requires a 12
   byte unique nonce for every packet.  I would propose that 4
   bytes be taken from the Packet ID which increments for every
   packet and therefore provides uniqueness.  The remaining 8
   bytes would be derived from the random key material that would
   normally be used to key the HMAC key.  This is possible since
   AEAD modes use a combined key for encryption and integrity
   checking, therefore the random key material for HMAC is
   unused and can be repurposed as an AEAD nonce source.  The 8
   byte nonce component derived from the HMAC keying material
   would remain constant for a given Key State.  Only the 4 byte
   Packet ID would increment for each packet.  Because AEAD
   encryption can be compromised if the nonce ever repeats for
   a given key, the implementation MUST disable encryption
   for a key if the 32-bit packet ID wraps.  In practical usage,
   renegotiation usually preempts wrapping, so the
   disable-encryption-on-wrap feature is a failsafe.

   AEAD Nonce:

 [ Packet ID ] [ HMAC keying material ]
 [ 4 bytes   ] [ 8 bytes  ]
 [ AEAD nonce total: 12 bytes ]

   TLS wire protocol:

 [ DATA_V2 opcode ] [ Packet ID ] [ AEAD Auth tag ] [ ciphertext ]
 [ 4 bytes] [ 4 bytes   ] [ 16 bytes  ]

   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  ]

   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.

3. Compression V2

   I have observed that compression in many cases, even when
   enabled, often does not produce packet size reduction
   because much of the packet data typically generated by web
   sessions is already compressed.  Further, the single byte that
   precedes the packet and indicates whether or not compression
   occurred has the unfortunate side effect of misaligning the IP
   packet in cases where compression did not occur.  To remedy this,
   I propose a Compression V2 header that is optimized for the
   case where compression does not occur.

   a. No compression occurred and first byte of IP/Ethernet packet
  is NOT 0x50 (0 bytes of overhead and maintains alignment):

[ uncompressed IP/Ethernet packet ]

   b. No compression occurred and first byte of IP/Ethernet packet
  is 0x50 (2 bytes of overhead but unlikely since no known
  IP packet can begin with 0x50):

[ 0x50 ] [ 0x00 ] [ uncompressed IP/Ethernet packet ]

   c. Compression occurred (2 bytes of overhead):

[ 0x50 ] [ compression Alg ID ] [ compressed IP/Ethernet packet ]

  Compression Alg ID is one-byte algorithm identifier
  for LZ4 (0x1), LZO (0x2), or Snappy (0x3).

   This approach has several beneficial effects:

   1. In the common case where compression does not occur, no
  compression op is required, therefore there is zero overhead.

   2. When compression does not occur, the IP/Ethernet packet
  alignment is retained.

   3. This technique does not require any byte swapping with
  the tail of the packet which can potentially incur an
  expensive cache miss.