[ovs-dev,v5,4/6] Documentation: IPsec tunnel tutorial and documentation.

Message ID 20180807164245.18639-5-qiuyu.xiao.qyx@gmail.com
State Superseded
Headers show
Series
  • IPsec support for tunneling
Related show

Commit Message

Qiuyu Xiao Aug. 7, 2018, 4:42 p.m.
tutorials/index.rst gives a step-by-setp guide to set up OVS IPsec
tunnel.

tutorials/ipsec.rst gives detailed explanation on the IPsec tunnel
configuration methods and forwarding modes.

Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>
Signed-off-by: Ansis Atteka <aatteka@ovn.org>
Co-authored-by: Ansis Atteka <aatteka@ovn.org>
---
 Documentation/automake.mk         |   2 +
 Documentation/howto/index.rst     |   1 +
 Documentation/howto/ipsec.rst     | 204 +++++++++++++++++
 Documentation/index.rst           |   3 +-
 Documentation/tutorials/index.rst |   1 +
 Documentation/tutorials/ipsec.rst | 353 ++++++++++++++++++++++++++++++
 vswitchd/vswitch.xml              | 157 ++++++++++++-
 7 files changed, 711 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/howto/ipsec.rst
 create mode 100644 Documentation/tutorials/ipsec.rst

Patch

diff --git a/Documentation/automake.mk b/Documentation/automake.mk
index 244479490..5401b9bad 100644
--- a/Documentation/automake.mk
+++ b/Documentation/automake.mk
@@ -28,6 +28,7 @@  DOC_SOURCE = \
 	Documentation/tutorials/ovn-openstack.rst \
 	Documentation/tutorials/ovn-sandbox.rst \
 	Documentation/tutorials/ovs-conntrack.rst \
+	Documentation/tutorials/ipsec.rst \
 	Documentation/topics/index.rst \
 	Documentation/topics/bonding.rst \
 	Documentation/topics/idl-compound-indexes.rst \
@@ -60,6 +61,7 @@  DOC_SOURCE = \
 	Documentation/howto/docker.rst \
 	Documentation/howto/dpdk.rst \
 	Documentation/howto/firewalld.rst \
+	Documentation/howto/ipsec.rst \
 	Documentation/howto/kvm.rst \
 	Documentation/howto/libvirt.rst \
 	Documentation/howto/selinux.rst \
diff --git a/Documentation/howto/index.rst b/Documentation/howto/index.rst
index 201d6936b..9a3487be3 100644
--- a/Documentation/howto/index.rst
+++ b/Documentation/howto/index.rst
@@ -37,6 +37,7 @@  OVS
    :maxdepth: 2
 
    kvm
+   ipsec
    selinux
    libvirt
    ssl
diff --git a/Documentation/howto/ipsec.rst b/Documentation/howto/ipsec.rst
new file mode 100644
index 000000000..d3fb190be
--- /dev/null
+++ b/Documentation/howto/ipsec.rst
@@ -0,0 +1,204 @@ 
+..
+      Licensed under the Apache License, Version 2.0 (the "License"); you may
+      not use this file except in compliance with the License. You may obtain
+      a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+      WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+      License for the specific language governing permissions and limitations
+      under the License.
+
+      Convention for heading levels in Open vSwitch documentation:
+
+      =======  Heading 0 (reserved for the title in a document)
+      -------  Heading 1
+      ~~~~~~~  Heading 2
+      +++++++  Heading 3
+      '''''''  Heading 4
+
+      Avoid deeper levels because they do not render well.
+
+=======================================
+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 :doc:`/tutorials/ipsec`.
+
+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:local_ip=1.1.1.1 \
+                                     options:remote_ip=2.2.2.2 \
+                                     options:psk=swordfish
+
+   .. note::
+
+      The ``local_ip`` field is required for the IPsec tunnel.
+
+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:local_ip=1.1.1.1 \
+                                 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 :doc:`/tutorials/ipsec` 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 :doc:`/tutorials/ipsec`). 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:local_ip=1.1.1.1 \
+                                     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:local_ip=1.1.1.1 \
+                                     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:local_ip=1.1.1.1 \
+                                    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 whitelist
+   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:local_ip=1.1.1.1 \
+                                    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 :doc:`/internals/security`.
+
+If the bug does not have security implications, then report it according to
+instructions in :doc:`/internals/bugs`.
diff --git a/Documentation/index.rst b/Documentation/index.rst
index 06602f728..bab5ba1f1 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -65,7 +65,8 @@  vSwitch? Start here.
   :doc:`tutorials/ovs-advanced` |
   :doc:`tutorials/ovn-sandbox` |
   :doc:`tutorials/ovn-openstack` |
