Self-signed certificates should never be used, as they have no Chain of Trust and are therefore insecure and pointless; the recommended way is to create a self-signed CA, using that CA to sign the certificate via an openssl.cnf
, such as this custom one.
- The
commonName
[CN
] cannot be an IP or DNS name, since doing so is insecure; I always recommend using the CN
to name the cert (e.g. Apache Web Server X
, VPN Server 1
, etc.)
- SAN [
SubjectAltName
] profiles can contain:
email
: email address
URI
: Uniform Resource Indicator
DNS
: DNS domain name [local or FQDN]
ID
: Registered ID: Object Identifier [OID]
IP
: IP address
dirName
: Distinguished Name
otherName
: OID;content
[arbitrary data associated with an OID]
(Content value is in standard ASN1_generate_nconf
format)
Execute all commands from within the directory that will contain openssl.cnf
:
- Download the custom
openssl.cnf
: (Linux/Windows)
# Linux:
wget https://raw.githubusercontent.com/JW0914/Wikis/master/Scripts%2BConfigs/OpenSSL/Linux/openssl.cnf
# Windows:
wget https://raw.githubusercontent.com/JW0914/Wikis/master/Scripts%2BConfigs/OpenSSL/openssl.cnf
- Edit the SAN profiles of the certs to be created: (lines 151 - 244)
- CA: Edit line 170 [
Router.1
] to name your CA
[ alt_ca_main ]
DNS.1 = Router.1
IP.1 = 127.0.0.1
[ alt_ca_main ]
alt_
: specifies a SAN profile
ca_main
: custom name for the SAN profile
(If renaming: update CA V3 profile line 264 [@alt_ca_main
])
DNS.1
:
Names the CA to make it easier when managing multiple CAs/ICAs
IP.1
:
Some router OSes require the loopback IP to be specified in the master CA
- Client/Server Cert: Edit lines 189 - 193
[ alt_sophos ]
IP.1 = 192.168.2.1
IP.2 = 127.0.0.1
DNS.1 = UTM.WRT
DNS.2 = your.ddns.com
[ alt_sophos ]
:
SAN profile name; change sophos
only if wishing to rename
(If renaming: update V3 profile lines 331 [v3_sophos
] and 337 [@alt_sophos
])
IP.1
:
Server IP (if accessible via SSH, loopback IP must be specified [IP.2
])
(list additional IPs on new lines with chronological listings; e.g. IP.3
)
DNS.1
:
LocalHostname.LocalDomain
DNS.2
:
DDNS/FQDN
(list additional names on new lines with chronological listings; e.g. DNS.3
)
- Create prerequisite files and directories: (lines 436 - 455)
mkdir crl; echo 01 > crl\crlnumber; echo > index; echo > rand; echo 00 > serial
crlnumber
:
serial for the next CRL [Certificate Revocation List] signed (lines 443 - 446)
index
:
list of all certs created (lines 448 - 451 and 642 - 686)
openssl ca
must be used to maintain the index
automatically, which I don't cover, as it overcomplicates the process (manually maintain: lines 642 - 686)
rand
:
random characters used for certificate/key creation (lines 453 - 455)
serial
:
serial [hex] of last cert signed, can be any number (lines 438 - 441 and 671 - 681)
- Create CA:
# CA key should have a secure passphrase of at least 20 characters, containing:
# 2 uppercase, 2 lowercase, 2 numbers, and 2 symbols
# Request:
openssl req -x509 -new -sha512 -days 3650 -newkey rsa:4096 -keyout 'CA.key.pem' -out 'CA.crt.pem' -config '.\openssl.cnf' -extensions v3_ca
# Generate CA CRL Cert:
openssl ca -gencrl -keyfile 'CA.key.pem' -cert 'CA.crt.pem' -out 'CA.crl.pem' -config '.\openssl.cnf'
# Convert CA CRL Cert to DER CRL:
openssl crl -inform PEM -in '.\CA.crl.pem' -outform DER -out '.\CA.crl'
Most can ignore, as vast majority are fine using RSA:
Type of key chosen determines the Key Exchange Algorithms that can be used [below]
- It's imperative the CA V3 profile's KUs are not altered (lines 260 - 265)
- (Optional) Create ICA [Intermediate CA]:
Useful if needing multiple CAs to lower risk of any one being compromised
# ICA key should have a secure passphrase of at least 20 characters, containing:
# 2 uppercase, 2 lowercase, 2 numbers, and 2 symbols
# Request:
openssl req -out '.\ICA.csr' -new -days 3650 -sha512 -newkey rsa:4096 -keyout 'ICA.key.pem' -config '.\openssl.cnf' -extensions v3_ica_router2
# Sign ICA with CA:
openssl x509 -req -sha512 -days 3650 -in '.\ICA.csr' -CA 'CA.crt.pem' -CAkey 'CA.key.pem' -CAserial '.\serial' -out 'ICA.crt.pem' -extfile '.\openssl.cnf' -extensions v3_ica_router2
# Generate ICA CRL Cert:
openssl ca -config '.\openssl.cnf' -gencrl -keyfile 'ICA.key.pem' -cert 'ICA.crt.pem' -out '.\ICA.crl.pem'
# Convert ICA CRL Cert to DER CRL:
openssl crl -inform PEM -in '.\ICA.crl.pem' -outform DER -out '.\ICA.crl'
# Concatenate ICA and CA Cert:
# Linux:
cat './ICA.crt.pem' './CA.crt.pem' > './CA-ICA-Chain.crt.pem'
# Windows:
cmd /c type '.\ICA.crt.pem' '.\CA.crt.pem' > '.\CA-ICA-Chain.crt.pem'
Most can ignore, as vast majority are fine using RSA:
Type of key chosen determines the Key Exchange Algorithms that can be used [below]
- It's imperative the ICA V3 profiles' KUs are not altered (lines 267 - 279)
- ICA V3 profiles contian
pathlen:0
(they can sign certs, but not CAs/ICAs); if pathlen
is not specified/number set, it can sign an infinite/specified number of CAs/ICAs
- Create certificates: (if V3 profile was renamed in 2.2, update here)
# Server certs: add -nodes to the end of the Request command; else server requires
# manually entering encryption passphrase when starting (impractical)
# Request:
openssl req -out '.\server.csr' -new -days 825 -sha512 -newkey rsa:2048 -keyout '.\server.key.pem' -config '.\openssl.cnf' -extensions v3_sophos -nodes
# Sign:
# CA only:
openssl x509 -req -sha512 -days 825 -in '.\server.csr' -CA '.\CA.crt.pem' -CAkey '.\CA.key.pem' -CAserial '.\serial' -out '.\server.crt.pem' -extfile '.\openssl.cnf' -extensions v3_sophos
# ICA: (change to)
-CA '.\CA-ICA-Chain.crt.pem' -CAkey '.\ICA.key.pem'
# Chain of Trust: Concatenate CA or ICA and CA to Cert:
# For ICA, change CA.crt.pem to CA-ICA-Chain.crt.pem
# Linux:
cat './CA.crt.pem' >> './server.crt.pem'
# Windows:
cmd /c type './CA.crt.pem' >> './server.crt.pem'
# (Optional) Export:
# CA only:
openssl pkcs12 -export -out '.\server.p12' -inkey '.\server.key.pem' -in '.\server.crt.pem' -certfile 'CA.crt.pem'
# ICA: (change to)
-certfile 'CA-ICA-Chain.crt.pem'
# CA - ICA chain cert must be exported to maintain the Chain of Trust of: Cert → ICA → CA
Most can ignore, as vast majority are fine using RSA:
Type of key chosen determines the Key Exchange Algorithms that can be used [below]
References:
Certificate Verification:
- Certificate:
openssl x509 -text -noout -in 'cert.crt.pem'
- Certificate Signing Request [CSR]:
openssl req -text -noout -verify -in 'cert.csr'
- Key:
openssl rsa -check -in 'cert.key.pem'
- PKCS12 [
.pfx
/.p12
]:
openssl pkcs12 -info -in 'cert.p12'
Hex ⟷ Dec Conversion:
index
:
-
# Manually maintain the index file by inputting one cert entry per line in the following format:
# 1 2-----------> 3-> 4> 5-----> 6---------------------------------------------------------------------------->
V 261231235959Z 0a unknown /C=US/ST=State/L=Locality/O=Org/OU=Unit/CN=Common Name/[email protected]
# 1 Status of Certificate:
V # Valid
R # Revoked
E # Expired
# 2 Expiration Date:
YYMMDDHHMMSSZ # Date format followed by 'Z' (2026.12.31 @ 23:59:59)
# 3 Revocation Date: (empty if not revoked)
YYMMDDHHMMSSZ,reason
# Valid reasons are:
## keyCompromise
## CACompromise
## affiliationChanged
## superseded
## cessationOfOperation
## certificateHold
## privilegeWithdrawn
## AACompromise
# Certain distros error out without a whitespace for 3
# 4 Serial number in hex format:
0a # hex for 10
# 5 Certificate Filename or Literal String
unknown # Certificate filename or literal string 'unknown'
# 6 Distinguished Name
Key Exchange Algorithms:
RSA
:
Encrypts a random value, chosen by the client, via the server public key
- Required:
Server public key must be an RSA key
Server certificate must have KU keyAgreement
DH_RSA
:
Key exchange occurs via a static Diffie-Hellman key
- Required:
CA must be using an RSA signing key
Server public key must be a Diffie-Hellman key
Diffie-Hellman key must have been issued by a CA
DH_DSA
:
Like DH_RSA
, except the CA used a DSA key in lieu of RSA
DHE_RSA
:
Key exchange occurs via an Ephemeral Diffie-Hellman
- Server dynamically generates & signs a DH public key, sending it to the client
- Required:
Server public key must be an RSA key
Server certificate must have KU digitalSignature
DHE_DSA
:
Like DHE_RSA
, except the CA used a DSA key in lieu of RSA
Elliptic-Curve Key Exchange Algorithms:
ECDH_RSA
:
Like DH_RSA
, but with elliptic-curves
- Required:
Server public key must be an ECDH key
Server certificate must be issued by a CA using an RSA public key
ECDH_ECDSA
:
Like ECDH_RSA
, except the CA used an ECDSA key
ECDHE_RSA
: Server sends dynamically generated EC Diffie-Hellman key, signing it via it's RSA key
- Server public key signs the Ephemeral EC Diffie-Hellman key
ECDHE_ECDSA
:
Like ECDHE_RSA
, except server public key is an ECDSA key
- Equivalent to
DHE_DSS
, but with elliptic curves for both the Diffie-Hellman & signature
KUs & EKUs:
Man Pages:
While my GitHub will always maintain the customized openssl.cnf
linked to throughout, since this answer relies on this, the Linux version is being provided for redundancy:
(Windows version couldn't be included due to the 30K character limit)
#
##::[[--- Linux OpenSSL Config ---]]::##
#====================================================================
##----- Notes -----##
#====================================================================
# All commands required can be found beginning on line 430
# Windows users, either:
# Change file paths from "/" to "\\"
# Download the Windows openssl.cnf: https://github.com/JW0914/Wikis/blob/master/Scripts+Configs/OpenSSL/openssl.cnf
# Sophos users:
# If not using SANs, prior to generating user certs, ensure 'x509_extensions = usr_cert_not_dn'
# This results with 'RFC822 Name = [email protected]' in the SubjectAlternativeName of the certificate.
# Without this, it will be impossible to authenticate to VPNs on Sophos.
# Intermediate CAs & Intermediate CA client certs CANNOT be utilized on Sophos UTM due to how Sophos authenticates.
# Only exception is the WebAdmin certificate, which can be signed by a Public ICA authority for a FQDN.
# For chain of trust to be maintained, CA & ICA must be installed on devices accessing the WebAdmin/User Portal.
#====================================================================
##----- Establish Build Variables -----##
#====================================================================
dir = /etc/ssl
cnf = /etc/ssl/openssl.cnf
CNF = $dir/openssl.cnf
#====================================================================
##----- Establish CA Profile and Policy -----##
#====================================================================
[ default ]
UTM = "Sophos UTM CA"
WRT = "Router 2 ICA"
VPN = "Router 2 VPN ICA"
[ ca ]
default_ca = CA_default
#====================================================================
[ CA_default ]
certs = $dir
new_certs_dir = $dir
database = $dir/index
RANDFILE = $dir/rand
serial = $dir/serial
crldir = $dir/crl
crlnumber = $crldir/crlnumber
crl = $crldir/ca.crl.pem
default_crl_days = 3650
certificate = "$dir/ca/$UTM.crt.pem"
private_key = "$dir/ca/$UTM.key.pem"
default_days = 3650
preserve = no
default_md = sha512
x509_extensions = usr_cert_not_dn
copy_extensions = copy
unique_subject = yes
policy = policy_match
name_opt = esc_2253,esc_ctrl,esc_msb,sep_comma_plus_space,ignore_type
cert_opt = ca_default
#====================================================================
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = match
commonName = supplied
emailAddress = optional
[ policy_supply ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = match
commonName = optional
emailAddress = optional
#====================================================================
##----- Establish Certificate Options -----#
#--------------------------------------------------------------------
# x64 machines always process SHA512 faster than SHA256.
# 'encrypt_key = yes' is not currently commented out.
# When creating a key for a server, add '-nodes' to the Request command.
[ req ]
default_bits = 2048
default_keyfile = private.key.pem
preserve = no
default_md = sha512
string_mask = utf8only
utf8 = yes
distinguished_name = req_distinguished_name
attributes = req_attributes
req_extensions = v3_req
x509_extensions = v3_ca
copy_extensions = copy
encrypt_key = yes
[ req_attributes ]
challengePassword =
challengePassword_min = 12
challengePassword_max = 40
#====================================================================
[ req_distinguished_name ]
countryName = Country
countryName_max = 2
stateOrProvinceName = State
localityName = Locality
0.organizationName = Organization
organizationalUnitName = Organizational Unit
commonName = Common Name
commonName_max = 64
emailAddres = Email
emailAddress_max = 64
countryName_default = xx
stateOrProvinceName_default = State
localityName_default = Locality
0.organizationName_default = Sophos UTM
organizationalUnitName_default = LAN
#====================================================================
##----- Establish SubjectAltName (SAN) Profiles -----##
#====================================================================
# All server certs with WebUIs should have their loopback IP specified in their SAN profile.
# This prevents certificate errors if connecting to the device, router, or server via an SSH tunnel.
# Certain OS CA certs must have the loopback IP specified in SAN profile (i.e. Sophos UTM's CA).
# Provided SAN profiles are utilized, Common Names can be whatever one wishes (i.e. not the DNS or IP)
# SANs can be: 'email' (email address), 'URI' (Uniform Resource Indicator), 'DNS' (DNS domain name),
# 'RID' (Registered ID: OBJECT IDENTIFIER), 'IP' (IP address), 'dirName' (Distinguished Name), and 'otherName'.
#--------------------------------------------------------------------
##----- Certificate Authorities -----##
#--------------------------------------------------------------------
# Main #
[ alt_ca_main ]
DNS.1 = Router.1
IP.1 = 127.0.0.1
# Router 2 #
[ alt_ica_router2 ]
DNS.1 = Router.2
IP.1 = 127.0.0.1
# Code Signing #
[ alt_signing_ica ]
DNS.1 = Code-Signing
#--------------------------------------------------------------------
##----- Certificate Authority Clients -----##
#--------------------------------------------------------------------
# Main #
# Servers #
[ alt_sophos ]
IP.1 = 192.168.2.1
IP.2 = 127.0.0.1
DNS.1 = UTM.WRT
DNS.2 = your.ddns.com
[ alt_truenas ]
IP.1 = 192.168.2.13
IP.2 = 192.168.2.130
IP.3 = 127.0.0.1
DNS.1 = TrueNAS.WRT
DNS.2 = your-fqdn.com
[ alt_vpn_server1 ]
IP.1 = 10.0.0.1
DNS.1 = your.ddns.com
# Clients #
[ alt_vpn1_user1 ]
email.1 = [email protected]
DNS.1 = VPN1-Client1-Device1
DNS.2 = VPN1-Client1-Device2
#--------------------------------------------------------------------
##----- Intermediate Certificate Authority Clients -----##
#--------------------------------------------------------------------
# Router 2 #
# Servers #
[ alt_openwrt ]
IP.1 = 192.168.2.2
IP.2 = 127.0.0.1
DNS.1 = LAN.WRT
[ alt_vpn_server2 ]
IP.1 = 10.0.1.1
DNS.1 = your.ddns.com
# Clients #
[ alt_vpn2_user1 ]
DNS.1 = VPN2-Client1-Device1
email.1 = [email protected]
[ alt_vpn2_user2 ]
DNS.1 = VPN2-Client2-Device1
DNS.2 = VPN2-Client2-Device2
email.1 = [email protected]
# Code Signing #
# Cert1 #
[ alt_codesign ]
email.1 = [email protected]
#====================================================================
##----- Establish Certificate Authority V3 Profiles -----##
#--------------------------------------------------------------------
# These V3 CA profiles must not be modified to contain any more, or any less, KUs.
# These have been configured specifically for security & its imperative no other keyUsages are set
# For an ICA to be capable of signing CAs/ICAs, 'pathlen' number must mirror number of CAs/ICAs it can sign
# By default, all ICAs 'pathlen' values are set to 0, meaning they can sign certs, but not other CAs/ICAs.
# If 'pathlen' is not specified, CA/ICA can sign an infinite number of other CAs/ICAs.
[ v3_ca ]
basicConstraints = critical, CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
subjectAltName = @alt_ca_main
keyUsage = critical, cRLSign, digitalSignature, keyCertSign
[ v3_ica_router2 ]
basicConstraints = critical, CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
subjectAltName = @alt_ica_router2
keyUsage = critical, cRLSign, digitalSignature, keyCertSign
[ v3_signing_ica ]
basicConstraints = critical, CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, cRLSign, digitalSignature, keyCertSign
subjectAltName = @alt_signing_ica
[ crl_ext ]
issuerAltName = issuer:copy
authorityKeyIdentifier = keyid:always, issuer:always
#====================================================================
##----- Establish Generalized V3 Certificate Profiles -----##
#--------------------------------------------------------------------
[ v3_req ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
[ usr_cert_dn ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth, emailProtection
[ usr_cert_not_dn ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
subjectAltName = email:copy
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth, emailProtection
#====================================================================
##----- Establish Client Certificate V3 Profiles -----##
#--------------------------------------------------------------------
# These V3 profiles should not be modified to contain less than what they are currently configured with.
# These have been specifically configured with security in mind.
# All servers capable of TLS should contain all keyUsages, except for 'dataEncipherment'
# VPN and file servers should not have less than: 'digitalSignature, keyEncipherment, keyAgreement'
# All servers must contain EKU 'serverAuth'
# All server [VPN] clients must contain EKU 'clientAuth'
#--------------------------------------------------------------------
##----- Certificate Authority Clients -----##
#--------------------------------------------------------------------
# Main #
# Servers #
[ v3_sophos ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
subjectAltName = @alt_sophos
[ v3_truenas ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
subjectAltName = @alt_truenas
[ v3_vpn_server1 ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
subjectAltName = @alt_vpn_server1
# Clients #
[ v3_vpn1_user1 ]
basicConstraints = critical,CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth
subjectAltName = @alt_vpn1_user1
#--------------------------------------------------------------------
##----- Intermediate Certificate Authority Clients -----##
#--------------------------------------------------------------------
# Router 2 #
# Servers #
[ v3_openwrt ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
subjectAltName = @alt_openwrt
[ v3_vpn_server2 ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
subjectAltName = @alt_vpn_server2
# Clients #
[ v3_vpn2_user1 ]
basicConstraints = critical,CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth
subjectAltName = @alt_vpn2_user1
[ v3_vpn2_user2 ]
basicConstraints = critical,CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth
subjectAltName = @alt_vpn2_user2
# Code Signing #
# Certificates #
[ v3_codesign ]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, nonRepudiation, digitalSignature
extendedKeyUsage = critical, codeSigning, msCodeInd, msCodeCom, msCTLSign, timeStamping
subjectAltName = @alt_codesign