QKDLite Plugin For strongSwan ================================================================================ Overview -------------------------------------------------------------------------------- QKDLite Plugin For strongSwan provides strongSwan VPN gateways with fresh PPKs (Postquantum Preshared Key) for connections. .. figure:: images/strongSwan1.png :alt: QKDLite Plugin for strongSwan :align: center QKDLite Plugin For strongSwan QKDLite Plugin For strongSwan can be co-located together with the strongSwan gateway to provide a quantum-safe connection to the QKDLite node either locally or over the internet. As shown in diagram above, the connections from the QKDLite to the plugin are quantum-safe connections. The plugin will provide PPKs to strongSwan to use during the IKE_AUTH process. Prerequisite -------------------------------------------------------------------------------- For QKDLite Plugin For strongSwan to work, **OpenSSL 3.5 and above is required.** To check and subsequently install the version see `Error: plugin requires OpenSSL 3.5 or newer!`_ Installation -------------------------------------------------------------------------------- In this section, we will guide you on how to set up plugin for strongSwan to retrieve PPK from QKDLite's ETSI GS QKD 014 API. #. Download and extract the QKDLite plugin for strongSwan package. #. Copy ``libstrongswan-qkdlite.la`` and ``libstrongswan-qkdlite.so`` in the package to the plugin directory in a strongSwan instance. .. code-block:: text # possible default locations: /usr/lib/ipsec/plugins/ /usr/lib64/ipsec/plugins/ /usr/lib/strongswan/plugins/ /usr/local/lib/ipsec/plugins/ /usr/libexec/ipsec/plugins/ #. Add the following parameters in ``/etc/strongswan.conf`` or ``/etc/strongswan.d/`` to load the plugin. .. code-block:: cfg :caption: strongswan.conf charon { ... plugins { add a qkdlite entry under plugins qkdlite { # add a global entry global { # replace below parameters with existing ETSI API endpoint # and the certs to connect to the endpoint # https of QKDLite ETSI server key_source_url = https://localhost:8080 # Paired/Remote key source ID remote_key_source_id = SAE_B # certificates to connect to the ETSI endpoint cacert = /path/to/CA.crt clientcert = /path/to/client.crt clientkey = /path/to/client.key } } } ... # load the plugin in charon load = ... qkdlite } #. Restart strongSwan to load the plugin. .. code-block:: bash :caption: bash systemctl restart strongswan #. Verify that the plugin is registered when starting strongSwan. .. code-block:: bash :caption: bash 00[CFG] QKDLite_plugin: QKDLite plugin registered #. (Optional) repeat steps above for another strongSwan instance. Configuration -------------------------------------------------------------------------------- For the following guide we assume that you have 2 strongSwan instances that have installed the plugin, and you want to connect the 2 instance. We will refer the initiator instance as ``alice`` (the one who will initiate the connection), and responder instance as ``bob`` (the one who will receive the connection). For the ``alice`` instance, #. Add ppk configuration for a connection in ``/etc/swanctl/swanctl.conf``. .. code-block:: cfg :caption: swanctl.conf connections { example_connection { ... # add this line as it is ppk_id = qkdlite # To make ppk compulsory for this connection add this # ppk_required = yes } } #. Restart strongSwan to load the new configurations. .. code-block:: bash :caption: bash systemctl restart strongswan .. note:: To allow 2-way initiation repeat the above steps in ``bob`` instance for the connection to ``alice``. Connect strongSwan instances -------------------------------------------------------------------------------- To test that the plugin is working and can be used in connections for strongSwan: In ``alice`` instance, #. Open an vpn connection to ``bob`` instance: .. code-block:: bash :caption: bash swanctl --initiate --ike # or swanctl --initiate --child #. you should see this line: .. code-block:: bash :caption: bash [CFG] using PPK for PPK_ID 'qkdlite' #. On ``bob`` instance, verify that the PPK ID is in use via: .. code-block:: bash :caption: bash swanctl --log #. you should see this line within the logs: .. code-block:: bash :caption: bash [CFG] using PPK for PPK_ID 'xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx' .. note:: This is the PPK being used between the 2 instances, which appear on ``alice`` instance only as PPK_ID ``qkdlite``. #. Verify that the connection is successfully established .. code-block:: bash :caption: bash [IKE] IKE_SA example_connection[1] established between 172.30.0.3[alice@strongswan.org]...172.30.0.2[bob.strongswan.org] Debugging -------------------------------------------------------------------------------- #. For verbose logging, in ``/etc/strongswan.conf`` or ``/etc/strongswan.d/`` change cfg logging to level 2 and restart strongSwan .. code-block:: cfg :caption: strongswan.conf charon { start-scripts { ... } # example config filelog { stderr { default = 1 # for more verbose logs cfg = 2 # ... } } # to use for charon-systemd charon-systemd { journal { default = 1 # for more verbose logs cfg = 2 # ... } } ... } .. note:: For logging configurations refer to https://docs.strongswan.org/docs/latest/config/logging.html #. Repeat connecting from ``alice`` instance to ``bob`` instance: .. code-block:: bash :caption: bash swanctl --initiate --ike # or swanctl --initiate --child #. View the verbose logs using preferred logging usage: .. code-block:: bash :caption: bash # if charon-systemd journal is used journalctl -u strongswan #. You should be able to find the plugin logs with ``QKDLite_plugin``: .. code-block:: bash :caption: bash 01[CFG] QKDLite_plugin: IKE_SA: example_connection[1] 01[CFG] QKDLite_plugin: IKE SA SPIs - Initiator: 3ef9449c7fbade09, Responder: 3032ecb188ca62f2, initiator 01[CFG] QKDLite_plugin: PPK requested - PPK ID: qkdlite 01[CFG] QKDLite_plugin: Updated qkdlite PPK with PPK from xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx 01[CFG] QKDLite_plugin: Successfully retrieved response from source: https://localhost:8000, destination: SAE_B 01[CFG] QKDLite_plugin: Cached PPK ID for IKE_SA example_connection[1] Troubleshooting Guide -------------------------------------------------------------------------------- Error: plugin requires OpenSSL 3.5 or newer! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Symptom** When starting up the plugin, swanctl returns with: .. code-block:: bash :caption: bash [CFG] QKDLite_plugin: Error: plugin requires OpenSSL 3.5 or newer! **Likely Cause** The OpenSSL installed and configured is using an older version of OpenSSL. Verify with .. code-block:: bash :caption: bash openssl version Usually for newer OS versions, the latest version of OpenSSL is installed by default, but for older OS versions, building from source and install is required. To download the openssl latest version refer to: https://openssl-library.org/source/ For installation refer to: https://github.com/openssl/openssl/?tab=readme-ov-file#build-and-install PPK required but no PPK found for 'qkdlite' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Symptom** When trying to connect to another strongSwan instance, swanctl returns with: .. code-block:: bash :caption: bash [CFG] QKDLite_plugin: Failed to retrieve PPK from server, Error code: 3 [CFG] QKDLite_plugin: Failed to retrieve PPK for 'qkdlite' [CFG] PPK required but no PPK found for 'qkdlite' **Likely Cause** The plugin is not able to connect to the ETSI API endpoint, it could be a firewall issue, or invalid/wrong certificates between the strongSwan plugin and the endpoint. Do a basic curl to the ETSI API endpoint to verify the external cause: .. code-block:: bash :caption: bash curl --cert /path/to/client.crt \ --key /path/to/client.key \ --cacert /path/to/CA.crt \ https://host.docker.internal:8444