[ovs-dev,v4,9/9] Documentation: OVN RBAC and IPsec tutorial
diff mbox series

Message ID 20180731210854.31682-10-qiuyu.xiao.qyx@gmail.com
State Changes Requested
Headers show
Series
  • IPsec support for tunneling
Related show

Commit Message

Qiuyu Xiao July 31, 2018, 9:08 p.m. UTC
This patch adds step-by-step guide for configuring OVN Role-Based Access
Control and IPsec.

Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>
---
 Documentation/automake.mk             |   2 +
 Documentation/tutorials/index.rst     |   2 +
 Documentation/tutorials/ovn-ipsec.rst | 144 ++++++++++++++++++++++++++
 Documentation/tutorials/ovn-rbac.rst  | 134 ++++++++++++++++++++++++
 4 files changed, 282 insertions(+)
 create mode 100644 Documentation/tutorials/ovn-ipsec.rst
 create mode 100644 Documentation/tutorials/ovn-rbac.rst

Comments

0-day Robot July 31, 2018, 10:54 p.m. UTC | #1
Bleep bloop.  Greetings Qiuyu Xiao, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


checkpatch:
WARNING: Line is 81 characters long (recommended limit is 79)
#141 FILE: Documentation/tutorials/ovn-ipsec.rst:93:
   Interface name: ovn-host_2-0 v1 (CONFIGURED) <--- Should be set to CONFIGURED.

Lines checked: 336, Warnings: 1, Errors: 0


Please check this out.  If you feel there has been an error, please email aconole@bytheb.org

Thanks,
0-day Robot
Ben Pfaff Aug. 1, 2018, 5:03 p.m. UTC | #2
On Tue, Jul 31, 2018 at 02:08:54PM -0700, Qiuyu Xiao wrote:
> This patch adds step-by-step guide for configuring OVN Role-Based Access
> Control and IPsec.
> 
> Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>

You wrote a lot of documentation, and it's really good!  Thank you.

I spent some time working to make it even better.  I'm appending an
incremental that I'd suggest folding in.  Does it make sense to you?

Thanks,

Ben.

--8<--------------------------cut here-------------------------->8--

diff --git a/Documentation/howto/ipsec.rst b/Documentation/howto/ipsec.rst
index 17dead5010cf..32e55b5acd0d 100644
--- a/Documentation/howto/ipsec.rst
+++ b/Documentation/howto/ipsec.rst
@@ -48,7 +48,10 @@ 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 fowarding modes based on your system requirement.
+and forwarding modes based on your requirements.
+
+OVS does not currently provide any support for IPsec encryption for traffic not
+encapsulated in a tunnel.
 
 Configuration
 -------------
@@ -59,7 +62,7 @@ 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 pre-shared key (PSK) to do authentication. In both hosts, set
+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::
@@ -72,9 +75,9 @@ channel. There are three authentication methods:
 
    .. note::
 
-      The local_ip field is required for the IPsec tunnel.
+      The ``local_ip`` field is required for the IPsec tunnel.
 
-2) You can use self-signed certificate to do authentication. In each host,
+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::
 
@@ -98,6 +101,10 @@ channel. There are three authentication methods:
       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
@@ -133,8 +140,8 @@ actually taking affect to encrypt packets. To offset the risk of unencrypted
 packets leaking out during this period, you can choose a more secure forwarding
 mode.  There are three forwarding modes:
 
-1) The default mode allows unencrypted packets being sent out before IPsec
-   taking effect::
+1) The default mode allows unencrypted packets to be sent before IPsec
+   completes negotiation::
 
      $ ovs-vsctl add-port br0 ipsec_gre0 -- \
                   set interface ipsec_gre0 type=gre \
@@ -146,7 +153,7 @@ mode.  There are three forwarding modes:
    and/or if there is firewall that can drop the plain packets that
    occasionally leak the tunnel unencrypted on OVSDB (re)configuration events.
 
-2) The ipsec_skb_mark mode filters unencrypted packets by using skb mark of
+2) The ipsec_skb_mark mode drops unencrypted packets by using skb_mark of
    tunnel packets::
 
      $ ovs-vsctl set Open_vSwitch . other_config:ipsec_skb_mark=0/1
@@ -156,15 +163,15 @@ mode.  There are three forwarding modes:
                                     options:remote_ip=2.2.2.2 \
                                     options:psk=swordfish
 
-   OVS IPsec filters unencrypted packets which carry the same skb mark as
+   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
+   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
+   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 filters tunnel packets with skb mark
+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
@@ -174,9 +181,9 @@ mode.  There are three forwarding modes:
                                     options:remote_ip=2.2.2.2 \
                                     options:psk=swordfish
 
-   Opposite to 2), this mode doesn't filter unencrypted tunnel packets by
-   default. To filter unencrypted IPsec tunnel traffic, you need to explicitly
-   set skb mark to a non-zero value for those tunnel traffic by installing
+   Opposite to 2), this mode 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
@@ -185,9 +192,9 @@ 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;
+2) IPsec protected tunnel allowed packets to leave unencrypted
 
-Then report such bugs according to :doc:`/internals/security`.
+then please report such bugs according to :doc:`/internals/security`.
 
-If bug does not have security implications, then report it according to
+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 06602f7289ee..bab5ba1f1a98 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/ipsec.rst b/Documentation/tutorials/ipsec.rst
index d25fcb0f717f..e78766705598 100644
--- a/Documentation/tutorials/ipsec.rst
+++ b/Documentation/tutorials/ipsec.rst
@@ -99,18 +99,24 @@ Configuring IPsec tunnel
 Suppose you want to build IPsec tunnel between two hosts. `host_1`'s external
 IP is `ip_1`. `host_2`'s external IP is `ip_2`.
 
+0. Set up some variables to make life easier.  On both hosts, set ``ip_1`` and
+   ``ip_2`` variables, e.g.::
+
+     $ ip_1=192.0.0.1
+     $ ip_2=192.0.0.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 addr $ip_1 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 addr add $ip_2 dev br-ipsec
        $ ip link set br-ipsec up
 
 2. Set up IPsec tunnel.
@@ -118,31 +124,31 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
    There are three authentication methods. You can choose one to set up your
    IPsec tunnel.
 
-   a) Using pre-shared key
+   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: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: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 system.
+        cautiously in production systems.
 
