Encrypt Open vSwitch Tunnels with IPsec

This document gives detailed description on the OVS IPsec tunnel and its configuration modes. If you want to follow a step-by-step guide to run and test IPsec tunnel, please refer to OVS IPsec Tutorial.

Overview

Why do encryption?

OVS tunnel packets are transported from one machine to another. Along the path, the packets are processed by physical routers and physical switches. There are risks that these physical devices might read or write the contents of the tunnel packets. IPsec encrypts IP payload and prevents the malicious party sniffing or manipulating the tunnel traffic.

OVS IPsec

OVS IPsec aims to provide a simple interface for user to add encryption on OVS tunnels. It supports GRE, GENEVE, VXLAN, and STT tunnel. The IPsec configuration is done by setting options of the tunnel interface and other_config of Open_vSwitch. You can choose different authentication methods and plaintext tunnel policies based on your requirements.

OVS does not currently provide any support for IPsec encryption for traffic not encapsulated in a tunnel.

Configuration

Authentication Methods

Hosts of the IPsec tunnel need to authenticate each other to build a secure channel. There are three authentication methods:

  1. You can use a pre-shared key (PSK) to do authentication. In both hosts, set the same PSK value. This PSK is like your password. You should never reveal it to untrusted parties. This method is easier to use but less secure than the certificate-based methods:

    $ ovs-vsctl add-port br0 ipsec_gre0 -- \
                set interface ipsec_gre0 type=gre \
                                   options:remote_ip=2.2.2.2 \
                                   options:psk=swordfish
    
  2. You can use a self-signed certificate to do authentication. In each host, generate a certificate and the paired private key. Copy the certificate of the remote host to the local host and configure the OVS as following:

    $ ovs-vsctl set Open_vSwitch . \
                other_config:certificate=/path/to/local_cert.pem \
                other_config:private_key=/path/to/priv_key.pem
    $ ovs-vsctl add-port br0 ipsec_gre0 -- \
                set interface ipsec_gre0 type=gre \
                               options:remote_ip=2.2.2.2 \
                               options:remote_cert=/path/to/remote_cert.pem
    

    local_cert.pem is the certificate of the local host. priv_key.pem is the private key of the local host. priv_key.pem needs to be stored in a secure location. remote_cert.pem is the certificate of the remote host.

    Note

    OVS IPsec requires x.509 version 3 certificate with the subjectAltName DNS field setting the same string as the common name (CN) field. You can follow the tutorial in OVS IPsec Tutorial and use ovs-pki(8) to generate compatible certificate and key.

    (Before OVS version 2.10.90, ovs-pki(8) did not generate x.509 v3 certificates, so if your existing PKI was generated by an older version, it is not suitable for this purpose.)

  3. You can also use CA-signed certificate to do authentication. First, you need to create a CA certificate and sign each host certificate with the CA key (please see OVS IPsec Tutorial). Copy the CA certificate to each host and configure the OVS as following:

    $ ovs-vsctl set Open_vSwitch . \
                other_config:certificate=/path/to/local_cert.pem \
                other_config:private_key=/path/to/priv_key.pem \
                other_config:ca_cert=/path/to/ca_cert.pem
    $ ovs-vsctl add-port br0 ipsec_gre0 -- \
                set interface ipsec_gre0 type=gre \
                                   options:remote_ip=2.2.2.2 \
                                   options:remote_name=remote_cn
    

    ca_cert.pem is the CA certificate. You need to set remote_cn as the common name (CN) of the remote host’s certificate so that only the certificate with the expected CN can be trusted in this connection. It is preferable to use this method than 2) if there are many remote hosts since you don’t have to copy every remote certificate to the local host.

    Note

    When using certificate-based authentication, you should not set psk in the interface options. When using psk-based authentication, you should not set certificate, private_key, ca_cert, remote_cert, and remote_name.

Plaintext Policies

When an IPsec tunnel is configured in this database, multiple independent components take responsibility for implementing it. ovs-vswitchd and its datapath handle packet forwarding to the tunnel and a separate daemon pushes the tunnel’s IPsec policy configuration to the kernel or other entity that implements it. There is a race: if the former configuration completes before the latter, then packets sent by the local host over the tunnel can be transmitted in plaintext. Using this setting, OVS users can avoid this undesirable situation.

  1. The default setting allows unencrypted packets to be sent before IPsec completes negotiation:

    $ ovs-vsctl add-port br0 ipsec_gre0 -- \
                 set interface ipsec_gre0 type=gre \
                                    options:remote_ip=2.2.2.2 \
                                    options:psk=swordfish
    

    This setting should be used only and only if tunnel configuration is static and/or if there is firewall that can drop the plain packets that occasionally leak the tunnel unencrypted on OVSDB (re)configuration events.

  2. Setiing ipsec_skb_mark drops unencrypted packets by using skb_mark of tunnel packets:

    $ ovs-vsctl set Open_vSwitch . other_config:ipsec_skb_mark=0/1
    $ ovs-vsctl add-port br0 ipsec_gre0 -- \
                set interface ipsec_gre0 type=gre \
                                   options:remote_ip=2.2.2.2 \
                                   options:psk=swordfish
    

    OVS IPsec drops unencrypted packets which carry the same skb_mark as ipsec_skb_mark. By setting the ipsec_skb_mark as 0/1, OVS IPsec prevents all unencrypted tunnel packets leaving the host since the default skb_mark value for tunnel packets are 0. This affects all OVS tunnels including those without IPsec being set up. You can install OpenFlow rules to enable those non-IPsec tunnels by setting the skb_mark of the tunnel traffic as non-zero value.

  3. Setting ipsec_skb_mark as 1/1 only drops tunnel packets with skb_mark value being 1:

    $ ovs-vsctl set Open_vSwitch . other_config:ipsec_skb_mark=1/1
    $ ovs-vsctl add-port br0 ipsec_gre0 -- \
                set interface ipsec_gre0 type=gre \
                                   options:remote_ip=2.2.2.2 \
                                   options:psk=swordfish
    

    Opposite to 2), this setting passes through unencrypted tunnel packets by default. To drop unencrypted IPsec tunnel traffic, you need to explicitly set skb_mark to a non-zero value for those tunnel traffic by installing OpenFlow rules.

Bug Reporting

If you think you may have found a bug with security implications, like

  1. IPsec protected tunnel accepted packets that came unencrypted; OR

  2. IPsec protected tunnel allowed packets to leave unencrypted

then please report such bugs according to Security Process.

If the bug does not have security implications, then report it according to instructions in Reporting Bugs.