[KIND OF SOLVED] Allow only specific cert to connect
Under http://doc.pfsense.org/index.php/VPN_Capability_IPsec#Configuring_the_VPN_Tunnel (11th item) there is a reference to a "Peer certificate" option, which as far as I could investigate, is useful to specify which remote certificate should be trusted.
That article seems to have been written based on pfSense 1.2.3, is there a similar option on pfSense 2.0+?
The point is that I generated an RSA site-to-site VPN between two pfSense boxes. It works great, but the RSA authentication seems to be based only on the CA cert. That means that ANY other server cert signed by the same CA will also authenticate the VPN! (there are several other server certs around in the wild, signed by the same CA)
I am missing a concept here? Should I use a completely different CA to generate the IPsec certs?
EDIT: changed topic title to a more descriptive one
Well, I've been investigating a little more. As per the racoon.conf manual:
my_identifier idtype …;
specifies the identifier sent to the remote host and the
type to use in the phase 1 negotiation. address, fqdn,
user_fqdn, keyid and asn1dn can be used as an idtype.
they are used like:
my_identifier address [address];
the type is the IP address. This is the default
type if you do not specify an identifier to use.
my_identifier user_fqdn string;
the type is a USER_FQDN (user fully-qualified
my_identifier fqdn string;
the type is a FQDN (fully-qualified domain name).
my_identifier keyid file;
the type is a KEY_ID.
my_identifier asn1dn [string];
the type is an ASN.1 distinguished name. If
string is omitted, racoon will get DN from
Subject field in the certificate.
peers_identifier idtype …;
specifies the peer's identifier to be received. If it is
not defined then racoon will not verify the peer's
identifier in ID payload transmitted from the peer. If
it is defined, the behavior of the verification depends
on the flag of verify_identifier. The usage of idtype is
same to my_identifier.
verify_identifier (on | off);
If you want to verify the peer's identifier, set this to
on. In this case, if the value defined by
peers_identifier is not same to the peer's identifier in
the ID payload, the negotiation will failed. The default
So what I get is that by entering a specific DN on the "peers_identifier" part, I should be able to allow just that certificate to connect. The point is that it doesn't work. I even manually added the "verify_identifier on" on the racoon.conf since it does not get added by default, but still any certificate signed by the same CA is able to connect.
So, in short, how do I tell racoon which certificate in particular should be allowed to connect and refuse all others???
Ok, I figured it out after hours of investigating and with some help from the guys at the ipsec-tools-users mailing list. Since this information is not clearly stated anywhere, I'll sum it up here (at some point I think this needs to be added to the wiki)
When using an IPsec site-to-site with RSA validation, both "My identifier" and "Peers identifier" must be set to "ASN.1 Distinguished Name".
If you leave them blank, the ASN1DN value will be taken from the certificate (own certificate for my_identifier and peer's CERT on the received payload for peers_identifier). Usually, you want to leave the "my_identifier" value blank, so racoon will send the value from the certificate itself. Most gateways will plainly refuse your connection if the sent value does not match the cert you are sending, which makes perfect sense.
Now, if you want to tell racoon to only authenticate connections FROM a specific certificate or set of certificates (instead of anything signed by the same CA), it can be done with the peers_identifier option. What you need to type in the box is the exact string from the subject field of the certificate. You can get this value by directly looking at the racoon log and watch for the received payload, or parse the remote certificate with:
openssl x509 -in certificate.pem -text
Where "certificate.pem" is the certificate you want to allow. You can also allow a set of certificates by using wildcards. Individual component values of an asn1dn identifier may be specified as * to match any value (e.g. "C=XX, O=MyOrg, OU=*, CN=Mine"). Bear in mind that if the information includes special characters like – ,=+<>#; – , they will need to be escaped by a backslash.
The final caveat for this to work is that there is an additional option that needs to be set on the racoon.conf file: verify_identifier on;
If this is not set, racoon will allow the connection even if the DN does not match. At this point, the pfSense webGUI does not set this flag, and since it defaults to off, makes it allow any cert to connect. Of course you can add the option to the racoon.conf file and manually restart racoon, but it won't survive a reboot.
In my particular case, I also had to manually delete all the SADs and SPDs on both ends since it looked like they were cached or something, the VPN was connecting no matter what I set as the peers_identifier.
I will raise a request to add a checkbox for the "verify_identifier on" on the webGUI.
As usual, hope this helps anybody :)
EDIT: added a feature request on redmine: http://redmine.pfsense.org/issues/2904