-  :doc:`tutorials/ovs-conntrack`
+  :doc:`tutorials/ovs-conntrack` |
+  :doc:`tutorials/ipsec`
 
 Deeper Dive
 -----------
diff --git a/Documentation/tutorials/index.rst b/Documentation/tutorials/index.rst
index ab90b7c84..b481090a0 100644
--- a/Documentation/tutorials/index.rst
+++ b/Documentation/tutorials/index.rst
@@ -40,6 +40,7 @@  vSwitch.
    :maxdepth: 2
 
    faucet
+   ipsec
    ovs-advanced
    ovn-sandbox
    ovn-openstack
diff --git a/Documentation/tutorials/ipsec.rst b/Documentation/tutorials/ipsec.rst
new file mode 100644
index 000000000..492ed223c
--- /dev/null
+++ b/Documentation/tutorials/ipsec.rst
@@ -0,0 +1,353 @@ 
+..
+      Licensed under the Apache License, Version 2.0 (the "License"); you may
+      not use this file except in compliance with the License. You may obtain
+      a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+      WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+      License for the specific language governing permissions and limitations
+      under the License.
+
+      Convention for heading levels in Open vSwitch documentation:
+
+      =======  Heading 0 (reserved for the title in a document)
+      -------  Heading 1
+      ~~~~~~~  Heading 2
+      +++++++  Heading 3
+      '''''''  Heading 4
+
+      Avoid deeper levels because they do not render well.
+
+==================
+OVS IPsec Tutorial
+==================
+
+This document provides a step-by-step guide for running IPsec tunnel in Open
+vSwitch. A more detailed description on OVS IPsec tunnel and its
+configuration modes can be found in :doc:`/howto/ipsec`.
+
+Requirements
+------------
+
+OVS IPsec tunnel requires Linux kernel (>= v3.10.0) and OVS out-of-tree kernel
+module. The compatible IKE daemons are LibreSwan (>= v3.23) and StrongSwan
+(>= v5.3.5).
+
+.. _install-ovs-ipsec:
+
+Installing OVS and IPsec Packages
+---------------------------------
+
+OVS IPsec has .deb and .rpm packages. You should use the right package
+based on your Linux distribution. This tutorial uses Ubuntu 16.04 and Fedora 27
+as examples.
+
+Ubuntu
+~~~~~~
+
+1. Follow :doc:`/intro/install/debian` to build debian packages.
+
+   .. note::
+
+     If you have already installed OVS, then you only need to install
+     openvswitch-pki_*.deb and openvswitch-ipsec_*.deb in the following step.
+     If your kernel version is below v4.13.0, update your kernel to v4.13.0 or
+     above.
+
+2. Install the related packages::
+
+       $ apt-get install dkms strongswan
+       $ dpkg -i libopenvswitch_*.deb openvswitch-common_*.deb \
+             openvswitch-switch_*.deb openvswitch-datapath-dkms_*.deb \
+             python-openvswitch_*.deb openvswitch-pki_*.deb \
+             openvswitch-ipsec_*.deb
+
+   If the installation is successful, you should be able to see the
+   ovs-monitor-ipsec daemon is running in your system.
+
+Fedora
+~~~~~~
+
+1. Follow :doc:`/intro/install/fedora` to build RPM packages.
+
+2. Install the related packages::
+
+       $ dnf install python2-openvswitch libreswan \
+                     "kernel-devel-uname-r == $(uname -r)"
+       $ rpm -i openvswitch-*.rpm openvswitch-kmod-*.rpm \
+                openvswitch-openvswitch-ipsec-*.rpm
+
+3. Install firewall rules to allow ESP traffic::
+
+       $ iptables -A IN_FedoraServer_allow -p esp -j ACCEPT
+
+4. Run the openvswitch-ipsec service::
+
+       $ systemctl start openvswitch-ipsec.service
+
+   .. note::
+
+     The SELinux policies might prevent openvswitch-ipsec.service to access
+     certain resources. You can configure SELinux to remove such restrictions.
+
+Configuring IPsec tunnel
+------------------------
+
+Suppose you want to build IPsec tunnel between two hosts. Assume `host_1`'s
+external IP is 1.1.1.1, and `host_2`'s external IP is 2.2.2.2. Make sure
+`host_1` and `host_2` can ping each other via these external IPs.
+
+0. Set up some variables to make life easier.  On both hosts, set ``ip_1`` and
+   ``ip_2`` variables, e.g.::
+
+     $ ip_1=1.1.1.1
+     $ ip_2=2.2.2.2
+
+1. Set up OVS bridges in both hosts.
+
+   In `host_1`::
+
+       $ ovs-vsctl add-br br-ipsec
+       $ ip addr add 192.0.0.1/24 dev br-ipsec
+       $ ip link set br-ipsec up
+
+   In `host_2`::
+
+       $ ovs-vsctl add-br br-ipsec
+       $ ip addr add 192.0.0.2/24 dev br-ipsec
+       $ ip link set br-ipsec up
+
+2. Set up IPsec tunnel.
+
+   There are three authentication methods. You can choose one to set up your
+   IPsec tunnel.
+
+   a) Using pre-shared key:
+
+      In `host_1`::
+
+          $ ovs-vsctl add-port br-ipsec tun -- \
+                      set interface tun type=gre \
+                                    options:local_ip=$ip_1 \
+                                    options:remote_ip=$ip_2 \
+                                    options:psk=swordfish
+
+      In `host_2`::
+
+          $ ovs-vsctl add-port br-ipsec tun -- \
+                      set interface tun type=gre \
+                                    options:local_ip=$ip_2 \
+                                    options:remote_ip=$ip_1 \
+                                    options:psk=swordfish
+
+      .. note::
+
+        Pre-shared key (PSK) based authentication is easy to set up but less
+        secure compared with other authentication methods. You should use it
+        cautiously in production systems.
+
+   b) Using self-signed certificate:
+
+      Generate self-signed certificate in both `host_1` and `host_2`. Then copy
+      the certificate of `host_1` to `host_2` and the certificate of `host_2`
+      to `host_1`.
+
+      In `host_1`::
+
+          $ ovs-pki req -u host_1
+          $ ovs-pki self-sign host_1
+          $ scp host_1-cert.pem $ip_2:/etc/keys/host_1-cert.pem
+
+      In `host_2`::
+
+          $ ovs-pki req -u host_2
+          $ ovs-pki self-sign host_2
+          $ scp host_2-cert.pem $ip_1:/etc/keys/host_2-cert.pem
+
+      .. note::
+
+        If you use StrongSwan as IKE daemon, please move the host certificates
+        to /etc/ipsec.d/certs/ and private key to /etc/ipsec.d/private/ so that
+        StrongSwan has permission to access those files.
+
+      Configure IPsec tunnel to use self-signed certificates.
+
+      In `host_1`::
+
+          $ ovs-vsctl set Open_vSwitch . \
+                     other_config:certificate=/etc/keys/host_1-cert.pem \
+                     other_config:private_key=/etc/keys/host_1-privkey.pem
+          $ ovs-vsctl add-port br-ipsec tun -- \
+                      set interface tun type=gre \
+                             options:local_ip=$ip_1 \
+                             options:remote_ip=$ip_2 \
+                             options:remote_cert=/etc/keys/host_2-cert.pem
+
+      In `host_2`::
+
+          $ ovs-vsctl set Open_vSwitch . \
+                     other_config:certificate=/etc/keys/host_2-cert.pem \
+                     other_config:private_key=/etc/keys/host_2-privkey.pem
+          $ ovs-vsctl add-port br-ipsec tun -- \
+                      set interface tun type=gre \
+                             options:local_ip=$ip_2 \
+                             options:remote_ip=$ip_1 \
+                             options:remote_cert=/etc/keys/host_1-cert.pem
+
+      .. note::
+
+        The confidentiality of the private key is very critical.  Don't copy it
+        to places where it might be compromised.  (The certificate need not be
+        kept confidential.)
+
+   c) Using CA-signed certificate:
+
+      First you need to establish a public key infrastructure (PKI). Suppose
+      you choose `host_1` to host PKI.
+
+      In `host_1`::
+
+          $ ovs-pki init
+
+      Generate certificate requests and copy the certificate request of
+      `host_2` to `host_1`.
+
+      In `host_1`::
+
+          $ ovs-pki req -u host_1
+
+      In `host_2`::
+
+          $ ovs-pki req -u host_2
+          $ scp host_2-req.pem $ip_1:/etc/keys/host_2-req.pem
+
+      Sign the certificate requests with the CA key. Copy `host_2`'s signed
+      certificate and the CA certificate to `host_2`.
+
+      In `host_1`::
+
+          $ ovs-pki sign host_1 switch
+          $ ovs-pki sign host_2 switch
+          $ scp host_2-cert.pem $ip_2:/etc/keys/host_2-cert.pem
+          $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
+                    $ip_2:/etc/keys/cacert.pem
+
+      .. note::
+
+        If you use StrongSwan as IKE daemon, please move the host certificates
+        to /etc/ipsec.d/certs/, CA certificate to /etc/ipsec.d/cacerts/, and
+        private key to /etc/ipsec.d/private/ so that StrongSwan has permission
+        to access those files.
+
+      Configure IPsec tunnel to use CA-signed certificate.
+
+      In `host_1`::
+
+          $ ovs-vsctl set Open_vSwitch . \
+                  other_config:certificate=/etc/keys/host_1-cert.pem \
+                  other_config:private_key=/etc/keys/host_1-privkey.pem \
+                  other_config:ca_cert=/etc/keys/cacert.pem
+          $ ovs-vsctl add-port br-ipsec tun -- \
+                   set interface tun type=gre \
+                                 options:local_ip=$ip_1 \
+                                 options:remote_ip=$ip_2 \
+                                 options:remote_name=host_2
+
+      In `host_2`::
+
+          $ ovs-vsctl set Open_vSwitch . \
+                  other_config:certificate=/etc/keys/host_2-cert.pem \
+                  other_config:private_key=/etc/keys/host_2-privkey.pem \
+                  other_config:ca_cert=/etc/keys/cacert.pem
+          $ ovs-vsctl add-port br-ipsec tun -- \
+                   set interface tun type=gre \
+                                 options:local_ip=$ip_2 \
+                                 options:remote_ip=$ip_1 \
+                                 options:remote_name=host_1
+
+      .. note::
+
+        remote_name is the common name (CN) of the signed-certificate.  It must
+        match the name given as the argument to the ``ovs-pki sign command``.
+        It ensures that only certificate with the expected CN can be
+        authenticated; otherwise, any certificate signed by the CA would be
+        accepted.
+
+3. Test IPsec tunnel.
+
+   Now you should have an IPsec GRE tunnel running between two hosts. To verify
+   it, in `host_1`::
+
+       $ ping 192.0.0.2 &
+       $ tcpdump -ni any net $ip_2
+
+   You should be able to see that ESP packets are being sent from `host_1` to
+   `host_2`.
+
+Troubleshooting
+---------------
+
+The ``ovs-monitor-ipsec`` daemon manages and monitors the IPsec tunnel state.
+Use the following ``ovs-appctl`` command to view ``ovs-monitor-ipsec`` internal
+representation of tunnel configuration::
+
+    $ ovs-appctl -t ovs-monitor-ipsec tunnels/show
+
+If there is misconfiguration, then ``ovs-appctl`` should indicate why.
+For example::
+
+   Interface name: gre0 v5 (CONFIGURED) <--- Should be set to CONFIGURED.
+                                             Otherwise, error message will
+                                             be provided
+   Tunnel Type:    gre
+   Local IP:       1.1.1.1
+   Remote IP:      2.2.2.2
+   SKB mark:       None
+   Local cert:     None
+   Local name:     None
+   Local key:      None
+   Remote cert:    None
+   Remote name:    None
+   CA cert:        None
+   PSK:            swordfish
+   Ofport:         1          <--- Whether ovs-vswitchd has assigned Ofport
+                                   number to this Tunnel Port
+   CFM state:      Up         <--- Whether CFM declared this tunnel healthy
+   Kernel policies installed:
+   ...                          <--- IPsec policies for this OVS tunnel in
+                                     Linux Kernel installed by strongSwan
+   Kernel security associations installed:
+   ...                          <--- IPsec security associations for this OVS
+                                     tunnel in Linux Kernel installed by
+                                     strongswan
+   IPsec connections that are active:
+   ...                          <--- IPsec "connections" for this OVS
+                                     tunnel
+
+If you don't see any active connections, try to run the following command to
+refresh the ``ovs-monitor-ipsec`` daemon::
+
+    $ ovs-appctl -t ovs-monitor-ipsec refresh
+
+You can also check the logs of the ``ovs-monitor-ipsec`` daemon and the IKE
+daemon to locate issues. ``ovs-monitor-ipsec`` outputs log messages to
+/var/log/openvswitch/ovs-monitor-ipsec.log.
+
+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 report such bugs according to :doc:`/internals/security`.
+
+If bug does not have security implications, then report it according to
+instructions in :doc:`/internals/bugs`.
+
+If you have suggestions to improve this tutorial, please send a email to
+ovs-discuss@openvswitch.org.
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 634294944..e9a8d20fe 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -503,10 +503,8 @@ 
           OpenFlow specification mandates the timeout to be at least one
           second. The default is 10 seconds.
         </p>
