summaryrefslogtreecommitdiff
path: root/Documentation/tutorials/ipsec.rst
blob: 9d6cc7779a73359751497ba13e240ac46ffcb774 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
..
      Licensed under the Apache License, Version 2.0 (the "License"); you may
      not use this file except in compliance with the License. You may obtain
      a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
      WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
      License for the specific language governing permissions and limitations
      under the License.

      Convention for heading levels in Open vSwitch documentation:

      =======  Heading 0 (reserved for the title in a document)
      -------  Heading 1
      ~~~~~~~  Heading 2
      +++++++  Heading 3
      '''''''  Heading 4

      Avoid deeper levels because they do not render well.

==================
OVS IPsec Tutorial
==================

This document provides a step-by-step guide for running IPsec tunnel in Open
vSwitch. A more detailed description on OVS IPsec tunnel and its
configuration modes can be found in :doc:`/howto/ipsec`.

Requirements
------------

OVS IPsec tunnel requires Linux kernel (>= v3.10.0) and OVS out-of-tree kernel
module. The compatible IKE daemons are LibreSwan (>= v3.23) and StrongSwan
(>= v5.3.5).

.. _install-ovs-ipsec:

Installing OVS and IPsec Packages
---------------------------------

OVS IPsec has .deb and .rpm packages. You should use the right package
based on your Linux distribution. This tutorial uses Ubuntu 22.04 and Fedora 32
as examples.

Ubuntu
~~~~~~

1. Install the related packages::

       # apt-get install openvswitch-ipsec

   If the installation is successful, you should be able to see the
   ovs-monitor-ipsec daemon is running in your system.

Fedora
~~~~~~

1. Install the related packages. Fedora 32 does not require installation of
   the out-of-tree kernel module::

       # dnf install python3-openvswitch libreswan \
                     openvswitch openvswitch-ipsec

2. Install firewall rules to allow ESP and IKE traffic::

       # systemctl start firewalld
       # firewall-cmd --add-service ipsec

   Or to make permanent::

       # systemctl enable firewalld
       # firewall-cmd --permanent --add-service ipsec

3. Run the openvswitch-ipsec service::

       # systemctl start openvswitch-ipsec.service

   .. note::

     The SELinux policies might prevent openvswitch-ipsec.service to access
     certain resources. You can configure SELinux to remove such restrictions.

Configuring IPsec tunnel
------------------------

Suppose you want to build an IPsec tunnel between two hosts. Assume `host_1`'s
external IP is 1.1.1.1, and `host_2`'s external IP is 2.2.2.2. Make sure
`host_1` and `host_2` can ping each other via these external IPs.

0. Set up some variables to make life easier.  On both hosts, set ``ip_1`` and
   ``ip_2`` variables, e.g.::

     # ip_1=1.1.1.1
     # ip_2=2.2.2.2

1. Set up OVS bridges in both hosts.

   In `host_1`::

       # ovs-vsctl add-br br-ipsec
       # ip addr add 192.0.0.1/24 dev br-ipsec
       # ip link set br-ipsec up

   In `host_2`::

       # ovs-vsctl add-br br-ipsec
       # ip addr add 192.0.0.2/24 dev br-ipsec
       # ip link set br-ipsec up

