A Guide to Hardening IPsec Roadwarrior on Windows 10

** WARNING THIS WILL BREAK ALL EXISTING IPSEC CONNECTIONS, YOU WILL NEED TO MAKE NEW CERTIFICATES FOR EXISTING CONNECTIONS **

Having setup IPsec roadwarrior IPFire - Windows 10 recently, I noticed that the ciphers chosen in Windows 10 were quite bad.

IPFire in fact tells you that the modp-1024 used by default in a Windows 10 connection is considered broken.

image

By default Windows 10 wants to use AES256-CBC/SHA1/MODP-1024 and really none of these are fantastic for the task.

It should be said that whilst SHA1 is considered weak, this is mostly from an auth context. Comparing password hashes or certificate/file fingerprints using SHA1 is bad. Doing integrity checking of data with SHA1 (HMAC-SHA1 in fact) is less bad, because by the time an attacker can generate a collision, we’re already onto new packets and new hashes. But still some risk remains, if they precompute some bad packets I guess it could be possible, and we can do better, so we should.

Go ahead and use this wiki article to set up a working config for your Windows devices to connect to your IPFire appliance.

Through the process, once you connect a Windows 10 device to your IPsec VPN, you will want to SSH into your IPFire appliance and use cat /var/log/messages to see entries from charon regarding what ciphers are being selected. It is also good to look here for errors.

Now we are going to deliberately break things.

On your Windows 10 client, open PowerShell and type the following:

Set-VpnConnectionIPsecConfiguration -Name "<nameOfYourVPNConnectionHere>" `
>>         -AuthenticationTransformConstants GCMAES128 `
>>         -CipherTransformConstants GCMAES128`
>>         -DHGroup ECP384 `
>>         -IntegrityCheckMethod SHA384 `
>>         -PfsGroup ECP384 `
>>         -EncryptionMethod GCMAES128

You can substitute GCMAES128 with GCMAES256 if you are one of those people that must 256bit key all the things, or are dealing with Government compliance surrounding the transmission of Top Secret data. If you do not fall into those categories, I’d suggest you stick with 128.

Now try and connect the VPN, you will get an error about the IKE machine certificate being invalid. This is because when using ECP384 for the VPN, Windows requires the host certificate and client certificate to also be using ECP384.

By default, IPFire is creating an RSA4096 CA (Root) certificate, and a RSA 2048 host certificate for IPsec. We will need to manually create ECP384 (ECDSA) certificates instead, to use with our hardened Windows 10 clients.

The following commands will need to be done by you via SSH to your IPFire appliance:

It is important to note the different commands for creating the CA, Host and Client certificates. There are subtle differences, we give different usage permissions to each certificate type, so please ensure you follow and paste each command below in exact order, substituting your own values in <> fields.

CA cert creation

Create CA key

pki --gen --type ecdsa --size 384 --outform pem > cakey.pem

Create CA x509 certificate

pki --self --in cakey.pem --dn "C = <Country Code i.e. US>, ST = <State i.e. IL>, L = <City>, O = <Company Name>, OU = <Department>, CN = <Company Name> CA" --ca --outform pem > cacert.pem

Host cert creation

Create host key

pki --gen --type ecdsa --size 384 --outform pem > hostkey.pem

Create Host x509 certificate

pki --issue --in hostkey.pem --type priv --cacert cacert.pem --cakey cakey.pem 
                --dn "C=<Country>,ST=<State>,O=<Company Name>,OU=<Department>,CN=<FQDN of VPN Server i.e. vpn.contoso.com>" --flag serverAuth 
                --flag ikeIntermediate --san  <FQDN of VPN Server i.e. vpn.contoso.com> --outform pem > hostcert.pem

Move newly created certs to their respective stores, set permissions

mv cacert.pem /var/ipfire/ca/cacert.pem
mv cakey.pem /var/ipfire/private/cakey.pem
mv hostcert.pem /var/ipfire/certs/hostcert.pem
mv hostkey.pem /var/ipfire/certs/hostkey.pem
chown nobody:nobody /var/ipfire/private/cakey.pem
chown nobody:nobody /var/ipfire/ca/cacert.pem
chown nobody:nobody /var/ipfire/certs/hostcert.pem
chown nobody:nobody /var/ipfire/certs/hostkey.pem
chmod 600 /var/ipfire/private/cakey.pem
chmod 644 /var/ipfire/ca/cacert.pem
chmod 644 /var/ipfire/certs/hostcert.pem
chmod 600 /var/ipfire/certs/hostkey.pem

