1

I have an AWS server running Ubuntu that has a pptpd server for VPNs, and many clients with different credentials. It works great. But apparently I'm not supposed to be using that any more, I'm supposed to be using ipsec. I'm trying this out on a local computer running Ubuntu 16.04 first before attempting to do it on the live server.

The only relevant tutorial I could find was this one. Others seem to be for site-to-site VPNs when I have a "road warrior" setup, or for other operating systems, or just generally seem to be targeted at sysadmins who do this every day (no-one's paying me to do this).

https://raymii.org/s/tutorials/IPSEC_vpn_with_Ubuntu_16.04.html

The tutorial says to use certificates for authentication because they're "easier to use".

I followed the instructions. The server is called "winter" and is at 192.168.3.144. The client is called "charly" and is at 192.168.3.138. I generated the server certificate like this:

ipsec pki --pub --in private/vpnHostKey.der --type rsa | ipsec pki --issue --lifetime 730 --cacert cacerts/strongswanCert.der --cakey private/strongswanKey.der --dn "C=CN, O=Winter, CN=winter.lan" --san winter --san 192.168.3.144 --san @192.168.3.144 --flag serverAuth --flag ikeIntermediate --outform der > certs/vpnHostCert.der

The syslog shows:

May 30 20:34:36 winter charon: 03[CFG] adding virtual IP address pool 2002:25f7:7489:3::/112
May 30 20:34:36 winter charon: 03[CFG]   loaded certificate "C=CN, O=Winter, CN=winter.lan" from 'vpnHostCert.der'
May 30 20:34:36 winter charon: 03[CFG]   id 'winter.lan' not confirmed by certificate, defaulting to 'C=CN, O=Winter, CN=winter.lan'

The connections section of "sudo ipsec statusall" looks like this:

Connections:
 IPSec-IKEv2:  %any...%any  IKEv2, dpddelay=300s
 IPSec-IKEv2:   local:  [C=CN, O=Winter, CN=winter.lan] uses public key authentication
 IPSec-IKEv2:    cert:  "C=CN, O=Winter, CN=winter.lan"
 IPSec-IKEv2:   remote: uses public key authentication
 IPSec-IKEv2:   child:  0.0.0.0/0 === dynamic TUNNEL, dpdaction=clear

I generated a client certificate like this:

cat Charly-public.der | sudo ipsec pki --issue --lifetime 730 --cacert /etc/ipsec.d/cacerts/strongswanCert.der --cakey /etc/ipsec.d/private/strongswanKey.der --dn "C=CN, O=Winter, CN=mat@winter.lan" --san "mat@winter" --san "mat@192.168.3.144" --outform der > Charly-cert.der

...and now I'm trying to connect using my Macbook running macOS 10.13.4. I configure the macintosh VPN as:

  • Server Address: winter
  • Remote ID: mat@winter.lan
  • Local ID:

...and give it the certificate I created under Authentication Settings.

When I try to connect it fails immediately with no error message. In the server log:

May 30 20:53:15 winter charon: 06[CFG] looking for peer configs matching 192.168.3.144[mat@winter.lan]...192.168.3.138[192.168.3.138]
May 30 20:53:15 winter charon: 06[CFG] peer config match local: 0 (ID_RFC822_ADDR -> 6d:61:74:40:77:69:6e:74:65:72:2e:6c:61:6e)
May 30 20:53:15 winter charon: 06[CFG] peer config match remote: 1 (ID_IPV4_ADDR -> c0:a8:03:8a)
May 30 20:53:15 winter charon: 06[CFG] ike config match: 28 (192.168.3.144 192.168.3.138 IKEv2)
May 30 20:53:15 winter charon: 06[CFG] no matching peer config found

Here's the left and right config:

mat@winter:~$ sudo grep -E 'left|right' /etc/ipsec.conf
    left=%any
    leftid=winter.lan
    leftsubnet=0.0.0.0/0
    leftcert=vpnHostCert.der
    leftsendcert=always
    right=%any
    rightsourceip=10.42.42.0/24,2002:25f7:7489:3::/112
    rightdns=8.8.8.8,2001:4860:4860::8888

My real question is, what does "looking for peer configs matching 192.168.3.144[mat@winter]...192.168.3.138[192.168.3.138] / no matching peer config found" mean? I don't understand how the matching works - what values would be acceptable, what values are being sent by the client, and how I control those on the client and server side. And I don't understand how to parse that line, what each of the sections represents.

Thanks!


This was correctly answered below, but here's my explanation of what I did wrong in terms I understand. tl;dr : the leftid needs to be in the certificate as a SAN, not just as the CN in the DN.

The idea is to connect two certificates, a server certificate and a client certificate, such that the two parties can trust each other. Both certificates were signed by a certificate authority ("CA"), and both parties have the CA public key. If the two parties recognise that each other's certificates were signed by the same CA, they will be happy. The trouble is convincing StrongSwan to recognise that the incoming client connection wants to connect to a particular server certificate. To me, this seems like a no-brainer, since I only configured one certificate. But StrongSwan is designed for more complex setups.

The crucial component is the "leftid" configured in ipsec.conf. You can configure any number of distinct VPNs in StrongSwan, each distinguished by a different leftid. When a client connects, it asks for a VPN with this name, which in my case is configured in VPN settings under "Remote ID". It then expects the server to send it a certificate, and that certificate should identify itself as being that same VPN name / leftid / Remote ID.

So StrongSwan needs a certificate for its leftid. You generate a server certificate with ipsec. You supply a "Distinguished Name" ("DN") which is a long string of components like "C=CN, O=Winter, CN=winter.lan". You can also supply any number of Subject Alternate Names ("SAN"). When the server starts, it reads in the "leftid" and "leftcert" configuration. It tries to find the leftid in either the DN or the SANs.

Here's the trick: if it can't find the leftid, it throws away the leftid and just uses the entire DN instead. This looks like:

May 30 20:34:36 winter charon: 03[CFG]   id 'winter.lan' not confirmed by certificate, defaulting to 'C=CN, O=Winter, CN=winter.lan'

That means the VPN is now not named "winter.lan" any more, it's named "C=CN, O=Winter, CN=winter.lan". If a client wants to connect, it has to ask for that name, not "winter.lan". It sorta makes sense that it does this, because if the name doesn't match there's no point even running. Clients can connect to winter.lan, but if the server sends that certificate it won't match what the client asked for, and the client will abort the connection. On the other hand, it's a real bummer it does this, because there's no way to convince a Macintosh to ask for that leftid.

The big problem in the tutorial I was following is that the leftid it uses is "vpn.example.org", and in the suggested ipsec command to generate the server certificate, that is only used in the DN, not added as a SAN. If I do that with "winter.lan", it fails. The id does not match the certificate.

May 31 21:32:00 winter charon: 05[CFG]   loaded certificate "C=CN, O=Winter, CN=winter.lan" from 'vpnHostCert.der'
May 31 21:32:00 winter charon: 05[CFG]   id 'winter.lan' not confirmed by certificate, defaulting to 'C=CN, O=Winter, CN=winter.lan'

It only works if I also supply the leftid as a SAN with --san. The tutorial even says "you need to make sure the leftid= is the same as the CN in your certificate". I don't know if they're using a different version of strongswan than me, or what the problem is there.

An extra layer of confusion arises because it's not clear when and where the string "C=CN, O=Winter, CN=winter.lan" matches the string "winter.lan". This may be because these identifiers also have "types" attached, which have to match, and the types are usually invisible in the logs.

Anyway, the crucial thing to look out for is the "not confirmed by certificate" line at server startup. Don't bother trying to connect with a client until that's fixed.

  • it will match left and right. what's the right part of the config? you only put left. There are a lot of examples of StrongSwan configuration on... strongswan's site. eg wiki.strongswan.org/projects/strongswan/wiki/… – A.B May 26 '18 at 8:36
  • I added the right part of the config. It was just copied from the original tutorial. There are lots and lots of examples in that wiki. Which one answers my question? – Matthew Exon May 27 '18 at 9:45
  • this would probably be similar: strongswan.org/testing/testresults/ikev2/rw-cert take with a grain of salt. Also I don't think that makes a difference, but you put CN=mat@winter + server's ip in san on the client, while you identify the server as mat@winter . Just to make sure everything is clear in the settings. you should state left= to the server's ip instead of any, to avoid any confusion – A.B May 27 '18 at 11:56
  • The only thing there that seems significantly different from my setup is that the IP address of the server is the "left" variable, whereas I had it as "%any". I tried setting it to the IP address but I still got the same result. I also tried using "mat@192.168.3.144" as the leftid and client Remote ID, but it made no difference. Is there any documentation on strongswan's site about how it performs this matching? I searched but couldn't find anything. – Matthew Exon May 29 '18 at 12:30
  • No, wait, I take that back. Your suggestion does work if I both set "left" to the IP address, and use mat@IP address as the "leftid". I will update the question. I'm still not clear why it works though, so I don't really consider the question answered yet. I also don't have a working VPN yet, but that must be some other problem. – Matthew Exon May 29 '18 at 12:38
2

One of the subjectAltName extensions you added to the certificate is mat@winter.lan, however, you configured leftid=mat@winter. Since that doesn't match, the local identity will fall back to the subject DN of the certificate (i.e. C=HK, O=Winter, CN=mat@winter). This, in turn, doesn't match the remote identity proposed by the client (looking for peer configs matching 192.168.3.144[mat@winter]).

So either configure leftid=mat@winter.lan and change the remote identity in the client config accordingly, or configure the full subject DN as remote identity on the client (but some IKEv2 clients don't actually support that, most notably those by Apple).

With your updated config, winter.lan has to be contained as subjectAltName. It won't be matched against the CN relative DN of the subject DN. So you have to explicitly add --san winter.lan when issuing the server certificate.


When the local identity that's configured doesn't match any of the identities in the local certificate (subject DN or any of the subjectAltNames - note that the type must match too) the subject DN will be used as identity. There is an appropriate message in the log when the config is loaded (something like id 'mat@winter' not confirmed by certificate, defaulting to 'C=HK, O=Winter, CN=mat@winter') and this can also be seen in the output of ipsec statusall in the Connections section, where the configured IPs and identities are listed. So make sure the identity you configured is what the IKE daemon will actually use during authentication.

The components of the looking for peer config... log message are really quite simple. For example 192.168.3.144[mat@winter]...192.168.3.138[192.168.3.138]:

  • 192.168.3.144: Local IP address of the IKE_SA (= responder/server's IP)
  • [mat@winter]: Responder/Server identity proposed by the initiator/client (IDr), must match the identity that's configured (leftid)
  • 192.168.3.138: Remote IP address of the IKE_SA (= initiator/client's IP)
  • [192.168.3.138]: Initiator/Client identity proposed by the initiator/client (IDi), must match the remote identity that's configured on the server (rightid, defaults to %any, if not configured)

Note that the type of compared identities (e.g. FQDN vs. USER_FQDN or KEY_ID) must match too (identities might look the same in the log and e.g. ipsec statusall but their type could be different). More details about this comparison (including the type) are logged only if the log level for cfg is increased to 3.


Identities matter for two things. One, they allow the selection of a specific configuration. So by sending a specific identity in the IDr payload the client states it wants to connect to the server with that particular identity and the server will select a config that matches that identity. The payload is optional and some clients don't send it (e.g. Windows clients), which allows the server to select whichever configuration it deems fit. Same goes for client identities, which allow the server to switch to a particular config if it doesn't match (however, with rightid=%any, the default, the client identity will be ignored when selecting configs - but it must be confirmed by the client certificate).

Second, identities are important to prevent just anybody with a valid certificate to authenticate themselves with whatever identity they like. For instance, if your client has other CAs installed besides your CA "X" and you don't enforce a particular identity (they are usually made to match the hostname of the server), the client would accept any certificate issued by any of these CAs, not just one issued specifically for that identity/hostname (it would even accept another client certificate as server certificate if CA "X" is the only CA that's trusted if it woulnd't enforce a particular server identity). Same goes for clients. You don't want your client "Y" to authenticate itself as client "Z" with the certificate that was specifically issued to client "Y". That's particularly important if there are multiple connection definitions with different rightid settings and e.g. different subnets or virtual IP ranges to allow access to different networks via VPN based on the client identity.


The big problem in the tutorial I was following is that the leftid it uses is "vpn.example.org", and in the suggested ipsec command to generate the server certificate, that is only used in the DN, not added as a SAN.

Yes, for some reason they add two unrelated SANs with different TLDs (.com and .net) to the certificate.

The tutorial even says "you need to make sure the leftid= is the same as the CN in your certificate". I don't know if they're using a different version of strongswan than me, or what the problem is there.

It doesn't depend on the strongSwan version, but the client. If it doesn't send a remote identity, the server is free to select a config that uses the full subject DN as identity. It's then up to the client whether it accepts that identity when it's returned by the server. So clients that match the remote identity they want to enforce (e.g. the server's FQDN) against the CN of the DN sent by the server will be fine. Windows clients do this, Apple clients possibly too (although some versions of macOS also require a matching SAN). But strongSwan, as client, does not and will require that the configured remote identity fully matches the identity returned by the server (and its type). There is a special client configuration (rightid=%vpn.example.com), in which strongSwan doesn't send a remote identity and also matches the configured identity against all identities in the server certificate. This allows the client to enforce an FQDN as identity while the server identifies itself with the full subject DN, as long as that FQDN is also contained as subjectAltName in the server certificate.

An extra layer of confusion arises because it's not clear when and where the string "C=CN, O=Winter, CN=winter.lan" matches the string "winter.lan". This may be because these identifiers also have "types" attached, which have to match, and the types are usually invisible in the logs.

That's mainly because strongSwan doesn't match identities against parts of DNs. But as mentioned above, some clients do that (at least they match FQDNs against CNs).

Anyway, the crucial thing to look out for is the "not confirmed by certificate" line at server startup. Don't bother trying to connect with a client until that's fixed.

It's definitely a good idea to check for that log message, or whether the output of ipsec statusall matches the intended configuration.

And if clients fail to connect with no matching peer config found, make sure to compare the IPs and identities listed in the looking for peer configs... log message against the IPs and identities of the configured connections in ipsec statusall.

  • I tried your suggestion, with the leftid set to X and the client "Remote ID" also set to X, with X in "mat@winter.lan", "mat@192.168.3.144", "@192.168.3.144". All failed in a similar way, with X in the "looking for..." line. My client is a Mac, so the DN solution doesn't work. Can you explain 1) how it falls back through the different --san options, and 2) what the different components of the "looking for..." line are trying to tell me? – Matthew Exon May 29 '18 at 12:23
  • Added answers to your two questions. Make sure to compare the log and status output for inconsistencies. – ecdsa May 29 '18 at 15:37
  • I made my config more consistent and updated the question. Your response helps, especially the "[192.168.3.138]" bit - I now know I control that with the "Local ID" field on the Macintosh. I still can't connect though. "id 'winter.lan' not confirmed by certificate, defaulting to 'C=CN, O=Winter, CN=winter.lan'" - that looks like it should match. What's the problem there? How can I generate a certificate that will confirm "winter.lan"? – Matthew Exon May 30 '18 at 13:25
  • And another question: why do any of these names matter at all? I gave my server CA "X". Client presents certificate "Y", which has a valid signature from "X". Authentication should finish right there. Why does it have to be so picky? – Matthew Exon May 30 '18 at 13:30
  • I've updated the first and last block of my answer. – ecdsa May 30 '18 at 13:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.