Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editing EAP Secrets in StrongMan GUI broke preconfigured secrets. #163

Open
sbbbv opened this issue Feb 11, 2025 · 2 comments
Open

Editing EAP Secrets in StrongMan GUI broke preconfigured secrets. #163

sbbbv opened this issue Feb 11, 2025 · 2 comments

Comments

@sbbbv
Copy link

sbbbv commented Feb 11, 2025

Hello

Debian 11.11. Strongswan 5.9.1. StrongMan from git

I have preconfigured Strongswan with static config files like:

/etc/swanctl/ikev1-l2tp-accel-ppp.conf

    ikev1-l2tp-auth-in-l2tp {
        version = 1
        unique=never
        proposals = aes256-aes128-sha256-modp3072-modp2048-modp1024,default
        rekey_time = 0s
        fragmentation = yes
        dpd_delay = 30s
        dpd_timeout = 90s

        send_certreq = no

        local-1 {
            auth = psk
        }
        remote-1 {
            auth = psk
        }
        children {
            ikev1-l2tp-auth-in-l2tp {
                local_ts = dynamic[/1701]
                esp_proposals = aes128-sha256-modp3072,default
                mode = transport
                rekey_time = 0s
                dpd_action = clear
            }
        }
    }

secrets {

    # PSK secret
    ike-psk- {
        secret = "XXXXXXXXXX"
    }
    ike-psk-xx-xxx-xxxxx-xxx {
        id = xx.xxx.xxxxx.xxx
        secret = "XXXXXXXXXX"
    }
}

This configuration is used for old clients who can't do anything else L2TP-PSK+login\pass

Successful connection logs like:

Feb 11 16:05:20 vpn05 charon-systemd[1998]: received MS NT5 ISAKMPOAKLEY vendor ID
Feb 11 16:05:20 vpn05 charon-systemd[1998]: received NAT-T (RFC 3947) vendor ID
Feb 11 16:05:20 vpn05 charon-systemd[1998]: received draft-ietf-ipsec-nat-t-ike-02\n vendor ID
Feb 11 16:05:20 vpn05 charon-systemd[1998]: received FRAGMENTATION vendor ID
Feb 11 16:05:20 vpn05 charon-systemd[1998]: 192.168.50.17 is initiating a Main Mode IKE_SA
Feb 11 16:05:20 vpn05 charon-systemd[1998]: IKE_SA ikev1-l2tp-auth-in-l2tp[1] established between 192.168.50.219[192.168.50.219]...192.168.50.17[192.168.50.17]
Feb 11 16:05:20 vpn05 charon-systemd[1998]: DPD not supported by peer, disabled
Feb 11 16:05:20 vpn05 charon-systemd[1998]: received 3600s lifetime, configured 0s
Feb 11 16:05:20 vpn05 charon-systemd[1998]: received 250000000 lifebytes, configured 0
Feb 11 16:05:20 vpn05 charon-systemd[1998]: got SPI c8ed7a00
Feb 11 16:05:20 vpn05 charon-systemd[1998]: adding SAD entry with SPI c8ed7a00 and reqid {1}

I installed StrongMan for IKEv2 clients on the same server. Everything works fine until I add or remove any EAP Secrets in StrongMan GUI. Preconfigured L2TP connections immediately stop working with a message in the log - "no shared key found for".

As I understand it, editing EAP Secrets from GUI deletes secrets that are loaded from the static configuration files.
This is bug ?

Feb 11 16:04:45 vpn05 charon-systemd[1621]: received MS NT5 ISAKMPOAKLEY vendor ID
Feb 11 16:04:45 vpn05 charon-systemd[1621]: received NAT-T (RFC 3947) vendor ID
Feb 11 16:04:45 vpn05 charon-systemd[1621]: received draft-ietf-ipsec-nat-t-ike-02\n vendor ID
Feb 11 16:04:45 vpn05 charon-systemd[1621]: received FRAGMENTATION vendor ID
Feb 11 16:04:45 vpn05 charon-systemd[1621]: 192.168.50.17 is initiating a Main Mode IKE_SA
Feb 11 16:04:45 vpn05 charon-systemd[1621]: no shared key found for 'xx.xxx.xxxxx.xxx'[192.168.50.219] - '%any'[192.168.50.17]
Feb 11 16:04:45 vpn05 charon-systemd[1621]: no shared key found for 'xx.xxx.xxxxx.xxx'[192.168.50.219] - '%any'[192.168.50.17]
Feb 11 16:04:45 vpn05 charon-systemd[1621]: no shared key found for 192.168.50.219 - 192.168.50.17

