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).
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, CNfirstname.lastname@example.org" --san "mat@winter" --san "email@example.com" --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: firstname.lastname@example.org
- 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[email@example.com]...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=18.104.22.168,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.
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.