-   b) Using self-signed certificate
+   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`
@@ -152,13 +158,13 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
 
           $ ovs-pki req -u host_1
           $ ovs-pki self-sign host_1
-          $ scp host_1-cert.pem host_2@ip_2:/path/to/host_1-cert.pem
+          $ 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 host_1@ip_1:/path/to/host_2-cert.pem
+          $ scp host_2-cert.pem $ip_1:/etc/keys/host_2-cert.pem
 
       .. note::
 
@@ -166,36 +172,37 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
         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 certificate.
+      Configure IPsec tunnel to use self-signed certificates.
 
       In `host_1`::
 
           $ ovs-vsctl set Open_vSwitch . \
-                     other_config:certificate=/path/to/host_1-cert.pem \
-                     other_config:private_key=/path/to/host_1-privkey.pem
+                     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=/path/to/host_2-cert.pem
+                             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=/path/to/host_2-cert.pem \
-                     other_config:private_key=/path/to/host_2-privkey.pem
+                     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=/path/to/host_1-cert.pem
+                             options:local_ip=$ip_2 \
+                             options:remote_ip=$ip_1 \
+                             options:remote_cert=/etc/keys/host_1-cert.pem
 
       .. note::
 
-        The security of the private key is very critical. Don't copy the
-        private key to unsafe place.
+        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
+   c) Using CA-signed certificate:
 
       First you need to establish a public key infrastructure (PKI). Suppose
       you choose `host_1` to host PKI.
@@ -214,7 +221,7 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
       In `host_2`::
 
           $ ovs-pki req -u host_2
-          $ scp host_2-req.pem host_1@ip_1:/path/to/host_2-req.pem
+          $ 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`.
@@ -223,9 +230,9 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
 
           $ ovs-pki sign host_1 switch
           $ ovs-pki sign host_2 switch
-          $ scp host_2-cert.pem host_2@ip_2:/path/to/host_2-cert.pem
+          $ scp host_2-cert.pem $ip_2:/etc/keys/host_2-cert.pem
           $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
-                    host_2@ip_2:/path/to/cacert.pem
+                    $ip_2:/etc/keys/cacert.pem
 
       .. note::
 
@@ -239,40 +246,42 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
       In `host_1`::
 
           $ ovs-vsctl set Open_vSwitch . \
-                  other_config:certificate=/path/to/host_1-cert.pem \
-                  other_config:private_key=/path/to/host_1-privkey.pem \
-                  other_config:ca_cert=/path/to/cacert.pem
+                  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: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=/path/to/host_2-cert.pem \
-                  other_config:private_key=/path/to/host_2-privkey.pem \
-                  other_config:ca_cert=/path/to/cacert.pem
+                  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: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
-        should be set correctly so that only certificate with the expected CN
-        can be authenticated.
+        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
+       $ ping $ip_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`.
@@ -280,7 +289,7 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
 Troubleshooting
 ---------------
 
-Use following ovs-apptcl command to get ovs-monitor-ipsec internal
+Use following ovs-appctl command to get ovs-monitor-ipsec internal
 representation of tunnel configuration::
 
     $ ovs-appctl -t ovs-monitor-ipsec tunnels/show
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index df96f30d1146..3caef4f79539 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -770,57 +770,32 @@
 
     <group title="IPsec">
       <p>
-        The global configuration of IPsec tunnels is set in the
-        <code>other_config</code> column of the <code>Open_vSwitch</code>
-        table. The individual IPsec tunnel configuration is set in the
-        <code>options</code> column of the <code>Interface</code> table.
+        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>
-        <code>ipsec_skb_mark</code> is set to choose forwarding mode which
-        prevents unencrypted packets being sent out since there is delay
-        between the user setting up IPsec tunnel and the IPsec tunnel actually
-        taking affect to encrypt packets.
-      </p>
-      <p>
-        There are three authentication modes:
+        OVS IPsec supports the following three forms of authentication.
+        Currently, all IPsec tunnels must use the same form:
       </p>
       <ol>
         <li>
-          Pre-shared key mode: <code>private_key</code>,
-          <code>certificate</code>, and <code>ca_cert</code> must not be set.
-          <code>psk</code> in the <code>options</code> column of the
-          <code>Interface</code> table should be set as the preshared key.
+          Pre-shared keys: Omit the global settings.  On each tunnel, set <ref
+          column="options" key="psk"/>.
         </li>
         <li>
-          Self-signed certificate mode: <code>private_key</code> and
-          <code>certificate</code> must be set. <code>remote_cert</code> in the
-          <code>options</code> column of the <code>Interface</code> table must
-          be set. The remote certificate can be self-signed.
+          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 certificate mode: <code>private_key</code>,
-          <code>certificate</code>, and <code>ca_cert</code> must be set.
-          <code>remote_name</code> in the <code>options</code> column of the
-          <code>Interface</code> table must be set as the common name (CN) of
-          the remote certificate. The remote certificate must be signed by the
-          CA.
+          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="ipsec_skb_mark"
-              type='{"type": "string"}'>
-          <p>
-            Setting ipsec_skb_mark as 1/1 blocks unecrypted packets with skb
-            mark setting as 1. Besides, the OpenFlow rule with set SKB mark
-            action specified in OVSDB needs to be installed in Open_vSwitch
-            table before the first packet was able to leave the OVS tunnel.
-          </p>
-          <p>
-            Setting ipsec_skb_mark as 0/1 blocks unecrypted packets without skb
-            mark. As a result, IPsec assumes that all packets coming from
-            tunnels should be encrypted unless OpenFlow actions explicitly
-            set skb mark to a non-zero value.
-          </p>
-      </column>
       <column name="other_config" key="private_key"
               type='{"type": "string"}'>
           <p>
@@ -845,6 +820,60 @@
             that a remote switch of the IPsec tunnel is trustworthy.
           </p>
       </column>
+
+      <group title="Plaintext Tunnel Policy">
+        <p>
+          After an IPsec tunnel is configured, it takes a few round trips to
+          negotiate details of the encryption with the remote host.  In the
+          meantime, packets sent by the local host over the tunnel can be
+          transmitted in plaintext.  This setting controls the behavior in this
+          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">
@@ -2475,9 +2504,9 @@
 
       <column name="options" key="local_ip">
         <p>
-          Optional (except for IPsec tunnels).  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>
@@ -2753,28 +2782,30 @@
 
       <group title="Tunnel Options: IPsec">
         <p>
-          <code>gre</code>, <code>geneve</code>, <code>vxlan</code>, and
-          <code>stt</code> interfaces support these options.
+          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>
-            The preshared secret to negotiate tunnel in PSK mode. This value
-            must match on both tunnel ends and must be unset when
-            <code>remote_cert</code> or <code>remote_name</code>is set.
+            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>
-            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). It
-            must be unset when <code>psk</code> is set.
+            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>
-            Common name (CN) of the remote certificate. It must be unset when
-            <code>psk</code> is set.
+            In CA-signed certificate mode only, common name (CN) of the remote
+            certificate.
           </p>
         </column>
       </group>
Ben Pfaff Aug. 1, 2018, 5:04 p.m. UTC | #3
On Wed, Aug 01, 2018 at 10:03:38AM -0700, Ben Pfaff wrote:
> On Tue, Jul 31, 2018 at 02:08:54PM -0700, Qiuyu Xiao wrote:
> > This patch adds step-by-step guide for configuring OVN Role-Based Access
> > Control and IPsec.
> > 
> > Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>
> 
> You wrote a lot of documentation, and it's really good!  Thank you.
> 
> I spent some time working to make it even better.  I'm appending an
> incremental that I'd suggest folding in.  Does it make sense to you?

Oops, this was supposed to be for the patch "Documentation: IPsec tunnel
tutorial and documentation."
Qiuyu Xiao Aug. 2, 2018, 12:28 a.m. UTC | #4
Thanks Ben! I made a few comments below. Other than that, all looks pretty good!

-Qiuyu

On Wed, Aug 1, 2018 at 10:03 AM, Ben Pfaff <blp@ovn.org> wrote:
> On Tue, Jul 31, 2018 at 02:08:54PM -0700, Qiuyu Xiao wrote:
>> This patch adds step-by-step guide for configuring OVN Role-Based Access
>> Control and IPsec.
>>
>> Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>
>
> You wrote a lot of documentation, and it's really good!  Thank you.
>
> I spent some time working to make it even better.  I'm appending an
> incremental that I'd suggest folding in.  Does it make sense to you?
>
> Thanks,
>
> Ben.
>
> --8<--------------------------cut here-------------------------->8--
>
> diff --git a/Documentation/howto/ipsec.rst b/Documentation/howto/ipsec.rst
> index 17dead5010cf..32e55b5acd0d 100644
> --- a/Documentation/howto/ipsec.rst
> +++ b/Documentation/howto/ipsec.rst
> @@ -48,7 +48,10 @@ 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 fowarding modes based on your system requirement.
> +and forwarding modes based on your requirements.
> +
> +OVS does not currently provide any support for IPsec encryption for traffic not
> +encapsulated in a tunnel.
>
>  Configuration
>  -------------
> @@ -59,7 +62,7 @@ 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 pre-shared key (PSK) to do authentication. In both hosts, set
> +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::
> @@ -72,9 +75,9 @@ channel. There are three authentication methods:
>
>     .. note::
>
> -      The local_ip field is required for the IPsec tunnel.
> +      The ``local_ip`` field is required for the IPsec tunnel.
>
> -2) You can use self-signed certificate to do authentication. In each host,
> +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::
>
> @@ -98,6 +101,10 @@ channel. There are three authentication methods:
>        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
> @@ -133,8 +140,8 @@ actually taking affect to encrypt packets. To offset the risk of unencrypted
>  packets leaking out during this period, you can choose a more secure forwarding
>  mode.  There are three forwarding modes:
>
> -1) The default mode allows unencrypted packets being sent out before IPsec
> -   taking effect::
> +1) The default mode allows unencrypted packets to be sent before IPsec
> +   completes negotiation::
>
>       $ ovs-vsctl add-port br0 ipsec_gre0 -- \
>                    set interface ipsec_gre0 type=gre \
> @@ -146,7 +153,7 @@ mode.  There are three forwarding modes:
>     and/or if there is firewall that can drop the plain packets that
>     occasionally leak the tunnel unencrypted on OVSDB (re)configuration events.
>
> -2) The ipsec_skb_mark mode filters unencrypted packets by using skb mark of
> +2) The ipsec_skb_mark mode drops unencrypted packets by using skb_mark of
>     tunnel packets::
>
>       $ ovs-vsctl set Open_vSwitch . other_config:ipsec_skb_mark=0/1
> @@ -156,15 +163,15 @@ mode.  There are three forwarding modes:
>                                      options:remote_ip=2.2.2.2 \
>                                      options:psk=swordfish
>
> -   OVS IPsec filters unencrypted packets which carry the same skb mark as
> +   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
> +   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
> +   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 filters tunnel packets with skb mark
> +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
> @@ -174,9 +181,9 @@ mode.  There are three forwarding modes:
>                                      options:remote_ip=2.2.2.2 \
>                                      options:psk=swordfish
>
> -   Opposite to 2), this mode doesn't filter unencrypted tunnel packets by
> -   default. To filter unencrypted IPsec tunnel traffic, you need to explicitly
> -   set skb mark to a non-zero value for those tunnel traffic by installing
> +   Opposite to 2), this mode 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
> @@ -185,9 +192,9 @@ 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;
> +2) IPsec protected tunnel allowed packets to leave unencrypted
>
> -Then report such bugs according to :doc:`/internals/security`.
> +then please report such bugs according to :doc:`/internals/security`.
>
> -If bug does not have security implications, then report it according to
> +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 06602f7289ee..bab5ba1f1a98 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/ipsec.rst b/Documentation/tutorials/ipsec.rst
> index d25fcb0f717f..e78766705598 100644
> --- a/Documentation/tutorials/ipsec.rst
> +++ b/Documentation/tutorials/ipsec.rst
> @@ -99,18 +99,24 @@ Configuring IPsec tunnel
>  Suppose you want to build IPsec tunnel between two hosts. `host_1`'s external
>  IP is `ip_1`. `host_2`'s external IP is `ip_2`.
>
> +0. Set up some variables to make life easier.  On both hosts, set ``ip_1`` and
> +   ``ip_2`` variables, e.g.::
> +
> +     $ ip_1=192.0.0.1
> +     $ ip_2=192.0.0.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 addr $ip_1 dev br-ipsec

Needs to be $ ip addr add $ip_1/24 dev br-ipsec. Otherwise, the route
information won't be automatic added.

>         $ 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 addr add $ip_2 dev br-ipsec

Needs to be $ ip addr add $ip_2/24 dev br-ipsec. Otherwise, the route
information won't be automatic added.

>         $ ip link set br-ipsec up
>
>  2. Set up IPsec tunnel.
> @@ -118,31 +124,31 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
>     There are three authentication methods. You can choose one to set up your
>     IPsec tunnel.
>
> -   a) Using pre-shared key
> +   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:local_ip=$ip_1 \
> +                                    options:remote_ip=$ip_2 \

The predefined $ip_1 is 192.0.0.1. But here I intended to use ip_1 to
represent the external IP address which can be pinged by other hosts.
In other words, 192.0.0.1 is the inner IP and ip_1 is the outer IP.
Maybe we can use another variable to represent ip_1 and 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: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 system.
> +        cautiously in production systems.
>
> -   b) Using self-signed certificate
> +   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`
> @@ -152,13 +158,13 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
>
>            $ ovs-pki req -u host_1
>            $ ovs-pki self-sign host_1
> -          $ scp host_1-cert.pem host_2@ip_2:/path/to/host_1-cert.pem
> +          $ 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 host_1@ip_1:/path/to/host_2-cert.pem
> +          $ scp host_2-cert.pem $ip_1:/etc/keys/host_2-cert.pem
>
>        .. note::
>
> @@ -166,36 +172,37 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
>          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 certificate.
> +      Configure IPsec tunnel to use self-signed certificates.
>
>        In `host_1`::
>
>            $ ovs-vsctl set Open_vSwitch . \
> -                     other_config:certificate=/path/to/host_1-cert.pem \
> -                     other_config:private_key=/path/to/host_1-privkey.pem
> +                     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=/path/to/host_2-cert.pem
> +                             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=/path/to/host_2-cert.pem \
> -                     other_config:private_key=/path/to/host_2-privkey.pem
> +                     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=/path/to/host_1-cert.pem
> +                             options:local_ip=$ip_2 \
> +                             options:remote_ip=$ip_1 \
> +                             options:remote_cert=/etc/keys/host_1-cert.pem
>
>        .. note::
>
> -        The security of the private key is very critical. Don't copy the
> -        private key to unsafe place.
> +        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
> +   c) Using CA-signed certificate:
>
>        First you need to establish a public key infrastructure (PKI). Suppose
>        you choose `host_1` to host PKI.
> @@ -214,7 +221,7 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
>        In `host_2`::
>
>            $ ovs-pki req -u host_2
> -          $ scp host_2-req.pem host_1@ip_1:/path/to/host_2-req.pem
> +          $ 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`.
> @@ -223,9 +230,9 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
>
>            $ ovs-pki sign host_1 switch
>            $ ovs-pki sign host_2 switch
> -          $ scp host_2-cert.pem host_2@ip_2:/path/to/host_2-cert.pem
> +          $ scp host_2-cert.pem $ip_2:/etc/keys/host_2-cert.pem
>            $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
> -                    host_2@ip_2:/path/to/cacert.pem
> +                    $ip_2:/etc/keys/cacert.pem
>
>        .. note::
>
> @@ -239,40 +246,42 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
>        In `host_1`::
>
>            $ ovs-vsctl set Open_vSwitch . \
> -                  other_config:certificate=/path/to/host_1-cert.pem \
> -                  other_config:private_key=/path/to/host_1-privkey.pem \
> -                  other_config:ca_cert=/path/to/cacert.pem
> +                  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: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=/path/to/host_2-cert.pem \
> -                  other_config:private_key=/path/to/host_2-privkey.pem \
> -                  other_config:ca_cert=/path/to/cacert.pem
> +                  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: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
> -        should be set correctly so that only certificate with the expected CN
> -        can be authenticated.
> +        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
> +       $ ping $ip_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`.
> @@ -280,7 +289,7 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
>  Troubleshooting
>  ---------------
>
> -Use following ovs-apptcl command to get ovs-monitor-ipsec internal
> +Use following ovs-appctl command to get ovs-monitor-ipsec internal
>  representation of tunnel configuration::
>
>      $ ovs-appctl -t ovs-monitor-ipsec tunnels/show
> diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
> index df96f30d1146..3caef4f79539 100644
> --- a/vswitchd/vswitch.xml
> +++ b/vswitchd/vswitch.xml
> @@ -770,57 +770,32 @@
>
>      <group title="IPsec">
>        <p>
> -        The global configuration of IPsec tunnels is set in the
> -        <code>other_config</code> column of the <code>Open_vSwitch</code>
> -        table. The individual IPsec tunnel configuration is set in the
> -        <code>options</code> column of the <code>Interface</code> table.
> +        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>
> -        <code>ipsec_skb_mark</code> is set to choose forwarding mode which
> -        prevents unencrypted packets being sent out since there is delay
> -        between the user setting up IPsec tunnel and the IPsec tunnel actually
> -        taking affect to encrypt packets.
> -      </p>
> -      <p>
> -        There are three authentication modes:
> +        OVS IPsec supports the following three forms of authentication.
> +        Currently, all IPsec tunnels must use the same form:
>        </p>
>        <ol>
>          <li>
> -          Pre-shared key mode: <code>private_key</code>,
> -          <code>certificate</code>, and <code>ca_cert</code> must not be set.
> -          <code>psk</code> in the <code>options</code> column of the
> -          <code>Interface</code> table should be set as the preshared key.
> +          Pre-shared keys: Omit the global settings.  On each tunnel, set <ref
> +          column="options" key="psk"/>.
>          </li>
>          <li>
> -          Self-signed certificate mode: <code>private_key</code> and
> -          <code>certificate</code> must be set. <code>remote_cert</code> in the
> -          <code>options</code> column of the <code>Interface</code> table must
> -          be set. The remote certificate can be self-signed.
> +          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 certificate mode: <code>private_key</code>,
> -          <code>certificate</code>, and <code>ca_cert</code> must be set.
> -          <code>remote_name</code> in the <code>options</code> column of the
> -          <code>Interface</code> table must be set as the common name (CN) of
> -          the remote certificate. The remote certificate must be signed by the
> -          CA.
> +          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="ipsec_skb_mark"
> -              type='{"type": "string"}'>
> -          <p>
> -            Setting ipsec_skb_mark as 1/1 blocks unecrypted packets with skb
> -            mark setting as 1. Besides, the OpenFlow rule with set SKB mark
> -            action specified in OVSDB needs to be installed in Open_vSwitch
> -            table before the first packet was able to leave the OVS tunnel.
> -          </p>
> -          <p>
> -            Setting ipsec_skb_mark as 0/1 blocks unecrypted packets without skb
> -            mark. As a result, IPsec assumes that all packets coming from
> -            tunnels should be encrypted unless OpenFlow actions explicitly
> -            set skb mark to a non-zero value.
> -          </p>
> -      </column>
>        <column name="other_config" key="private_key"
>                type='{"type": "string"}'>
>            <p>
> @@ -845,6 +820,60 @@
>              that a remote switch of the IPsec tunnel is trustworthy.
>            </p>
>        </column>
> +
> +      <group title="Plaintext Tunnel Policy">
> +        <p>
> +          After an IPsec tunnel is configured, it takes a few round trips to
> +          negotiate details of the encryption with the remote host.  In the
> +          meantime, packets sent by the local host over the tunnel can be
> +          transmitted in plaintext.  This setting controls the behavior in this
> +          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">
> @@ -2475,9 +2504,9 @@
>
>        <column name="options" key="local_ip">
>          <p>
> -          Optional (except for IPsec tunnels).  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>
> @@ -2753,28 +2782,30 @@
>
>        <group title="Tunnel Options: IPsec">
>          <p>
> -          <code>gre</code>, <code>geneve</code>, <code>vxlan</code>, and
> -          <code>stt</code> interfaces support these options.
> +          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>
> -            The preshared secret to negotiate tunnel in PSK mode. This value
> -            must match on both tunnel ends and must be unset when
> -            <code>remote_cert</code> or <code>remote_name</code>is set.
> +            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>
> -            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). It
> -            must be unset when <code>psk</code> is set.
> +            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>
> -            Common name (CN) of the remote certificate. It must be unset when
> -            <code>psk</code> is set.
> +            In CA-signed certificate mode only, common name (CN) of the remote
> +            certificate.
>            </p>
>          </column>
>        </group>
Ben Pfaff Aug. 2, 2018, 6:32 p.m. UTC | #5
Thanks for the comments.  Can you integrate my suggestions and your
comments for v5?

