Dieser Inhalt ist in der von Ihnen ausgewählten Sprache nicht verfügbar.

Chapter 6. Setting up an IPsec VPN


Libreswan is an implementation of the Internet Protocol Security (IPsec) protocol suite. You can use Libreswan to configure Virtual Private Networks (VPNs) that establish secure, encrypted tunnels over untrusted networks, such as the internet. These tunnels ensure the confidentiality and integrity of data in transit. Common use cases include connecting branch offices to headquarters or providing remote users with secure access to a corporate network.

RHEL provides different options to configure Libreswan:

  • Manually edit the Libreswan configuration files for granular control over advanced options.
  • Use the vpn RHEL system role to automate the process of creating Libreswan VPN configurations.
  • Use Nmstate to configure a Libreswan connection through a declarative API.

Libreswan does not use terms such as "client" and "server". Instead, IPsec refers to endpoints as "left" and "right". This design often enables you to use the same configuration on both hosts because Libreswan dynamically determines which role to adopt. As a convention, administrators typically use "left" for the local host and "right" for the remote host.

Note

Libreswan is the only supported VPN technology in RHEL.

IPsec relies on standardized protocols, such as Internet Key Exchange (IKE), to ensure that different systems can communicate effectively. However, in practice, minor differences in how vendors implement these standards can lead to compatibility problems. If you encounter such interoperability issues when connecting Libreswan to a third-party IPsec peer, contact Red Hat Support.

6.1. Components in an IPsec VPN

Setting up an IPsec VPN involves the following main components:

  • Internet Key Exchange (IKE): The two endpoints use this protocol to authenticate each other and negotiate the rules for the connection, including the encryption algorithms to be used. Libreswan implements the IKE protocol in a daemon called pluto.
  • IPsec: The part of the protocol that actually encrypts and transports the data according to the policy agreed upon during the IKE negotiation. The Linux kernel implements the IPsec protocol suite.

6.2. Libreswan authentication methods

Libreswan supports the following authentication methods:

Pre-Shared key
The Pre-Shared Key (PSK) method involves both endpoints by using the same secret to authenticate each other. PSKs offer simplicity and broad compatibility, making them suitable for small-scale deployments. However, managing PSKs is risky if the key is reused or not rotated frequently. For security, PSKs should consist of more than 64 random characters and must meet FIPS strength requirements if your host operates in FIPS mode.
Raw RSA key
This method uses an RSA public and private key pair on each peer for mutual identification. Raw RSA keys provide stronger security than PSKs and are ideal for environments where a full certificate infrastructure is not required.
X.509 certificates
This method uses X.509 certificates issued by a trusted Certificate Authority (CA). Each peer proves its identity by using its certificate and private key, which the other peer verifies against the trusted CA. While providing the highest level of security and scalability for large enterprises, this method is more complex as it requires deploying and maintaining a public key infrastructure (PKI).
NULL authentication
This method provides only encryption with no authentication between peers. Because it does not verify the identity of the remote endpoint, NULL authentication is insecure and offers no protection against man-in-the-middle attacks.
Protection against quantum computers
While not a standalone authentication method, Libreswan offers Post-quantum Pre-shared Keys (PPKs) to protect modern IKEv2 connections from future attacks by quantum computers. This feature is necessary because neither the older IKEv1 protocol nor standard IKEv2 is inherently quantum-resistant on its own. A PPK adds another layer of security on top of the primary authentication method, and its security relies on using a cryptographically strong key that has been distributed securely through an external communication channel.

A host-to-host VPN establishes a direct, secure, and encrypted connection between two devices, allowing applications to communicate safely over an insecure network, such as the internet.

For authentication, RSA keys are more secure than pre-shared keys (PSKs) because their asymmetric encryption eliminates the risk of a shared secret. Using RSA keys also simplifies deployment by avoiding the need for a certificate authority (CA), while still providing strong peer-to-peer authentication.

Perform the steps on both hosts.

Procedure

  1. If Libreswan is not yet installed, perform the following steps:

    1. Install the libreswan package:

      # dnf install libreswan
      Copy to Clipboard Toggle word wrap
    2. Initialize the Network Security Services (NSS) database:

      # ipsec initnss
      Copy to Clipboard Toggle word wrap

      The command creates the database in the /var/lib/ipsec/nss/ directory.

    3. Enable and start the ipsec service:

      # systemctl enable --now ipsec
      Copy to Clipboard Toggle word wrap
    4. Open the IPsec ports and protocols in the firewall:

      # firewall-cmd --permanent --add-service="ipsec"
      # firewall-cmd --reload
      Copy to Clipboard Toggle word wrap
  2. Create an RSA key pair:

    # ipsec newhostkey
    Copy to Clipboard Toggle word wrap

    The ipsec utility stores the key pair in the NSS database.

  3. Designate your peers. In an IPsec tunnel, you must designate one host as left and the other as right. This is an arbitrary choice. A common practice is to call your local host left and the remote host right.
  4. Display the Certificate Key Attribute ID (CKAID) on both the left and right peer:

    # ipsec showhostkey --list
    < 1> RSA keyid: <key_id> ckaid: <ckaid>
    Copy to Clipboard Toggle word wrap

    You require the CKAIDs of both peers in the next steps.

  5. Display the public keys:

    1. On the left peer, enter:

      # ipsec showhostkey --left --ckaid <ckaid_of_left_peer>
      	# rsakey AwEAAdKCx
      	leftrsasigkey=0sAwEAAdKCxpc9db48cehzQiQD...
      Copy to Clipboard Toggle word wrap
    2. On the right peer, enter:

      # ipsec showhostkey --right --ckaid <ckaid_of_right_peer>
      	# rsakey AwEAAcNWC
      	rightrsasigkey=0sAwEAAcNWCzZO+PR1j8WbO8X...
      Copy to Clipboard Toggle word wrap

    The commands display the public keys with the corresponding parameters that you must use in the configuration file.

  6. Create a .conf file for the connection in the /etc/ipsec.d/ directory. For example, create the /etc/ipsec.d/host-to-host.conf file with the following settings:

    conn <connection_name>
        # General setup and authentication type
        auto=start
        authby=rsasig
    
        # Peer A
        left=<ip_address_or_fqdn_of_left_peer>
        leftid=@peer_a
        leftrsasigkey=<public_key_of_left_peer>
    
        # Peer B
        right=<ip_address_or_fqdn_of_right_peer>
        rightid=@peer_b
        rightrsasigkey=<public_key_of_right_peer>
    Copy to Clipboard Toggle word wrap
    Note

    You can use the same configuration file on both hosts, and Libreswan identifies whether it is operating on the left or right host by using internal information. However, it is important that all values in left* parameters belong to one peer and the values in right* parameters belong to the other.

    The settings specified in the example include the following:

    conn <connection_name>
    Defines the connection name. The name is arbitrary, and Libreswan uses it to identify the connection. You must indent parameters in this connection by at least one space or tab.
    auto=<type>
    Controls how the connection is initiated. If you set the value to start, Libreswan activates the connection automatically when the service starts.
    authby=rsasig
    Enables RSA signature authentication for this connection.
    left=<ip_address_or_fqdn_of_left_peer> and right=<ip_address_or_fqdn_of_right_peer>
    Defines the IP address or DNS name of the peers.
    leftid=<id> and rightid=<id>
    Defines how each peer is identified during the Internet Key Exchange (IKE) negotiation process. This can be a fully-qualified domain name (FQDN), an IP address, or a literal string. In the latter case, precede the string with an @ sign.
    leftrsasigkey=<public_key> and rightrsasigkey=<public_key>
    Specifies the public key of the peers. Use the values displayed by the ipsec showhostkey command in a previous step.
  7. Restart the ipsec service:

    # systemctl restart ipsec
    Copy to Clipboard Toggle word wrap

    If you use auto=start in the configuration file, the connection is automatically activated. With other methods, additional steps are required to activate the connection. For details, see the ipsec.conf(5) man page on your system.

Verification

  • Display the IPsec status:

    # ipsec status
    Copy to Clipboard Toggle word wrap

    If the connection is successfully established, the output contains lines as follows:

    • Phase 1 of an Internet Key Exchange version 2 (IKEv2) negotiation has been successfully completed:

      000 #1: "<connection_name>":500 STATE_V2_ESTABLISHED_IKE_SA (established IKE SA); REKEY in 27935s; REPLACE in 28610s; newest; idle;
      Copy to Clipboard Toggle word wrap

      The Security Association (SA) is now ready to negotiate the actual data encryption tunnels, known as child SAs or Phase 2 SAs.

    • A child SA has been established:

      000 #2: "<connection_name>":500 STATE_V2_ESTABLISHED_CHILD_SA (established Child SA); REKEY in 27671s; REPLACE in 28610s; IKE SA #1; idle;
      Copy to Clipboard Toggle word wrap

      This is the actual tunnel that your data traffic flows through.

Next steps

A site-to-site VPN establishes a secure, encrypted tunnel between two distinct networks, seamlessly linking them across an insecure public network such as the internet. For example, this enables devices in a branch office to access resources at a corporate headquarters just as if they were all part of the same local network.

For authenticating the gateway devices, RSA keys are more secure than pre-shared keys (PSKs) because their asymmetric encryption eliminates the risk of a shared secret. Using RSA keys also simplifies deployment by avoiding the need for a certificate authority (CA), while still providing strong peer-to-peer authentication.

Perform the steps on both gateway devices.

Prerequisites

  • Routes in both networks ensure that the traffic to the remote networks is sent through the local VPN gateway devices.

