- Lab 4: Cloud Encryption Using RHEL Opportunistic IPsec
- 4.1: Introduction
- 4.2: Creating and Installing X.509 Certificates
- 4.3: Configuring Opportunistic IPsec
- 4.4: Transferring the Configuration to a Second System
- 4.5: Using Opportunistic IPsec
- 4.6: Troubleshooting (Optional)
- 4.7: Resetting the IPsec NSS Certificate Database (Optional)
-
Medium/Average (~15 mins)
-
Learn how to deploy Opportunistic IPsec to encrypt all host-to-host communication within an enterprise network
-
Generate X.509 certificates using a Python helper script
-
Configure Opportunistic IPsec on two or more nodes
-
Debug and monitor the network for IPsec encryption
Whenever two hosts in the network send any kind of traffic, IPsec security automatically activates and encrypts all traffic between those hosts. This is also called mesh encryption.
Imagine a LAN of various machines. Each machine is given an X.509 certificate in the form of a PKCS#12 file (for example, ipsecXXX.example.com). Machines in the network automatically initiate IPsec encryption and authenticate each other based on these certificates whenever any traffic is attempted between these nodes. This is called Opportunistic IPsec.
There are two machines available to you for this lab. But because this configuration method’s main feature is scalability, you can use another X.509 certificate and repeat the process for any other provided lab VM. But be careful—if you misconfigure IPsec and do not allow fallback to cleartext, you can lock yourself out of a VM.
In this section, you generate the required X.509 certificates. To make this
easier, a script (/root/vpn-cert-gen.py
) provided on ipsec.example.com generates x.509 certificates for ipsec.example.com and
ipsec2.example.com for the lab. If you want to try to add
more machines to the encrypted mesh network, it also creates certificates
for audit.example.com and usbguard.example.com. All your actions are run as root.
-
If you are not already there, log in to the workstation bastion host as lab-user from your desktop system (replacing
GUID
with your lab-provided GUID and using r3dh4t1! as the password):[localhost ~]$ ssh [email protected]
-
Log in to the ipsec.example.com host as root:
[lab-user@workstation-GUID ~]$ ssh [email protected]
-
Create the X.509 certificates for the lab:
[root@ipsec ~]# mkdir /root/labcerts [root@ipsec ~]# cd /root/labcerts [root@ipsec labcerts]# /root/vpn-cert-gen.py --wipe creating CA cert OK: CA system completely re-initialized [root@ipsec labcerts]# ls cacerts certs keys mobileconfig pkcs12 serial.txt [root@ipsec labcerts]# ls pkcs12/ audit.example.com.p12 ipsec2.example.com.p12 ipsec.example.com.p12 servera.example.com.p12 usbguard.example.com.p12
The
cacerts/
directory contains the CA certificate.The
certs/
directory contains the regular node certificates.The
keys/
directory contains the private keys, but the script has already combined these for you into PKCS#12-based certificates in thepkcs12/
directory.The
mobileconfig/
directory has Apple device profiles that include the PKCS#12 certificate and all of the other configuration items that are needed for those devices. These files are only useful when building a Remote Access VPN server. You do not use them for this mesh host-to-host encryption using Opportunistic IPsec. -
Select the proper
pkcs12/*.p12
files for each of the hosts you want to add to the crypto mesh.
Important
|
Due to security issues, the certificates must have a |
-
Install
libreswan
and initialize the certificate database using the following commands to first set up ipsec.example.com:[root@ipsec ~]# yum install libreswan [root@ipsec ~]# ipsec initnss
-
After
libreswan
is installed, import the PKCS#12 certificate:[root@ipsec ~]# ipsec import /root/labcerts/pkcs12/ipsec.example.com.p12 Enter password for PKCS12 file: pk12util: PKCS12 IMPORT SUCCESSFUL correcting trust bits for Certificate Agency (CA) - Test Org
-
When prompted for the import password, type secret.
-
Confirm that the node’s certificate and CA certificate are installed and available to
libreswan
:[root@ipsec ~]# certutil -L -d sql:/etc/ipsec.d Certificate Nickname Trust Attributes SSL,S/MIME,JAR/XPI mycert u,u,u Certificate Agency (CA) - Test Org CT,,
In this section, you configure the ipsec.example.com and ipsec2.example.com hosts
for IPsec. For these two hosts, the configuration file is already created for
you and placed on the machine at /root/oe-cert.conf
.
-
Copy this file into the
/etc/ipsec.d/
directory so thatlibreswan
can use it:[root@ipsec ~]# cp /root/oe-cert.conf /etc/ipsec.d/
NoteIf you look at the
/root/oe-cert.conf
file, you can see it defines a number of connections. These connections are the groups that you can assign to network IP ranges. A connection specification is defined within aconn
section in the configuration file.-
conn private
means that IPsec is mandatory and all plaintext is to be dropped. -
conn private-or-clear
means that IPsec is attempted, but it falls back to cleartext if it fails. -
conn clear-or-private
means that it does not initiate IPsec, but responds to a request for IPsec. -
conn clear
never allows or initiates IPsec.
-
-
If you are running with SElinux enabled, make sure that all of the files are properly labeled:
[root@ipsec ~]# restorecon -Rv /etc/ipsec.*
-
Add an IP address (for example,
192.168.0.66
) or network range (for example,192.168.0.0/24
) into one of these groups, by simply adding one line with the IP address or network (in CIDR notation) into one of the files matching the connection name in/etc/ipsec.d/policies
. -
Configure the machines to attempt Opportunistic IPsec for the entire
192.168.0.0/24
range by adding that network range to theprivate-or-clear
group:[root@ipsec ~]# echo "192.168.0.0/24" >> /etc/ipsec.d/policies/private-or-clear
-
Add a more specific entry into the "clear" group so that workstation communication always takes place unencrypted and you can always use it to log in to other machines to reconfigure or debug:
[root@ipsec ~]# echo "192.168.0.3/32" >> /etc/ipsec.d/policies/clear
This allows you to log in to all of the machines via the workstation.
-
Tell the
firewalld
system service that you want to open the firewall for the required packets for IPsec:[root@ipsec ~]# firewall-cmd --add-service=ipsec --permanent [root@ipsec ~]# firewall-cmd --reload
In this section, you configure the next machine, ipsec2.example.com. Because the ipsec.example.com host contains all of the certificates, you must copy the certificate onto ipsec2.example.com via the workstation VM:
-
If you are not already there, log in to the workstation bastion host as lab-user from your desktop system (replacing
GUID
with your lab-provided GUID and using r3dh4t1! as the password):[localhost ~]$ ssh [email protected] [lab-user@workstation-GUID ~]$ scp [email protected]:/root/labcerts/pkcs12/ipsec2.example.com.p12 . [lab-user@workstation-GUID ~]$ scp [email protected]:/root/oe-cert.conf . [lab-user@workstation-GUID ~]$ scp ipsec2.example.com.p12 oe-cert.conf [email protected]:/root/
-
Install
libreswan
, import the certificate on ipsec2.example.com, and configure it for Opportunistic IPsec: -
Log in to the ipsec2.example.com host as root:
[lab-user@workstation-GUID ~]$ ssh [email protected]
[root@ipsec2 ~]# yum install libreswan [root@ipsec2 ~]# ipsec initnss [root@ipsec2 ~]# ipsec import /root/ipsec2.example.com.p12 (Note: The password for PKCS12 file is "secret".) [root@ipsec2 ~]# rm /root/ipsec2.example.com.p12 [root@ipsec2 ~]# mv /root/oe-cert.conf /etc/ipsec.d/ [root@ipsec2 ~]# restorecon -Rv /etc/ipsec.d [root@ipsec2 ~]# echo "192.168.0.0/24" >> /etc/ipsec.d/policies/private-or-clear [root@ipsec2 ~]# echo "192.168.0.3/32" >> /etc/ipsec.d/policies/clear [root@ipsec2 ~]# firewall-cmd --add-service=ipsec --permanent [root@ipsec2 ~]# firewall-cmd --reload
Now you have configured the first two nodes. For each additional node, all you need to do is generate and install a new certificate, add the same configuration file with the updated
leftcert=
entry, and update the policy groups in/etc/ipsec.d/policies/
to match the first two nodes of the cluster. So for each added node, you do not need to reconfigure any of the previous nodes, as those are already configured to trust the same CA and talk IPsec to the same IP ranges as the new nodes. Because all of the configuration files (other then the PKCS#12 certificate) are identical on all or the nodes, in a production setting, you should be able to populate new nodes using Ansible®.
You are now ready to test the configuration.
First, you start the IPsec subsystem on both of the hosts.
-
Start the IPsec subsystem on ipsec.example.com:
[root@ipsec ~]# systemctl start ipsec
-
Start the IPsec subsystem on ipsec2.example.com:
[root@ipsec2 ~]# systemctl start ipsec
-
Wait a few seconds for the two hosts to load their IPsec policies.
-
On ipsec.example.com,
ping
ipsec2.example.com from ipsec.example.com to trigger an IPsec tunnel:[root@ipsec ~]# ping -c3 ipsec2.example.com
The first
ping
may fail depending on the time it takes to set up the IPsec connection. -
Examine the system logs in
/var/log/secure
, or you can use one of the various status commands available:[root@ipsec ~]# ipsec trafficstatus 006 #2: "private-or-clear#192.168.0.0/24"[1] ...192.168.0.22, type=ESP, add_time=1523268130, inBytes=1848, outBytes=1848, id='C=CA, ST=Ontario, L=Toronto, O=Test Org, OU=Clients, CN=ipsec.example.com, [email protected]'
-
Examine the output to see the non-zero byte counters for IPsec packets that shows that the kernel IPsec subsystem has encrypted and decrypted network packets.
TipA more verbose command is:
[root@ipsec ~]# ipsec status <lots of output>
Your two nodes now have an IPsec-encrypted mesh network running.
-
If you think something went wrong and the
ipsec status
command does not show you theprivate
,private-or-clear
, andclear-or-private
connections (and their instances), issue a manual command to see why loading failed:[root@ipsec ~]# ipsec auto --add private
-
If there is some kind of failure (such as the group is
private
but the remote end is not functioning), do not expect to see a visible IPsec tunnel, but examine the results and expect to see the shunts that prevent or allow unencrypted traffic on the network:[root@ipsec ~]# ipsec whack --shuntstatus 000 Bare Shunt list: 000 000 192.168.0.23/32:0 -0-> 192.168.0.22/32:0 => %drop 0 oe-failing
NoteThere are a few kinds of shunts. The
negotiationshunt
determines what to do with packets while the IPsec connection is being established. Usually people want to hold the packets to prevent leaks, but if encryption is only "nice to have" and an uninterrupted service is more important, you can set this option topassthrough
. Thefailureshunt
option determines what to do when negotiation fails. For theprivate-or-clear
entry in your configuration file, you can see it is set topassthrough
, allowing unencrypted traffic. For theprivate
entry you can see it is set todrop
to disallow unencrypted traffic. -
Run
ping
on one host andtcpdump
on the other host to confirm that the connection is encrypted:[root@ipsec ~]# tcpdump -i ens3 -n esp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens3, link-type EN10MB (Ethernet), capture size 262144 bytes 05:58:18.003410 IP 192.168.0.22 > 192.168.0.23: ESP(spi=0x84019944,seq=0x6), length 120 05:58:18.003684 IP 192.168.0.23 > 192.168.0.22: ESP(spi=0x5b312cc5,seq=0x6), length 120 05:58:19.004840 IP 192.168.0.22 > 192.168.0.23: ESP(spi=0x84019944,seq=0x7), length 120 05:58:19.005096 IP 192.168.0.23 > 192.168.0.22: ESP(spi=0x5b312cc5,seq=0x7), length 120 05:58:20.006529 IP 192.168.0.22 > 192.168.0.23: ESP(spi=0x84019944,seq=0x8), length 120 05:58:20.006730 IP 192.168.0.23 > 192.168.0.22: ESP(spi=0x5b312cc5,seq=0x8), length 120
If you see ESP packets with
tcpdump
, it means the connection is sending encrypted traffic. If you useping
and see ICMP packets, then the connection is not encrypted. Due to how the kernel hooks for IPsec andtcpdump
interact, if you look at all traffic over an interface, you might see unencrypted packets going out and encrypted (proto ESP) and decrypted packets coming in. This happens because packets are encrypted by IPsec after thetcpdump
hook has seen the packet on some kernel versions. The easiest indicator of whether traffic is encrypted is to use the above-mentionedtrafficstatus
command. -
Simply repeat this process on any new node to create your crypto mesh.
If you added the entire network range (
192.168.0.0/24
) to theprivate
orprivate-or-clear
groups, then for every new node you add, you do not need to reconfigure anything on the existing node. -
Optionally, redo the test—but this time, do not run
libreswan
on one node—then perform a ping.Expect to see a few packets stalled or failing (based on whether the IP or subnet appears in
/etc/ipsec.d/policies/private
or/etc/ipsec.d/policies/private-or-clear
) before it fails to clear or installs a block. -
Additionally, if you run into more problems or you want to see in detail what is happening, enable two lines in
/etc/ipsec.conf
to get all of the logs in a file with full debugging:# example /etc/ipsec.conf config setup logfile=/var/log/pluto.log plutodebug=all include /etc/ipsec.d/*.conf
It is important to use file logging with full debugging because otherwise the
rsyslog
orsystemd ratelimit
may cause you to miss messages. -
If everything works as expected, enable the IPsec services on your cluster on every startup—on each node run:
[root@ipsec ~]# systemctl enable ipsec
For more information on Opportunistic IPsec, see Opportunistic IPsec.
Libreswan uses the NDD cryptographic library. It keeps all of its X.509
certificates and keys in its own NSS database in /etc/ipsec.d
.
-
If you want restart the entire lab from scratch, run the following commands to remove the entire
libreswan
NSS database:WarningExecuting these commands requires you to restart the IPsec lab from the beginning.
[root@ipsec ~]# systemctl stop ipsec [root@ipsec ~]# rm /etc/ipsec.d/*.db [root@ipsec ~]# ipsec initnss Initializing NSS database
-
Follow the same procedure for ipsec2.example.com.