-    </column>
-
+      </column>
     </group>
-
     <group title="Status">
       <column name="next_cfg">
         Sequence number for client to increment.  When a client modifies
@@ -770,6 +768,118 @@ 
       </column>
     </group>
 
+    <group title="IPsec">
+      <p>
+        These settings control the global configuration of IPsec tunnels.  The
+        <code>options</code> column of the <code>Interface</code> table
+        configures IPsec for individual tunnels.
+      </p>
+      <p>
+        OVS IPsec supports the following three forms of authentication.
+        Currently, all IPsec tunnels must use the same form:
+      </p>
+      <ol>
+        <li>
+          Pre-shared keys: Omit the global settings.  On each tunnel, set <ref
+          column="options" key="psk"/>.
+        </li>
+        <li>
+          Self-signed certificates: Set the <code>private_key</code> and
+          <code>certificate</code> global settings.  On each tunnel, set <ref
+          column="options" key="remote_cert"/>.  The remote certificate can be
+          self-signed.
+        </li>
+        <li>
+          CA-signed certificates: Set all of the global settings.  On each
+          tunnel, set <ref column="options" key="remote_name"/> to the common
+          name (CN) of the remote certificate. The remote certificate must be
+          signed by the CA.
+        </li>
+      </ol>
+      <column name="other_config" key="private_key"
+              type='{"type": "string"}'>
+          <p>
+            Name of a PEM file containing the private key used as the switch's
+            identity for IPsec tunnels.
+          </p>
+      </column>
+      <column name="other_config" key="certificate"
+              type='{"type": "string"}'>
+          <p>
+            Name of a PEM file containing a certificate that certifies the
+            switch's private key, and identifies a trustworthy switch for IPsec
+            tunnels. The certificate must be x.509 version 3 and with the
+            string in common name (CN) also set in the subject alternative name
+            (SAN).
+          </p>
+      </column>
+      <column name="other_config" key="ca_cert"
+              type='{"type": "string"}'>
+          <p>
+            Name of a PEM file containing the CA certificate used to verify
+            that a remote switch of the IPsec tunnel is trustworthy.
+          </p>
+      </column>
+
+      <group title="Plaintext Tunnel Policy">
+        <p>
+          When an IPsec tunnel is configured in this database, multiple
+          independent components take responsibility for implementing it.
+          <code>ovs-vswitchd</code> 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.
+        </p>
+        <column name="other_config" key="ipsec_skb_mark"
+                type='{"type": "string"}'>
+          <p>
+            This setting takes the form
+            <code><var>value</var>/<var>mask</var></code>.  If it is specified,
+            then the <code>skb_mark</code> field in every outgoing tunneled
+            packet sent in plaintext is compared against it and, if it matches,
+            the packet is dropped.  This is a global setting that is applied to
+            every tunneled packet, regardless of whether IPsec encryption is
+            enabled for the tunnel, the type of tunnel, or whether OVS is
+            involved.
+          </p>
+
+          <p>
+            Example policies:
+          </p>
+
+          <dl>
+            <dt><code>1/1</code></dt>
+            <dd>
+              Drop all unencrypted tunneled packets in which the
+              least-significant bit of <code>skb_mark</code> is 1.  This would
+              be a useful policy given an OpenFlow flow table that sets
+              <code>skb_mark</code> to 1 for traffic that should be encrypted.
+              The default <code>skb_mark</code> is 0, so this would not affect
+              other traffic.
+            </dd>
+
+            <dt><code>0/1</code></dt>
+            <dd>
+              Drop all unencrypted tunneled packets in which the
+              least-significant bit of <code>skb_mark</code> is 0.  This would
+              be a useful policy if no unencrypted tunneled traffic should exit
+              the system without being specially whitelisted by setting
+              <code>skb_mark</code> to 1.
+            </dd>
+
+            <dt>(empty)</dt>
+            <dd>
+              If this setting is empty or unset, then all unencrypted tunneled
+              packets are transmitted in the usual way.
+            </dd>
+          </dl>
+        </column>
+      </group>
+    </group>
+
     <group title="Common Columns">
       The overall purpose of these columns is described under <code>Common
       Columns</code> at the beginning of this document.
@@ -1409,7 +1519,7 @@ 
       <column name="external_ids"/>
     </group>
   </table>
-  
+
   <table name="Port" table="Port or bond configuration.">
     <p>A port within a <ref table="Bridge"/>.</p>
     <p>Most commonly, a port has exactly one ``interface,'' pointed to by its
@@ -2398,9 +2508,9 @@ 
 
       <column name="options" key="local_ip">
         <p>
-          Optional.  The tunnel destination IP that received packets must
-          match.  Default is to match all addresses.  If specified, may be one
-          of:
+          Normally optional; required for IPsec tunnels.  The tunnel
+          destination IP that received packets must match.  Default is to match
+          all addresses.  If specified, may be one of:
         </p>
 
         <ul>
@@ -2655,7 +2765,7 @@ 
 
         <column name="options" key="csum" type='{"type": "boolean"}'>
           <p>
-            Optional.  Compute encapsulation header (either GRE or UDP) 
+            Optional.  Compute encapsulation header (either GRE or UDP)
             checksums on outgoing packets.  Default is disabled, set to
             <code>true</code> to enable.  Checksums present on incoming
             packets will be validated regardless of this setting.
@@ -2673,8 +2783,37 @@ 
 
         </column>
       </group>
-    </group>
 
+      <group title="Tunnel Options: IPsec">
+        <p>
+          Setting any of these options enables IPsec support for a given
+          tunnel.  <code>gre</code>, <code>geneve</code>, <code>vxlan</code>,
+          and <code>stt</code> interfaces support these options.  See the
+          <code>IPsec</code> section in the <ref table="Open_vSwitch"/> table
+          for a description of each mode.
+        </p>
+        <column name="options" key="psk" type='{"type": "string"}'>
+          <p>
+            In PSK mode only, the preshared secret to negotiate tunnel. This
+            value must match on both tunnel ends.
+          </p>
+        </column>
+        <column name="options" key="remote_cert" type='{"type": "string"}'>
+          <p>
+            In self-signed certificate mode only, name of a PEM file
+            containing a certificate of the remote switch.  The certificate
+            must be x.509 version 3 and with the string in common name (CN)
+            also set in the subject alternative name (SAN).
+          </p>
+        </column>
+        <column name="options" key="remote_name" type='{"type": "string"}'>
+          <p>
+            In CA-signed certificate mode only, common name (CN) of the remote
+            certificate.
+          </p>
+        </column>
+      </group>
+    </group>
     <group title="Tunnel Options: erspan only">
       <p>
         Only <code>erspan</code> interfaces support these options.