Procedure

  1. If Libreswan is not yet installed, perform the following steps:

    1. Install the libreswan package:

      # dnf install libreswan
      Copy to Clipboard Toggle word wrap
    2. Initialize the Network Security Services (NSS) database:

      # ipsec initnss
      Copy to Clipboard Toggle word wrap

      The command creates the database in the /var/lib/ipsec/nss/ directory.

    3. Enable and start the ipsec service:

      # systemctl enable --now ipsec
      Copy to Clipboard Toggle word wrap
    4. Open the IPsec ports and protocols in the firewall:

      # firewall-cmd --permanent --add-service="ipsec"
      # firewall-cmd --reload
      Copy to Clipboard Toggle word wrap
  2. Create an RSA key pair:

    # ipsec newhostkey
    Copy to Clipboard Toggle word wrap

    The ipsec utility stores the key pair in the NSS database.

  3. Designate your peers. In an IPsec tunnel, you must designate one host as left and the other as right. This is an arbitrary choice. A common practice is to call your local host left and the remote host right.
  4. Display the Certificate Key Attribute ID (CKAID) on both the left and right peer:

    # ipsec showhostkey --list
    < 1> RSA keyid: <key_id> ckaid: <ckaid>
    Copy to Clipboard Toggle word wrap

    You require the CKAIDs of both peers in the next steps.

  5. Display the public keys:

    1. On the left peer, enter:

      # ipsec showhostkey --left --ckaid <ckaid_of_left_peer>
      	# rsakey AwEAAdKCx
      	leftrsasigkey=0sAwEAAdKCxpc9db48cehzQiQD...
      Copy to Clipboard Toggle word wrap
    2. On the right peer, enter:

      # ipsec showhostkey --right --ckaid <ckaid_of_right_peer>
      	# rsakey AwEAAcNWC
      	rightrsasigkey=0sAwEAAcNWCzZO+PR1j8WbO8X...
      Copy to Clipboard Toggle word wrap

    The commands display the public keys with the corresponding parameters that you must use in the configuration file.

  6. Create a .conf file for the connection in the /etc/ipsec.d/ directory. For example, create the /etc/ipsec.d/site-to-site.conf file with the following settings:

    conn <connection_name>
        # General setup and authentication type
        auto=start
        authby=rsasig
    
        # Site A
        left=<ip_address_or_fqdn_of_left_peer>
        leftid=@site_a
        leftrsasigkey=<public_key_of_left_peer>
        leftsubnet=192.0.2.0/24
    
        # Site B
        right=<ip_address_or_fqdn_of_right_peer>
        rightid=@site_b
        rightrsasigkey=<public_key_of_right_peer>
        rightsubnet={198.51.100.0/24, 203.0.113.0/24}
    Copy to Clipboard Toggle word wrap
    Note

    You can use the same configuration file on both gateway devices, and Libreswan identifies whether it is operating on the left or right host by using internal information. However, it is important that all values in left* parameters belong to one peer and the values in right* parameters belong to the other.

    The settings specified in the example include the following:

    conn <connection_name>
    Defines the connection name. The name is arbitrary, and Libreswan uses it to identify the connection. You must indent parameters in this connection by at least one space or tab.
    auto=<type>
    Controls how the connection is initiated. If you set the value to start, Libreswan activates the connection automatically when the service starts.
    authby=rsasig
    Enables RSA signature authentication for this connection.
    left=<ip_address_or_fqdn_of_left_peer> and right=<ip_address_or_fqdn_of_right_peer>
    Defines the IP address or DNS name of the peers.
    leftid=<id> and rightid=<id>
    Defines how each peer is identified during the Internet Key Exchange (IKE) negotiation process. This can be a fully-qualified domain name (FQDN), an IP address, or a literal string. In the latter case, precede the string with an @ sign.
    leftrsasigkey=<public_key> and rightrsasigkey=<public_key>
    Specifies the public key of the peers. Use the values displayed by the ipsec showhostkey command in a previous step.
    leftsubnet=<subnet> and rightsubnet=<subnet>
    Defines subnets in classless inter-domain routing (CIDR) format that are connected through the tunnel. If you want to tunnel multiple subnets on one side, specify them in curly brackets and separate them with a comma.
  7. Enable packet forwarding:

    # echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
    # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
    Copy to Clipboard Toggle word wrap
  8. Restart the ipsec service:

    # systemctl restart ipsec
    Copy to Clipboard Toggle word wrap

    If you use auto=start in the configuration file, the connection is automatically activated. With other methods, additional steps are required to activate the connection. For details, see the ipsec.conf(5) man page on your system.

Verification

  1. Display the IPsec status:

    # ipsec status
    Copy to Clipboard Toggle word wrap

    If the connection is successfully established, the output contains lines as follows:

    • Phase 1 of an Internet Key Exchange version 2 (IKEv2) negotiation has been successfully completed:

      #2: "<connection_name>":500 ESTABLISHED_IKE_SA (established IKE SA); REKEY in 28523s; REPLACE in 28793s; newest; idle;
      Copy to Clipboard Toggle word wrap

      The Security Association (SA) is now ready to negotiate the actual data encryption tunnels, known as child SAs or Phase 2 SAs.

    • A child SA has been established:

      #3: "<connection_name>":500 ESTABLISHED_CHILD_SA (established Child SA); REKEY in 28523s; REPLACE in 28793s; newest; eroute owner; IKE SA #2; idle;
      Copy to Clipboard Toggle word wrap

      This is the actual tunnel that your data traffic flows through.

  2. From a client in the local subnet, ping a client in the remote subnet.

Next steps

A host-to-site VPN establishes a secure, encrypted connection between an individual remote computer and a private network, allowing them to be seamlessly linked across an insecure public network, such as the internet. This is ideal for remote employees who need to access resources on their company’s internal network from their computer as if they were physically in the office.

For authentication, using digital certificates managed by a Certificate Authority (CA) offers a highly secure and scalable solution. Each connecting host and the gateway presents a certificate signed by a trusted CA. This method provides strong, verifiable authentication and simplifies user management. Access can be granted or revoked centrally at the CA, and Libreswan enforces this by checking each certificate against a certificate revocation list (CRL), denying access if a certificate appears on the list.

6.5.1. Setting up an IPsec gateway manually

You must configure the Libreswan IPsec gateway properly to enable secure remote access. Libreswan reads the server certificate, private key, and CA certificate from a Network Security Services (NSS) database.

The following example permits authenticated clients to access the internal 192.0.2.0/24 subnet and dynamically assigns an IP address from a virtual IP pool to each client. To maintain security, the gateway verifies that client certificates are issued by the same trusted CA and automatically uses a certificate revocation list (CRL) to ensure access is denied for any revoked certificates.

Prerequisites

  • The Public Key Cryptography Standards #12 (PKCS #12) file ~/file.p12 exists on the gateway with the following contents:

    • The private key of the server
    • The server certificate
    • The CA certificate
    • If required, intermediate certificates

    For details about creating a private key and certificate signing request (CSR), as well as about requesting a certificate from a CA, see your CA’s documentation.

  • The server certificate contains the following fields:

    • Extended Key Usage (EKU) is set to TLS Web Server Authentication.
    • Common Name (CN) or Subject Alternative Name (SAN) is set to the fully-qualified domain name (FQDN) of the gateway.
    • X509v3 CRL distribution points contains URLs to Certificate Revocation Lists (CRLs).
  • A return route for VPN client traffic is configured on the internal network, pointing to the VPN gateway.

Procedure

  1. If Libreswan is not yet installed:

    1. Install the libreswan package:

      # dnf install libreswan
      Copy to Clipboard Toggle word wrap
    2. Initialize the Network Security Services (NSS) database:

      # ipsec initnss
      Copy to Clipboard Toggle word wrap

      The command creates the database in the /var/lib/ipsec/nss/ directory.

    3. Enable and start the ipsec service:

      # systemctl enable --now ipsec
      Copy to Clipboard Toggle word wrap
    4. Open the IPsec ports and protocols in the firewall:

      # firewall-cmd --permanent --add-service="ipsec"
      # firewall-cmd --reload
      Copy to Clipboard Toggle word wrap
  2. Import the PKCS #12 file into the NSS database:

    # ipsec import ~/file.p12
    Enter password for PKCS12 file: <password>
    pk12util: PKCS12 IMPORT SUCCESSFUL
    correcting trust bits for Example-CA
    Copy to Clipboard Toggle word wrap
  3. Display the nicknames of the server and CA certificates:

    # certutil -L -d /var/lib/ipsec/nss/
    Certificate Nickname     Trust Attributes
                             SSL,S/MIME,JAR/XPI
    
    vpn-gateway              u,u,u
    Example-CA               CT,,
    ...
    Copy to Clipboard Toggle word wrap

    You need this information for the configuration file.

  4. Create a .conf file for the connection in the /etc/ipsec.d/ directory. For example, create the /etc/ipsec.d/host-to-site.conf file with the following settings:

    1. Add a config setup section to enable CRL checks:

      config setup
          crl-strict=yes
          crlcheckinterval=1h
      Copy to Clipboard Toggle word wrap

      The settings specified in the example include the following:

      crl-strict=yes
      Enables CRL checks. Authenticating clients are rejected if no CRL is available in the NSS database.
      crlcheckinterval=1h
      Re-fetches the CRL from the URL specified in the server’s certificate after the specified period.
    2. Add a section for the gateway:

      conn <connection_name>
          # General setup and authentication type
          auto=start
          ikev2=insist
          authby=rsasig
      
          # VPN gateway settings
          left=%defaultroute
          leftid=%fromcert
          leftcert="<server_certificate_nickname>"
          leftrsasigkey=%cert
          leftsendcert=always
          leftsubnet=192.0.2.0/24
          rekey=no
          mobike=yes
          narrowing=yes
      
          # Client-related settings
          right=%any
          rightid=%fromcert
          rightrsasigkey=%cert
          rightaddresspool=198.51.100.129-198.51.100.254
          rightmodecfgclient=yes
          modecfgclient=yes
          modecfgdns=192.0.2.5
          modecfgdomains="example.com"
      
          # Dead Peer Detection
          dpddelay=30
          dpdtimeout=120
          dpdaction=clear
      Copy to Clipboard Toggle word wrap

      The settings specified in the example include the following:

      ikev2=insist
      Defines the modern IKEv2 protocol as the only allowed protocol without fallback to IKEv1.
      left=%defaultroute
      Dynamically sets the IP address of the default route interface when the ipsec service starts. Alternatively, you can set the left parameter to the IP address or the FQDN of the host.
      leftid=%fromcert and rightid=%fromcert
      Configures Libreswan to retrieve the identity from the distinguished name (DN) field of the certificate.
      leftcert="<server_certificate_nickname>"
      Sets the nickname of the server’s certificate used in the NSS database.
      leftrsasigkey=%cert and rightrsasigkey=%cert
      Configures Libreswan to use the RSA public key embedded in the certificate.
      leftsendcert=always
      Instructs the gateway to always send the certificate, so that clients can validate it against the CA certificate.
      leftsubnet=<subnets>
      Specifies the subnets connected to the gateway that clients can access through the tunnel.
      mobike=yes
      Enables clients to seamlessly roam among networks.
      rightaddresspool=<ip_range>
      Specifies from which range the gateway can assign IP addresses to the clients.
      modecfgclient=yes
      Enables clients to receive the DNS server IP set in the modecfgdns parameter and the DNS search domain set in modecfgdomains.

    For details about all parameters used in the example, see the ipsec.conf(5) man page on your system.

  5. Enable packet forwarding:

    # echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
    # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
    Copy to Clipboard Toggle word wrap
  6. Restart the ipsec service:

    # systemctl restart ipsec
    Copy to Clipboard Toggle word wrap

    If you use auto=start in the configuration file, the connection is automatically activated. With other methods, additional steps are required to activate the connection. For details, see the ipsec.conf(5) man page on your system.

Verification

  1. Configure a client and connect to the VPN gateway.
  2. Check if the service loaded the CRL and added the entries to the NSS database:

    # ipsec listcrls
    
    List of CRLs:
    
    issuer: CN=Example-CA
    revoked certs: 1
    updates: this Tue Jul 15 10:22:36 2025
             next Sun Jan 11 10:22:36 2026
    
    List of CRL fetch requests:
    
    Jul 15 15:13:56 2025, trials: 1
           issuer:  'CN=Example-CA'
           distPts: 'https://ca.example.com/crl.pem'
    Copy to Clipboard Toggle word wrap

