# IPSEC on OpenBSD using Certificates The following document will use the domain name example.com when refering to the domain name the CA authority should be created for. Replace it with your domain name. ## 1. Preparation ### 1.1 Certificate Configurations Create a directory holding all CA related files. Make this directory read only for your user / or root. To make certificate creation easier copy the file `/etc/ssl/openssl.cnf` to the directory and add default values for these entries under the `req_distinguished_name` block: - countryName (two letters, DE) - stateOrProvince - localityName (e.g. city) - 0.organisationName (Your name, company name, domain) - organizationalUnitName ("VPN Auth") - commonName (ca@example.com) Create a directory named `private` below the CA's root directory and make the directory accessible only to the user managing the CA (e.g. `chmod 700 private/`). `openssl.cnf`: ``` CNAME = ca@example [ req ] default_bits = 2048 default_md = sha256 default_keyfile = privkey.pem distinguished_name = req_distinguished_name prompt = no [ req_distinguished_name ] countryName = DE stateOrProvinceName = NRW localityName = Big City 0.organizationName = John Doe organizationalUnitName = VPN Auth commonName = $ENV::CNAME ``` ### 1.2 CA Configuration File `x509v3.cnf`: ``` CERTPATHLEN = 1 CERTUSAGE = digitalSignature,keyCertSign,cRLSign EXTCERTUSAGE = serverAuth,clientAuth CADB = index.txt CASERIAL = serial.txt NSCERTTYPE = server,client [ x509v3_extensions ] nsCertType = 0x40 [ x509v3_CA ] basicConstraints = critical,CA:true,pathlen:$ENV::CERTPATHLEN keyUsage = $ENV::CERTUSAGE [ ca ] default_ca = CA_default [ CA_sign_policy ] countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ CA_default ] database = $ENV::CADB serial = $ENV::CASERIAL default_md = sha256 default_days = 365 default_crl_days = 365 unique_subject = yes email_in_dn = yes policy = CA_sign_policy ``` ### 1.3 Network setup Create the enc0 interface: ```shell echo up > /etc/hostname.enc0 ``` and start it: ```shell sh /etc/netstart enc0 ``` ## 2. Key Creation and Signing Create a password for the private key first, you may type it in every time you use the CA private key or you can store the passphrase in a file (e.g. `ca.pass`) for the time setting up the CA. You can add the `-passin file:ca.pass` and `-passout file:ca.pass` arguments to the `openssl` commands listed below. Hint for password creation: ```shell tr -cd [0-9A-Za-z.,_-] < /dev/urandom | dd bs=1 count=32 2>/dev/null >ca.pass chmod 600 ca.pass ``` Feel free to add more characters to the set of characters not to be deleted passed to `tr`. ### 2.1 Key Creation Create the password protected CA key: ```shell openssl genrsa -aes256 -out private/ca.key 4096 ``` Use the `-passout file:ca.pass` parameter or type in the CA password. ### 2.2 Create Signing Request ```shell openssl req -new -key private/ca.key -config openssl.cnf -out ca.csr ``` Use the `-passin file:ca.pass` parameter from now on when using a password file. Don't fill in the emailAddress and use "ca@example.com" for the commonName value. ### 2.3 Sign the CA Certificate ```shell openssl x509 -sha256 -req -days 3650 -in ca.csr -signkey private/ca.key \ -extfile x509v3.cnf -extensions x509v3_CA -out ca/ca.crt ``` Adjust the valid period of the certificate to your needs. ## 3. Creating Certificates Certificate creation can either be done on the target system or on the system the CA resides on. To keep things central and simple the next steps will assume that all keys and certificates are created on the CA system and the necessary files are distributed to the IPSEC clients from there. All files created and required for a client are put into separate directories below a newly created clients dirctory. Assuming creating a certificate and key for the client named foobar, with foobar beeing the full qualified domain name the following script would create the certificate: ```shell #! /bin/sh # TODO ``` Since libressl removed the support for passing environment variables we need to pass our own config file for the x509v3 FQDN extension. ## 4. Setup ipsec.conf | Variable | Value | |------------------|:--------------------------------| | CLIENT_NET_OR_IP | e.g. 10.x.y.z/16 | | SERVER_IP | IP address of lo1 | | SERVER_PUBLIC_IP | Public IP address of the server | | FQDN_CLIENT | CN of the client certificate | | FQDN_SERVER | CN of the server certificate | Feel free to change the used ciphers for your needs. aes-128 is just the one cipher that is fully supported by the hardware crypto device in my soekris 5501 router. ### 4.1 Client ``` ike dynamic esp from CLIENT_NET_OR_IP to SERVER_IP peer SERVER_PUBLIC_IP \ main auth hmac-sha2-256 enc aes-128 group modp1024 \ quick auth hmac-sha2-256 enc aes-128 group modp1024 \ srcid FQDN_CLIENT dstid FQDN_SERVER ``` ### 4.2 Server ``` ike passive esp from SERVER_IP to CLIENT_NET_OR_IP peer any \ main auth hmac-sha2-256 enc aes-128 group modp1024 \ quick auth hmac-sha2-256 enc aes-128 group modp1024 \ srcid FQDN_SERVER dstid FQDN_CLIENT ``` Each tunnel definition can be live in a single file using the include statement inside `/etc/ipsec.conf`. Adding tunnels that way enables you to remove tunnels on the fly using `ipsecctl -d -f CLIENT.conf`. ### 4.3 Startup Add the following lines to `/etc/rc.conf.local`: ipsec=YES isakmpd_flags=-4 -K