2. Set up IPsec tunnel.

   There are three authentication methods.  Choose one method to set up your
   IPsec tunnel and follow the steps below.

   a) Using pre-shared key:

      In `host_1`::

          # ovs-vsctl add-port br-ipsec tun -- \
                      set interface tun type=gre \
                                    options:remote_ip=$ip_2 \
                                    options:psk=swordfish

      In `host_2`::

          # ovs-vsctl add-port br-ipsec tun -- \
                      set interface tun type=gre \
                                    options:remote_ip=$ip_1 \
                                    options:psk=swordfish

      .. note::

        Pre-shared key (PSK) based authentication is easy to set up but less
        secure compared with other authentication methods. You should use it
        cautiously in production systems.

   b) Using self-signed certificate:

      Generate self-signed certificate in both `host_1` and `host_2`. Then copy
      the certificate of `host_1` to `host_2` and the certificate of `host_2`
      to `host_1`.

      In `host_1`::

          # ovs-pki req -u host_1
          # ovs-pki self-sign host_1
          # scp host_1-cert.pem $ip_2:/etc/keys/host_1-cert.pem

      In `host_2`::

          # ovs-pki req -u host_2
          # ovs-pki self-sign host_2
          # scp host_2-cert.pem $ip_1:/etc/keys/host_2-cert.pem

      .. note::

        If you use StrongSwan as IKE daemon, please move the host certificates
        to /etc/ipsec.d/certs/ and private key to /etc/ipsec.d/private/ so that
        StrongSwan has permission to access those files.

      Configure IPsec tunnel to use self-signed certificates.

      In `host_1`::

          # ovs-vsctl set Open_vSwitch . \
                     other_config:certificate=/etc/keys/host_1-cert.pem \
                     other_config:private_key=/etc/keys/host_1-privkey.pem
          # ovs-vsctl add-port br-ipsec tun -- \
                      set interface tun type=gre \
                             options:remote_ip=$ip_2 \
                             options:remote_cert=/etc/keys/host_2-cert.pem

      In `host_2`::

          # ovs-vsctl set Open_vSwitch . \
                     other_config:certificate=/etc/keys/host_2-cert.pem \
                     other_config:private_key=/etc/keys/host_2-privkey.pem
          # ovs-vsctl add-port br-ipsec tun -- \
                      set interface tun type=gre \
                             options:remote_ip=$ip_1 \
                             options:remote_cert=/etc/keys/host_1-cert.pem

      .. note::

        The confidentiality of the private key is very critical.  Don't copy it
        to places where it might be compromised.  (The certificate need not be
        kept confidential.)

   c) Using CA-signed certificate:

      First you need to establish a public key infrastructure (PKI). Suppose
      you choose `host_1` to host PKI.

      In `host_1`::

          # ovs-pki init

      Generate certificate requests and copy the certificate request of
      `host_2` to `host_1`.

      In `host_1`::

          # ovs-pki req -u host_1

      In `host_2`::

          # ovs-pki req -u host_2
          # scp host_2-req.pem $ip_1:/etc/keys/host_2-req.pem

      Sign the certificate requests with the CA key. Copy `host_2`'s signed
      certificate and the CA certificate to `host_2`.

      In `host_1`::

          # ovs-pki sign host_1 switch
          # ovs-pki sign host_2 switch
          # scp host_2-cert.pem $ip_2:/etc/keys/host_2-cert.pem
          # scp /var/lib/openvswitch/pki/switchca/cacert.pem \
                    $ip_2:/etc/keys/cacert.pem

      .. note::

        If you use StrongSwan as IKE daemon, please move the host certificates
        to /etc/ipsec.d/certs/, CA certificate to /etc/ipsec.d/cacerts/, and
        private key to /etc/ipsec.d/private/ so that StrongSwan has permission
        to access those files.

      Configure IPsec tunnel to use CA-signed certificate.

      In `host_1`::

          # ovs-vsctl set Open_vSwitch . \
                  other_config:certificate=/etc/keys/host_1-cert.pem \
                  other_config:private_key=/etc/keys/host_1-privkey.pem \
                  other_config:ca_cert=/etc/keys/cacert.pem
          # ovs-vsctl add-port br-ipsec tun -- \
                   set interface tun type=gre \
                                 options:remote_ip=$ip_2 \
                                 options:remote_name=host_2

      In `host_2`::

          # ovs-vsctl set Open_vSwitch . \
                  other_config:certificate=/etc/keys/host_2-cert.pem \
                  other_config:private_key=/etc/keys/host_2-privkey.pem \
                  other_config:ca_cert=/etc/keys/cacert.pem
          # ovs-vsctl add-port br-ipsec tun -- \
                   set interface tun type=gre \
                                 options:remote_ip=$ip_1 \
                                 options:remote_name=host_1

      .. note::

        remote_name is the common name (CN) of the signed-certificate.  It must
        match the name given as the argument to the ``ovs-pki sign command``.
        It ensures that only certificate with the expected CN can be
        authenticated; otherwise, any certificate signed by the CA would be
        accepted.