Next steps:

To access resources on the remote private network, users must first configure an IPsec VPN connection. The GNOME Settings application provides a graphical solution to create an IPsec VPN connection profile in NetworkManager and to establish the tunnel.

Prerequisites

  • You configured the IPsec VPN gateway.
  • The NetworkManager-libreswan-gnome package is installed.
  • The PKCS #12 file ~/file.p12 exists on the client with the following contents:

    • The private key of the user
    • The user certificate
    • The CA certificate
    • If required, intermediate certificates

    For details about creating a private key and certificate signing request (CSR), as well as about requesting a certificate from a CA, see your CA’s documentation.

  • The Extended Key Usage (EKU) in the certificate is set to TLS Web Client Authentication.

Procedure

  1. Initialize the Network Security Services (NSS) database:

    # ipsec initnss
    Copy to Clipboard Toggle word wrap

    The command creates the database in the /var/lib/ipsec/nss/ directory.

  2. Import the PKCS #12 file into the NSS database:

    # ipsec import ~/file.p12
    Enter password for PKCS12 file: <password>
    pk12util: PKCS12 IMPORT SUCCESSFUL
    correcting trust bits for Example-CA
    Copy to Clipboard Toggle word wrap
  3. Display the nicknames of the user and CA certificates:

    # certutil -L -d /var/lib/ipsec/nss/
    Certificate Nickname     Trust Attributes
                             SSL,S/MIME,JAR/XPI
    
    user                     u,u,u
    Example-CA               CT,,
    ...
    Copy to Clipboard Toggle word wrap

    You require this information in the configuration file.

  4. Press the Super key, type Settings, and press Enter to open the GNOME Settings application.
  5. Click the + button next to the VPN entry.
  6. Select IPsec based VPN from the list.
  7. On the Identity tab, fill the fields as follows:

    Expand
    Table 6.1. Identity tab settings
    Field nameValueCorresponding ipsec.conf parameter

    Name

    <networkmanager_profile_name>

    N/A

    Gateway

    <ip_address_or_fqdn_of_the_gateway>

    right

    Type

    IKEv2 (certificate)

    authby

    Group name

    %fromcert

    leftid

    Certificate name

    <user_certificate_nickname>

    leftcert

    Remote ID

    %fromcert

    rightid

  8. Click Advanced.
  9. In the Advanced properties window, fill the fields of the Connectivity tab as follows:

    Expand
    Table 6.2. Connectivity tab settings
    Field nameValueCorresponding ipsec.conf parameter

    Remote Network

    192.0.2.0/24

    rightsubnet

    Narrowing

    Selected

    narrowing

    Enable MOBIKE

    yes

    mobike

    Delay

    30

    dpddelay

    Timeout

    120

    dpdtimeout

    Action

    Clear

    dpdaction

  10. Click Apply to return to the connection settings.
  11. Click Apply to save the connection.
  12. In the Network tab of the Settings application, toggle the switch next to the VPN profile to activate the connection.

Verification

  • Establish a connection to a host in the remote network or ping it.

Next steps

An IPsec mesh creates a fully interconnected network where every server can communicate securely and directly with every other server. This is ideal for distributed database clusters or high-availability environments that span multiple data centers or cloud providers. Establishing a direct, encrypted tunnel between each pair of servers ensures secure communication without a central bottleneck.

For authentication, using digital certificates managed by a Certificate Authority (CA) offers a highly secure and scalable solution. Each host in the mesh presents a certificate signed by a trusted CA. This method provides strong, verifiable authentication and simplifies user management. Access can be granted or revoked centrally at the CA, and Libreswan enforces this by checking each certificate against a certificate revocation list (CRL), denying access if a certificate appears on the list.

Prerequisites

  • A Public Key Cryptography Standards #12 (PKCS #12) file exists on each peer in the mesh with the following contents:

    • The private key of the server
    • The server certificate
    • The CA certificate
    • If required, intermediate certificates

    For details about creating a private key and certificate signing request (CSR), as well as about requesting a certificate from a CA, see your CA’s documentation.

  • The server certificate contains the following fields:

    • Extended Key Usage (EKU) is set to TLS Web Server Authentication.
    • Common Name (CN) or Subject Alternative Name (SAN) is set to the fully-qualified domain name (FQDN) of the host.
    • X509v3 CRL distribution points contains URLs to Certificate Revocation Lists (CRLs).

Procedure

  1. If Libreswan is not yet installed, perform the following steps:

    1. Install the libreswan package:

      # dnf install libreswan
      Copy to Clipboard Toggle word wrap
    2. Initialize the Network Security Services (NSS) database:

      # ipsec initnss
      Copy to Clipboard Toggle word wrap

      The command creates the database in the /var/lib/ipsec/nss/ directory.

    3. Enable and start the ipsec service:

      # systemctl enable --now ipsec
      Copy to Clipboard Toggle word wrap
    4. Open the IPsec ports and protocols in the firewall:

      # firewall-cmd --permanent --add-service="ipsec"
      # firewall-cmd --reload
      Copy to Clipboard Toggle word wrap
  2. Import the PKCS #12 file into the NSS database:

    # ipsec import <file>.p12
    Enter password for PKCS12 file: <password>
    pk12util: PKCS12 IMPORT SUCCESSFUL
    correcting trust bits for Example-CA
    Copy to Clipboard Toggle word wrap
  3. Display the nicknames of the server and CA certificates:

    # certutil -L -d /var/lib/ipsec/nss/
    Certificate Nickname     Trust Attributes
                             SSL,S/MIME,JAR/XPI
    
    server1                  u,u,u
    Example-CA               CT,,
    ...
    Copy to Clipboard Toggle word wrap

    You need this information for the configuration file.

  4. Create a .conf file for the connection in the /etc/ipsec.d/ directory. For example, create the /etc/ipsec.d/mesh.conf file with the following settings:

    1. Add a config setup section to enable CRL checks:

      config setup
          crl-strict=yes
          crlcheckinterval=1h
      Copy to Clipboard Toggle word wrap

      The settings specified in the example include the following:

      crl-strict=yes
      Enables CRL checks. Authenticating peers are rejected if no CRL is available in the NSS database.
      crlcheckinterval=1h
      Re-fetches the CRL from the URL specified in the server’s certificate after the specified period.
    2. Add a section that enforces traffic among members in the mesh:

      conn <connection_name>
          # General setup and authentication type
          auto=ondemand
          authby=rsasig
      
          # Local settings settings
          left=%defaultroute
          leftid=%fromcert
          leftcert="<server_certificate_nickname>"
          leftrsasigkey=%cert
          leftsendcert=always
          failureshunt=drop
          type=transport
      
          # Settings related to other peers in the mesh
          right=%opportunisticgroup
          rightid=%fromcert
      Copy to Clipboard Toggle word wrap

      The settings specified in the example include the following:

      left=%defaultroute
      Dynamically sets the IP address of the default route interface when the ipsec service starts. Alternatively, you can set the left parameter to the IP address or the FQDN of the host.
      leftid=%fromcert and rightid=%fromcert
      Configures Libreswan to retrieve the identity from the distinguished name (DN) field of the certificate.
      leftcert="<server_certificate_nickname>"
      Sets the nickname of the server’s certificate used in the NSS database.
      leftrsasigkey=%cert
      Configures Libreswan to use the RSA public key embedded in the certificate.
      leftsendcert=always
      Instructs the peer to always send the certificate, so that peers can validate it against the CA certificate.
      failureshunt=drop
      Enforces encryption and drops traffic if IPsec negotiation fails. This is critical for a secure mesh.
      right=%opportunisticgroup
      Specifies that the connection should apply to a dynamic group of remote peers defined in a policy file. This enables Libreswan to instantiate IPsec tunnels opportunistically for each listed IP or subnet in that group.

    For details about all parameters used in the example, see the ipsec.conf(5) man page on your system.

  5. Create the /etc/ipsec.d/policies/server-mesh policy file that specifies the peers or subnets in classless inter-domain routing (CIDR) format:

    192.0.2.0/24
    198.51.100.0/24
    Copy to Clipboard Toggle word wrap

    With these settings, the ipsec service encrypts traffic between hosts in these subnets. If a host is not configured as a member of the IPsec mesh, communication between this host and the mesh members fails.

  6. Restart the ipsec service:

    # systemctl restart ipsec
    Copy to Clipboard Toggle word wrap
  7. Repeat the procedure on every host in the subnets you specified in the policy file.

Verification

  1. Send traffic to a host in the mesh to establish the tunnel. For example, ping the host:

    # ping -c3 <peer_in_mesh>
    Copy to Clipboard Toggle word wrap
  2. Display the IPsec status:

    # ipsec status
    Copy to Clipboard Toggle word wrap

    If the connection is successfully established, the output contains lines as follows for the peer:

    • Phase 1 of an Internet Key Exchange version 2 (IKEv2) negotiation has been successfully completed:

      #1: "<connection_name>#192.0.2.0/24"[1] ...192.0.2.2:500 ESTABLISHED_IKE_SA (established IKE SA); REKEY in 12822s; REPLACE in 13875s; newest; idle;
      Copy to Clipboard Toggle word wrap

      The Security Association (SA) is now ready to negotiate the actual data encryption tunnels, known as child SAs or Phase 2 SAs.

    • A child SA has been established:

      #2: "<connection_name>#192.0.2.0/24"[1] ...192.0.2.2:500 ESTABLISHED_CHILD_SA (established Child SA); REKEY in 13071s; REPLACE in 13875s; newest; eroute owner; IKE SA #1; idle;
      Copy to Clipboard Toggle word wrap

      This is the actual tunnel that your data traffic flows through.

  3. Check if the service loaded the CRL and added the entries to the NSS database:

    # ipsec listcrls
    
    List of CRLs:
    
    issuer: CN=Example-CA
    revoked certs: 1
    updates: this Tue Jul 15 10:22:36 2025
             next Sun Jan 11 10:22:36 2026
    
    List of CRL fetch requests:
    
    Jul 15 15:13:56 2025, trials: 1
           issuer:  'CN=Example-CA'
           distPts: 'https://ca.example.com/crl.pem'
    Copy to Clipboard Toggle word wrap

Next steps

6.7. Protecting the IPsec NSS database with a password

By default, only the root user can access the IPsec Network Security Services (NSS) database in the /var/lib/ipsec/nss/ directory. If you want, you can additionally protect the database with a password. For example, this is required if you run RHEL in Federal Information Processing Standard (FIPS) mode.

Prerequisites

  • The /var/lib/ipsec/nss/ directory contains the NSS database.

