What is the Subject Alternative Name and Why is it Important for VPN?

By Team equinuxFebruary 14, 2024March 7th, 2024No Comments

In our previous post, we explored which kind of certificates exist and how they are created, as well as the role Certificate Signing Requests (CSR) play in this process.

When creating an email or server certificate, there is one important final step: The Subject Alternative Name (SAN). This is the attribute that people most often ignore, that is commonly missing completely in certificates or used incorrectly which causes all kind of undesired behaviour – putting the security of servers and VPNs at risk.

What is the Subject Alternative Name (SAN) Attribute?

Certificates contain attributes and attributes can be grouped into major sections. Those major sections are:

  1. The owner section: Who owns that certificate? (name, e-mail, geographical location, etc.)
  2. The issuer section: Who issued that certificate? (same attributes as for the owner section)
  3. The info section: What kind of certificate is it? (which algorithm, how many bits, when did it became valid, how long is it valid, etc.)
  4. The usage section: What will this certificate be used for? (signing data, encrypting data, signing certificates, authenticating a user or a server, etc.)

One of the most important attributes in the 4th section is the Subject Alternative Name (SAN).

Certificates for VPN Servers

If you're looking to create a certificate for your VPN server, you will need to include a SAN attribute in order for it to be considered valid. This way, you and your users can easily get connected in your VPN client.

Discover VPN Tracker - the #1 VPN client for Mac and iOS →

When a certificate is created for an email account (an email certificate) or for a server (web server, VPN gateway, etc.), the standard requires that this certificate must have a correctly populated SAN attribute to be considered valid.

Before there was the SAN attribute, an e-mail certificate would simply use the email attribute of the owner section. That had two downsides:

Only one email address was permitted:
What if you have 20 email addresses? Then you would need 20 certificates, one for every email address. Not only is it confusing and annoying to deal with that many certificates, obtaining an email certificate from a public CA doesn't come cheap, so you have to pay for every single one.

The certificate owner and the certificate user are not always the same:
Think of a company support address, like support@example.com. The certificate used for signing support answers and for sending encrypted mails to the support team does not belong to the support system, but to the company. So the ownership email would rather be something like cert-admin@example.com, even though the cert is intended for support@example.com.

The SAN attribute solves both these issues. It is independent of the ownership address and it is a list of address, so you can enter any number of email addresses.

Before the SAN attribute existed, a server certificate would simply use name (Common Name, aka CN) of the owner section for the server address. That also had two downsides:

A server can have several addresses under which it is known:
E.g. it may have multiple IPv4 addresses, multiple IPv6 address, and/or multiple domain names that all point to this one server. Yet there is only one name field in the ownership section.

The name attribute is just defined to be a string of human readable letters and digits, there are no rules about its format: 
So how would software know if the content of that field is just a name, an IP address of any kind or a domain name? Well, actually it cannot know that at all, all it can do is look at the name and take an educated guess, like "that looks like an IPv4 address" but what if I just wanted to name my certificate 1.0.0.0 or Example.net for whatever reason and not because I wanted this to be an IP address or a domain name?

Again, the SAN attribute solves both issues. Being a list, it can contain any number of server addresses and as every entry in that list has an explicit type, the type tells software how to interpret the entry, e.g. telling it "this is an IPv6 address", so it must be parsable as such an address, otherwise the entry is invalid.

How to Create a Certificate with a SAN Attribute

By default, certificates don't receive a SAN attribute, as only email and server certificates require one. For example, certificates only used to authenticate a person or root/intermediate certificates used for signing other certificates don't require one at all.

Using the Certificate Assistant

If you have a CA or intermediate certificate installed on your Mac and someone sends you a CSR, you can create a certificate based on that CSR that contains a SAN list using the macOS Certificate Assistant.
Just ensure that the request has the file extension certSigningRequest and you can double click the file to open the assistant. In the very first assistant step you have to make sure the checkbox "Let me override defaults for this request" is checked. This allows you to fine tune attributes for the new certificate.
During this process, you can configure the SAN attribute, i.e. whether it is present at all and which address entries will be added to its list (you can add multiple entries per type by separating them with space).

Using Terminal

Creating a certificate on your Mac in Terminal is a bit more complicated, as this time you need to first create a config file that defines the SAN field values.
Here's an example of what such a file could look like:

subjectAltName = DNS:example.com, DNS:www.example.com, IP:10.200.0.1

Entries are separated by comma and every entry begins with a type name (DNS, IP, email; other types also exist like URI, RID, dirName, but we are not going cover these types here). If you just want to specify a few SAN entries, this format is okay but if you want to specify a lot of entries, there is an alternative format you can use instead:

subjectAltName = @altnames
[altnames]
DNS.1 = example.com
DNS.2 = www.example.com
IP.1 = 10.200.0.1
IP.2 = 192.168.100.1
IP.3 = 2001:DB8::
email.1 = admin@example.com
email.2 = webadmin@example.com

The first line tells OpenSSL that the SAN entries are defined in a subsection named "altnames". This subsection contains one line per entry. Again, every entry starts with a type but as every line in a subsection must start with a unique key, you just append a counter value to the type.
Store this file as ca-ext.conf. Further we assume that your CA cert is stored in a PEM file named ca-cert.pem, your CA private key is stored in a PEM file named ca-key.pem and your request is stored in a file request.csr, then you would use the following command to create a signed certificate:

openssl x509 -req -in request.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -extfile ca-ext.conf -out certificate.pem

The command creates a PEM file certificate.pem, which contains the signed certificate. It will also create a serial number file named ca-cert.srl that contains the randomly chosen serial number of the certificate. Keep in mind that no two certificates signed by the same CA may have the same serial number, so you may want to document that this number has been used and may never be used again in the future.

Embedding SAN Entries into a Certificate Signing Request

Both methods described above have the downside that somebody has to manually specify the SAN entries for the final certificate. For the Certificate Assistant, they must be entered in one of the configuration steps and for the Terminal solution, a config file must be created for them.
Wouldn't it be a lot better, to have the SAN entries already in the certificate request itself, so the entire process can be automated?
Actually, this is possible using Terminal. If you remember our previous post, we created a CSR in Terminal using the following command:

openssl req -new -out certRequest.csr -keyout privateKey.pem

To add a list of SAN entries, simply append the following:

-addext "subjectAltName = DNS:example.com, DNS:www.example.com, IP:10.200.0.1"

Now those entries are already embedded into the request. All you need to tell openssl when signing the request is to keep those embedded entries. As for all field values, the issuer has the last word what goes into which field value and extended attributes in signing requests are ignored by default.
To copy the extended attributes from the request, we need to use "openssl ca" instead of "openssl x509", which has the downside that we need a more complex config file:

[ ca ]
default_ca      = CA_default
[ CA_default ]
database        = index.txt
serial          = serial.txt
policy          = policy_default
new_certs_dir   = .
opy_extensions = copy
[ policy_default ]

We can now save this file as ca-ext-copy.conf and run the following command to create an empty index.txt file in the current directory (this file must exist prior to using the config):

touch index.txt

Finally we can sign the request with:

openssl ca -in certRequest.csr -cert ca-cert.pem -keyfile ca-key.pem -days 365 -md default -config ca-ext-copy.conf -create_serial -batch -out certificate.pem

This command results in a signed certificate which has the same SAN entries as found in the certificate signing request.
Note that the final certificate will appear twice after running that command, once as certificate.pem but also once as <SERIAL_NUMBER>.pem, where <SERIAL_NUMBER> is a randomly chosen serial number. You can control where this second file is stored using the `new_certs_dir` in the config file. The dot we put there just means "in the current directory where the command is executed from".
Also note that instead of using the option `-create_serial`, which creates a random serial number if no serial.txt file exists, you can first create the file serial.txt, e.g. by running this command

echo 01 >serial.txt

Now this file contains the value 01 and this will be the serial for the first certificate signed (serial numbers must have at least two characters, so you cannot start with just 1 but 01 will work). After it has been signed, the value in the file is automatically increased to 02 and keeps counting upwards with every request signed. If you are building your own certificate management system, you want to store the serial.txt and index.txt file in a central place, as they will let you know which certificates you signed in the past (index.txt) and which serial number to use for the next certificate signed (serial.txt).

Can I embed a SAN entry using macOS Certificate Assistant?

Unfortunately the macOS Certificate Assistant will always ignore embedded extended attributes like SAN. So if you plan to sign your certificates using the assistant, embedding SAN entries into the request is just a waste of time and you will instead need to use the Terminal commands described above.

Next steps for VPN users

Now that your certificate contains all the relevant information, you can install it on your VPN gateway.  Your VPN client will use the certificate to check the identity of your gateway so you can get connected to your VPN server.

Why VPN Tracker?

VPN Tracker is the best VPN client for Mac, iPhone and iPad and is compatible with the most popular VPN gateways, including UniFi, NETGEAR, TP Link, Draytek, and many more.

Your VPN Tracker benefits

  • Securely connect with your home and office networks
  • Use your own gateway
  • Preconfigured profiles for 300+ VPN devices
  • Expert productivity features for teams
  • For Mac, iPhone, iPad
  • Explore all features
connect to IPsec vpn on iOS
5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedback
View all comments
Privacy-Settings / Datenschutz-Einstellungen
0
Feedback or improvements? Let us know!x
()
x