3. Set the `local_ip` field in the Interface table (Optional)

    Make sure that the `local_ip` field in the Interface table is set to the
    NIC used for egress traffic.

    On `host 1`::

       # ovs-vsctl set Interface tun options:local_ip=$ip_1

    Similarly, on `host 2`::

       # ovs-vsctl set Interface tun options:local_ip=$ip_2

   .. note::

        It is not strictly necessary to set the `local_ip` field if your system
        only has one NIC or the default gateway interface is set to the NIC
        used for egress traffic.

4. Test IPsec tunnel.

   Now you should have an IPsec GRE tunnel running between two hosts. To verify
   it, in `host_1`::

       # ping 192.0.0.2 &
       # tcpdump -ni any net $ip_2

   You should be able to see that ESP packets are being sent from `host_1` to
   `host_2`.

Custom options
--------------

Any parameter prefixed with `ipsec_` will be added to the connection profile.
For example::

    # ovs-vsctl set interface tun options:ipsec_encapsulation=yes

Will result in::

    #  ovs-appctl -t ovs-monitor-ipsec tunnels/show
    Interface name: tun v7 (CONFIGURED)
    Tunnel Type:    vxlan
    Local IP:       192.0.0.1
    Remote IP:      192.0.0.2
    Address Family: IPv4
    SKB mark:       None
    Local cert:     None
    Local name:     None
    Local key:      None
    Remote cert:    None
    Remote name:    None
    CA cert:        None
    PSK:            swordfish
    Custom Options: {'encapsulation': 'yes'}

And in the following connection profiles::

    conn tun-in-7
        left=192.0.0.1
        right=192.0.0.2
        authby=secret
        encapsulation=yes
        leftprotoport=udp/4789
        rightprotoport=udp

    conn tun-out-7
        left=192.0.0.1
        right=192.0.0.2
        authby=secret
        encapsulation=yes
        leftprotoport=udp
        rightprotoport=udp/4789

Troubleshooting
---------------

The ``ovs-monitor-ipsec`` daemon manages and monitors the IPsec tunnel state.
Use the following ``ovs-appctl`` command to view ``ovs-monitor-ipsec`` internal
representation of tunnel configuration::

    # ovs-appctl -t ovs-monitor-ipsec tunnels/show

If there is misconfiguration, then ``ovs-appctl`` should indicate why.
For example::

   Interface name: gre0 v5 (CONFIGURED) <--- Should be set to CONFIGURED.
                                             Otherwise, error message will
                                             be provided
   Tunnel Type:    gre
   Local IP:       %defaultroute
   Remote IP:      2.2.2.2
   SKB mark:       None
   Local cert:     None
   Local name:     None
   Local key:      None
   Remote cert:    None
   Remote name:    None
   CA cert:        None
   PSK:            swordfish
   Custom Options: {}
   Ofport:         1          <--- Whether ovs-vswitchd has assigned Ofport
                                   number to this Tunnel Port
   CFM state:      Up         <--- Whether CFM declared this tunnel healthy
   Kernel policies installed:
   ...                          <--- IPsec policies for this OVS tunnel in
                                     Linux Kernel installed by strongSwan
   Kernel security associations installed:
   ...                          <--- IPsec security associations for this OVS
                                     tunnel in Linux Kernel installed by
                                     strongswan
   IPsec connections that are active:
   ...                          <--- IPsec "connections" for this OVS
                                     tunnel

If you don't see any active connections, try to run the following command to
refresh the ``ovs-monitor-ipsec`` daemon::

    # ovs-appctl -t ovs-monitor-ipsec refresh

You can also check the logs of the ``ovs-monitor-ipsec`` daemon and the IKE
daemon to locate issues. ``ovs-monitor-ipsec`` outputs log messages to
/var/log/openvswitch/ovs-monitor-ipsec.log.

Bug Reporting
-------------

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

1. IPsec protected tunnel accepted packets that came unencrypted; OR
2. IPsec protected tunnel allowed packets to leave unencrypted;

Then report such bugs according to :doc:`/internals/security`.

If bug does not have security implications, then report it according to
instructions in :doc:`/internals/bugs`.

If you have suggestions to improve this tutorial, please send a email to
ovs-discuss@openvswitch.org.