Procedure

  1. Enable password protection for the Libreswan NSS database:

    # certutil -W -d /var/lib/ipsec/nss/
    Copy to Clipboard Toggle word wrap
  2. Enter the current password:

    Enter Password or Pin for "NSS Certificate DB": <password>
    Copy to Clipboard Toggle word wrap

    If the database is currently not protected by a password, press Enter.

  3. Enter the new password:

    Enter new password: <new_password>
    Re-enter password: <new_password>
    Copy to Clipboard Toggle word wrap
  4. To unlock the database, the ipsec service requires the /etc/ipsec.d/nsspassword file. Create the file with the following content:

    • If the host does not run in FIPS mode:

      NSS Certificate DB:<password>
      Copy to Clipboard Toggle word wrap
    • If the host runs in FIPS mode:

      NSS FIPS 140-2 Certificate DB:<password>
      Copy to Clipboard Toggle word wrap
  5. Set secure permissions on the /etc/ipsec.d/nsspassword file:

    # chmod 600 /etc/ipsec.d/nsspassword
    # chown root:root /etc/ipsec.d/nsspassword
    Copy to Clipboard Toggle word wrap
  6. Restart the ipsec service:

    # systemctl restart ipsec
    Copy to Clipboard Toggle word wrap

Verification

  1. Verify that the ipsec service is running:

    # systemctl is-active ipsec
    Copy to Clipboard Toggle word wrap

    If the command returns active, the service successfully uses the password file to unlock the NSS database.

  2. Perform an action on the NSS database that requires the password. For example, display the private keys:

    # certutil -K -d /var/lib/ipsec/nss/
    certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services"
    Enter Password or Pin for "NSS Certificate DB":
    Copy to Clipboard Toggle word wrap

    Verify that the command prompts for the password.

6.8. Using IPsec on a system with FIPS mode enabled

RHEL in Federal Information Processing Standard (FIPS) mode exclusively uses FIPS 140-2 or FIPS 140-3 validated cryptographic modules, automatically disabling legacy protocols and ciphers. Enabling FIPS mode is often a requirement for federal compliance and enhances system security.

The Libreswan IPsec implementation provided by RHEL is fully FIPS-compliant. When the system is in FIPS mode, Libreswan automatically uses the certified cryptographic modules without requiring any additional configuration, regardless of whether Libreswan is installed on a new FIPS-enabled system or when FIPS mode is activated on a system with an existing Libreswan VPN.

If FIPS mode is enabled, you can confirm that Libreswan is running in FIPS mode:

# ipsec whack --fipsstatus
FIPS mode enabled
Copy to Clipboard Toggle word wrap

To list the allowed algorithms and ciphers in Libreswan in FIPS mode, enter:

# ipsec pluto --selftest 2>&1
...
FIPS Encryption algorithms:
  AES_CCM_16  {256,192,*128} IKEv1:  ESP  IKEv2:  ESP  FIPS   aes_ccm, aes_ccm_c
  AES_CCM_12  {256,192,*128} IKEv1:  ESP  IKEv2:  ESP  FIPS   aes_ccm_b
  AES_CCM_8   {256,192,*128} IKEv1:  ESP  IKEv2:  ESP  FIPS   aes_ccm_a
...
Copy to Clipboard Toggle word wrap

6.9. Configuring TCP fallback for an IPsec VPN connection

Standard IPsec VPNs can fail on restrictive networks that block the UDP and Encapsulating Security Payload (ESP) protocols. To ensure connectivity in such environments, Libreswan can encapsulate all VPN traffic within a TCP connection, a method described in RFC 8229.

Important

Encapsulating VPN packets within TCP can reduce throughput and increase latency. For this reason, use TCP encapsulation only as a fallback option or if UDP-based connections are consistently blocked in your environment.

Prerequisites

  • The IPsec connection is configured.

Procedure

  1. Edit the /etc/ipsec.conf file, and make the following changes in the config setup section:

    1. Configure Libreswan to listen on a TCP port:

      listen-tcp=yes
      Copy to Clipboard Toggle word wrap
    2. By default, Libreswan listens on port 4500. If you want to use a different port, enter:

      tcp-remoteport=<port_number>
      Copy to Clipboard Toggle word wrap
    3. Decide whether TCP should be used as a fallback option if UDP is not available or permanent:

      • As a fallback option, enter:

        enable-tcp=fallback
        retransmit-timeout=5s
        Copy to Clipboard Toggle word wrap

        By default, Libreswan waits 60 seconds after a failed attempt to connect by using UDP before retrying the connection over TCP. Lowering the retransmit-timeout value shortens the delay, enabling the fallback protocol to initiate more quickly.

      • As a permanent replacement for UDP, enter:

        enable-tcp=yes
        Copy to Clipboard Toggle word wrap
  2. Restart the ipsec service:

    # systemctl restart ipsec
    Copy to Clipboard Toggle word wrap
  3. If you configured a TCP port other than the default 4500, open the port in the firewall:

    # firewall-cmd --permanent --add-port=<tcp_port>/tcp
    # firewall-cmd --reload
    Copy to Clipboard Toggle word wrap
  4. Repeat the procedure on the peers that use this gateway.

6.10. Enabling legacy ciphers and algorithms in Libreswan

RHEL uses system-wide cryptographic policies to enforce a consistent and secure baseline for all applications, including Libreswan. These policies ensure that IPsec and Internet Key Exchange (IKE) use only strong, modern encryption ciphers and algorithms by default. However, you might need to intentionally lower the security for backward compatibility with other IPsec peers.

The RHEL system-wide cryptographic policies create a special connection called %default. This connection sets the default values for the keyexchange, esp, and ike parameters.

Prerequisites

  • Libreswan is installed.

Procedure

  1. To override the defaults set by the RHEL system-wide cryptographic policies, add the keyexchange, esp, and ike parameters to your connection configuration and set them to the values you require. For example:

    conn <connection_name>
        keyexchange=ikev1
        ike=aes-sha2,aes-sha1;modp2048
        esp=aes-sha2,aes-sha1
        ...
    Copy to Clipboard Toggle word wrap
  2. Restart the ipsec service:

    # systemctl restart ipsec
    Copy to Clipboard Toggle word wrap

Both a DHCP server and Stateless Address Autoconfiguration (SLAAC) can add routes to a client’s routing table. For example, a malicious DHCP server can use this feature to force a host with VPN connection to redirect traffic through a physical interface instead of the VPN tunnel. This vulnerability is also known as TunnelVision and described in the CVE-2024-3661 vulnerability article.

To mitigate this vulnerability, you can assign the VPN connection to a dedicated routing table. This prevents the DHCP configuration or SLAAC from manipulating routing decisions for network packets intended for the VPN tunnel.

Follow the steps if at least one of the conditions applies to your environment:

  • At least one network interface uses DHCP or SLAAC.
  • Your network does not use mechanisms, such as DHCP snooping, that prevent a rogue DHCP server.
Important

Routing the entire traffic through the VPN prevents the host from accessing local network resources.

Procedure

  1. Decide which routing table you want to use. The following steps use table 75. By default, RHEL does not use the tables 1-254, and you can use any of them.
  2. Configure the VPN connection profile to place the VPN routes in a dedicated routing table:

    # nmcli connection modify <vpn_connection_profile> ipv4.route-table 75 ipv6.route-table 75
    Copy to Clipboard Toggle word wrap
  3. Set a low priority value for the table you used in the previous command:

    # nmcli connection modify <vpn_connection_profile> ipv4.routing-rules "priority 32345 from all table 75" ipv6.routing-rules "priority 32345 from all table 75"
    Copy to Clipboard Toggle word wrap

    The priority value can be any value between 1 and 32766. The lower the value, the higher the priority.

  4. Reconnect the VPN connection:

    # nmcli connection down <vpn_connection_profile>
    # nmcli connection up <vpn_connection_profile>
    Copy to Clipboard Toggle word wrap

Verification

  1. Display the IPv4 routes in table 75:

    # ip route show table 75
    ...
    192.0.2.0/24 via 192.0.2.254 dev vpn_device proto static metric 50
    default dev vpn_device proto static scope link metric 50
    Copy to Clipboard Toggle word wrap

    The output confirms that both the route to the remote network and the default gateway are assigned to routing table 75 and, therefore, all traffic is routed through the tunnel. If you set ipv4.never-default true in the VPN connection profile, a default route is not created and, therefore, not visible in this output.

  2. Display the IPv6 routes in table 75:

    # ip -6 route show table 75
    ...
    2001:db8:1::/64 dev vpn_device proto kernel metric 50 pref medium
    default dev vpn_device proto static metric 50 pref medium
    Copy to Clipboard Toggle word wrap

    The output confirms that both the route to the remote network and the default gateway are assigned to routing table 75 and, therefore, all traffic is routed through the tunnel. If you set ipv6.never-default true in the VPN connection profile, a default route is not created and, therefore, not visible in this output.

6.12. Configuring IPsec VPN connections by using RHEL system roles

You can use a Virtual Private Network (VPN) to establish a secure, encrypted tunnel over untrusted networks, such as the internet. Such a tunnel ensures the confidentiality and integrity of data in transit. Common use cases include connecting branch offices to a headquarters.

By using the vpn RHEL system role, you can automate the process of creating Libreswan IPsec VPN configurations.

Note

The vpn RHEL system role can only create VPN configurations that use pre-shared keys (PSKs) or certificates to authenticate peers to each other.

A host-to-host VPN establishes a direct, secure, and encrypted connection between two devices, allowing applications to communicate safely over an insecure network, such as the internet.

For authentication, a pre-shared key (PSK) is a straightforward method that uses a single, shared secret known only to the two peers. This approach is simple to configure and ideal for basic setups where ease of deployment is a priority. However, you must keep the key strictly confidential. An attacker with access to the key can compromise the connection.

By using the vpn RHEL system role, you can automate the process of creating IPsec host-to-host connections with PSK authentication. By default, the role creates a tunnel-based VPN.

Prerequisites

Procedure

  1. Create a playbook file, for example, ~/playbook.yml, with the following content:

    ---
    - name: Configuring VPN
      hosts: managed-node-01.example.com, managed-node-02.example.com
      tasks:
        - name: IPsec VPN with PSK authentication
          ansible.builtin.include_role:
            name: redhat.rhel_system_roles.vpn
          vars:
            vpn_connections:
              - hosts:
                  managed-node-01.example.com:
                  managed-node-02.example.com:
                auth_method: psk
                auto: start
            vpn_manage_firewall: true
            vpn_manage_selinux: true
    Copy to Clipboard Toggle word wrap

    The settings specified in the example playbook include the following:

    hosts: <list>

    Defines a YAML dictionary with the peers between which you want to configure a VPN. If an entry is not an Ansible managed node, you must specify its fully-qualified domain name (FQDN) or IP address in the hostname parameter, for example:

              ...
              - hosts:
                  ...
                  external-host.example.com:
                    hostname: 192.0.2.1
    Copy to Clipboard Toggle word wrap

    The role configures the VPN connection on each managed node. The connections are named <peer_A>-to-<peer_B>, for example, managed-node-01.example.com-to-managed-node-02.example.com. Note that the role cannot configure Libreswan on external (unmanaged) nodes. You must manually create the configuration on these peers.

    auth_method: psk
    Enables PSK authentication between the peers. The role uses openssl on the control node to create the PSK.
    auto: <startup_method>
    Specifies the startup method of the connection. Valid values are add, ondemand, start, and ignore. For details, see the ipsec.conf(5) man page on a system with Libreswan installed. The default value of this variable is null, which means no automatic startup operation.
    vpn_manage_firewall: true
    Defines that the role opens the required ports in the firewalld service on the managed nodes.
    vpn_manage_selinux: true
    Defines that the role sets the required SELinux port type on the IPsec ports.

    For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.vpn/README.md file on the control node.

  2. Validate the playbook syntax:

    $ ansible-playbook --syntax-check ~/playbook.yml
    Copy to Clipboard Toggle word wrap

    Note that this command only validates the syntax and does not protect against a wrong but valid configuration.

  3. Run the playbook:

    $ ansible-playbook ~/playbook.yml
    Copy to Clipboard Toggle word wrap

Verification

  • Confirm that the connections are successfully started, for example:

    # ansible managed-node-01.example.com -m shell -a 'ipsec trafficstatus | grep "managed-node-01.example.com-to-managed-node-02.example.com"'
    ...
    006 #3: "managed-node-01.example.com-to-managed-node-02.example.com", type=ESP, add_time=1741857153, inBytes=38622, outBytes=324626, maxBytes=2^63B, id='@managed-node-02.example.com'
    Copy to Clipboard Toggle word wrap

    Note that this command only succeeds if the VPN connection is active. If you set the auto variable in the playbook to a value other than start, you might need to manually activate the connection on the managed nodes first.

A host-to-host VPN establishes a direct, secure, and encrypted connection between two devices, allowing applications to communicate safely over an insecure network, such as the internet.

For authentication, a pre-shared key (PSK) is a straightforward method that uses a single, shared secret known only to the two peers. This approach is simple to configure and ideal for basic setups where ease of deployment is a priority. However, you must keep the key strictly confidential. An attacker with access to the key can compromise the connection.

For example, to enhance security by minimizing the risk of control messages being intercepted or disrupted, you can configure separate connections for both the data traffic and the control traffic. By using the vpn RHEL system role, you can automate the process of creating IPsec host-to-host connections with a separate data and control plane and PSK authentication.

Prerequisites

Procedure

  1. Create a playbook file, for example, ~/playbook.yml, with the following content:

    ---
    - name: Configuring VPN
      hosts: managed-node-01.example.com, managed-node-02.example.com
      tasks:
        - name: IPsec VPN with PSK authentication
          ansible.builtin.include_role:
            name: redhat.rhel_system_roles.vpn
          vars:
            vpn_connections:
              - name: control_plane_vpn
                hosts:
                  managed-node-01.example.com:
                    hostname: 203.0.113.1  # IP address for the control plane
                  managed-node-02.example.com:
                    hostname: 198.51.100.2 # IP address for the control plane
                auth_method: psk
                auto: start
              - name: data_plane_vpn
                hosts:
                  managed-node-01.example.com:
                    hostname: 10.0.0.1   # IP address for the data plane
                  managed-node-02.example.com:
                    hostname: 172.16.0.2 # IP address for the data plane
                auth_method: psk
                auto: start
            vpn_manage_firewall: true
            vpn_manage_selinux: true
    Copy to Clipboard Toggle word wrap

    The settings specified in the example playbook include the following:

    hosts: <list>

    Defines a YAML dictionary with the hosts between which you want to configure a VPN. The connections are named <name>-<IP_address_A>-to-<IP_address_B>, for example control_plane_vpn-203.0.113.1-to-198.51.100.2.

    The role configures the VPN connection on each managed node. Note that the role cannot configure Libreswan on external (unmanaged) nodes. You must manually create the configuration on these hosts.

    auth_method: psk
    Enables PSK authentication between the hosts. The role uses openssl on the control node to create the pre-shared key.
    auto: <startup_method>
    Specifies the startup method of the connection. Valid values are add, ondemand, start, and ignore. For details, see the ipsec.conf(5) man page on a system with Libreswan installed. The default value of this variable is null, which means no automatic startup operation.
    vpn_manage_firewall: true
    Defines that the role opens the required ports in the firewalld service on the managed nodes.
    vpn_manage_selinux: true
    Defines that the role sets the required SELinux port type on the IPsec ports.

    For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.vpn/README.md file on the control node.

  2. Validate the playbook syntax:

    $ ansible-playbook --syntax-check ~/playbook.yml
    Copy to Clipboard Toggle word wrap

    Note that this command only validates the syntax and does not protect against a wrong but valid configuration.

  3. Run the playbook:

    $ ansible-playbook ~/playbook.yml
    Copy to Clipboard Toggle word wrap

Verification

  • Confirm that the connections are successfully started, for example:

    # ansible managed-node-01.example.com -m shell -a 'ipsec trafficstatus | grep "control_plane_vpn-203.0.113.1-to-198.51.100.2"'
    ...
    006 #3: "control_plane_vpn-203.0.113.1-to-198.51.100.2", type=ESP, add_time=1741860073, inBytes=0, outBytes=0, maxBytes=2^63B, id='198.51.100.2'
    Copy to Clipboard Toggle word wrap

    Note that this command only succeeds if the VPN connection is active. If you set the auto variable in the playbook to a value other than start, you might need to manually activate the connection on the managed nodes first.

A site-to-site VPN establishes a secure, encrypted tunnel between two distinct networks, seamlessly linking them across an insecure public network such as the internet. For example, this enables devices in a branch office to access resources at a corporate headquarters just as if they were all part of the same local network.

For authentication, a pre-shared key (PSK) is a straightforward method that uses a single, shared secret known only to the two peers. This approach is simple to configure and ideal for basic setups where ease of deployment is a priority. However, you must keep the key strictly confidential. An attacker with access to the key can compromise the connection.

By using the vpn RHEL system role, you can automate the process of creating IPsec site-to-site connections with PSK authentication. By default, the role creates a tunnel-based VPN.

Prerequisites

Procedure

  1. Create a playbook file, for example, ~/playbook.yml, with the following content:

    ---
    - name: Configuring VPN
      hosts: managed-node-01.example.com, managed-node-02.example.com
      tasks:
        - name: IPsec VPN with PSK authentication
          ansible.builtin.include_role:
            name: redhat.rhel_system_roles.vpn
          vars:
            vpn_connections:
              - hosts:
                  managed-node-01.example.com:
                    subnets:
                      - 192.0.2.0/24
                  managed-node-02.example.com:
                    subnets:
                      - 198.51.100.0/24
                      - 203.0.113.0/24
                auth_method: psk
                auto: start
            vpn_manage_firewall: true
            vpn_manage_selinux: true
    Copy to Clipboard Toggle word wrap

    The settings specified in the example playbook include the following:

    hosts: <list>

    Defines a YAML dictionary with the gateways between which you want to configure a VPN. If an entry is not an Ansible-managed node, you must specify its fully-qualified domain name (FQDN) or IP address in the hostname parameter, for example:

              ...
              - hosts:
                  ...
                  external-host.example.com:
                    hostname: 192.0.2.1
    Copy to Clipboard Toggle word wrap

    The role configures the VPN connection on each managed node. The connections are named <gateway_A>-to-<gateway_B>, for example, managed-node-01.example.com-to-managed-node-02.example.com. Note that the role cannot configure Libreswan on external (unmanaged) nodes. You must manually create the configuration on these peers.

    subnets: <yaml_list_of_subnets>
    Defines subnets in classless inter-domain routing (CIDR) format that are connected through the tunnel.
    auth_method: psk
    Enables PSK authentication between the peers. The role uses openssl on the control node to create the PSK.
    auto: <startup_method>
    Specifies the startup method of the connection. Valid values are add, ondemand, start, and ignore. For details, see the ipsec.conf(5) man page on a system with Libreswan installed. The default value of this variable is null, which means no automatic startup operation.
    vpn_manage_firewall: true
    Defines that the role opens the required ports in the firewalld service on the managed nodes.
    vpn_manage_selinux: true
    Defines that the role sets the required SELinux port type on the IPsec ports.

    For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.vpn/README.md file on the control node.

  2. Validate the playbook syntax:

    $ ansible-playbook --syntax-check ~/playbook.yml
    Copy to Clipboard Toggle word wrap

    Note that this command only validates the syntax and does not protect against a wrong but valid configuration.

  3. Run the playbook:

    $ ansible-playbook ~/playbook.yml
    Copy to Clipboard Toggle word wrap

Verification

  • Confirm that the connections are successfully started, for example:

    # ansible managed-node-01.example.com -m shell -a 'ipsec trafficstatus | grep "managed-node-01.example.com-to-managed-node-02.example.com"'
    ...
    006 #3: "managed-node-01.example.com-to-managed-node-02.example.com", type=ESP, add_time=1741857153, inBytes=38622, outBytes=324626, maxBytes=2^63B, id='@managed-node-02.example.com'
    Copy to Clipboard Toggle word wrap

    Note that this command only succeeds if the VPN connection is active. If you set the auto variable in the playbook to a value other than start, you might need to manually activate the connection on the managed nodes first.

An IPsec mesh creates a fully interconnected network where every server can communicate securely and directly with every other server. This is ideal for distributed database clusters or high-availability environments that span multiple data centers or cloud providers. Establishing a direct, encrypted tunnel between each pair of servers ensures secure communication without a central bottleneck.

For authentication, using digital certificates managed by a Certificate Authority (CA) offers a highly secure and scalable solution. Each host in the mesh presents a certificate signed by a trusted CA. This method provides strong, verifiable authentication and simplifies user management. Access can be granted or revoked centrally at the CA, and Libreswan enforces this by checking each certificate against a certificate revocation list (CRL), denying access if a certificate appears on the list.

By using the vpn RHEL system role, you can automate configuring a VPN mesh with certificate-based authentication among managed nodes.

Prerequisites

  • You have prepared the control node and the managed nodes.
  • You are logged in to the control node as a user who can run playbooks on the managed nodes.
  • The account you use to connect to the managed nodes has sudo permissions on them.
  • You prepared a PKCS #12 file for each managed node:

    • Each file contains:

      • The private key of the server
      • The server certificate
      • The CA certificate
      • If required, intermediate certificates
    • The files are named <managed_node_name_as_in_the_inventory>.p12.
    • The files are stored in the same directory as the playbook.
    • The server certificate contains the following fields:

      • Extended Key Usage (EKU) is set to TLS Web Server Authentication.
      • Common Name (CN) or Subject Alternative Name (SAN) is set to the fully-qualified domain name (FQDN) of the host.
      • X509v3 CRL distribution points contains URLs to Certificate Revocation Lists (CRLs).