Also IKEv2+PSK+login/pass start got same error.

Feb 11 16:57:52 vpn05 charon-systemd[1998]: received MS NT5 ISAKMPOAKLEY v9 vendor ID
Feb 11 16:57:52 vpn05 charon-systemd[1998]: received MS-Negotiation Discovery Capable vendor ID
Feb 11 16:57:52 vpn05 charon-systemd[1998]: received Vid-Initial-Contact vendor ID
Feb 11 16:57:52 vpn05 charon-systemd[1998]: 192.168.50.19 is initiating an IKE_SA
Feb 11 16:57:52 vpn05 charon-systemd[1998]: received 66 cert requests for an unknown ca
Feb 11 16:57:52 vpn05 charon-systemd[1998]: initiating EAP_IDENTITY method (id 0x00)
Feb 11 16:57:52 vpn05 charon-systemd[1998]: peer supports MOBIKE
Feb 11 16:57:52 vpn05 charon-systemd[1998]: no private key found for 'xx.xxx.xxxxx.xxx'
@tobiasbrunner
Copy link
Member

Everything works fine until I add or remove any EAP Secrets in StrongMan GUI.

The problem is that both clients (swanctl and strongMan) basically assume they have exclusive access to the config. So strongMan sends a clear-creds() message to the daemon before it reloads all the shared secrets. This was written before secrets could be tagged with a unique identifier, which allows to delete specific ones. However, adding such an identifier wouldn't be a complete solution. Because while swanctl doesn't use clear-creds() when loading shared secrets, it does use such identifiers and it will actually remove all shared secrets with an identifier it doesn't know about (assuming they were removed from the config file before it was reloaded). I guess it would require some kind of namespacing (e.g. adding something like swanctl: and strongman: before the unqiue identifiers, in order to then only remove secrets from the same client).

@sbbbv
Copy link
Author

sbbbv commented Feb 14, 2025

Oh boy. I'm not very good at programming.
I tried to do it without large-scale code modifications

  1. Add with running clear_cred() creating lock file in vici wrapper

strongMan/strongMan/helper_apps/vici/wrapper/wrapper.py

    def clear_creds(self):
        try:
            self.session.clear_creds()
            with open('/tmp/clear_creds.lck', 'w') as file:
                pass
        except Exception as e:
            raise ViciLoadException("Credentials cannot be cleared! " + str(e))
  1. Start from rc.local monitoring script like this.

/root/scripts/clear_creds.sh

#!/bin/bash

rm -rf /tmp/clear_creds.lck

inotifywait -m /tmp -e create  |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
        if [[ "$file" = clear_creds.lck ]]; then
            # give some time to strongMan internal processing
            sleep 5
            echo " $file"
            /usr/sbin/swanctl --load-creds
            # may be you want also reload strongMan cred for...nothing
            #/root/strongMan/load-creds.py
            rm -rf /tmp/clear_creds.lck
        fi
    done

  1. Edited configloader.py for loading only creds

strongMan/load-creds.py

import os

path = os.path.dirname(os.path.realpath(__file__))
activate = os.path.join(path, 'env/bin/activate_this.py')
if os.path.exists(activate):
    with open(activate) as f:
        exec(f.read(), {'__file__': activate})

os.chdir(path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "strongMan.settings.production")
import django
django.setup()

from collections import OrderedDict
from strongMan.apps.certificates.models.certificates import PrivateKey, Certificate
from strongMan.apps.eap_secrets.models import Secret
from strongMan.helper_apps.vici.wrapper.wrapper import ViciWrapper


def load_secrets(vici=ViciWrapper()):
    for secret in Secret.objects.all():
        vici.load_secret(secret.dict())


def load_keys(vici=ViciWrapper()):
    for key in PrivateKey.objects.all():
        vici.load_key(OrderedDict(type=key.get_algorithm_type(), data=key.der_container))


def load_certificates(vici=ViciWrapper()):
    for cert in Certificate.objects.all():
        vici.load_certificate(OrderedDict(type=cert.type, flag='None', data=cert.der_container))


def load_credentials(vici=ViciWrapper()):
    load_secrets(vici)
    load_keys(vici)
    load_certificates(vici)


def main():
    vici = ViciWrapper()
    load_credentials(vici)

if __name__ == "__main__":
    main()

Working well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants