Score:0

Can I make strongSwan accept any certificate as long as it is only signed by a specific CA?

mv flag

Using a swanctl config, is there a way to make strongSwan accept any certificate for an IKEv2 connection as long as it is signed by a specific CA? What I mean is, without having to install the public keys of all possible certs on the server, after all the certs are sent by the client in reply to a cert request sent by stongSwan.

I tried something like this:

    local {
        auth = pubkey
        certs = server.pem
        id = fqdn:strongSwan
    }
    
    remote {
        auth = pubkey
        cacerts = my_ca.pem                     
        id = fqdn:cert                                              
    }

But that doesn't seem to do the trick (and yes, the client did send cert as ID). I also tried id = %any and made the client sent the cert identifier but that makes no difference at all.

The sent certs definitely verify with the CA cert in my_ca.pem and swanctl --list-certs shows the server and the CA cert, so the files are found by strongSwan. Still I get no trusted RSA public key found for ... whatever the identifier was.

The idea is that whatever the client sends as cert is totally fine, as long as it has been signed by my_ca.pem. So a new client just needs to send a certificate signing request, gets their cert signed and can use VPN at once, without any change to the VPN config and without having to place the cert on the VPN server first.

Update 1

Here's a log excerpt (I cannot post raw logs because I must not expose IP addresses, company names or user cert details here):

charon-systemd[31259]: verifying message structure
charon-systemd[31259]: found payload of type NOTIFY
charon-systemd[31259]: found payload of type NOTIFY
charon-systemd[31259]: found payload of type NOTIFY
charon-systemd[31259]: found payload of type NOTIFY
charon-systemd[31259]: found payload of type AUTH
charon-systemd[31259]: found payload of type ID_INITIATOR
charon-systemd[31259]: found payload of type CERTIFICATE
charon-systemd[31259]: found payload of type ID_RESPONDER
charon-systemd[31259]: found payload of type SECURITY_ASSOCIATION
charon-systemd[31259]: found payload of type TS_INITIATOR
charon-systemd[31259]: found payload of type TS_RESPONDER
charon-systemd[31259]: found payload of type CONFIGURATION
charon-systemd[31259]: parsed IKE_AUTH request 1 [ IDi CERT N(INIT_CONTACT) IDr AUTH CPRQ(ADDR MASK DHCP DNS ADDR6 DHCP6 DNS6 DOMAIN) N(ESP_TFC_PAD_N) N(NON_FIRST_FRAG) SA TSi TSr N(MOBIKE_SUP) ]
charon-systemd[31259]: received end entity cert "E=<user-email>, CN=<user-name>"
charon-systemd[31259]: looking for peer configs matching <serverIP>[strongSwan]..<clientIP>[cert]
charon-systemd[31259]: selected peer config 'cert'
charon-systemd[31259]: IDx' => 8 bytes @ 0x7ffa369a2970
     0: 02 00 00 00 63 65 72 74                          ....cert
charon-systemd[31259]: SK_p => 32 bytes @ 0x7ff9fc0126d0
     0: B4 36 B4 D5 CE 09 CE 98 FD 41 75 35 45 9E AD 98  .6.......Au5E...
    16: DA BF D3 EB 4C 39 C0 46 5A 23 E1 A0 EB 85 05 6B  ....L9.FZ#.....k