Procedure

  1. Edit the ~/inventory file, and append the cert_name variable:

    managed-node-01.example.com cert_name=managed-node-01.example.com
    managed-node-02.example.com cert_name=managed-node-02.example.com
    managed-node-03.example.com cert_name=managed-node-03.example.com
    Copy to Clipboard Toggle word wrap

    Set the cert_name variable to the value of the common name (CN) field used in the certificate for each host. Typically, the CN field is set to the fully-qualified domain name (FQDN).

  2. Store your sensitive variables in an encrypted file:

    1. Create the vault:

      $ ansible-vault create ~/vault.yml
      New Vault password: <vault_password>
      Confirm New Vault password: <vault_password>
      Copy to Clipboard Toggle word wrap
    2. After the ansible-vault create command opens an editor, enter the sensitive data in the <key>: <value> format:

      pkcs12_pwd: <password>
      Copy to Clipboard Toggle word wrap
    3. Save the changes, and close the editor. Ansible encrypts the data in the vault.
  3. Create a playbook file, for example, ~/playbook.yml, with the following content:

    - name: Configuring VPN
      hosts: managed-node-01.example.com, managed-node-02.example.com, managed-node-03.example.com
      vars_files:
        - ~/vault.yml
      tasks:
        - name: Install LibreSwan
          ansible.builtin.package:
            name: libreswan
            state: present
    
        - name: Identify the path to IPsec NSS database
          ansible.builtin.set_fact:
            nss_db_dir: "{{ '/etc/ipsec.d/' if
              ansible_distribution in ['CentOS', 'RedHat']
              and ansible_distribution_major_version is version('8', '=')
              else '/var/lib/ipsec/nss/' }}"
    
        - name: Locate IPsec NSS database files
          ansible.builtin.find:
            paths: "{{ nss_db_dir }}"
            patterns: "*.db"
          register: db_files
    
        - name: Initialize IPsec NSS database if not initialized
          ansible.builtin.command:
            cmd: ipsec initnss
          when: db_files.matched == 0
    
        - name: Copy PKCS #12 file to the managed node
          ansible.builtin.copy:
            src: "~/{{ inventory_hostname }}.p12"
            dest: "/etc/ipsec.d/{{ inventory_hostname }}.p12"
            mode: 0600
    
        - name: Import PKCS #12 file in IPsec NSS database
          ansible.builtin.shell:
            cmd: 'pk12util -d {{ nss_db_dir }} -i /etc/ipsec.d/{{ inventory_hostname }}.p12 -W "{{ pkcs12_pwd }}"'
    
        - name: Remove PKCS #12 file
          ansible.builtin.file:
            path: "/etc/ipsec.d/{{ inventory_hostname }}.p12"
            state: absent
    
        - name: Opportunistic mesh IPsec VPN with certificate-based authentication
          ansible.builtin.include_role:
            name: redhat.rhel_system_roles.vpn
          vars:
            vpn_connections:
              - opportunistic: true
                auth_method: cert
                policies:
                  - policy: private
                    cidr: default
                  - policy: private
                    cidr: 192.0.2.0/24
                  - policy: clear
                    cidr: 192.0.2.1/32
            vpn_manage_firewall: true
            vpn_manage_selinux: true
    Copy to Clipboard Toggle word wrap

    The settings specified in the example playbook include the following:

    opportunistic: true
    Enables an opportunistic mesh among multiple hosts. The policies variable defines for which subnets and hosts traffic must or can be encrypted and which of them should continue using plain text connections.
    auth_method: cert
    Enables certificate-based authentication. This requires that you specify the nickname of each managed node’s certificate in the inventory.
    policies: <list_of_policies>

    Defines the Libreswan policies in YAML list format.

    The default policy is private-or-clear. To change it to private, the above playbook contains an according policy for the default cidr entry.

    To prevent a loss of the SSH connection during the execution of the playbook if the Ansible control node is in the same IP subnet as the managed nodes, add a clear policy for the control node’s IP address. For example, if the mesh should be configured for the 192.0.2.0/24 subnet and the control node uses the IP address 192.0.2.1, you require a clear policy for 192.0.2.1/32 as shown in the playbook.

    For details about policies, see the ipsec.conf(5) man page on a system with Libreswan installed.

    vpn_manage_firewall: true
    Defines that the role opens the required ports in the firewalld service on the managed nodes.
    vpn_manage_selinux: true
    Defines that the role sets the required SELinux port type on the IPsec ports.

    For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.vpn/README.md file on the control node.

  4. Validate the playbook syntax:

    $ ansible-playbook --ask-vault-pass --syntax-check ~/playbook.yml
    Copy to Clipboard Toggle word wrap

    Note that this command only validates the syntax and does not protect against a wrong but valid configuration.

  5. Run the playbook:

    $ ansible-playbook --ask-vault-pass ~/playbook.yml
    Copy to Clipboard Toggle word wrap

Verification

  1. On a node in the mesh, ping another node to activate the connection:

    [root@managed-node-01]# ping managed-node-02.example.com
    Copy to Clipboard Toggle word wrap
  2. Confirm that the connection is active:

    [root@managed-node-01]# ipsec trafficstatus
    006 #2: "private#192.0.2.0/24"[1] ...192.0.2.2, type=ESP, add_time=1741938929, inBytes=372408, outBytes=545728, maxBytes=2^63B, id='CN=managed-node-02.example.com'
    Copy to Clipboard Toggle word wrap

6.13. Configuring IPsec VPN connections by using nmstatectl

You can use a Virtual Private Network (VPN) to establish a secure, encrypted tunnel over untrusted networks, such as the internet. Such a tunnel ensures the confidentiality and integrity of data in transit. Common use cases include connecting branch offices to a headquarters.

You can use the nmstatectl utility to configure Libreswan IPsec VPN connections through the Nmstate API. The nmstatectl utility is a command-line tool to manage host networking through the declarative Nmstate API. Instead of running multiple imperative commands to configure an interface, you define the expected state in a YAML file. Nmstate then takes this definition and applies it to the system. A key advantage of this approach is an atomic result. Nmstate ensures that the resulting configuration precisely matches your YAML definition. If any part of the configuration fails to apply, it automatically rolls back all changes and prevents the system from entering an incorrect or broken network state.

Note

Due to the design of the NetworkManager-libreswan plugin, you can use nmstatectl only on one peer and must manually configure Libreswan on the other peer.

A host-to-host VPN establishes a direct, secure, and encrypted connection between two devices, allowing applications to communicate safely over an insecure network, such as the internet.

For authentication, RSA keys are more secure than pre-shared keys (PSKs) because their asymmetric encryption eliminates the risk of a shared secret. Using RSA keys also simplifies deployment by avoiding the need for a certificate authority (CA), while still providing strong peer-to-peer authentication.

You can use the Nmstate API to configure a connection with an existing Libreswan IPsec host. In this case, Nmstate ensures that the resulting configuration matches the definition in the YAML file or it automatically rolls back the changes to avoid an incorrect state of the system. Note that Nmstate validates only the state and does not protect against a wrong but valid configuration.

Note

In general, the choice of which host is named left and right is arbitrary. However, NetworkManager always uses the term left for the local host and right for the remote host.

Prerequisites

  • The remote peer runs Libreswan IPsec and is prepared for a host-to-host connection.

    Due to the design of the NetworkManager-libreswan plugin, Nmstate cannot communicate with other peers that also use this plugin for the same connection.

Procedure

  1. If Libreswan is not yet installed, perform the following steps:

    1. Install the required packages:

      # dnf install nmstate libreswan NetworkManager-libreswan
      Copy to Clipboard Toggle word wrap
    2. Restart the NetworkManager service:

      # systemctl restart NetworkManager
      Copy to Clipboard Toggle word wrap
    3. Initialize the Network Security Services (NSS) database:

      # ipsec initnss
      Copy to Clipboard Toggle word wrap

      The command creates the database in the /var/lib/ipsec/nss/ directory.

    4. Open the IPsec ports and protocols in the firewall:

      # firewall-cmd --permanent --add-service="ipsec"
      # firewall-cmd --reload
      Copy to Clipboard Toggle word wrap
  2. Create an RSA key pair:

    # ipsec newhostkey
    Copy to Clipboard Toggle word wrap

    The ipsec utility stores the key pair in the NSS database.

  3. Display the Certificate Key Attribute ID (CKAID) on both the left and right peers:

    # ipsec showhostkey --list
    < 1> RSA keyid: <key_id> ckaid: <ckaid>
    Copy to Clipboard Toggle word wrap

    You require the CKAIDs of both peers in the next steps.

  4. Display the public keys:

    1. On the left peer, enter:

      # ipsec showhostkey --left --ckaid <ckaid_of_left_peer>
              # rsakey AwEAAdKCx
              leftrsasigkey=0sAwEAAdKCxpc9db48cehzQiQD...
      Copy to Clipboard Toggle word wrap
    2. On the right peer, enter:

      # ipsec showhostkey --right --ckaid <ckaid_of_right_peer>
              # rsakey AwEAAcNWC
              rightrsasigkey=0sAwEAAcNWCzZO+PR1j8WbO8X...
      Copy to Clipboard Toggle word wrap

    The commands display the public keys with the corresponding parameters that you must use in the configuration file.

  5. Create a YAML file, for example ~/ipsec-host-to-host-rsa-auth.yml, with the following content:

    ---
    interfaces:
    - name: '<connection_name>'
      type: ipsec
      libreswan:
        ikev2: insist
    
        left: <ip_address_or_fqdn_of_left_peer>
        leftid: peer_b
        leftrsasigkey: <public_key_of_left_peer>
        leftmodecfgclient: false
    
        right: <ip_address_or_fqdn_of_right_peer>
        rightid: peer_a
        rightrsasigkey: <public_key_of_right_peer>
        rightsubnet: <ip_address_of_right_peer>/32
    Copy to Clipboard Toggle word wrap

    The settings specified in the example include the following:

    ikev2: insist
    Defines the modern IKEv2 protocol as the only allowed protocol without fallback to IKEv1. This setting is mandatory in a host-to-host configuration with Nmstate.
    left=<ip_address_or_fqdn_of_left_peer> and right=<ip_address_or_fqdn_of_right_peer>
    Defines the IP address or DNS name of the peers.
    leftid=<id> and rightid=<id>
    Defines how each peer is identified during the Internet Key Exchange (IKE) negotiation process. This can be an IP address or a literal string. Note that NetworkManager interprets all values other than IP addresses as a literal string and internally adds a leading @ sign. This requires that the Libreswan peer also uses literal strings as IDs or authentication fails.
    leftrsasigkey=<public_key> and rightrsasigkey=<public_key>
    Specifies the public key of the peers. Use the values displayed by the ipsec showhostkey command in a previous step.
    leftmodecfgclient: false
    Disables dynamic configuration on this host. This setting is mandatory in a host-to-host configuration with Nmstate.
    rightsubnet: <ip_address_of_right_peer>/32
    Defines that the host can only access this peer. This setting is mandatory in a host-to-host configuration with Nmstate.
  6. Apply the settings to the system:

    # nmstatectl apply ~/ipsec-host-to-host-rsa-auth.yml
    Copy to Clipboard Toggle word wrap

