Edit: March 11, 2020
There appears to be some behavior in the USG's configuration system that made it seem like the below Just Worked with intermediate certificates, however it doesn't. A software update exposed that weakness. Everything else seems to hold true even in version v4.4.50 (current as of now). See this post for the updated information on intermediate CA certificates.
I had to roll my internal certificate authority the other day since my previous one was using SHA-1 signatures and with the new version of Debian SHA-1 signed certificates are no longer trusted. I chose to switch to ECDSA certificates with SHA2-256 signatures to bring my CA in line with modern cryptography.
I chose to split out the VPN and the server certificates into intermediate CAs signed by my internal root. This provides a little isolation and some trust domains, so someone with a server certificate cannot impersonate a VPN user or vice-versa. I then had to flail a bit at the USG to get it to connect.
I tried plopping the newly generated cert and key into /config/auth as
I talk about in my previous post about the USG. This flatly didn't work. It
turns out that the script that vyatta uses to generate the
config file for strongSwan (
/opt/vyatta/sbin/vpn-config.pl) hard codes
: RSA as the prefix for the key, forcing the key type to RSA when I'm
using ECDSA. This causes strongSwan to fail to load the key since it isn't
an RSA key.
So I went and revoked the certificate and generated a new one with an RSA key.
With the new RSA certificate / key in place the USG started trying to initiate the IKEv2 connection to my VPN server but the server was complaining that it was receiving the wrong authentication method. This was very similar to an issue I had with a MikroTik RouterOS client. So just like I did in that post I plopped the public key in the right spot on the server and restarted iked.
Now I had the USG trying to connect and the VPN server authenticating it properly, but the USG would abort the connection prior to establishing a CHILD_SA. There was no obvious reason from the server side so I went back to the USG and dug into it.
Typically when using an intermediate CA my first reaction is (like with apache)
to create a bundle of the root and the intermediate certs. In fact that
is how it works with OpenBSD's iked. That clearly was not working
in this case as
sudo swanctl --log was showing unknown issuer for the
server's cert. A bit of flailing around and I figured out that you need only
the root CA in the
ca-cert-file that you give the USG. It will quite happily walk the chain and validate the certificates as long as it ends with the trust
11[CFG] using trusted ca certificate "C=US, CN=ub3rgeek.net Internal Root CA" 11[CFG] checking certificate status of "C=US, O=ub3rgeek.net, CN=ub3rgeek.net VPN Signing CA" 11[CFG] fetching crl from '[REDACTED]'
Shortly thereafter the tunnel came up and everything seems to be working.
So while strongSwan supports ECDSA keys, the version of vyatta that EdgeOS does not seem to support configuring them. Your CA can use ECDSA signatures but the certificate and key pair for the USG must be RSA. Also either strongSwan or vyatta only supports a single certificate in the ca.crt file. Thankfully as long as it is the trust root, it seems like it will work properly.