Thanks,

Ben.

On Wed, Aug 01, 2018 at 05:28:02PM -0700, Qiuyu Xiao wrote:
> Thanks Ben! I made a few comments below. Other than that, all looks pretty good!
> 
> -Qiuyu
> 
> On Wed, Aug 1, 2018 at 10:03 AM, Ben Pfaff <blp@ovn.org> wrote:
> > On Tue, Jul 31, 2018 at 02:08:54PM -0700, Qiuyu Xiao wrote:
> >> This patch adds step-by-step guide for configuring OVN Role-Based Access
> >> Control and IPsec.
> >>
> >> Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>
> >
> > You wrote a lot of documentation, and it's really good!  Thank you.
> >
> > I spent some time working to make it even better.  I'm appending an
> > incremental that I'd suggest folding in.  Does it make sense to you?
> >
> > Thanks,
> >
> > Ben.
> >
> > --8<--------------------------cut here-------------------------->8--
> >
> > diff --git a/Documentation/howto/ipsec.rst b/Documentation/howto/ipsec.rst
> > index 17dead5010cf..32e55b5acd0d 100644
> > --- a/Documentation/howto/ipsec.rst
> > +++ b/Documentation/howto/ipsec.rst
> > @@ -48,7 +48,10 @@ 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 fowarding modes based on your system requirement.
> > +and forwarding modes based on your requirements.
> > +
> > +OVS does not currently provide any support for IPsec encryption for traffic not
> > +encapsulated in a tunnel.
> >
> >  Configuration
> >  -------------
> > @@ -59,7 +62,7 @@ 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 pre-shared key (PSK) to do authentication. In both hosts, set
> > +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::
> > @@ -72,9 +75,9 @@ channel. There are three authentication methods:
> >
> >     .. note::
> >
> > -      The local_ip field is required for the IPsec tunnel.
> > +      The ``local_ip`` field is required for the IPsec tunnel.
> >
> > -2) You can use self-signed certificate to do authentication. In each host,
> > +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::
> >
> > @@ -98,6 +101,10 @@ channel. There are three authentication methods:
> >        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
> > @@ -133,8 +140,8 @@ actually taking affect to encrypt packets. To offset the risk of unencrypted
> >  packets leaking out during this period, you can choose a more secure forwarding
> >  mode.  There are three forwarding modes:
> >
> > -1) The default mode allows unencrypted packets being sent out before IPsec
> > -   taking effect::
> > +1) The default mode allows unencrypted packets to be sent before IPsec
> > +   completes negotiation::
> >
> >       $ ovs-vsctl add-port br0 ipsec_gre0 -- \
> >                    set interface ipsec_gre0 type=gre \
> > @@ -146,7 +153,7 @@ mode.  There are three forwarding modes:
> >     and/or if there is firewall that can drop the plain packets that
> >     occasionally leak the tunnel unencrypted on OVSDB (re)configuration events.
> >
> > -2) The ipsec_skb_mark mode filters unencrypted packets by using skb mark of
> > +2) The ipsec_skb_mark mode drops unencrypted packets by using skb_mark of
> >     tunnel packets::
> >
> >       $ ovs-vsctl set Open_vSwitch . other_config:ipsec_skb_mark=0/1
> > @@ -156,15 +163,15 @@ mode.  There are three forwarding modes:
> >                                      options:remote_ip=2.2.2.2 \
> >                                      options:psk=swordfish
> >
> > -   OVS IPsec filters unencrypted packets which carry the same skb mark as
> > +   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
> > +   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
> > +   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 filters tunnel packets with skb mark
> > +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
> > @@ -174,9 +181,9 @@ mode.  There are three forwarding modes:
> >                                      options:remote_ip=2.2.2.2 \
> >                                      options:psk=swordfish
> >
> > -   Opposite to 2), this mode doesn't filter unencrypted tunnel packets by
> > -   default. To filter unencrypted IPsec tunnel traffic, you need to explicitly
> > -   set skb mark to a non-zero value for those tunnel traffic by installing
> > +   Opposite to 2), this mode 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
> > @@ -185,9 +192,9 @@ 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;
> > +2) IPsec protected tunnel allowed packets to leave unencrypted
> >
> > -Then report such bugs according to :doc:`/internals/security`.
> > +then please report such bugs according to :doc:`/internals/security`.
> >
> > -If bug does not have security implications, then report it according to
> > +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 06602f7289ee..bab5ba1f1a98 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/ipsec.rst b/Documentation/tutorials/ipsec.rst
> > index d25fcb0f717f..e78766705598 100644
> > --- a/Documentation/tutorials/ipsec.rst
> > +++ b/Documentation/tutorials/ipsec.rst
> > @@ -99,18 +99,24 @@ Configuring IPsec tunnel
> >  Suppose you want to build IPsec tunnel between two hosts. `host_1`'s external
> >  IP is `ip_1`. `host_2`'s external IP is `ip_2`.
> >
> > +0. Set up some variables to make life easier.  On both hosts, set ``ip_1`` and
> > +   ``ip_2`` variables, e.g.::
> > +
> > +     $ ip_1=192.0.0.1
> > +     $ ip_2=192.0.0.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 addr $ip_1 dev br-ipsec
> 
> Needs to be $ ip addr add $ip_1/24 dev br-ipsec. Otherwise, the route
> information won't be automatic added.
> 
> >         $ 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 addr add $ip_2 dev br-ipsec
> 
> Needs to be $ ip addr add $ip_2/24 dev br-ipsec. Otherwise, the route
> information won't be automatic added.
> 
> >         $ ip link set br-ipsec up
> >
> >  2. Set up IPsec tunnel.
> > @@ -118,31 +124,31 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
> >     There are three authentication methods. You can choose one to set up your
> >     IPsec tunnel.
> >
> > -   a) Using pre-shared key
> > +   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:local_ip=$ip_1 \
> > +                                    options:remote_ip=$ip_2 \
> 
> The predefined $ip_1 is 192.0.0.1. But here I intended to use ip_1 to
> represent the external IP address which can be pinged by other hosts.
> In other words, 192.0.0.1 is the inner IP and ip_1 is the outer IP.
> Maybe we can use another variable to represent ip_1 and 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: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 system.
> > +        cautiously in production systems.
> >
> > -   b) Using self-signed certificate
> > +   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`
> > @@ -152,13 +158,13 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
> >
> >            $ ovs-pki req -u host_1
> >            $ ovs-pki self-sign host_1
> > -          $ scp host_1-cert.pem host_2@ip_2:/path/to/host_1-cert.pem
> > +          $ 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 host_1@ip_1:/path/to/host_2-cert.pem
> > +          $ scp host_2-cert.pem $ip_1:/etc/keys/host_2-cert.pem
> >
> >        .. note::
> >
> > @@ -166,36 +172,37 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
> >          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 certificate.
> > +      Configure IPsec tunnel to use self-signed certificates.
> >
> >        In `host_1`::
> >
> >            $ ovs-vsctl set Open_vSwitch . \
> > -                     other_config:certificate=/path/to/host_1-cert.pem \
> > -                     other_config:private_key=/path/to/host_1-privkey.pem
> > +                     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=/path/to/host_2-cert.pem
> > +                             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=/path/to/host_2-cert.pem \
> > -                     other_config:private_key=/path/to/host_2-privkey.pem
> > +                     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=/path/to/host_1-cert.pem
> > +                             options:local_ip=$ip_2 \
> > +                             options:remote_ip=$ip_1 \
> > +                             options:remote_cert=/etc/keys/host_1-cert.pem
> >
> >        .. note::
> >
> > -        The security of the private key is very critical. Don't copy the
> > -        private key to unsafe place.
> > +        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
> > +   c) Using CA-signed certificate:
> >
> >        First you need to establish a public key infrastructure (PKI). Suppose
> >        you choose `host_1` to host PKI.
> > @@ -214,7 +221,7 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
> >        In `host_2`::
> >
> >            $ ovs-pki req -u host_2
> > -          $ scp host_2-req.pem host_1@ip_1:/path/to/host_2-req.pem
> > +          $ 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`.
> > @@ -223,9 +230,9 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
> >
> >            $ ovs-pki sign host_1 switch
> >            $ ovs-pki sign host_2 switch
> > -          $ scp host_2-cert.pem host_2@ip_2:/path/to/host_2-cert.pem
> > +          $ scp host_2-cert.pem $ip_2:/etc/keys/host_2-cert.pem
> >            $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
> > -                    host_2@ip_2:/path/to/cacert.pem
> > +                    $ip_2:/etc/keys/cacert.pem
> >
> >        .. note::
> >
> > @@ -239,40 +246,42 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
> >        In `host_1`::
> >
> >            $ ovs-vsctl set Open_vSwitch . \
> > -                  other_config:certificate=/path/to/host_1-cert.pem \
> > -                  other_config:private_key=/path/to/host_1-privkey.pem \
> > -                  other_config:ca_cert=/path/to/cacert.pem
> > +                  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: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=/path/to/host_2-cert.pem \
> > -                  other_config:private_key=/path/to/host_2-privkey.pem \
> > -                  other_config:ca_cert=/path/to/cacert.pem
> > +                  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: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
> > -        should be set correctly so that only certificate with the expected CN
> > -        can be authenticated.
> > +        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
> > +       $ ping $ip_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`.
> > @@ -280,7 +289,7 @@ IP is `ip_1`. `host_2`'s external IP is `ip_2`.
> >  Troubleshooting
> >  ---------------
> >
> > -Use following ovs-apptcl command to get ovs-monitor-ipsec internal
> > +Use following ovs-appctl command to get ovs-monitor-ipsec internal
> >  representation of tunnel configuration::
> >
> >      $ ovs-appctl -t ovs-monitor-ipsec tunnels/show
> > diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
> > index df96f30d1146..3caef4f79539 100644
> > --- a/vswitchd/vswitch.xml
> > +++ b/vswitchd/vswitch.xml
> > @@ -770,57 +770,32 @@
> >
> >      <group title="IPsec">
> >        <p>
> > -        The global configuration of IPsec tunnels is set in the
> > -        <code>other_config</code> column of the <code>Open_vSwitch</code>
> > -        table. The individual IPsec tunnel configuration is set in the
> > -        <code>options</code> column of the <code>Interface</code> table.
> > +        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>
> > -        <code>ipsec_skb_mark</code> is set to choose forwarding mode which
> > -        prevents unencrypted packets being sent out since there is delay
> > -        between the user setting up IPsec tunnel and the IPsec tunnel actually
> > -        taking affect to encrypt packets.
> > -      </p>
> > -      <p>
> > -        There are three authentication modes:
> > +        OVS IPsec supports the following three forms of authentication.
> > +        Currently, all IPsec tunnels must use the same form:
> >        </p>
> >        <ol>
> >          <li>
> > -          Pre-shared key mode: <code>private_key</code>,
> > -          <code>certificate</code>, and <code>ca_cert</code> must not be set.
> > -          <code>psk</code> in the <code>options</code> column of the
> > -          <code>Interface</code> table should be set as the preshared key.
> > +          Pre-shared keys: Omit the global settings.  On each tunnel, set <ref
> > +          column="options" key="psk"/>.
> >          </li>
> >          <li>
> > -          Self-signed certificate mode: <code>private_key</code> and
> > -          <code>certificate</code> must be set. <code>remote_cert</code> in the
> > -          <code>options</code> column of the <code>Interface</code> table must
> > -          be set. The remote certificate can be self-signed.
> > +          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 certificate mode: <code>private_key</code>,
> > -          <code>certificate</code>, and <code>ca_cert</code> must be set.
> > -          <code>remote_name</code> in the <code>options</code> column of the
> > -          <code>Interface</code> table must be set as the common name (CN) of
> > -          the remote certificate. The remote certificate must be signed by the
> > -          CA.
> > +          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="ipsec_skb_mark"
> > -              type='{"type": "string"}'>
> > -          <p>
> > -            Setting ipsec_skb_mark as 1/1 blocks unecrypted packets with skb
> > -            mark setting as 1. Besides, the OpenFlow rule with set SKB mark
> > -            action specified in OVSDB needs to be installed in Open_vSwitch
> > -            table before the first packet was able to leave the OVS tunnel.
> > -          </p>
> > -          <p>
> > -            Setting ipsec_skb_mark as 0/1 blocks unecrypted packets without skb
> > -            mark. As a result, IPsec assumes that all packets coming from
> > -            tunnels should be encrypted unless OpenFlow actions explicitly
> > -            set skb mark to a non-zero value.
> > -          </p>
> > -      </column>
> >        <column name="other_config" key="private_key"
> >                type='{"type": "string"}'>
> >            <p>
> > @@ -845,6 +820,60 @@
> >              that a remote switch of the IPsec tunnel is trustworthy.
> >            </p>
> >        </column>
> > +
> > +      <group title="Plaintext Tunnel Policy">
> > +        <p>
> > +          After an IPsec tunnel is configured, it takes a few round trips to
> > +          negotiate details of the encryption with the remote host.  In the
> > +          meantime, packets sent by the local host over the tunnel can be
> > +          transmitted in plaintext.  This setting controls the behavior in this
> > +          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">
> > @@ -2475,9 +2504,9 @@
> >
> >        <column name="options" key="local_ip">
> >          <p>
> > -          Optional (except for IPsec tunnels).  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>
> > @@ -2753,28 +2782,30 @@
> >
> >        <group title="Tunnel Options: IPsec">
> >          <p>
> > -          <code>gre</code>, <code>geneve</code>, <code>vxlan</code>, and
> > -          <code>stt</code> interfaces support these options.
> > +          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>
> > -            The preshared secret to negotiate tunnel in PSK mode. This value
> > -            must match on both tunnel ends and must be unset when
> > -            <code>remote_cert</code> or <code>remote_name</code>is set.
> > +            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>
> > -            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). It
> > -            must be unset when <code>psk</code> is set.
> > +            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>
> > -            Common name (CN) of the remote certificate. It must be unset when
> > -            <code>psk</code> is set.
> > +            In CA-signed certificate mode only, common name (CN) of the remote
> > +            certificate.
> >            </p>
> >          </column>
> >        </group>
Ben Pfaff Aug. 2, 2018, 6:46 p.m. UTC | #6
On Tue, Jul 31, 2018 at 02:08:54PM -0700, Qiuyu Xiao wrote:
> This patch adds step-by-step guide for configuring OVN Role-Based Access
> Control and IPsec.
> 
> Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>

Here are my suggestions for this patch (really for this one, this time).

I'll look forward to v5 of this series!

Thanks,

Ben.

--8<--------------------------cut here-------------------------->8--

diff --git a/Documentation/index.rst b/Documentation/index.rst
index bab5ba1f1a98..46261235c732 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -66,7 +66,9 @@ vSwitch? Start here.
   :doc:`tutorials/ovn-sandbox` |
   :doc:`tutorials/ovn-openstack` |
   :doc:`tutorials/ovs-conntrack` |
-  :doc:`tutorials/ipsec`
+  :doc:`tutorials/ipsec` |
+  :doc:`tutorials/ovn-ipsec` |
+  :doc:`tutorials/ovn-rbac`
 
 Deeper Dive
 -----------
diff --git a/Documentation/tutorials/ovn-ipsec.rst b/Documentation/tutorials/ovn-ipsec.rst
index 76269c46a784..5a8701905fa1 100644
--- a/Documentation/tutorials/ovn-ipsec.rst
+++ b/Documentation/tutorials/ovn-ipsec.rst
@@ -43,15 +43,17 @@ Generating Certificates and Keys
 OVN chassis uses CA-signed certificate to authenticate peer chassis for
 building IPsec tunnel. If you have enabled Role-Based Access Control (RBAC) in
 OVN, you can use the RBAC SSL certificates and keys to set up OVN IPsec. Or you
-can generate seperate certificates and keys with ``ovs-pki`` (refer to
+can generate separate certificates and keys with ``ovs-pki`` (refer to
 :ref:`gen-certs-keys`).
 
 .. note::
 
    OVN IPsec requires x.509 version 3 certificate with the subjectAltName DNS
    field setting the same string as the common name (CN) field. CN should be
-   set as the chassis name.  Please generate compatible certificates if you use
-   another PKI tool to manage certificates.
+   set as the chassis name.  ``ovs-pki`` in Open vSwitch 2.10.90 and later
+   generates such certificates.  Please generate compatible certificates if you
+   use another PKI tool, or an older version of ``ovs-pki``, to manage
+   certificates.
 
 Configuring OVN IPsec
 ---------------------
@@ -67,27 +69,27 @@ each chassis. Use the following command::
 Enabling OVN IPsec
 ------------------
 
-To enable OVN IPsec, set `ipsec` column in `NB_Global` table of the northbound
-database to be true::
+To enable OVN IPsec, set ``ipsec`` column in ``NB_Global`` table of the
+northbound database to true::
 
     $ ovn-nbctl set nb_global . ipsec=true
 
 With OVN IPsec enabled, all tunnel traffic in OVN will be encrypted with IPsec.
-To disable it, set `ipsec` column in `NB_Global` table of the northbound
-database to be false::
+To disable it, set ``ipsec`` column in ``NB_Global`` table of the northbound
+database to false::
 
     $ ovn-nbctl set nb_global . ipsec=false
 
 Troubleshooting
 ---------------
 
-ovs-monitor-ipsec daemon in each chassis manages and monitors the IPsec tunnel
-state. Use the following ovs-apptcl command to get ovs-monitor-ipsec internal
-representation of tunnel configuration::
+The ``ovs-monitor-ipsec`` daemon in each chassis 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.
+If there is a misconfiguration, then ``ovs-appctl`` should indicate why.
 For example::
 
    Interface name: ovn-host_2-0 v1 (CONFIGURED) <--- Should be set to CONFIGURED.
@@ -119,13 +121,13 @@ For example::
                                      tunnel
 
 If you don't see any active connections, try to run the following command to
-refresh the ovs-monitor-ipsec daemon::
+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. The logs of the ovs-monitor-ipsec is in
-/var/log/openvswitch/ovs-monitor-ipsec.log.
+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
 -------------
diff --git a/Documentation/tutorials/ovn-rbac.rst b/Documentation/tutorials/ovn-rbac.rst
index ff93ba54bdc6..ec163e2df369 100644
--- a/Documentation/tutorials/ovn-rbac.rst
+++ b/Documentation/tutorials/ovn-rbac.rst
@@ -81,7 +81,7 @@ address `machine_3-ip`. `machine_3` also hosts public key infrastructure (PKI).
 
    .. note::
 
-     chassis_1 must be the same string as the external_ids:system-id in the
+     chassis_1 must be the same string as ``external_ids:system-id`` in the
      Open_vSwitch table (the chassis name) of machine_1. Same applies for
      chassis_2.

Patch
diff mbox series

diff --git a/Documentation/automake.mk b/Documentation/automake.mk
index 5401b9bad..082438e09 100644
--- a/Documentation/automake.mk
+++ b/Documentation/automake.mk
@@ -29,6 +29,8 @@  DOC_SOURCE = \
 	Documentation/tutorials/ovn-sandbox.rst \
 	Documentation/tutorials/ovs-conntrack.rst \
 	Documentation/tutorials/ipsec.rst \
+	Documentation/tutorials/ovn-ipsec.rst \
+	Documentation/tutorials/ovn-rbac.rst \
 	Documentation/topics/index.rst \
 	Documentation/topics/bonding.rst \
 	Documentation/topics/idl-compound-indexes.rst \
diff --git a/Documentation/tutorials/index.rst b/Documentation/tutorials/index.rst
index b481090a0..35340ee56 100644
--- a/Documentation/tutorials/index.rst
+++ b/Documentation/tutorials/index.rst
@@ -44,4 +44,6 @@  vSwitch.
    ovs-advanced
    ovn-sandbox
    ovn-openstack
+   ovn-rbac
+   ovn-ipsec
    ovs-conntrack
diff --git a/Documentation/tutorials/ovn-ipsec.rst b/Documentation/tutorials/ovn-ipsec.rst
new file mode 100644
index 000000000..76269c46a
--- /dev/null
+++ b/Documentation/tutorials/ovn-ipsec.rst
@@ -0,0 +1,144 @@ 
+..
+      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.
+
+==================
+OVN IPsec Tutorial
+==================
+
+This document provides a step-by-step guide for encrypting tunnel traffic with
+IPsec in Open Virtual Network (OVN). OVN tunnel traffic is transported by
+physical routers and switches. These physical devices could be untrusted
+(devices in public network) or might be compromised.  Enabling IPsec encryption
+for the tunnel traffic can prevent the traffic data from being monitored and
+manipulated. More details about the OVN IPsec design can be found in
+``ovn-architecture``\(7) manpage.
+
+This document assumes OVN is installed in your system and runs normally. Also,
+you need to install OVS IPsec packages in each chassis (refer to
+:ref:`install-ovs-ipsec`).
+
+Generating Certificates and Keys
+--------------------------------
+
+OVN chassis uses CA-signed certificate to authenticate peer chassis for
+building IPsec tunnel. If you have enabled Role-Based Access Control (RBAC) in
+OVN, you can use the RBAC SSL certificates and keys to set up OVN IPsec. Or you
+can generate seperate certificates and keys with ``ovs-pki`` (refer to
+:ref:`gen-certs-keys`).
+
+.. note::
+
+   OVN IPsec requires x.509 version 3 certificate with the subjectAltName DNS
+   field setting the same string as the common name (CN) field. CN should be
+   set as the chassis name.  Please generate compatible certificates if you use
+   another PKI tool to manage certificates.
+
+Configuring OVN IPsec
+---------------------
+
+You need to install the CA certificate, chassis certificate and private key in
+each chassis. Use the following command::
+
+    $ ovs-vsctl set Open_vSwitch . \
+            other_config:certificate=/path/to/chassis-cert.pem \
+            other_config:private_key=/path/to/chassis-privkey.pem \
+            other_config:ca_cert=/path/to/cacert.pem
+
+Enabling OVN IPsec
+------------------
+
+To enable OVN IPsec, set `ipsec` column in `NB_Global` table of the northbound
+database to be true::
+
+    $ ovn-nbctl set nb_global . ipsec=true
+
+With OVN IPsec enabled, all tunnel traffic in OVN will be encrypted with IPsec.
+To disable it, set `ipsec` column in `NB_Global` table of the northbound
+database to be false::
+
+    $ ovn-nbctl set nb_global . ipsec=false
+
+Troubleshooting
+---------------
+
+ovs-monitor-ipsec daemon in each chassis manages and monitors the IPsec tunnel
+state. Use the following ovs-apptcl command to get 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: ovn-host_2-0 v1 (CONFIGURED) <--- Should be set to CONFIGURED.
+                                             Otherwise, error message will
+                                             be provided
+   Tunnel Type:    geneve
+   Local IP:       1.1.1.1
+   Remote IP:      2.2.2.2
+   SKB mark:       None
+   Local cert:     /path/to/chassis-cert.pem
+   Local name:     host_1
+   Local key:      /path/to/chassis-privkey.pem
+   Remote cert:    None
+   Remote name:    host_2
+   CA cert:        /path/to/cacert.pem
+   PSK:            None
+   Ofport:         2          <--- Whether ovs-vswitchd has assigned Ofport
+                                   number to this Tunnel Port
+   CFM state:      Disabled     <--- 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. The logs of the ovs-monitor-ipsec is in
+/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/Documentation/tutorials/ovn-rbac.rst b/Documentation/tutorials/ovn-rbac.rst
new file mode 100644
index 000000000..ff93ba54b
--- /dev/null
+++ b/Documentation/tutorials/ovn-rbac.rst
@@ -0,0 +1,134 @@ 
+..
+      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.
+
+=============================================
+OVN Role-Based Access Control (RBAC) Tutorial
+=============================================
+
+This document provides a step-by-step guide for setting up role-based access
+control (RBAC) in OVN. In OVN, hypervisors (chassis) read and write the
+southbound database to do configuration. Without restricting hypervisor's
+access to the southbound database, a compromised hypervisor might disrupt the
+entire OVN deployment by corrupting the database. RBAC ensures that each
+hypervisor can only modify its own data and thus improves the security of OVN.
+More details about the RBAC design can be found in ``ovn-architecture``\(7)
+manpage.
+
+This document assumes OVN is installed in your system and runs normally.
+
+.. _gen-certs-keys:
+
+Generating Certificates and Keys
+--------------------------------
+
+In the OVN RBAC deployment, ovn-controller connects to the southbound database
+via SSL connection. The southbound database uses CA-signed certificate to
+authenticate ovn-controller.
+
+Suppose there are three machines in your deployment. `machine_1` runs
+`chassis_1` and has IP address `machine_1-ip`. `machine_2` runs `chassis_2` and
+has IP address `machine_2-ip`. `machine_3` hosts southbound database and has IP
+address `machine_3-ip`. `machine_3` also hosts public key infrastructure (PKI).
+
+1. Initiate PKI.
+
+   In `machine_3`::
+
+      $ ovs-pki init
+
+2. Generate southbound database's certificate request. Sign the certificate
+   request with the CA key.
+
+   In `machine_3`::
+
+      $ ovs-pki req -u sbdb
+      $ ovs-pki sign sbdb switch
+
+3. Generate chassis certificate requests. Copy the certificate requests to
+   `machine_3`.
+
+   In `machine_1`::
+
+      $ ovs-pki req -u chassis_1
+      $ scp chassis_1-req.pem \
+                    machine_3@machine_3-ip:/path/to/chassis_1-req.pem
+
+   In `machine_2`::
+
+      $ ovs-pki req -u chassis_2
+      $ scp chassis_2-req.pem \
+                    machine_3@machine_3-ip:/path/to/chassis_2-req.pem
+
+   .. note::
+
+     chassis_1 must be the same string as the external_ids:system-id in the
+     Open_vSwitch table (the chassis name) of machine_1. Same applies for
+     chassis_2.
+
+4. Sign the chassis certificate requests with the CA key. Copy `chassis_1`'s
+   signed certificate and the CA certificate to `machine_1`. Copy `chassis_2`'s
+   signed certificate and the CA certificate to `machine_2`.
+
+   In `machine_3`::
+
+      $ ovs-pki sign chassis_1 switch
+      $ ovs-pki sign chassis_2 switch
+      $ scp chassis_1-cert.pem \
+                    machine_1@machine_1-ip:/path/to/chassis_1-cert.pem
+      $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
+                    machine_1@machine_1-ip:/path/to/cacert.pem
+      $ scp chassis_2-cert.pem \
+                    machine_2@machine_2-ip:/path/to/chassis_2-cert.pem
+      $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
+                    machine_2@machine_2-ip:/path/to/cacert.pem
+
+Configuring RBAC
+----------------
+
+1. Set certificate, private key, and CA certificate for the southbound
+   database. Configure the southbound database to listen on SSL connection and
+   enforce role-based access control.
+
+   In `machine_3`::
+
+      $ ovn-sbctl set-ssl /path/to/sbdb-privkey.pem \
+                          /path/to/sbdb-cert.pem /path/to/cacert.pem
+      $ ovn-sbctl set-connection role=ovn-controller pssl:6642
+
+2. Set certificate, private key, and CA certificate for `chassis_1` and
+   `chassis_2`. Configure `chassis_1` and `chassis_2` to connect southbound
+   database via SSL.
+
+   In `machine_1`::
+
+      $ ovs-vsctl set-ssl /path/to/chassis_1-privkey.pem \
+                    /path/to/chassis_1-cert.pem /path/to/cacert.pem
+      $ ovs-vsctl set open_vswitch . \
+                    external_ids:ovn-remote=ssl:machine_3-ip:6642
+
+   In `machine_2`::
+
+      $ ovs-vsctl set-ssl /path/to/chassis_2-privkey.pem \
+                    /path/to/chassis_2-cert.pem /path/to/cacert.pem
+      $ ovs-vsctl set open_vswitch . \
+                    external_ids:ovn-remote=ssl:machine_3-ip:6642