diff mbox series

[ovs-dev,v4,8/9] OVN: native support for tunnel encryption

Message ID 20180731210854.31682-9-qiuyu.xiao.qyx@gmail.com
State Changes Requested
Headers show
Series IPsec support for tunneling | expand

Commit Message

Qiuyu Xiao July 31, 2018, 9:08 p.m. UTC
This patch adds IPsec support for OVN tunnel. Basically, OVN offers a
binary option to its user for encryption configuration. If the IPsec
option is turned on, all tunnels will be encrypted. Otherwise, no tunnel
will be encrypted.

The changes are summarized as below:
1) Added a ipsec column on the NB_Global table and SB_Global table. The
value of ipsec column is propagated by ovn-northd from NB_Global to
SB_Global.

2) ovn-controller monitors the ipsec column in SB_Global. If the ipsec
value is true, ovn-controller sets options of the tunnel interface by
specifying "options:remote_name=<remote_chassis_name>". If the ipsec
value is false, ovn-controller removes these options.

3) ovs-monitor-ipsec daemon
(https://mail.openvswitch.org/pipermail/ovs-dev/2018-June/348701.html)
monitors the tunnel interface options and configures IKE daemon
accordingly for IPsec encryption.

Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>
---
 ovn/controller/encaps.c         | 31 ++++++++++++++++++++++----
 ovn/controller/encaps.h         |  7 +++++-
 ovn/controller/ovn-controller.c |  4 +++-
 ovn/northd/ovn-northd.c         |  8 +++++--
 ovn/ovn-architecture.7.xml      | 39 +++++++++++++++++++++++++++++++++
 ovn/ovn-nb.ovsschema            |  7 +++---
 ovn/ovn-nb.xml                  |  6 +++++
 ovn/ovn-sb.ovsschema            |  7 +++---
 ovn/ovn-sb.xml                  |  6 +++++
 9 files changed, 101 insertions(+), 14 deletions(-)

Comments

Ben Pfaff Aug. 2, 2018, 6:31 p.m. UTC | #1
On Tue, Jul 31, 2018 at 02:08:53PM -0700, Qiuyu Xiao wrote:
> This patch adds IPsec support for OVN tunnel. Basically, OVN offers a
> binary option to its user for encryption configuration. If the IPsec
> option is turned on, all tunnels will be encrypted. Otherwise, no tunnel
> will be encrypted.
> 
> The changes are summarized as below:
> 1) Added a ipsec column on the NB_Global table and SB_Global table. The
> value of ipsec column is propagated by ovn-northd from NB_Global to
> SB_Global.
> 
> 2) ovn-controller monitors the ipsec column in SB_Global. If the ipsec
> value is true, ovn-controller sets options of the tunnel interface by
> specifying "options:remote_name=<remote_chassis_name>". If the ipsec
> value is false, ovn-controller removes these options.
> 
> 3) ovs-monitor-ipsec daemon
> (https://mail.openvswitch.org/pipermail/ovs-dev/2018-June/348701.html)
> monitors the tunnel interface options and configures IKE daemon
> accordingly for IPsec encryption.
> 
> Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>

It seems like, to be more secure, it would be wise for ovn-controller in
ipsec mode to set ipsec_skb_mark to 1/1 and then add an OpenFlow flow
that sets skb_mark to 1.  What do you think?

Thanks,

Ben.
Qiuyu Xiao Aug. 2, 2018, 8:07 p.m. UTC | #2
Yes, it makes sense. I will add this to the next revision.

Thanks,
Qiuyu

On Thu, Aug 2, 2018 at 11:31 AM, Ben Pfaff <blp@ovn.org> wrote:
> On Tue, Jul 31, 2018 at 02:08:53PM -0700, Qiuyu Xiao wrote:
>> This patch adds IPsec support for OVN tunnel. Basically, OVN offers a
>> binary option to its user for encryption configuration. If the IPsec
>> option is turned on, all tunnels will be encrypted. Otherwise, no tunnel
>> will be encrypted.
>>
>> The changes are summarized as below:
>> 1) Added a ipsec column on the NB_Global table and SB_Global table. The
>> value of ipsec column is propagated by ovn-northd from NB_Global to
>> SB_Global.
>>
>> 2) ovn-controller monitors the ipsec column in SB_Global. If the ipsec
>> value is true, ovn-controller sets options of the tunnel interface by
>> specifying "options:remote_name=<remote_chassis_name>". If the ipsec
>> value is false, ovn-controller removes these options.
>>
>> 3) ovs-monitor-ipsec daemon
>> (https://mail.openvswitch.org/pipermail/ovs-dev/2018-June/348701.html)
>> monitors the tunnel interface options and configures IKE daemon
>> accordingly for IPsec encryption.
>>
>> Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com>
>
> It seems like, to be more secure, it would be wise for ovn-controller in
> ipsec mode to set ipsec_skb_mark to 1/1 and then add an OpenFlow flow
> that sets skb_mark to 1.  What do you think?
>
> Thanks,
>
> Ben.
diff mbox series

Patch

diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c
index fde017586..2169920ba 100644
--- a/ovn/controller/encaps.c
+++ b/ovn/controller/encaps.c
@@ -79,8 +79,9 @@  tunnel_create_name(struct tunnel_ctx *tc, const char *chassis_id)
 }
 
 static void