charon-systemd[31259]: octets = message + nonce + prf(Sk_px, IDx') => 668 bytes @ 0x7ffa1400eac0
     0: 94 83 EA 26 E3 16 36 8D 00 00 00 00 00 00 00 00
    <entire packet follows below>
charon-systemd[31259]: no trusted RSA public key found for 'cert'

<user-email> and <user-name> show the mail and name from the user cert, so the client has sent the user cert, otherwise how would strongSwan know any of that? <serverIP> and <clientIP> are also the correct IP addresses involved.

Upadate 2

I also tried to change the config to id = %any on the server side and then on the client side I send E=<user-email>, CN=<user-name> as id, which matches exactly the values as found in the certificate. But then the log says:

charon-systemd[31978]: no trusted RSA public key found for 'E=<user-email>, CN=<user>'

One thing I noticed that the user certs do not have a SAN (Subject Alternative Name). So far those certs have been used for OpenVPN connections and for SSTP connections and they worked fine for both purposes. I just really want to get rid of OpenVPN/SSTP as I consider both to be poor VPN protocols and their performance is a joke compared to the throughput I get with IPsec and strongSwan.

user1686 avatar
fr flag
Does the client _need_ to send exactly `fqdn:cert` as an ID in your setup?
cn flag
Does the client send the certificate? It would help if you posted the complete log of a client trying to connect.
Mecki avatar
mv flag
@user1686 The client can send as ID whatever I want it to send. As I have more than one VPN config, so I need to make sure there is no clash with the other configs. I tried making the clients sent `fqdn:cert` which causes strongSwan to select the right config but I also tried `%any` and each client would send the e-mail address of its cert but the log error stays the same
Mecki avatar
mv flag
@ecdsa Yes, the client does send the cert and strongSwan also logs the cert correctly as ` emailAddress = ..., CN = ...`, so it has seen and parsed the cert. It just seem to not trust it or not find it when searching for a trusted cert. Note that "openssl verify -CAfile my_ca.pem cert.pem` for the same cert says that the cert is valid. I cannot add complete log because it contains company information I must not share but I guess can add some censored log excerpts.
cn flag
What identity does the client send? It does have to match either the full subject DN of the certificate, or one of the subjectAltName extensions contained in it.
Mecki avatar
mv flag
@ecdsa I tried sending `E=<user-email>, CN=<user-name>` and configured `%any` on the server but that didn't work either. Still the correct connection was selected but it still said it cannot find a trusted key. Also tried only sending `<user-name>` and only `<user-email>` (I'll make another update for that one). Also if I have to use that as an ID, how could I have two separate cert based connection configs? How would the client select which of the two it wants to connect to when it cannot select that by identity?
cn flag
Not sure I understand your questions. You might be confusing something (maybe server and client config?). What exactly is `[cert]` in your log (note that that's the identity the client sends)? Is that literally the value `cert`?
cn flag
What exactly does "and then on the client side I send E=<user-email>, CN=<user-name> as id" mean? What clients? How is it configured there? In what format is it sent (as string or actually as ASN.1 encoded DN)?
Mecki avatar
mv flag
@ecdsa Cert is the name of the connection. Every connection in strongSwan hat a name. And cert was only sent as the identity in the first log, see second update where it sent the cert identity. I explained all of this twice in my question and once more in the comments.
Score:1
mv flag

After a whole day of trial and error, it turns out that the user certificates indeed requires a subject alternative name (SAN), which is the user e-mail address in that case and the identifier must be %any in the configuration and the identifier the client sends must match the SAN (identifier type seems to be ignored, only the string value is relevant).

Apparently strongSwan builds a list of all local certificates configured, adds all certificates clients send to that list as well (RFC says a client can send at least up to 4 different certs) and then searches that list for any certificate whose SAN matches the sent identifier. Certificates without a SAN can never match at all and are always skipped during that search. The last part was the problem as none of our user certs has a SAN value to begin with.

cn flag
If the client actually sends the subject DN of the certificate as its identity, that works too. So SANs are not technically required. However, some clients (e.g. iOS) are unable to send ASN.1 encoded DNs as identity. So domain names or email addresses encoded as SANs are usually easier to use.
Score:-1
lk flag

strongswan seems to have the option:

left|rightca = <issuer dn> | %same

the distinguished name of a certificate authority which is required to lie in the trust path going from the
left|right participant's certificate up to the root certification authority.
%same means that the value configured for the other participant should be reused.

https://wiki.strongswan.org/projects/strongswan/wiki/connsection

I would go for strongswan config directly and abandon swanctl in that case

user1686 avatar
fr flag
ipsec.conf is not "strongswan config directly" any more than swanctl.conf is – *both* are processed by separate tools and plugins ("starter"/"stroke" for ipsec.conf, "swanctl" for swanctl.conf); the stroke/starter/ipsec.conf format is strongly deprecated since 5.2.0.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.