Verification

  • Display the IPsec status:

    # ipsec status
    Copy to Clipboard Toggle word wrap

    If the connection is successfully established, the output contains lines as follows:

    • Phase 1 of an Internet Key Exchange version 2 (IKEv2) negotiation has been successfully completed:

      000 #1: "<connection_name>":500 STATE_V2_ESTABLISHED_IKE_SA (established IKE SA); REKEY in 27935s; REPLACE in 28610s; newest; idle;
      Copy to Clipboard Toggle word wrap

      The Security Association (SA) is now ready to negotiate the actual data encryption tunnels, known as child SAs or Phase 2 SAs.

    • A child SA has been established:

      000 #2: "<connection_name>":500 STATE_V2_ESTABLISHED_CHILD_SA (established Child SA); REKEY in 27671s; REPLACE in 28610s; IKE SA #1; idle;
      Copy to Clipboard Toggle word wrap

      This is the actual tunnel that your data traffic flows through.

Troubleshooting

  • To display the actual configuration NetworkManager passes to Libreswan, enter:

    # nmcli connection export <connection_name>
    Copy to Clipboard Toggle word wrap

    The output can help to identify deviating settings, such as IDs and keys, when you compare them with the Libreswan configuration on the remote host.

Next steps

A site-to-site VPN establishes a secure, encrypted tunnel between two distinct networks, seamlessly linking them across an insecure public network such as the internet. For example, this enables devices in a branch office to access resources at a corporate headquarter just as if they were all part of the same local network.

For authenticating the gateway devices, RSA keys are more secure than pre-shared keys (PSKs) because their asymmetric encryption eliminates the risk of a shared secret. Using RSA keys also simplifies deployment by avoiding the need for a certificate authority (CA), while still providing strong peer-to-peer authentication.

You can use the Nmstate API to configure a connection with an existing Libreswan IPsec gateway. In this case, Nmstate ensures that the resulting configuration matches the definition in the YAML file or it automatically rolls back the changes to avoid an incorrect state of the system. Note that Nmstate validates only the state and does not protect against a wrong but valid configuration.

Note

In general, the choice which host is named left and right is arbitrary. However, NetworkManager always uses the term left for the local host and right for the remote host.

Prerequisites

  • The remote gateway runs Libreswan IPsec and is prepared for a site-to-site connection.

    Due to the design of the NetworkManager-libreswan plugin, Nmstate cannot communicate with other peers that also use this plugin for the same connection.

Procedure

  1. If Libreswan is not yet installed, perform the following steps:

    1. Install the required packages:

      # dnf install nmstate libreswan NetworkManager-libreswan
      Copy to Clipboard Toggle word wrap
    2. Restart the NetworkManager service:

      # systemctl restart NetworkManager
      Copy to Clipboard Toggle word wrap
    3. Initialize the Network Security Services (NSS) database:

      # ipsec initnss
      Copy to Clipboard Toggle word wrap

      The command creates the database in the /var/lib/ipsec/nss/ directory.

    4. Open the IPsec ports and protocols in the firewall:

      # firewall-cmd --permanent --add-service="ipsec"
      # firewall-cmd --reload
      Copy to Clipboard Toggle word wrap
  2. Create an RSA key pair:

    # ipsec newhostkey
    Copy to Clipboard Toggle word wrap

    The ipsec utility stores the key pair in the NSS database.

  3. Display the Certificate Key Attribute ID (CKAID) on both the left and right peer:

    # ipsec showhostkey --list
    < 1> RSA keyid: <key_id> ckaid: <ckaid>
    Copy to Clipboard Toggle word wrap

    You require the CKAIDs of both peers in the following steps.

  4. Display the public keys:

    1. On the left peer, enter:

      # ipsec showhostkey --left --ckaid <ckaid_of_left_peer>
              # rsakey AwEAAdKCx
              leftrsasigkey=0sAwEAAdKCxpc9db48cehzQiQD...
      Copy to Clipboard Toggle word wrap
    2. On the right peer, enter:

      # ipsec showhostkey --right --ckaid <ckaid_of_right_peer>
              # rsakey AwEAAcNWC
              rightrsasigkey=0sAwEAAcNWCzZO+PR1j8WbO8X...
      Copy to Clipboard Toggle word wrap

    The commands display the public keys with the corresponding parameters that you must use in the configuration file.

  5. Create a YAML file, for example ~/ipsec-site-to-site-rsa-auth.yml, with the following content:

    ---
    interfaces:
    - name: '<connection_name>'
      type: ipsec
      libreswan:
        ikev2: insist
    
        left: <ip_address_or_fqdn_of_left_peer>
        leftid: peer_b
        leftrsasigkey: <public_key_of_left_peer>
        leftmodecfgclient: false
        leftsubnet: 198.51.100.0/24
    
        right: <ip_address_or_fqdn_of_right_peer>
        rightid: peer_a
        rightrsasigkey: <public_key_of_right_peer>
        rightsubnet: 192.0.2.0/24
    Copy to Clipboard Toggle word wrap

    The settings specified in the example include the following:

    ikev2: insist
    Defines the modern IKEv2 protocol as the only allowed protocol without fallback to IKEv1. This setting is mandatory in a site-to-site configuration with Nmstate.
    left=<ip_address_or_fqdn_of_left_peer> and right=<ip_address_or_fqdn_of_right_peer>
    Defines the IP address or DNS name of the peers.
    leftid=<id> and rightid=<id>
    Defines how each peer is identified during the Internet Key Exchange (IKE) negotiation process. This can be an IP address or a literal string. Note that NetworkManager interprets all values other than IP addresses as a literal string and internally adds a leading @ sign. This requires that the Libreswan peer also uses literal strings as IDs or authentication fails.
    leftrsasigkey=<public_key> and rightrsasigkey=<public_key>
    Specifies the public key of the peers. Use the values displayed by the ipsec showhostkey command in a previous step.
    leftmodecfgclient: false
    Disables dynamic configuration on this host. This setting is mandatory in a site-to-site configuration with Nmstate.
    leftsubnet=<subnet> and rightsubnet=<subnet>
    Defines subnets in classless inter-domain routing (CIDR) format that are connected through the tunnel.
  6. Enable packet forwarding:

    # echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
    # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
    Copy to Clipboard Toggle word wrap
  7. Apply the settings to the system:

    # nmstatectl apply ~/ipsec-site-to-site-rsa-auth.yml
    Copy to Clipboard Toggle word wrap

Verification

  1. Display the IPsec status:

    # ipsec status
    Copy to Clipboard Toggle word wrap

    If the connection is successfully established, the output contains lines as follows:

    • Phase 1 of an Internet Key Exchange version 2 (IKEv2) negotiation has been successfully completed:

      000 #1: "<connection_name>":500 STATE_V2_ESTABLISHED_IKE_SA (established IKE SA); REKEY in 27935s; REPLACE in 28610s; newest; idle;
      Copy to Clipboard Toggle word wrap

      The Security Association (SA) is now ready to negotiate the actual data encryption tunnels, known as child SAs or Phase 2 SAs.

    • A child SA has been established:

      000 #2: "<connection_name>":500 STATE_V2_ESTABLISHED_CHILD_SA (established Child SA); REKEY in 27671s; REPLACE in 28610s; IKE SA #1; idle;
      Copy to Clipboard Toggle word wrap

      This is the actual tunnel that your data traffic flows through.

  2. From a client in the local subnet, ping a client in the remote subnet.

Troubleshooting

  • To display the actual configuration NetworkManager passes to Libreswan, enter:

    # nmcli connection export <connection_name>
    Copy to Clipboard Toggle word wrap

    The output can help to identify deviating settings, such as IDs and keys, when you compare them with the Libreswan configuration on the remote host.

Next steps

To access resources on the remote private network, users must first configure an IPsec VPN connection. You can use the Nmstate API to configure a connection with an existing Libreswan IPsec gateway. In this case, Nmstate ensures that the resulting configuration matches the definition in the YAML file or it automatically rolls back the changes to avoid an incorrect state of the system. Note that Nmstate validates only the state and does not protect against a wrong but valid configuration.

Note

In general, the choice of which host is named left and right is arbitrary. However, NetworkManager always uses the term left for the local host and right for the remote host.

Prerequisites

  • The remote gateway runs Libreswan IPsec and is prepared for a host-to-site connection with certificate-based authentication.

    Due to the design of the NetworkManager-libreswan plugin, Nmstate cannot communicate with other peers that also use this plugin for the same connection.

  • The PKCS#12 file ~/file.p12 exists on the client with the following contents:

    • The private key of the user
    • The user certificate
    • The CA certificate
    • If required, intermediate certificates

    For details about creating a private key and certificate signing request (CSR), as well as about requesting a certificate from a CA, see your CA’s documentation.

  • The Extended Key Usage (EKU) in the certificate is set to TLS Web Client Authentication.

Procedure

  1. If Libreswan is not yet installed:

    1. Install the required packages:

      # dnf install nmstate libreswan NetworkManager-libreswan
      Copy to Clipboard Toggle word wrap
    2. Restart the NetworkManager service:

      # systemctl restart NetworkManager
      Copy to Clipboard Toggle word wrap
    3. Initialize the Network Security Services (NSS) database:

      # ipsec initnss
      Copy to Clipboard Toggle word wrap

      The command creates the database in the /var/lib/ipsec/nss/ directory.

    4. Open the IPsec ports and protocols in the firewall:

      # firewall-cmd --permanent --add-service="ipsec"
      # firewall-cmd --reload
      Copy to Clipboard Toggle word wrap
  2. Import the PKCS #12 file into the NSS database:

    # ipsec import ~/file.p12
    Enter password for PKCS12 file: <password>
    pk12util: PKCS12 IMPORT SUCCESSFUL
    correcting trust bits for Example-CA
    Copy to Clipboard Toggle word wrap
  3. Display the nicknames of the user and CA certificates:

    # certutil -L -d /var/lib/ipsec/nss/
    Certificate Nickname     Trust Attributes
                             SSL,S/MIME,JAR/XPI
    
    user                     u,u,u
    Example-CA               CT,,
    ...
    Copy to Clipboard Toggle word wrap

    You require this information in the Nmstate YAML file.

  4. Create a YAML file, for example, ~/ipsec-host-to-site-cert-auth.yml, with the following content:

    ---
    interfaces:
    - name: '<connection_name>'
      type: ipsec
      libreswan:
        ikev2: insist
    
        left: <ip_address_or_fqdn_of_left_peer>
        leftid: '%fromcert'
        leftcert: <user_certificate_nickname>
    
        right: <ip_address_or_fqdn_of_right_peer>
        rightid: '%fromcert'
        rightsubnet: 192.0.2.0/24
    Copy to Clipboard Toggle word wrap

    The settings specified in the example include the following:

    ikev2: insist
    Defines the modern IKEv2 protocol as the only allowed protocol without fallback to IKEv1. This setting is mandatory in a host-to-site configuration with Nmstate.
    left=<ip_address_or_fqdn_of_left_peer> and right=<ip_address_or_fqdn_of_right_peer>
    Defines the IP address or DNS name of the peers.
    leftid=%fromcert and rightid=%fromcert
    Configures Libreswan to retrieve the identity from the distinguished name (DN) field of the certificate.
    leftcert="<server_certificate_nickname>"
    Sets the nickname of the server’s certificate used in the NSS database.
    rightsubnet: <subnet>
    Defines the subnet in classless inter-domain routing (CIDR) format that is connected to the gateway.
  5. Apply the settings to the system:

    # nmstatectl apply ~/ipsec-host-to-site-cert-auth.yml
    Copy to Clipboard Toggle word wrap