-tunnel_add(struct tunnel_ctx *tc, const char *new_chassis_id,
-           const struct sbrec_encap *encap)
+tunnel_add(struct tunnel_ctx *tc, const struct sbrec_sb_global *sbg,
+           const char *new_chassis_id, const struct sbrec_encap *encap,
+           const char *local_ip)
 {
     struct smap options = SMAP_INITIALIZER(&options);
     smap_add(&options, "remote_ip", encap->ip);
@@ -90,6 +91,16 @@  tunnel_add(struct tunnel_ctx *tc, const char *new_chassis_id,
         smap_add(&options, "csum", csum);
     }
 
+    /* Add auth info if ipsec is enabled. */
+    if (sbg->ipsec) {
+        smap_add(&options, "remote_name", new_chassis_id);
+        if (local_ip) {
+            smap_add(&options, "local_ip", local_ip);
+        } else {
+            VLOG_INFO("Need to specify encap ip for IPsec tunnels.");
+        }
+    }
+
     /* If there's an existing chassis record that does not need any change,
      * keep it.  Otherwise, create a new record (if there was an existing
      * record, the new record will supplant it and encaps_run() will delete
@@ -157,7 +168,9 @@  encaps_run(struct ovsdb_idl_txn *ovs_idl_txn,
            const struct ovsrec_bridge_table *bridge_table,
            const struct ovsrec_bridge *br_int,
            const struct sbrec_chassis_table *chassis_table,
-           const char *chassis_id)
+           const char *chassis_id,
+           const struct sbrec_sb_global *sbg,
+           const struct ovsrec_open_vswitch_table *ovs_table)
 {
     if (!ovs_idl_txn || !br_int) {
         return;
@@ -201,6 +214,16 @@  encaps_run(struct ovsdb_idl_txn *ovs_idl_txn,
         }
     }
 
+    /* Get IP address of local chassis. */
+    const char *chassis_ip;
+    const struct ovsrec_open_vswitch *cfg;
+    cfg = ovsrec_open_vswitch_table_first(ovs_table);
+    if (cfg) {
+        chassis_ip = smap_get(&cfg->external_ids, "ovn-encap-ip");
+    } else {
+        chassis_ip = NULL;
+    }
+
     SBREC_CHASSIS_TABLE_FOR_EACH (chassis_rec, chassis_table) {
         if (strcmp(chassis_rec->name, chassis_id)) {
             /* Create tunnels to the other chassis. */
@@ -209,7 +232,7 @@  encaps_run(struct ovsdb_idl_txn *ovs_idl_txn,
                 VLOG_INFO("No supported encaps for '%s'", chassis_rec->name);
                 continue;
             }
-            tunnel_add(&tc, chassis_rec->name, encap);
+            tunnel_add(&tc, sbg, chassis_rec->name, encap, chassis_ip);
         }
     }
 
diff --git a/ovn/controller/encaps.h b/ovn/controller/encaps.h
index 054bdfa78..680b62df7 100644
--- a/ovn/controller/encaps.h
+++ b/ovn/controller/encaps.h
@@ -23,13 +23,18 @@  struct ovsdb_idl_txn;
 struct ovsrec_bridge;
 struct ovsrec_bridge_table;
 struct sbrec_chassis_table;
+struct sbrec_sb_global;
+struct ovsrec_open_vswitch_table;
 
 void encaps_register_ovs_idl(struct ovsdb_idl *);
 void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn,
                 const struct ovsrec_bridge_table *,
                 const struct ovsrec_bridge *br_int,
                 const struct sbrec_chassis_table *,
-                const char *chassis_id);
+                const char *chassis_id,
+                const struct sbrec_sb_global *,
+                const struct ovsrec_open_vswitch_table *);
+
 bool encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn,
                     const struct ovsrec_bridge *br_int);
 
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 81d330683..b25e51f78 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -689,7 +689,9 @@  main(int argc, char *argv[])
                                   chassis_id, br_int);
             encaps_run(ovs_idl_txn,
                        ovsrec_bridge_table_get(ovs_idl_loop.idl), br_int,
-                       sbrec_chassis_table_get(ovnsb_idl_loop.idl), chassis_id);
+                       sbrec_chassis_table_get(ovnsb_idl_loop.idl), chassis_id,
+                       sbrec_sb_global_first(ovnsb_idl_loop.idl),
+                       ovsrec_open_vswitch_table_get(ovs_idl_loop.idl));
             bfd_calculate_active_tunnels(br_int, &active_tunnels);
             binding_run(ovnsb_idl_txn, ovs_idl_txn, sbrec_chassis_by_name,
                         sbrec_datapath_binding_by_key,
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 35baabcad..cd327d246 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -6884,8 +6884,8 @@  ovnnb_db_run(struct northd_context *ctx,
     }
     hmap_destroy(&ports);
 
-    /* Copy nb_cfg from northbound to southbound database.
-     *
+    /* Sync ipsec configuration.
+     * Copy nb_cfg from northbound to southbound database.
      * Also set up to update sb_cfg once our southbound transaction commits. */
     const struct nbrec_nb_global *nb = nbrec_nb_global_first(ctx->ovnnb_idl);
     if (!nb) {
@@ -6895,6 +6895,9 @@  ovnnb_db_run(struct northd_context *ctx,
     if (!sb) {
         sb = sbrec_sb_global_insert(ctx->ovnsb_txn);
     }
+    if (nb->ipsec != sb->ipsec) {
+        sbrec_sb_global_set_ipsec(sb, nb->ipsec);
+    }
     sbrec_sb_global_set_nb_cfg(sb, nb->nb_cfg);
     sb_loop->next_cfg = nb->nb_cfg;
 
@@ -7398,6 +7401,7 @@  main(int argc, char *argv[])
 
     ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_sb_global);
     add_column_noalert(ovnsb_idl_loop.idl, &sbrec_sb_global_col_nb_cfg);
+    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_sb_global_col_ipsec);
 
     ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_logical_flow);
     add_column_noalert(ovnsb_idl_loop.idl,
diff --git a/ovn/ovn-architecture.7.xml b/ovn/ovn-architecture.7.xml
index ae5ca8e4a..55a5db9ea 100644
--- a/ovn/ovn-architecture.7.xml
+++ b/ovn/ovn-architecture.7.xml
@@ -1621,6 +1621,45 @@ 
     </li>
   </ol>
 
+  <h2>Encrypt Tunnel Traffic with IPsec</h2>
+  <p>
+    OVN tunnel traffic goes through physical routers and switches. These
+    physical devices could be untrusted (devices in public network) or might be
+    compromised. Enabling encryption to the tunnel traffic can prevent the
+    traffic data from being monitored and manipulated.
+  </p>
+  <p>
+    The tunnel traffic is encrypted with IPsec. The CMS sets the
+    <code>ipsec</code> column in the northbound <code>NB_Global</code> table to
+    enable or disable IPsec encrytion. If <code>ipsec</code> is true, all OVN
+    tunnels will be encrypted. If <code>ipsec</code> is false, no OVN tunnels
+    will be encrypted.
+  </p>
+  <p>
+    When CMS updates the <code>ipsec</code> column in the northbound
+    <code>NB_Global</code> table, <code>ovn-northd</code> copies the value to
+    the <code>ipsec</code> column in the southbound <code>SB_Global</code>
+    table. <code>ovn-controller</code> in each chassis monitors the southbound
+    database and sets the options of the OVS tunnel interface accordingly. OVS
+    tunnel interface options are monitored by the
+    <code>ovs-monitor-ipsec</code> daemon which configures IKE daemon to set up
+    IPsec connections.
+  </p>
+  <p>
+    Chassis authenticates each other by using certificate. The authentication
+    succeeds if the other end in tunnel presents a certificate signed by a
+    trusted CA and the common name (CN) matches the expected chassis name.  The
+    SSL certificates used in role-based access controls (RBAC) can be used in
+    IPsec. Or use <code>ovs-pki</code> to create different certificates. The
+    certificate is required to be x.509 version 3, and with CN field and
+    subjectAltName field being set to the chassis name.
+  </p>
+  <p>
+    The CA certificate, chassis certificate and private key are required to be
+    installed in each chassis before enabling IPsec. Please see
+    <code>ovs-vswitchd.conf.db</code>(5) for setting up CA based IPsec
+    authentication.
+  </p>
   <h1>Design Decisions</h1>
 
   <h2>Tunnel Encapsulations</h2>
diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema
index 3e7164baa..3ee288935 100644
--- a/ovn/ovn-nb.ovsschema
+++ b/ovn/ovn-nb.ovsschema
@@ -1,7 +1,7 @@ 
 {
     "name": "OVN_Northbound",
-    "version": "5.13.0",
-    "cksum": "1278623084 20312",
+    "version": "5.14.0",
+    "cksum": "483549684 20358",
     "tables": {
         "NB_Global": {
             "columns": {
@@ -19,7 +19,8 @@ 
                 "ssl": {
                     "type": {"key": {"type": "uuid",
                                      "refTable": "SSL"},
-                                     "min": 0, "max": 1}}},
+                                     "min": 0, "max": 1}},
+                "ipsec": {"type": "boolean"}},
             "maxRows": 1,
             "isRoot": true},
         "Logical_Switch": {
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index bc60a25dd..8c2d736d2 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -80,6 +80,12 @@ 
         Global SSL configuration.
       </column>
     </group>
+    <group title="Security Configurations">
+      <column name="ipsec">
+        Tunnel encryption configuration. If this column is set to be true, all
+        OVN tunnels will be encrypted with IPsec.
+      </column>
+    </group>
   </table>
 
   <table name="Logical_Switch" title="L2 logical switch">
diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema
index ad6ad3b71..669b034e1 100644
--- a/ovn/ovn-sb.ovsschema
+++ b/ovn/ovn-sb.ovsschema
@@ -1,7 +1,7 @@ 
 {
     "name": "OVN_Southbound",
-    "version": "1.16.0",
-    "cksum": "3046632234 14844",
+    "version": "1.17.0",
+    "cksum": "3604753998 14890",
     "tables": {
         "SB_Global": {
             "columns": {
@@ -17,7 +17,8 @@ 
                 "ssl": {
                     "type": {"key": {"type": "uuid",
                                      "refTable": "SSL"},
-                                     "min": 0, "max": 1}}},
+                                     "min": 0, "max": 1}},
+                "ipsec": {"type": "boolean"}},
             "maxRows": 1,
             "isRoot": true},
         "Chassis": {
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index 68e31db31..6d4b662b9 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -174,6 +174,12 @@ 
         Global SSL configuration.
       </column>
     </group>
+    <group title="Security Configurations">
+      <column name="ipsec">
+        Tunnel encryption configuration. If this column is set to be true, all
+        OVN tunnels will be encrypted with IPsec.
+      </column>
+    </group>
   </table>
 
   <table name="Chassis" title="Physical Network Hypervisor and Gateway Information">