Add ECDSA host key to ipsec.user.secrets

echo ": ECDSA /var/ipfire/certs/hostkey.pem" >> ipsec.user.secrets

Create WIndows Client Certificate

Create client key

pki --gen --type ecdsa --size 384 --outform pem > clientkey.pem

Create client x509 certificate

pki --issue --in clientkey.pem --type priv --cacert /var/ipfire/ca/cacert.pem 
            --cakey /var/ipfire/private/cakey.pem --dn "C=<Country Code>,ST=<State>,O=<Company Name>,OU=<Department>,CN=<Connection Name>" 
            --flag clientAuth --outform pem > clientcert.pem

Create PKCS#12 certificate store file (.p12)

openssl pkcs12 -in clientcert.pem -inkey clientkey.pem \
            -certfile /var/ipfire/ca/cacert.pem -export -out clientcert.p12

Move the client certificate, certificate store, and set permissions

mv clientcert.p12 /var/ipfire/certs/<Connection Name>.p12
chown nobody:nobody /var/ipfire/certs/<Connection Name>.p12
chmod 600 /var/ipfire/certs/<Connection Name>.p12

mv clientcert.pem /var/ipfire/certs/<Connection Name>cert.pem
chown nobody:nobody /var/ipfire/certs/<Connection Name>cert.pem
chmod 644 /var/ipfire/certs/<Connection Name>cert.pem

Restart IPsec

ipsec restart

Now navigate to the IPSec page in the WUI, and download the .p12 certificate store for your Windows connection, just as you did previously following the wiki, and import them into Windows once again.

While you are in the WUI, also edit the ciphers that your IPsec connection is using like so:

Now you can try and connect the VPN once more, and it should succeed.

The command on IPFire cat /var/log/messages should show the following in the charon output: selected proposal: IKE:AES_GCM_16_128/PRF_HMAC_SHA2_384/ECP_384

This means that the WIndows client successfully negotiated and connected with our hardened configuration. Yay!

Note: I use AES-128-GCM because it is widely accepted that there is no great benefit to be obtained by using 256 over 128 bit keys in AES. AES-256 is mostly for resistance against future quantum threats, threats which are not known to exist yet. AES-128-GCM is the perfect algo for streaming like this, it is fast and when AES is used in GCM mode, it is actually providing integrity checking of the data as it is decrypting, making it a wonderful algorithm for streaming data we need to both encrypt and validate as is the case.

Edit Here is the cypher recommendations from my countries cyber spies. If you go with GCMAES256 using the above configuration, you will be meeting the necessary cipher combinations for TOP SECRET in Australia. Probably USA as well given that we really just copy everything USA does, one of five eyes and all that.

3 Likes

This is excellent. Would you consider taking a look at the CGI to allow the creation of ECDSA Certe directly through the WUI?

Are there downsides or limitations introduced by the use of ECDSA, perhaps the inability to use MODP-2084 with Windows 10?

I wouldn’t know where to begin with that, I’ve never looked at the WUI modifying before.

MODP-2048 aka DH group 14 is the absolute baseline minimum key exchange mechanism for AES-128 bit keys today. This article suggests to avoid MODP-2048 if possible https://www.infosecmonkey.com/2020/01/07/what-diffie-hellman-dh-group-should-i-use/

ECDSA does have a downside in that it is widely speculated (from Snowden material mostly) that the NSA have the private keys that correspond to the curve parameters that NIST defined in the specification. So there is every chance that the NSA can decrypt ECDSA ciphers through their BULLRUN program, and so you would need to consider if that is appropriate for your situation. Also consider that MODP-2048 being on that cusp of becoming obsolete, NSA (and worse) may be cracking it already.

Personally where I can, I try and use Ed25519 or Ed448 for my asymmetric cipher needs, but alas in this situation I really think that ECP-384 aka DH group 20 is about as good as we’ll do on Windows IPsec for now.

