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 <b...@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....@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> _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev