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.
|