Verification

  • Establish a connection to a host in the remote network or ping it.

Troubleshooting

  • To display the actual configuration NetworkManager passes to Libreswan, enter:

    # nmcli connection export <connection_name>
    Copy to Clipboard Toggle word wrap

    The output can help to identify deviating settings, such as IDs and keys, when you compare them with the Libreswan configuration on the remote host.

Next steps

6.14. Troubleshooting IPsec configurations

Diagnosing IPsec configuration failures can be challenging, because issues can be caused by mismatched settings, firewall rules, and kernel-level errors. The following information provides a systematic approach to resolving common problems with IPsec VPN connections.

6.14.1. Basic connection issues

Problems with VPN connections often occur due to mismatched configurations between the endpoints.

To confirm that an IPsec connection is established, enter:

# ipsec trafficstatus
006 #8: "vpn.example.com"[1] 192.0.2.1, type=ESP, add_time=1595296930, inBytes=5999, outBytes=3231, id='@vpn.example.com', lease=198.51.100.1/32
Copy to Clipboard Toggle word wrap

For a successful connection, the command shows an entry with the connection’s name and details. If the output is empty, the tunnel is not established.

6.14.3. Mismatched Configurations

VPN connections fail if the endpoints are not configured with matching Internet Key Exchange (IKE) versions, algorithms, IP address ranges, or pre-shared keys (PSK). If you identify a mismatch, you must align the settings on both endpoints to resolve the issue.

Remote Peer Not Running IKE/IPsec

If the connection was refused, an ICMP error is displayed:

# ipsec up vpn.example.com
...
000 "vpn.example.com"[1] 192.0.2.2 #16: ERROR: asynchronous network error report on wlp2s0 (192.0.2.2:500), complainant 198.51.100.1: Connection refused [errno 111, origin ICMP type 3 code 3 (not authenticated)]
Copy to Clipboard Toggle word wrap
Mismatched IKE Algorithms

The connection fails with a NO_PROPOSAL_CHOSEN notification during the initial setup:

# ipsec up vpn.example.com
...
003 "vpn.example.com"[1] 193.110.157.148 #3: dropping unexpected IKE_SA_INIT message containing NO_PROPOSAL_CHOSEN notification; message payloads: N; missing payloads: SA,KE,Ni
Copy to Clipboard Toggle word wrap
Mismatched IPsec Algorithms

The connection fails with a NO_PROPOSAL_CHOSEN error after the initial exchange:

# ipsec up vpn.example.com
...
182 "vpn.example.com"[1] 193.110.157.148 #5: STATE_PARENT_I2: sent v2I2, expected v2R2 {auth=IKEv2 cipher=AES_GCM_16_256 integ=n/a prf=HMAC_SHA2_256 group=MODP2048}
002 "vpn.example.com"[1] 193.110.157.148 #6: IKE_AUTH response contained the error notification NO_PROPOSAL_CHOSEN
Copy to Clipboard Toggle word wrap
Mismatched IP Address Ranges (IKEv2)

The remote peer responds with a TS_UNACCEPTABLE error:

# ipsec up vpn.example.com
...
1v2 "vpn.example.com" #1: STATE_PARENT_I2: sent v2I2, expected v2R2 {auth=IKEv2 cipher=AES_GCM_16_256 integ=n/a prf=HMAC_SHA2_512 group=MODP2048}
002 "vpn.example.com" #2: IKE_AUTH response contained the error notification TS_UNACCEPTABLE
Copy to Clipboard Toggle word wrap
Mismatched IP Address Ranges (IKEv1)

The connection times out during quick mode, with a message indicating the peer did not accept the proposal:

# ipsec up vpn.example.com
...
031 "vpn.example.com" #2: STATE_QUICK_I1: 60 second timeout exceeded after 0 retransmits.  No acceptable response to our first Quick Mode message: perhaps peer likes no proposal
Copy to Clipboard Toggle word wrap
Mismatched PSK (IKEv2)

The peer rejects the connection with an AUTHENTICATION_FAILED error:

# ipsec up vpn.example.com
...
003 "vpn.example.com" #1: received Hash Payload does not match computed value
223 "vpn.example.com" #1: sending notification INVALID_HASH_INFORMATION to 192.0.2.23:500
Copy to Clipboard Toggle word wrap
Mismatched PSK (IKEv1)

The hash payload does not match, making the IKE message unreadable and resulting in an INVALID_HASH_INFORMATION error:

# ipsec up vpn.example.com
...
002 "vpn.example.com" #1: IKE SA authentication request rejected by peer: AUTHENTICATION_FAILED
Copy to Clipboard Toggle word wrap

6.14.4. MTU issues

The encryption and encapsulation process increases the packet size. If a packet exceeds the network’s maximum transmission unit (MTU), which is typically 1500 bytes, the packet is fragmented. This can lead to intermittent connection failures where fragments are lost, and the original packet cannot be reassembled. A common symptom is that small packets, for example pings, work correctly, but larger packets, such as an SSH session, freeze after the login.

To fix the problem, lower the MTU for the tunnel by adding the mtu=1400 option to the configuration file.

6.14.5. NAT conflicts

If an IPsec host also functions as a NAT router, it can incorrectly apply NAT to packets intended for the IPsec tunnel. For example, if the source IP address of the packet is translated by a masquerade rule before IPsec encryption is applied, the packet’s source no longer matches the IPsec policy, and Libreswan sends it unencrypted over the network.

To solve this problem, add a firewall rule that excludes traffic between the IPsec subnets from NAT. This rule should be inserted at the beginning of the POSTROUTING chain to ensure it is processed before the general NAT rule.

Example 6.1. Solution by using the nftables framework

The following example uses nftables to set up a basic NAT environment that excludes traffic between the 192.0.2.0/24 and 198.51.100.0/24 subnets from address translation:

# nft add table ip nat
# nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
# nft add rule ip nat postrouting ip saddr 192.0.2.0/24 ip daddr 198.51.100.0/24 return
Copy to Clipboard Toggle word wrap

6.14.6. Kernel-level IPsec issues

A common issue is when a VPN tunnel appears to be established successfully, but no traffic passes through it. In this case, you can inspect the kernel’s IPsec state to check if the tunnel policies and cryptographic keys were correctly installed.

This process involves checking two components:

  • The Security Policy Database (SPD): The rule that instructs the kernel what traffic to encrypt.
  • The Security Association Database (SAD): The keys that instruct the kernel how to encrypt that traffic.

First, check if the correct policy exists in the SPD:

# ip xfrm policy
src 192.0.2.1/32 dst 10.0.0.0/8
	dir out priority 666 ptype main
	tmpl src 198.51.100.13 dst 203.0.113.22
		proto esp reqid 16417 mode tunnel
Copy to Clipboard Toggle word wrap

The output should contain the policies matching your leftsubnet and rightsubnet parameters with both in and out directions. If you do not see a policy for your traffic, Libreswan failed to create the kernel rule, and traffic is not encrypted.

If the policy exists, check if it has a corresponding set of keys in the SAD:

# ip xfrm state
src 203.0.113.22 dst 198.51.100.13
	proto esp spi 0xa78b3fdb reqid 16417 mode tunnel
	auth-trunc hmac(sha1) 0x3763cd3b... 96
	enc cbc(aes) 0xd9dba399...
Copy to Clipboard Toggle word wrap
Warning

This command displays private cryptographic keys. Do not share this output, because attackers can use it to decrypt your VPN traffic.

If a policy exists but you see no corresponding state with the same reqid, it typically means the Internet Key Exchange (IKE) negotiation failed. The two VPN endpoints could not agree on a set of keys.

For more detailed diagnostics, use the -s option with either of the commands. This option adds traffic counters, which can help you identify if the kernel processes packets by a specific rule.

6.14.7. Kernel IPsec subsystem bugs

Under rare conditions, a defect in the IPsec subsystem of the kernel can cause it to lose synchronization with the Internet Key Exchange (IKE) user-space daemon. This de-synchronization can result in discrepancies between negotiated security associations and the actual enforcement of IPsec policies within the kernel, potentially disrupting secure network communication. To check for kernel-level errors, display the transform (XFRM) statistics:

# cat /proc/net/xfrm_stat
Copy to Clipboard Toggle word wrap

If any of the counters in the output, such as XfrmInError, show a nonzero value, it indicates a problem with the kernel subsystem. In this case, open a support case, and attach the output of the command along with the corresponding IKE logs.

6.14.8. Displaying Libreswan logs

Libreswan logs events to the journal. To display the journal for the ipsec service, enter:

# journalctl -xeu ipsec
Copy to Clipboard Toggle word wrap

If the default logging level does not provide enough details, enable comprehensive debug logging by adding the following settings to the config setup section in the /etc/ipsec.conf file:

plutodebug=all
logfile=/var/log/pluto.log
Copy to Clipboard Toggle word wrap

Because debug logging can produce many entries, redirecting the messages to a dedicated log file can prevent the journald and systemd services from rate-limiting the messages.

Nach oben
Red Hat logoGithubredditYoutubeTwitter

Lernen

Testen, kaufen und verkaufen

Communitys

Über Red Hat Dokumentation

Wir helfen Red Hat Benutzern, mit unseren Produkten und Diensten innovativ zu sein und ihre Ziele zu erreichen – mit Inhalten, denen sie vertrauen können. Entdecken Sie unsere neuesten Updates.

Mehr Inklusion in Open Source

Red Hat hat sich verpflichtet, problematische Sprache in unserem Code, unserer Dokumentation und unseren Web-Eigenschaften zu ersetzen. Weitere Einzelheiten finden Sie in Red Hat Blog.

Über Red Hat

Wir liefern gehärtete Lösungen, die es Unternehmen leichter machen, plattform- und umgebungsübergreifend zu arbeiten, vom zentralen Rechenzentrum bis zum Netzwerkrand.

Theme

© 2025 Red Hat