Thanks, @anon45931963. You might consider joining the development mailing list, or perhaps just raising a bug on bugzilla pointing out that an ECDSA key is required to use ECP with Windows. If there’s a bug already (I might have opened one a while back), maybe add a comment?

As for MODP-2084, I am fully aware it’s not ideal, I was mostly asking to know whether using a different key would have operational limitations that might affect existing installations. Obviously, all tunnels will need to be set up again to use the new key, but if you need to select new ciphers for those tunnels and you don’t have control of both ends, that complicates things quite a lot.

Tom

Thanx @anon45931963 for posting this hardening guide. It realy looks promissing
Saw that you are banned???
you can email me at anon45931963@lycycledotcom And will appreciate any help.
I spend quite a lot of time on it and a lot is working the authentication gives the next Error(s)

I am testing this local, so dont go over the internet jet
the win10 client is directly connected to the red interface
the connection purposal gos great

he keeps complaining about

no private key found

I did run all the batch commands
and the powershell commands
in WIN10 i did go for the IPAdress insteed of the DNS name
in IPfire i choose also for IP adres (because we are testing local) and not Qualified domain name to be honest dont know what to choose there.

In older post I als o see that you have to run something like this to get and IPSEC vpn running
do i have to do this still?

this is my cat /var/log/messages

Aug 6 11:47:06 XenXfire charon: 01[NET] received packet: from 192.168.0.21[500] to 192.168.0.XXX[500] (376 bytes)
Aug 6 11:47:06 XenXfire charon: 01[ENC] parsed IKE_SA_INIT request 0 [ SA KE No N(FRAG_SUP) N(NATD_S_IP) N(NATD_D_IP) V V V V ]
Aug 6 11:47:06 XenXfire charon: 01[IKE] received MS NT5 ISAKMPOAKLEY v9 vendor ID
Aug 6 11:47:06 XenXfire charon: 01[IKE] received MS-Negotiation Discovery Capable vendor ID
Aug 6 11:47:06 XenXfire charon: 01[IKE] received Vid-Initial-Contact vendor ID
Aug 6 11:47:06 XenXfire charon: 01[ENC] received unknown vendor ID: 01:52:XX:XX:XX:XX:96:12:18:49:ab:9a:1c:5b:2a:51:00:00:00:02
Aug 6 11:47:06 XenXfire charon: 01[IKE] 192.168.0.21 is initiating an IKE_SA
Aug 6 11:47:06 XenXfire charon: 01[IKE] 192.168.0.21 is initiating an IKE_SA
Aug 6 11:47:06 XenXfire charon: 01[CFG] selected proposal: IKE:AES_GCM_16_128/PRF_HMAC_SHA2_384/ECP_384
Aug 6 11:47:06 XenXfire charon: 01[IKE] sending cert request for “C=NL, ST=ZH, L=Rotterdam, O=XenX, OU=IT, CN=XenX CA”
Aug 6 11:47:06 XenXfire charon: 01[ENC] generating IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) CERTREQ N(FRAG_SUP) N(CHDLESS_SUP) N(MULT_AUTH) ]
Aug 6 11:47:06 XenXfire charon: 01[NET] sending packet: from 192.168.0.XXX[500] to 192.168.0.21[500] (313 bytes)
Aug 6 11:47:06 XenXfire charon: 08[NET] received packet: from 192.168.0.21[4500] to 192.168.0.XXX[4500] (572 bytes)
Aug 6 11:47:06 XenXfire charon: 08[ENC] parsed IKE_AUTH request 1 [ EF(1/6) ]
Aug 6 11:47:06 XenXfire charon: 08[ENC] received fragment #1 of 6, waiting for complete IKE message
Aug 6 11:47:06 XenXfire charon: 13[NET] received packet: from 192.168.0.21[4500] to 192.168.0.XXX[4500] (572 bytes)
Aug 6 11:47:06 XenXfire charon: 13[ENC] parsed IKE_AUTH request 1 [ EF(3/6) ]
Aug 6 11:47:06 XenXfire charon: 13[ENC] received fragment #3 of 6, waiting for complete IKE message
Aug 6 11:47:06 XenXfire charon: 15[NET] received packet: from 192.168.0.21[4500] to 192.168.0.XXX[4500] (572 bytes)
Aug 6 11:47:06 XenXfire charon: 15[ENC] parsed IKE_AUTH request 1 [ EF(2/6) ]
Aug 6 11:47:06 XenXfire charon: 15[ENC] received fragment #2 of 6, waiting for complete IKE message
Aug 6 11:47:06 XenXfire charon: 05[NET] received packet: from 192.168.0.21[4500] to 192.168.0.XXX[4500] (572 bytes)
Aug 6 11:47:06 XenXfire charon: 05[ENC] parsed IKE_AUTH request 1 [ EF(4/6) ]
Aug 6 11:47:06 XenXfire charon: 05[ENC] received fragment #4 of 6, waiting for complete IKE message
Aug 6 11:47:06 XenXfire charon: 06[NET] received packet: from 192.168.0.21[4500] to 192.168.0.XXX[4500] (572 bytes)
Aug 6 11:47:06 XenXfire charon: 06[ENC] parsed IKE_AUTH request 1 [ EF(5/6) ]
Aug 6 11:47:06 XenXfire charon: 06[ENC] received fragment #5 of 6, waiting for complete IKE message
Aug 6 11:47:06 XenXfire charon: 14[NET] received packet: from 192.168.0.21[4500] to 192.168.0.XXX[4500] (460 bytes)
Aug 6 11:47:06 XenXfire charon: 14[ENC] parsed IKE_AUTH request 1 [ EF(6/6) ]
Aug 6 11:47:06 XenXfire charon: 14[ENC] received fragment #6 of 6, reassembled fragmented IKE message (2932 bytes)
Aug 6 11:47:06 XenXfire charon: 14[ENC] parsed IKE_AUTH request 1 [ IDi CERT CERTREQ AUTH N(MOBIKE_SUP) CPRQ(ADDR DNS NBNS SRV) SA TSi TSr ]
Aug 6 11:47:06 XenXfire charon: 14[IKE] received cert request for “C=NL, ST=ZH, L=Rotterdam, O=XenX, OU=IT, CN=XenX CA”
Aug 6 11:47:06 XenXfire charon: 14[IKE] received 95 cert requests for an unknown ca
Aug 6 11:47:06 XenXfire charon: 14[IKE] received end entity cert “C=NL, ST=ZH, O=XenX, OU=IT, CN=XenXIPSECVPNSaferXXXX”
Aug 6 11:47:06 XenXfire charon: 14[CFG] looking for peer configs matching 192.168.0.XXX[%any]…192.168.0.21[C=NL, ST=ZH, O=XenX, OU=IT, CN=XenXIPSECVPNSaferXXXX]
Aug 6 11:47:06 XenXfire charon: 14[CFG] selected peer config ‘XenXIPSECVPNSaferXXXX’
Aug 6 11:47:06 XenXfire charon: 14[CFG] using trusted ca certificate “C=NL, ST=ZH, L=Rotterdam, O=XenX, OU=IT, CN=XenX CA”
Aug 6 11:47:06 XenXfire charon: 14[CFG] checking certificate status of “C=NL, ST=ZH, O=XenX, OU=IT, CN=XenXIPSECVPNSaferXXXX”
Aug 6 11:47:06 XenXfire charon: 14[CFG] certificate status is not available
Aug 6 11:47:06 XenXfire charon: 14[CFG] reached self-signed root ca with a path length of 0
Aug 6 11:47:06 XenXfire charon: 14[CFG] using trusted certificate “C=NL, ST=ZH, O=XenX, OU=IT, CN=XenXIPSECVPNSaferXXXX”
Aug 6 11:47:06 XenXfire charon: 14[IKE] authentication of ‘C=NL, ST=ZH, O=XenX, OU=IT, CN=XenXIPSECVPNSaferXXXX’ with ECDSA-384 signature successful
Aug 6 11:47:06 XenXfire charon: 14[IKE] peer supports MOBIKE
Aug 6 11:47:06 XenXfire charon: 14[IKE] no private key found for ‘C=NL, ST=ZH, O=XenX, OU=IT, CN=192.168.0.XXX’
Aug 6 11:47:06 XenXfire charon: 14[ENC] generating IKE_AUTH response 1 [ N(AUTH_FAILED) ]
Aug 6 11:47:06 XenXfire charon: 14[NET] sending packet: from 192.168.0.XXX[4500] to 192.168.0.21[4500] (65 bytes)