OpenSSL Certificate Authority (CA) 101

Create your own Certificate Authority (CA). These directions are based upon the Feisty Duck documentation. This document shows you how to setup your own root authority and subordinate CA. And it includes OCSP.

Read the Docs

These directions are based upon the Feisty Duck directions.  It also helps to read the OpenSSL documentation.  Arch Linux has a decent WIKI article as well.  I built myself an OpenSSL CA a while back.  But the Feisty Duck directions are much better than the very basics.

.local

I am using 'lab.pahoehoe.local' for my domain.  I originally tried to use 'lab.pahoehoe.net'.  But I have been too lazy to finish setting up my home ESXi host and internal VLANs.  Once I finish this task I can setup internal DNS and properly use 'lab.pahoehoe.net'.

Identify the Proper Directory

Different distributions will compile OpenSSL with different directories.  Use 'openssl version -a |grep DIR' to identify the directory for your box.

$ openssl version -d  (Raspbian / Debian)
OPENSSLDIR: "/usr/lib/ssl"
pi@pi2:~ $ ls -l /usr/lib/ssl
total 4
lrwxrwxrwx 1 root root 14 May 3 23:03 certs -> /etc/ssl/certs
drwxr-xr-x 2 root root 4096 May 27 11:11 misc
lrwxrwxrwx 1 root root 20 May 3 23:03 openssl.cnf -> /etc/ssl/openssl.cnf
lrwxrwxrwx 1 root root 16 May 3 23:03 private -> /etc/ssl/private

# openssl version -d  (CentOS 7 / RHEL 7)
OPENSSLDIR: "/etc/pki/tls"
[root@zl01lab01 ~]# ls -l /etc/pki/tls
total 12
lrwxrwxrwx. 1 root root 49 Jul 5 19:37 cert.pem -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
drwxr-xr-x. 2 root root 112 Jul 5 19:37 certs
drwxr-xr-x. 2 root root 69 Jul 5 19:37 misc
-rw-r--r--. 1 root root 10923 Mar 5 2015 openssl.cnf
drwxr-xr-x. 2 root root 6 Jun 29 2015 private

Create the ROOT CA

Pick a directory for the configuration files.  You will create new directories and a new configuration file for the root CA.  My root CA will be on my CentOS 7 box.

  • cd /etc/pki
  • mkdir root-ca
  • cd /etc/pki/root-ca
  • mkdir certs db private pub csr
  • chmod 700 private
  • touch db/index
  • openssl rand -hex 16 > db/serial
  • echo 1001 > db/crlnumber
  • vi /etc/pki/root-ca/root-ca.conf  (See 'root-ca.conf and sub-ca.conf' below)

Now we can create the root CA CSR, private key and public key.  Plus we will create the CRL (Certificate Revocation List) and the OCSP certificates.  You must export the RANDFILE variable or openssl will default to '~/.rnd'.  Not that it matters either way.

export RANDFILE=/etc/pki/root-ca/private/.rnd

Create the root CA CSR (./root-ca.csr) and private key (./private/root-ca.key).  You must enter a passphrase.  But we will delete that passphrase.  You can keep it if desired.

openssl req -new \
-config root-ca.conf \
-out root-ca.csr \
-keyout private/root-ca.key

Remove the passphrase.

openssl rsa -in private/root-ca.key -out private/root-ca.key

Now we can self sign our CSR and create the public key (./root-ca.crt).

openssl ca -selfsign \
-config root-ca.conf \
-in root-ca.csr \
-out root-ca.crt \
-extensions ca_ext

To generate a CRL use the '-gencrl' command as shown below.  The output will be './root-ca.crl'.

openssl ca -gencrl \
-config root-ca.conf \
-out root-ca.crl

OCSP Responder

The feisty duck directions provide a basic OCSP (Online Certificate Status Protocol).  If you have a lightweight web server you can configure that to respond to the OCSP queries.  Or you could move that to another server entirely.  OCSP is better than CRL (Certificate Revocation List).  But it still puts a burden on the CA and adds additional exposure to the CA.  If you sniff the packets when you log into an HTTPS site you will notice that your laptop also queries the OCSP responder.

OCSP stapling is a better solution.  The HTTPS site will periodically query the CA and then provide a timestamp in the TLS handshake to the client.  The client does not query the OCSP server directly.  Obviously you cannot include the OCSP responder URL in the server certificate.  I need to read more about OCSP stapling.  However, I have seen a number of VM appliances that are black boxes.  I am not sure if they support OCSP stapling.

Perform this on the root CA and the sub CA.

  • Create a key and CSR for the OCSP responder.  You may choose to remove the passphrase on the private key.  See the example above.

openssl req -new \
-newkey rsa:2048 \
-subj "/C=US/O=Lava Dreams/CN=OSCP Root Responder" \
-keyout private/root-ocsp.key \
-out csr/root-ocsp.csr

  • Second use the root CA to issue a certificate.  The days are shortened since this certifcate cannot be revoked.

openssl ca \
-config root-ca.conf \
-in csr/root-ocsp.csr \
-out pub/root-ocsp.crt \
-extensions ocsp_ext \
-days 30

  • Start the OCSP Responder - Ideally this would be done in an HTTPD server on a standard port.

openssl ocsp -port 9080 -index db/index \
-rsigner pub/root-ocsp.crt \
-rkey private/root-ocsp.key \
-CA root-ca.crt -text &

Create the SUB CA

The steps are very similar.  I am using my Raspberry PI for my subordinate CA (aka intermediate CA).  Edit the configuration file as appropriate.

  • cd /etc/ssl
  • mkdir sub-ca
  • cd /etc/ssl/sub-ca
  • mkdir certs db private pub csr
  • chmod 700 private
  • touch db/index
  • openssl rand -hex 16 > db/serial
  • echo 1001 > db/crlnumber
  • vi /etc/ssl/sub-ca/sub-ca.conf  (See 'root-ca.conf and sub-ca.conf' below)

Now create the CSR (./sub-ca.csr) and the private key (./private/sub-ca.key).  This is done on the SUB CA.

openssl req -new \
-config sub-ca.conf \
-out sub-ca.csr \
-keyout private/sub-ca.key

Remove the passphrase.

openssl rsa -in private/sub-ca.key -out private/sub-ca.key

Transfer the CSR (sub-ca.csr) to the ROOT CA.  Then using the ROOT CA create a certificate for the SUB CA.

openssl ca \
-config root-ca.conf \
-in sub-ca.csr \
-out certs/sub-ca.crt \
-extensions sub_ca_ext

Transfer the 'sub-ca.crt' to the SUB CA.  Place it in '/etc/ssl/sub-ca/sub-ca.crt'.

Create a Certificate Chain

Some applications will not accept our CRT from our intermediate (SUB-CA).  We need to provide the application with the certificate chain.  The root-ca.crt and the sub-ca.crt files need to be converted to the PEM format and concatenated together.  The order is important on some older versions of java.  So use the following order.

  1. private key (if applicable / not recommended)
  2. client certificate (server.crt - convert to PEM)
  3. intermediate certificate (sub-ca.pem)
  4. root certificate (root-ca.pem)

From the root CA perform the following steps.

  • openssl x509 -in root-ca.crt -outform pem -out root-ca.pem
  • openssl x509 -in sub-ca.crt -outform pem -out sub-ca.pem
  • cat sub-ca.pem root-ca.pem > server-chain.pem  (copy the output to the SUB CA)

OCSP Responder

Perform the following steps to create the SUB CA OCSP responder.

  • Create a key and CSR for the OCSP responder.  You may choose to remove the passphrase on the private key.  See the example above.

openssl req -new \
-newkey rsa:2048 \
-subj "/C=US/O=Lava Dreams/CN=OSCP SUB-CA Responder" \
-keyout private/sub-ocsp.key \
-out csr/sub-ocsp.csr

  • Second use the root CA to issue a certificate.  The days are shortened since this certifcate cannot be revoked.

openssl ca \
-config sub-ca.conf \
-in csr/sub-ocsp.csr \
-out pub/sub-ocsp.crt \
-extensions ocsp_ext \
-days 30

  • Start the OCSP Responder - Ideally this would be done in an HTTPD server on a standard port.

openssl ocsp -port 9081 -index db/index \
-rsigner pub/sub-ocsp.crt \
-rkey private/sub-ocsp.key \
-CA sub-ca.crt -text &

SUB CA Operations

Now we can sign CSR and issue new server or client certificates.  Most of the time we will issue server certificates.  Use unique names so you can identify each file.  Typically this is the short hostname.

Server Certificates

openssl ca \
-config sub-ca.conf \
-in csr/${SERVER}.csr \
-out pub/${SERVER}.crt \
-extensions server_ext

This will create a 'SERIAL_NUM.pem' file in certs.  The serial number is the same number listed in db/serial.

Client Certificates

openssl ca \
-config sub-ca.conf \
-in csr/${CLIENT}.csr \
-out pub/${CLIENT}.crt \
-extensions client_ext

Import 'root-ca.crt' into Windows

The local trust store must be updated to include our new CA.  You can do this in Windows by following the steps below.  Transfer 'root-ca.crt' to your local box.

Chrome & MS Edge & MS Internet Explorer Browsers

  • Start // Run // inetcpl.cpl
  • Click on the 'Content' tab
  • Click on 'Certificates'
  • Click on the 'Trusted Root Certification Authorities' tab
  • Click 'Import...'
  • Click 'Next'
  • Browse to your 'root-ca.crt' file, click 'Open' and then 'Next'
  • Ensure that it is being placed in the 'Trusted Root Certification Authorities' Certificate store and click 'Next'
  • Review and click 'Finish'
  • Click 'Yes' on the Security Warning
  • Click 'OK' and click 'Close' on the Certificates Window
  • Click 'OK' on the Internet Properties window

Firefox Browser

  • Launch Firefox
  • Open a new tab and type in 'about:preferences'
  • Click Advanced
  • Click Certificates
  • Click 'View Certificates'
  • On the 'Authorities' tab click 'Import...'
  • Navigate to 'root-ca.crt' and click 'Open'
  • Click on 'Trust this CA to identify websites' and click 'OK'
  • Click 'OK'

Convert Files and View Files

You may need to convert a CRT file to a PEM file.  Or do some other sort of conversion.  Different applications expect different types of file formats.  You may also need to verify the contents or extract the contents of various files.

CRT to PEM - PEM to CRT

openssl x509 -in XYZ.crt -outform PEM -out XYZ.pem

openssl x509 -in XYZ.pem -outform der -out XYZ.crt

DER to PEM

openssl x509 -in XYZ.crt -inform DER -outform PEM -out XYZ.pem

Read the CSR or CRT or PEM

openssl req -in X.csr -text -noout

openssl x509 -in cert.crt -text -noout

openssl x509 -in X.pem -text -noout

Check a Private Key

openssl rsa -in X.key -check

Generate a New Private Key and CSR

openssl req -new -nodes -days 3650 -newkey rsa:4096 \
-keyout PRIVATE.key -out X.csr \
-subj "/C=US/ST=IL/L=Chicago/O=Lava Dreams/CN=hostname.lab.pahoehoe.local"

root-ca.conf and sub-ca.conf

You need to edit this file to suit your environment.  The blue lines must be edited.  There are other possible changes that you may make.  But you must read the official documentation to understand what you may or may not want to change.  This sample configuration file has both the root and subordinate CA information.

[default]
# ROOT-CA # name              = root-ca
# SUB-CA # name               = sub-ca
domain_suffix                 = lab.pahoehoe.local
aia_url                       = http://$name.$domain_suffix/$name.crt
crl_url                       = http://$name.$domain_suffix/$name.crl
# ROOT-CA # ocsp_url          = http://ocsp.$name.$domain_suffix:9080
# SUB-CA # ocsp_url           = http://ocsp.$name.$domain_suffix:9081
default_ca                    = ca_default
name_opt                      = utf8,esc_ctrl,multiline,lname,align

[ca_dn]
countryName                   = "US"
organizationName              = "Lava Dreams"
# ROOT-CA # commonName        = "Root CA"
# SUB-CA # commonName         = "Sub CA"

[ca_default]
home                          = .
database                      = $home/db/index
serial                        = $home/db/serial
crlnumber                     = $home/db/crlnumber
certificate                   = $home/$name.crt
private_key                   = $home/private/$name.key
RANDFILE                      = $home/private/.rnd
new_certs_dir                 = $home/certs
unique_subject                = no
# ROOT-CA # copy_extensions   = none
# ROOT-CA # default_days      = 3650
# ROOT-CA # default_crl_days  = 365
# SUB-CA # copy_extensions    = copy
# SUB-CA # default_days       = 365
# SUB-CA # default_crl_days   = 30
default_md                    = sha256
policy                        = policy_c_o_match

[policy_c_o_match]
countryName                   = match
stateOrProvinceName           = optional
organizationName              = match
organizationalUnitName        = optional
commonName                    = supplied
emailAddress                  = optional

[req]
default_bits                  = 4096
encrypt_key                   = yes
default_md                    = sha256
utf8                          = yes
string_mask                   = utf8only
prompt                        = no
distinguished_name            = ca_dn
req_extensions                = ca_ext

[ca_ext]
basicConstraints              = critical,CA:true
keyUsage                      = critical,keyCertSign,cRLSign
subjectKeyIdentifier          = hash

[sub_ca_ext]
authorityInfoAccess           = @issuer_info
authorityKeyIdentifier        = keyid:always
basicConstraints              = critical,CA:true,pathlen:0
crlDistributionPoints         = @crl_info
extendedKeyUsage              = clientAuth,serverAuth
keyUsage                      = critical,keyCertSign,cRLSign
nameConstraints               = @name_constraints
subjectKeyIdentifier          = hash

[crl_info]
URI.0                         = $crl_url

[issuer_info]
caIssuers;URI.0               = $aia_url
OCSP;URI.0                    = $ocsp_url

[name_constraints]
permitted;DNS.0=lab.pahoehoe.local
permitted;DNS.1=lab.pahoehoe.org
excluded;IP.0=0.0.0.0/0.0.0.0
excluded;IP.1=0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0

[ocsp_ext]
authorityKeyIdentifier        = keyid:always
basicConstraints              = critical,CA:false
extendedKeyUsage              = OCSPSigning
keyUsage                      = critical,digitalSignature
subjectKeyIdentifier          = hash

#
# SUB-CA ONLY server_ext & client_ext
#

# [server_ext]
# authorityInfoAccess         = @issuer_info
# authorityKeyIdentifier      = keyid:always
# basicConstraints            = critical,CA:false
# crlDistributionPoints       = @crl_info
# extendedKeyUsage            = clientAuth,serverAuth
# keyUsage                  = critical,digitalSignature,keyEncipherment
# subjectKeyIdentifier        = hash

# [client_ext]
# authorityInfoAccess         = @issuer_info
# authorityKeyIdentifier      = keyid:always
# basicConstraints            = critical,CA:false
# crlDistributionPoints       = @crl_info
# extendedKeyUsage            = clientAuth
# keyUsage                    = critical,digitalSignature
# subjectKeyIdentifier        = hash
# EOF

Install EXTPACK in Virtualbox

Installing Virtualbox Extension Pack

I run my Windows box from a standard user account.  This causes a few problems here and there when installing programs.  The Virtualbox extension packs will not install normally.  But it is a quick fix.

Open an Administrator Command Prompt

  • cd \program files\oracle\virtualbox
  • vboxmanage.exe extpack install --replace \users\<you>\downloads\Oracle_VM_VirtualBox_Extension_Pack-5.0.26-108824.vbox-extpack

Next verify that you have the proper extension pack installed.  It is wise to do this before and after to verify the version number has changed.

C:\Program Files\Oracle\VirtualBox>vboxmanage list extpacks
Extension Packs: 1
Pack no. 0: Oracle VM VirtualBox Extension Pack
Version: 5.0.26
Revision: 108824
Edition:
Description: USB 2.0 and USB 3.0 Host Controller, Host Webcam, VirtualBox RDP, PXE ROM, Disk Encryption.
VRDE Module: VBoxVRDP
Usable: true
Why unusable:

C:\Program Files\Oracle\VirtualBox>

DN, OU, CN and Others

Distinguished Names

Distinguished Names (DN) are used in PKI (Public Key Infrastructure) and LDAP (Lightweight Directory Access Protocol).  The DN is the combination of one or more RDNs (Relative Distinguished Name).  This is specified in the X.509 standard.  This is RFC 5280.

Below is a list of some of the more common RDN names.

RDN Name Abbreviation Example
Country C US
Organizaion O IBM
Organizational Unit OU (Multiple Allowed) Billing
State or Province Name ST IL
Common Name CN www.google.com
Serial Number SN 123456
Locality L Chicago
Domain Component DC (Multiple Allowed) www 
User Identifier UID / USERID John Doe
Title T IT Architect
Email Address MAIL you@yahoo.com
Postal Code PC 60020

Typical WWW Certificate

If you go to Digicert, GlobalSign, or InstantSSL they will ask for the same information.  Not all of the information may be required.  Here are the common fields.

  • Country (C) = US
  • State or Province (ST) = IL
  • Locality or City (L) = Chicago
  • Organization (O) = Company Name
  • Organization Unit or Department (OU) = Descriptive Department Name
  • Common Name (CN) = www.example.com, or *.example.com, or Public IP (1.2.3.4) - This is how the web will reach your server.

You also need to provide the key type and the key size.  This is typically RSA and the minimum size these days is 2048.  Elliptic curve keys will be smaller (256).

Please note that a standard certificate will only secure 'https://www.pahoehoe.net'.  It will not secure 'https://pahoehoe.net'.  Or some other sub-domain.  You need to get a SANs (Subject Alternative Name) or a wildcard certificate.  Extended validation (EV) certificates are the same as a regular certificate except the CA will more rigorously verify that you are who you say you are.

Examples

Here are some examples from Google and Yahoo and the CA itself.

DN: C=US, O=Symantec Corporation, OU=Symantec Trust Network,\ CN=Symantec Class 3 Secure Server CA - G4

DN: C=US, ST=Washington, L=Seattle, O=Amazon.com, Inc.,\ CN=www.amazon.com

DN: C=US, O=Equifax, OU=Equifax Secure Certificate Authority

DN: C=US, ST=California, L=Mountain View, O=Google Inc,\ CN=www.google.com

DD-WRT OpenVPN 101

DEPRECATED

This document is a bit old. It still works. But I created a new setup on my Synology NAS. And it is a better setup. I now better understand openssl and how to configure it. There are a few things I would probably change in this document. Plus as nice as DD-WRT may be, it is open source and free. Those nice folks do not have the same resources as Synology. My DD-WRT OpenSSL package is a bit out of date and so is my OpenVPN package. Synology isn't the latest and greatest either. But it is more current. And it is more likely to be updated before DD-WRT.

Please use my Synology OpenVPN setup guide.

Read the Docs

The official DD-WRT documentation (and this doc) is very good.  And the official OpenVPN documentation covers a lot more detail.  Also refer to the Wikipedia article on X.509.  This document just covers the steps I needed to perform and does not add a lot of explanation.

Backup DD-WRT

Backup your DD-WRT configuration before you start changing anything.

Routing (tun) vs Bridging (tap)

Routing or tunneling encapsulates the data over OSI L3.  I am using this method.  One reason is that the iPhone does not support bridging.  With routing you need to create a new private subnet for the VPN server.

Bridging encapsulates the data over OSI L2.  You are extending your local LAN subnet across the VPN.  The default DD-WRT subnet is 192.168.1.0/24.  You create a TAP interface on the server and the client.  As stated above this is not supported on Apple IOS devices.  And from what I have read it can be rather difficult to setup on Windows as well.

File Formats

This is provided as a reminder to myself.  With OpenSSL you can convert from almost any format to another.  This information is from Wikipedia, ssl.com, openssl.org,  and a few other sources.

  • *.pem - (Privacy-enhanced Electronic Mail) Base64 encoded DER certificate, enclosed between "----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----".  Certificate container format that may include just the public certificate, or the entire certificate chain including the public key, private key, and root certificates.  
    • Base64 (ASCII) Encoding - Group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation.
    • DER Encoding (Binary) - DER is a restricted variant of BER for producing unequivocal transfer syntax for data structures described by ASN.1.
      • X.690 is an ITU-T standard specifying several ASN.1 encoding formats:
      • Basic Encoding Rules (BER)
      • Canonical Encoding Rules (CER)
      • Distinguished Encoding Rules (DER)
  • *.cer, *.crt - X.509 certificate (Base64 (ASCII) or DER (binary) encoded) - PEM formatted file with a different extension.  Recognized by Windows explorer as a certificate.
    • *.der - (DEPRECATED) - Binary DER encoded certificates.  These may also use the "*.cer" or "*.crt" extensions.
  • *.key - This is the PEM formatted file containing just the private key.
  • *.p7b *p7c, *.spc - PKCS#7 SignedData structure without data, just certificate(s) or CRL(s).  (Certificate Revocation List)
  • *.crl - Certificate Revocation List
  • *.csr - Certificate Signing Request - Submit this to the CA.  Contains some or all of the key details (subject, organization, state, OU, CN, etc) and the public key.
  • *.stl, *.ctl - Certificate Trust List (MS IIS)
  • *.sst - Microsoft Serialized Certificate Store
  • *.p12 - PKCS#12 - May contain certificate(s) public and private keys.  This is password protected.  
  • *.pfx - PFX, predecessor of PKCS#12.  Usually contains data in PKCS#12 formate with PFX files generated in IIS.)

The Environment

I am using a non-standard port.  My Aunt has a Xfinity wireless router.  The firewall on that isn't very good.  I have setup maximum security on it but it doesn't allow for exceptions or specific rules.  But it does allow 500/UDP GRE (Generic Routing Encapsulation) VPNs.  So I will use that port for my OpenVPN configuration.  My main laptop runs Windows.  I will be using the Windows setup steps.  I will be creating client files for my iPhone, Android tablet, Nexus tablet, and my Windows laptop.  At the time of this writing I installed version 2.3.11 (64 bit) for Windows Vista and later.  These directions assume you have already setup Dynamic DNS for your router's public IP address or you have a static IP address.

Easy-RSA Certification Creation

From an Administrator command prompt switch to the easy-rsa directory.

  • C:\Program Files\OpenVPN\easy-rsa

Perform the following steps.  I have VIM and GOW installed on my Windows box.

  • init-config <ENTER>  (This will copy the vars.bat.sample to vars.bat.)
  • vim vars.bat  (Edit the following lines as appropriate.)

set KEY_COUNTRY=US
set KEY_PROVINCE=IL
set KEY_CITY=Chicago
set KEY_ORG=OpenVPN
set KEY_EMAIL=zaphod@example.com
set KEY_CN=OpenVPN-CA
set KEY_NAME=Zaphods Widgits
set KEY_OU=Zaphods
set PKCS11_MODULE_PATH=changeme (Ignore)
set PKCS11_PIN=1234  (Ignore)

  • vars <ENTER>  (This will source the environmental variables.)
  • clean-all <ENTER>  (Deletes anything in .\keys\* and recreates the index.txt and serial files in .\keys.)
  • build-ca <ENTER>  (Builds the Certificate Authority (CA) certificate (.\keys\ca.crt) and key (.\keys\ca.key).  This allows us to sign our certificates.)

WARNING: can't open config file: /etc/ssl/openssl.cnf
Loading 'screen' into random state - done
Generating a 1024 bit RSA private key
..............++++++
...++++++
writing new private key to 'keys\ca.key'
-----
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [IL]:
Locality Name (eg, city) [Chicago]:
Organization Name (eg, company) [OpenVPN]:
Organizational Unit Name (eg, section) [Zaphods]:
Common Name (eg, your name or your server's hostname) [OpenVPN-CA]:
Name [Zaphods Widgits]:
Email Address [zaphod@example.com]:

  • vars <ENTER> (re-source variables)
  • build-key-server server <ENTER>  (You can use any name, but using 'server' is easier.  This creates the server crt and key and csr.  You MUST USE 'server' as the CN in the example below.  Edited to highlight the important bits.)

Country Name (2 letter code) [US]:
State or Province Name (full name) [IL]:
Locality Name (eg, city) [Chicago]:
Organization Name (eg, company) [OpenVPN]:
Organizational Unit Name (eg, section) [Zaphods]:
Common Name (eg, your name or your server's hostname) [OpenVPN-CA]:server
Name [Zaphods Widgits]:
Email Address [zaphod@example.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:******* (Optional - used by revocation)
An optional company name []:
WARNING: can't open config file: /etc/ssl/openssl.cnf
Using configuration from openssl-1.0.0.cnf
Loading 'screen' into random state - done
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :PRINTABLE:'IL'
localityName :PRINTABLE:'Chicago'
organizationName :PRINTABLE:'OpenVPN'
organizationalUnitName:PRINTABLE:'Zaphods'
commonName :PRINTABLE:'server'
name :PRINTABLE:'Zaphods Widgits'
emailAddress :IA5STRING:'zaphod@example.com'
Certificate is to be certified until Jul 8 21:06:12 2026 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

C:\Program Files\OpenVPN\easy-rsa>

Create the Client Keys

You can use the same client key and crt files on every client.  But it is more secure to use unique keys.  This allows for client revocation.  You should use unique identifiable names for each client.  You MUST use the client name for the CN name during the file creation process.  You can come back to this section and create more client keys at any time.  This will create three files in the keys directory.  (*.crt, *.key, *.csr)

  • vars <ENTER>
  • build-key iphone <ENTER>  (Replace iphone with a unique name for each client.  Use the same name in commands below for the CN.)

Country Name (2 letter code) [US]:
State or Province Name (full name) [IL]:
Locality Name (eg, city) [Chicago]:
Organization Name (eg, company) [OpenVPN]:
Organizational Unit Name (eg, section) [Zaphods]:
Common Name (eg, your name or your server's hostname) [OpenVPN-CA]:iphone
Name [Zaphods Widgits]:
Email Address [zaphod@example.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:******* (Optional)
An optional company name []:
WARNING: can't open config file: /etc/ssl/openssl.cnf
Using configuration from openssl-1.0.0.cnf
Loading 'screen' into random state - done
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :PRINTABLE:'IL'
localityName :PRINTABLE:'Chicago'
organizationName :PRINTABLE:'OpenVPN'
organizationalUnitName:PRINTABLE:'Zaphods'
commonName :PRINTABLE:'iphone'
name :PRINTABLE:'Zaphods Widgits'
emailAddress :IA5STRING:'zaphod@pahoehoe.net'
Certificate is to be certified until Jul 8 22:36:47 2026 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

C:\Program Files\OpenVPN\easy-rsa>

Repeat as necessary for each client.

Create the Diffie Hellman Parameters

If this was a Linux server I would use a 2048 bit key.  This step will create the 'dh1024.pem' file.  To change this to 2048 bits edit 'vars.bat' and change the 'KEY_SIZE' variable from 1024 to 2048.  This will also change the output file from 'dh1024.pem' to 'dh2048.pem'.

  • vars <ENTER>
  • build-dh <ENTER>

Create the TLS Authentication File

This isn't part of the easy-rsa setup.  But while we are creating all of our files on our Windows box we may as well create this file as well.  I am copying this to the keys directory just to keep all of the files together.

  • cd ..\bin
  • openvpn.exe --genkey --secret ta.key
    • --genkey:  Generate a random key to be used as a shared secret, for use with the --secret option.
    • --secret file:  Write the key to a file.
  • move ta.key ..\easy-rsa\keys\ta.key
    • server config = tls-auth ta.key 0
    • client config = tls-auth ta.key 1
    • iphone = key-directive 1 (comment out tls-auth)

List of Files

All of these files are in the keys directory.  This is just the relevant files.  The "*.csr" files are not required anymore.

Filename Needed By Purpose Secret
ca.crt server & all clients Root CA Certificate No
ca.key Key Signing Machine Only Root CA Key Yes
dh{n}.pem server only DH Parameters No
server.crt server only Server Certificate No
server.key server only Server Key Yes
iphone.crt client 1 only (iphone) Client 1 Certificate No
iphone.key client 1 only (iphone) Client 1 Key Yes
ta.key server & all clients OpenVPN TLS Auth Yes

Setup the DD-WRT Gateway

Log into the DD-WRT web GUI.  Go to 'Services // VPN' and enable the 'OpenVPN Server/Daemon'.  I am using the WAN UP start type and configuring this as a daemon.  Copy the files we created via easy-rsa to the server.  Simply copy and paste the Base64 encoded sections of each file.  See the example below.  Most of the file has been replaced by '........'.

-----BEGIN CERTIFICATE-----  (Start Copy & Paste Here)
MIID1DCCAz2gAwIBAgIJAKs5r3xYQISKMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD
........
G0t7SngHbrooGimTgkuAALqvwTIO3mLOk52f10rQC5OoG6s5pClP1eNsWnr+Kxs3
mLvuSsTEx7Kts0R9ed8rBje4EB0PRhpT
-----END CERTIFICATE-----  (End Copy & Paste Here)

Box Name File to Insert
CA Cert ca.crt
Public Server Cert server.crt
Private Server Key server.key
DH PEM dh1024.pem
Additional Config See Server Config Below
TLS Auth Key ta.key
Certificate Revoke List crl.pem (If exists to revoke client X)

At this time the 'clr.pem' file does not exist.  If we revoke a client in the future we can add the 'crl.pem' file.

  • vars <ENTER>
  • revoke-full clientX <ENTER>  (Where clientX is the name of one of the clients.)

Server Config

OpenVPN includes a fully annotated sample configuration file.  I am configuring the server using the 'additional config' box.  This replicates how an OpenVPN server would be setup on a Linux box.  The results are the same using the web GUI or the command line.  See the config by running 'nvram get openvpn_config' from the DD-WRT command line.

Many sites recommend using 'push "dhcp-options DNS x.x.x.x"'.  I am not using that setting.  If I use that option I cannot get DNS working.  I suspect I have some strange setting in my DHCP setup.

I am using the 'push "redirect-gateway def1"' on the server.  This forces all traffic over the VPN.  You can use this option on the client side by removing the 'push' part.  Feel free to test this option using 'tcpdump -nl -i tun0' on your DD-WRT router.  Or by simply heading to 'ipchicken.com' or 'whatismyip.com'.

  • C:\Program Files\OpenVPN\sample-config\server.ovpn

There are two networks that connect over the internet (WAN).

  • Local LAN = 192.168.1.0/24 (DD-WRT Default - Update with your subnet)
  • OpenVPN Private Routing = 10.2.192.0/24 (Use whatever you like)

# Push route to clients for local LAN subnet
push "route 192.168.1.0 255.255.255.0"
# Set subnet mode (net30, p2p, subnet)
topology subnet

# VPN Server Subnet - OpenVPN uses x.x.x.1
# Clients use the remaining IPs
server 10.2.192.0 255.255.255.0

# Listen on non-standard port (default 1194)
port 500
# Set protocol tcp or udp
proto udp
# Set device (tunX|tapX|null) server/client identical
# tun - L3 // tap - L2
dev tun0
# keepalive n m = ping n ping-restart x
# ping every 10 sec // restart after no ping in 120 sec
keepalive 10 120
# path to certs and keys - hard coded dd-wrt paths
dh /tmp/openvpn/dh.pem
ca /tmp/openvpn/ca.crt
cert /tmp/openvpn/cert.pem
key /tmp/openvpn/key.pem
# Additional layer HMAC auth on top of TLS control

# channel to protect against DoS attacks
# server must be  0 // client 1
tls-auth /tmp/openvpn/ta.key 0
# Compression mode (yes|no|adaptive (default) )
comp-lzo adaptive
# Allow multiple clients with same CN to connect concurrently
# duplicate-cn
# Route all traffic over VPN - NOT split tunnel
# 1. create static route for remote address which forwards
#    to pre-existing default gateway
# 2. delete the default gateway route
# 3. Set new def gateway to be the VPN endpoint address
# local - both openvpn servers connected via common subnet (wireless)
#         causes step 1 to be omitted
# def1 - override def gateway (0.0.0.0/1,128.0.0.0/1) does not wipe
#        out original def gateway
push "redirect-gateway def1"

# Encrypt data channel packets
# cipher alg - server/client must match
# defaults to BF-CBC 128 bit
# openvpn --show-ciphers (to list ciphers)
cipher AES-256-CBC
# Authenticate packets with HMAC (message digest algorithm)
# auth alg - server/client must match
# defaults to sha1
# openvpn --show-digests (to list digests)
auth sha1

# Logging verbosity (services/services/syslogd)
# 0 silent except fatal
# 4 reasonable for general usage
# 5, 6 - debug
# 9 - extremely verbose
verb 0

# Only use crl-verify if you have revoke list
# crl-verify /tmp/openvpn/ca.crl

# Management parameter - DD-WRT can 
# access server's management port
management localhost 5001

Copy and paste the above into the 'additional config' box.  Edit as desired.  Now save and apply the settings.

DD-WRT Firewall Settings

Now we must allow the VPN traffic through the DD-WRT firewall.  Go to "Administrative // Commands".  Edit the rules below as required for your environment.  To help identify the correct interface run 'netstat -rn' from the DD-WRT command line or from the web GUI.  An edited example is shown below.  The public interface uses vlan2.  DD-WRT creates br0 for the internal networks.  And OpenVPN created tun0.

# netstat -rn (Removed Flags MSS Window and irtt)
Kernel IP routing table
Destination     Gateway       Genmask       Iface
0.0.0.0         001.002.003.1 0.0.0.0       vlan2  (Public Gateway)
10.2.192.0      0.0.0.0       255.255.255.0 tun0  (OpenVPN)
001.002.003.0   0.0.0.0       255.255.254.0 vlan2
127.0.0.0       0.0.0.0       255.0.0.0     lo
169.254.0.0     0.0.0.0       255.255.0.0   br0
192.168.1.0     0.0.0.0       255.255.255.0 br0 (DD-WRT Internal Bridged Networks)

Edit the lines below before adding them to the web GUI.  Cut and paste them into the 'Commands' box.  Then click 'Save Firewall'.  You will lose connectivity as the firewall rules are processed.  Edit the bold blue items as required.

  • udp - Change to tcp if required
  • 500 - Default port is 1194.  Edit as required
  • 10.2.192.0/24 - This is the VPN server subnet previously created.  Edit as appropriate.
  • br0 - Default DD-WRT internal bridge
  • tun0 - The newly created OpenVPN tunnel interface
  • vlan2 - The public interface for the DD-WRT router (netstat -rn)
  • # Accept incoming connections on port 500/UDP
    iptables -I INPUT 1 -p udp --dport 500 -j ACCEPT
    # Forward packets from VPN subnet 10.2.192.0/24

    iptables -I FORWARD 1 --source 10.2.192.0/24 -j ACCEPT
    # Forward packets inbound bridge outbound via tunnel

    iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
    # Forward packets inbound tunnel outbound via bridge

    iptables -I FORWARD -i tun0 -o br0 -j ACCEPT
    # SNAT 10.2.192.0/24 outbound packets as VLAN2 IP (public ip)

    iptables -t nat -A POSTROUTING -s 10.2.192.0/24 -o vlan2 -j MASQUERADE

To see the rules run 'iptables -nvL' and 'iptables -t nat -nvL'.

Client Config

You can edit the sample configuration file.  It is nicely annotated.

  • C:\Program Files\OpenVPN\sample-config\client.ovpn

# Specify that we are a client and that we
# will be pulling certain config file directives
# from the server.
client

# Specify virtual network device tunX|tapX|null
# X may be omitted for dynamic device
# Both ends must match settings
# tun - encapsulate IPv4-6 OSI L3
# tap - encapsulate IPv4-6 Ethernet 802.3 OSI L2
dev tun0

# Are we connecting to a TCP or
# UDP server? Use the same setting as
# on the server.
proto udp

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote DD-WRT-PUBLIC.dyndns.com 500

# Keep trying indefinitely to resolve the
# host name of the OpenVPN server. Very useful
# on machines which are not permanently connected
# to the internet such as laptops.
resolv-retry infinite

# Most clients don't need to bind to
# a specific local port number.
nobind

# Downgrade privileges after initialization (non-Windows only)
user nobody
group nobody

# Try to preserve some state across restarts.
persist-key
persist-tun

# Offers policy-level control over usage of external
# programs and scripts
# 0 -- strictly no calling of external programs
# 1 -- DEFAULT - Only call built-in exec - ifconfig, ip, route
# 2 -- All calling of built-in exec and user-defined scripts
# 3 -- Allow passwords to be passed to scripts via env variables
# script-security <level>

# SSL/TLS parms.
# See the server config file for more
# description.
# Using inline files - comment out here

# ca ca.crt
# cert client.crt
# key client.key
# tls-auth ta.key 1

# Verify server certificate by checking that the
# certicate has the correct key usage set.
# This is an important precaution to protect against
# a potential attack discussed here:
# http://openvpn.net/howto.html#mitm
#
# To use this feature, you will need to generate
# your server certificates with the keyUsage set to
# digitalSignature, keyEncipherment
# and the extendedKeyUsage to
# serverAuth
# EasyRSA can do this for you.
remote-cert-tls server

# If a tls-auth key is used on the server
# then every client must also have the key.
# tls-auth ta.key 1
# For inline files use key-direction not tls-auth
key-direction 1

# Allow remote peer to change IP (DHCP)
# Accept authenticated packets from any address
# not just address specified by 'remote' option
float

# Select a cryptographic cipher.
# If the cipher option is used on the server
# then you must also specify it here.
cipher AES-256-CBC

# Select HMAC Authentication
# server/client must match - default sha1
auth sha1

# Enable compression on the VPN link.
# Don't enable this unless it is also
# enabled in the server config file.
comp-lzo adaptive

# Set log file verbosity.
verb 0

# Redirect all traffic over vpn
# Optional - I am setting on server side via push

# redirect-gateway def1

Read the next section to add all of the TLS files to the OVPN configuration file.  This makes management of the files much easier.

Concatenate Key Files into OVPN

Instead of providing the clients with the "*.ovpn" file and the key files you can combine everything into the OVPN file.  At the bottom of the OVPN file add the following.

Here is a list of the files you will need to add.

File Description File to Insert Enclosed By
Root CA Certificate ca.crt (The same file on all clients) <ca> </ca>
Client Certificate iphone.crt (Replace iphone as required) Unique per client <crt> </crt>
Client Private Key iphone.key (Replace iphone as required) Unique per client <key> </key>
TLS Auth Key ta.key (The same file on all clients) <tls-auth> </tls-auth>

# Root Certificate Authority ca.crt
<ca>
-----BEGIN CERTIFICATE-----
MIID1DCCAz2gAwIBAgIJAKs5r3xYQISK
................
mLvuSsTEx7Kts0R9ed8rBje4EB0PRhpT
-----END CERTIFICATE-----
</ca>
# client cert iphone.crt
<cert>
-----BEGIN CERTIFICATE-----
MIIEFjCCA3+gAwIBAgIBAjANBgkqhkiG9
................
6PSxUlAeZkPnVpj8BZ3HpERWZvy7Ljw79Z36
-----END CERTIFICATE-----
</cert>

# client private key iphone.key
<key>
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEF
...................................
FDAQQyE4WV4GJ113Dtfagw==
-----END PRIVATE KEY-----
</key>
# tls auth ta.key
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
64b7b9b8b1b25825fa006aabe829b379
...............................
d200a5f90563facf2f5a374564904e15
-----END OpenVPN Static key V1-----
</tls-auth>

Verify Your Connection

Before you use this in the wild you need to verify that your VPN tunnel is operating correctly.  Here are a few commands to verify that all traffic is routing over the VPN.

From the DD-WRT command line run a few tcpdump commands.

  • tcpdump -nl -i tun0
  • tcpdump -nl -i tun0 port 53
  • To verify ipchicken.com
    • tcpdump -nl -i tun0 host 104.25.63.114 && host 104.25.64.114
  • To verify whatismyip.com
    • tcpdump -nl -i tun0 host 104.27.201.91 && host 104.27.202.91

Obviously use your browser and go to 'whatismyip.com' and 'ipchicken.com' before and after you establish your VPN tunnel.  Make sure your IP is now your ISP public IP address.

A Note on Windows

You must run the OpenVPN client as an Administrator.  And you must comment out the 'user nobody' and 'group nobody' lines in the client OVPN file.

DD-WRT (v24-sp2) YAMon3 Setup

Get YAMON3

You can download the installation script and donate to YAMon3 from the URL below.  And you can read the official documentation.

http://usage-monitoring.com/index.php

Format the USB Drive

I am using a small USB drive.  I will automount this to /opt via the DD-WRT GUI.  (Services // USB)  This is not a tutorial on using fdisk or mkfs.ext4.  I created the partition and the ext4 filesystem on a Raspberry PI.  I only created one partition since I am using the entire drive for /opt.  And I am just taking all of the defaults.  My router is a Buffalo WZR-1750DHP.

  • fdisk /dev/sdX (Where X is the USB Drive)
  • d (Delete any existing partitions)
  • n (create a new primary partition)
  • w (Write it to disk)
  • q (To exit fdisk)
  • unmount the drive
  • mkfs.ext4 /dev/sdX1
  • blkid /dev/sdX1 (To see the UUID)

Enable USB Storage in DD-WRT

Insert the USB drive into your router.  And enable USB storage in the GUI.  Go to 'Services // USB'.  Enable the following options save and apply your settings.

  • Core USB Support
  • USB Storage Support
  • Automatic Drive Mount

Once you save and apply the settings you should see something like the following.  Copy the UUID into the 'Mount this Partition to /opt'.

DD-WRT USB Storage Settings
DD-WRT USB Storage Settings

After you copy and paste the UUID, save your settings, apply your settings, and reboot the router you will see a screen like the one below.

DD-WRT USB Storage with UUID
DD-WRT USB Storage with UUID

Install YAMon3

At the time of this writing the latest zip of YAMon3 was "install (2016-06-19).zip".  Extract the 'install.sh' script and SCP that to your router.  Place it in /opt.  And make sure it is executable.

# ls -l /opt
-rwxr-x--- 1 root root 5085 Jun 20 02:02 install.sh
drwx------ 2 root root 16384 Jul 9 18:44 lost+found

Now simply run the script and it will walk you through the basic setup.  It is a lot easier than YAMon2.  I accepted all of the defaults.  This is what it created.  And also verify that '/tmp/YAMon3-running' exists.

# ls -lR /opt/YAMon3
/opt/YAMon3:
-rwxrwx--- 1 root root 9010 Jul 9 19:41 config.file
drw-rw-rw- 2 root root 4096 Jul 9 19:42 data
-rwxrwx--- 1 root root 9385 Jul 9 19:37 default_config.file
-rwxrwx--- 1 root root 1593 Jul 9 19:37 glc.sh
-rwxrwx--- 1 root root 4883 Jul 9 19:37 h2m.sh
drwxrwx--- 2 root root 4096 Jul 9 19:37 includes
drwxrwx--- 2 root root 4096 Jul 9 19:42 logs
-rwxrwx--- 1 root root 3641 Jul 9 19:37 organize.sh
-rwxrwx--- 1 root root 18225 Jul 9 19:37 readme.txt
-rwxrwx--- 1 root root 391 Jul 9 19:37 restart.sh
-rwxrwx--- 1 root root 12670 Jul 9 19:36 setup.sh
-rwxrwx--- 1 root root 902 Jul 9 19:37 shutdown.sh
-rwxrwx--- 1 root root 1400 Jul 9 19:37 startup.sh
drwxrwx--- 3 root root 4096 Jul 9 19:37 strings
drwxrwx--- 5 root root 4096 Jul 9 19:37 www
-rwxrwx--- 1 root root 39367 Jul 9 19:37 yamon3.0.16.sh
-rwxrwx--- 1 root root 32 Jul 9 19:36 yamonsetup.txt

/opt/YAMon3/data:
-rw-rw-rw- 1 root root 84 Jul 9 19:42 2016-07-05-mac_data.js
-rw-rw-rw- 1 root root 894 Jul 9 19:44 2016-07-09-hourly_data.js
-rw-rw-rw- 1 root root 1633 Jul 9 19:43 users.js

/opt/YAMon3/includes:
-rwxrwx--- 1 root root 4978 Jul 9 19:37 defaults.sh
-rwxrwx--- 1 root root 359 Jul 9 19:37 encode.sed
-rwxrwx--- 1 root root 1569 Jul 9 19:37 getLocalCopies.sh
-rwxrwx--- 1 root root 1889 Jul 9 19:37 getlatest.sh
-rwxrwx--- 1 root root 6288 Jul 9 19:37 hourly2monthly.sh
-rwxrwx--- 1 root root 13103 Jul 9 19:37 util.sh

/opt/YAMon3/logs:
-rw-r--r-- 1 root root 5136 Jul 9 19:44 monitor-2016-07-09.log
-rwxrwx--- 1 root root 0 Jul 9 19:37 setup.log

/opt/YAMon3/strings:
drwxrwx--- 2 root root 4096 Jul 9 19:37 en

/opt/YAMon3/strings/en:
-rwxrwx--- 1 root root 2115 Jul 9 19:37 strings.sh

/opt/YAMon3/www:
drwxrwx--- 2 root root 4096 Jul 9 19:37 css
drwxrwx--- 2 root root 4096 Jul 9 19:37 images
drwxrwx--- 2 root root 4096 Jul 9 19:37 js
-rwxrwx--- 1 root root 100108 Jul 9 19:37 yamon3.html

/opt/YAMon3/www/css:
-rwxrwx--- 1 root root 5500 Jul 9 19:37 custom.css
-rwxrwx--- 1 root root 7798 Jul 9 19:37 normalize.css

/opt/YAMon3/www/images:

/opt/YAMon3/www/js:

# ls -ld /tmp/YAMon3-running
drwxr-xr-x 2 root root 0 Jul 9 19:42 /tmp/YAMon3-running

Basic Configuration of YAMon3

There are some optional configuration steps.  Everything works as is.  But these two steps make it easier to use YAMon3 in my opinion.

Enable Database Integration Across Devices

In order to see the data from multiple devices we need to generate a key from the settings tab and add that to '/opt/YAMon3/config.file'.  Perform the following steps.

  • Open your browser:  https://<router_ip>/user/yamon3.html
  • Go to the settings tab.
  • Click 'Get Key' in the 'Database Integration' box.
  • Copy the key and edit '/opt/YAMon3/config.file'.
  • Add it to the '_dbkey='<your_db_key>' line.  Keep the single quotes.

_dbkey='' # if not null, this option will sync settings across all of             your devices...
          # NB - get the value for this parameter from the settings tab

  • Restart YAMon3 - /opt/YAMon3/restart.sh
  • Reload YAMon3 in your browser.  You should see the settings tab.  You must click all the green check marks.  And then click 'Save Settings'.  Then you can reload the web page.

Name Your Devices

To easily identify each device in the reports you can name them in '/opt/YAMon3/data/users.js'.  First you must stop YAMon3. (/opt/YAMon3/shutdown.sh)  Then you can edit the file and restart YAMon3.  This is from the readme.txt file from the YAMon3 ZIP file.  You can edit three fields.  The owner and name fields may use apostrophes but not double quotes.  I almost always edit the name field.  And I usually leave the other fields unchanged.

  • owner - The category in which the device should be placed.
  • name - A friendly description of the device.  (e.g.  HTPC or NAS or Shield-Tablet or Kurt's iPhone)
  • colour - One of the 140 named HTML colors or a valid hexidecimal color.  This color will be used in the graphs and reports for this device.

From:

ud_a({"mac":"00:XX:XX:XX:XX:XX",\ # MAC Address of device
"ip":"192.168.1.20",\ # IPv4 Address of device
"ip6":""\,\ # IPv6 Address of device if applicable
"owner":"Unknown",\
"name":"New Device",\
"colour":"",\
"added":"2016-07-09 19:42:31","updated":"2016-07-

To:

ud_a({"mac":"00:XX:XX:XX:XX:XX",\ # MAC Address of device
"ip":"192.168.1.20",\ # IPv4 Address of device
"ip6":""\,\ # IPv6 Address of device if applicable
"owner":"Storage",\
"name":"Synology NAS",\
"colour":"Crimson",\ (HEX # = DC143C)
"added":"2016-07-09 19:42:31","updated":"2016-07-

Raspbian wlan0 Static IP

Requirements

Raspbian is a Debian derivative.  Other flavors of Linux use different files.  But the setup is basically the same.  These steps are geared for home use.  If you are a business with LEAP, RADIUS, or certificate based authentication you will need to read the documentation.  And of course work with your technical support staff to find your settings.

I am using DD-WRT on my home router.  The latest and greatest home security uses WPA2.  This is WiFi Protected Access v2 and uses PSK (Pre-Shared Keys).  It is known by several names, such as WPA2-Personal, WPA-PSK, or WPA2-PSK.  You want to use WPA2.  There are two encryption algorithms.  You can use TKIP (Temporal Key Integrity Protocol) or AES (Advanced Encryption Standard).  You should use AES as it is more secure.  Please note that in Linux AES is known as CCMP (Counter Mode Cipher Block Chaining Message Authentication Code Protocol) which is part of the AES standard.

Please note that in Raspbian 8 (Jessie) you are actually supposed to set the static IP address in /etc/dhcpcd.conf.  But I don't want to be running DHCP anyway.  So I will be disabling DHCP and using the old fashioned method to set my static IP address.  Run these with sudo or switch to root.

  • systemctl stop dhcpcd
  • systemctl disable dhcpcd
  • shutdown -r now

Hash Your PSK

You need to hash your PSK (Pre-Shared Key) for your SSID.  Otherwise the key is in clear-text in the configuration file.  Use the 'wpa_passphrase' program to hash it.  In the example below the SSID is 'homenet' and the PSK is 'supersecretkey'.  This will create the basic lines for the 'network' section of '/etc/wpa_supplicant/wpa_supplicant.conf'.  You can acually use the real PSK in this file.  Make sure you delete the commented out PSK line.

# sudo wpa_passphrase
usage: wpa_passphrase <ssid> [passphrase]

If passphrase is left out, it will be read from stdin

# sudo wpa_passphrase homenet supersecretkey
network={
  ssid="homenet"
  #psk="supersecretkey"
  psk=4322bc0066242ca2ce0ee61c831ac9e8949069c16a7dcf06fc2cbf069d09cf20
}

Edit wpa_supplicant.conf

To find detailed information on all of the options look at the example documentation.

  • /usr/share/doc/wpasupplicant/examples/wpa_supplicant.conf.gz

This example is doing a simple setup for one SSID.  I am broadcasting my SSID on my router.  I have a couple of devices that don't work without the broadcast SSID.  Plus hiding the SSID doesn't really add that much security.  The information below is from the example documentation.

There are two sections in a basic configuration file.  There is a global configuration section and a network block configuration section.

Global Configuration:

There are three settings in a basic configuration.

  • country - The two letter country code where the device is operating.
  • ctrl_interface=DIR - The location of the wlan0 socket and group owner.  This may vary on different versions of Linux.
  • update_config - Whether to allow wpa_supplicant to update and overwrite the configuration.  I prefer to manually setup the networking.  As a result I turn this feature off.
    • 0 - Turn this feature off.
    • 1 - Turn this feature on.

Network Block:

Here is a brief explanation of each setting in the network block.

  • ssid - A mandatory field with the SSID for the network.  There are three ways to fill this out.  But the most common method will be used here.  Enter the SSID in ASCII text surrounded by double quotes.
  • scan_ssid - A probe request is a special frame sent by a client station requesting information from either a specific access point, specified by SSID, or all access points in the area, specified with the broadcast SSID.  You can either enable or disable this feature.  I have better luck enabling this feature (1).  Probably because I currently have 2 SSIDs.
    • 0 = Do not scan this SSID with specific Probe Request frames (default).
    • 1 = Scan with SSID-specific Probe Request frames.  This can be used to find APs that hide (do not broadcast) SSID or use multiple SSIDs.  This will add latency to the scanning.
  • proto - List of accepted protocols.  The default is 'WPA RSN'.  In this example we have WPA2 on our DD-WRT router.  And RSN is another name for WPA2.  So we will use RSN.  Although we can use the alias of WPA2.
    • WPA = WPA/IEEE 802.11i/D3.0
    • RSN = WPA2/IEEE 802.11i  (WPA2 can be used as an alias for RSN)
  • key_mgmt - List of accepted authenticated key management protocols.  For home use we need to set this to 'WPA-PSK'.  And we must have the 'psk' field as well.  Refer to the official documentation for a list of all of the options.
  • pairwise - List of accepted pairwise (unicast) ciphers for WPA.  The default is 'CCMP TKIP'.  This is the private key from the client to the AP.  In our home network we only have two choices and we will use the more secure option of 'AES' which is also known as 'CCMP'.
    • CCMP = AES in Counter mode with CBC-MAC
    • TKIP = Temporal Key Integrity Protocol
    • NONE = Use only Group Keys (deprecated)
  • group - List of accepted group (broacast/multicast) ciphers for WPA.  This defaults to use all options which is not secure.  These are the broadcasts from the AP to all clients.  In our home network we will use the most secure option, which is CCMP.
    • CCMP = AES in Counter mode with CBC-MAC
    • TKIP = Temporal Key Integrity Protocol
    • WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key.
    • WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key.
    • Defaults to 'CCMP TKIP WEP104 WEP40'
  • auth_alg - List of allowed IEEE 802.11 authentication algorithms.
    • OPEN = Open System Authentication (required for WPA/WPA2)
    • SHARED = Shared key authentication (requires static WEP keys)
    • LEAP = LEAP/Network EAP (only used with LEAP)
  • psk - WPA pre-shared key (256 bit pre-shared key)  We previously used 'wpa_passphrase' to generate our key from our ASCII PSK.

Sample /etc/wpa_supplicant/wpa_supplicant.conf

country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=0
network={
   ssid="homenet"
   scan_ssid=1
   proto=RSN
   key_mgmt=WPA-PSK
   pairwise=CCMP
   group=CCMP
   auth_alg=OPEN
   psk=4322bc0066242ca2ce0ee61c831ac9e8949069c16a7dcf06fc2cbf069d09cf20
}

Setup the Static IP Address

Different versions of Linux use different files.  In RHEL you setup the IP Address by editing '/etc/sysconfig/network-scripts/ifcfg-ethX'.  In Debian based distributions you need to edit '/etc/network/interfaces'.  The options are very similar in both distributions.  This example is for Raspbian.  This example is for a simple setup.  More advanced options allow for multiple sites by adding mapping stanzas.  Or by enabling VLANs, bridging, or 802.1Q VLAN tagging.  Read the official documentation for information about these advanced options.

We will be looking at three stanzas.  This information is from the man page.

  1. "auto" - Used to identify the physical interfaces to be brought up when ifup is run with the '-a' option.  Physical interfaces names should follow the word auto on the same line.  (e.g. auto lo && auto wlan0)
  2. "allow-" - Used to identify interfaces that should be brought up automatically by various subsystems.  For example running 'ifup --allow=hotplug eth0 eth1' will only bring up eth0 and eth1 if it is listed in an 'allow-hotplug' line.  This is hardware dependent.
  3. "iface" - This starts the stanza that defines the logical interface.  This lines is broken into 4 parts.  And then depending on the method (fourth part) additional options are used to configure the logical interface.

The iface Stanza

The 'iface' line is broken into four parts.

  • iface <name_logical_interace> <address_family> <method>
    • <name_logical_interface> - In our simple setup this will be 'wlan0'.  This is the logical name for the interface.  You need to use the mapping stanza to have more complicated setups.
  • <address_family> - In our case this will be 'inet' for TCP/IP networking.
    • inet = TCP/IP networking - The most common option
    • ipx = IPX networking
    • inet6 = IPv6 networking
  • <method> - In our example we are setting a static IP address so we will use 'static'.
    • lo = Loopback method.  Used for the loopback adapter
    • static = Interfaces with static IPv4 addresses
    • manual = Interfaces for which no configuration is done by default.  Such interface can be configured manually by means of up and down commands or by '/etc/network'if-*.d' scripts.
    • dhcp - Used to obtain an address by DHCP.
    • There are other uncommon methods.  They are 'bootp', 'tunnel', 'ppp', 'wvdial', and 'ipv411'.

The iface Options

There are additional options listed in the official documentation.  You should indent each option.

  • address = The dotted quad IP address
  • netmask = The netmask for your IP address - dotted quad or CIDR
  • network = The network block address (Not truly required but I like it.)
  • broadcast = The dotted quad broadcast IP address
  • gateway = The dotted quad IP address for the default gateway
  • wpa-conf = The path to your wpa_supplicant.conf file.
  • mtu = (OPTIONAL) The MTU size

I come from a enterprise server environment.  I am used to hard coding everything.  And I am used to having very explicit firewall rules.  For whatever reason Raspbian, and it appears other Linux distributions as well, now allow multiple programs to configure /etc/resolv.conf.  And you can have multiple versions of this file automatically configured as required.  As a result you need to add the DNS information into your iface stanza.  I think you can get rid of this and just manually setup /etc/resolv.conf if you disable and remove resolveconf.  If not you need to add the 'dns-nameservers' line at a minimum.  You can add 'dns-search' and 'dns-domain' as well.

  • dns-nameservers = Space delineated line of 1, 2 or 3 nameservers.

Sample /etc/network/interfaces

Here is the static IP address configuration for wlan0.

# interfaces(5) file used by ifup(8) and ifdown(8)

# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

# Loopback Interface
auto lo
iface lo inet loopback

# eth0 - No IP set
iface eth0 inet manual

# wlan0 static IP address
allow-hotplug wlan0
iface wlan0 inet static
    address 10.0.0.100
    netmask 255.255.255.0
    network 10.0.0.0
    broadcast 10.0.0.255
    gateway 10.0.0.1
    hwaddress b8:27:eb:87:6c:08
    dns-domain example.com
    dns-nameservers 8.8.8.8 4.2.2.1
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

# wlan1 - No IP set
allow-hotplug wlan1
iface wlan1 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

journalctl 101

The Basics

Systemd has a new logging feature that can replace syslog or rsyslog called journald.  As of now both logging services run by default.  Either one may be disabled.  The journald logging is a binary log that combines all logging in the system.  So instead of searching 'dmesg', '/var/log/messages', or some other log file everything is in journald.  The configuration file is '/etc/systemd/journald.conf'.  Refer to the man pages for the details on how to change the default configuration.  The binary logs are stored in a hierarchical directory under '/var/log/journal'.

Enable Persistent Storage

By default journald stores logs in memory or in a small ring-buffer in the '/var/log/journal' directory.  This is volatile storage.  Syslog reads the journal logs and stores them in '/var/log'.  To enable persistent storage you must edit '/etc/systemd/journald.conf'.  Change the storage line from 'auto' to 'persistent'.  Create the '/var/log/journal' directory.  And then restart 'journald'.  You can then disable 'syslogd'.  Obviously, this is a major change in how logging is done.

Various security requirements must be reviewed in your environment.  Most environments require that the logs must be kept for X number of days.  I am not sure if 'journald' has this option at this time.  You can rotate logs based on the size of the logs.  But this doesn't guarantee a specific time for the logs.  I know Splunk has a way to get the 'journald' logs.  But I don't know if other types of remote syslog can receive the logs.

At this time it is probably best to keep both syslog and journald running.

A Few Quick Journalctl Options

Just a quick reference for some basic logging options.  Do some Google searches and read the man pages for a lot more information.

  • journalctl - Page through all of the logs
  • journalctl -n # - Display last 10 lines or X # of lines if (#) is included
  • journalctl -o <form> - Controls the format - Refer to the man page
    • short - default - similar to standard syslog
    • verbose - shows the full-structured entry items with all fields
    • export - binary stream suitable for backups and network transfer
    • json - formats entries as JSON data structure
    • cat - a very terse output
  • journalctl -f - Live view and continues the tail of the logs
  • journalct -p <priority> - Filter by priority using keyword or number
    • emerg (0)
    • alert (1)
    • crit (2)
    • err (3)
    • warning (4)
    • notice (5)
    • info (6)
    • debug (7)
  • journalctl -F <FIELDNAME> - To see a list of fieldnames type 'journalctl' followed by 2 tabs
  • journalctl -u <unit_name> - Displays the logs for the specified unit

journalctl -h (Help Message)

# journalctl -h
journalctl [OPTIONS...] [MATCHES...]

Query the journal.

Flags:
  --system                Show only the system journal
  --user                  Show only the user journal for the current user
  -M --machine=CONTAINER  Operate on local container
  --since=DATE            Start showing entries on or newer than the                                 specified date
  --until=DATE            Stop showing entries on or newer than the                                   specified date
  -c --cursor=CURSOR      Start showing entries from the specified cursor
  --after-cursor=CURSOR   Start showing entries from after the specified                             cursor
  --show-cursor           Print the cursor after all the entries
  -b --boot[=ID]          Show data only from ID or, if unspecified, the                             current boot
  --list-boots            Show terse information about recorded boots
  -k --dmesg              Show kernel message log from the current boot
  -u --unit=UNIT          Show data only from the specified unit
  --user-unit=UNIT        Show data only from the specified user session                             unit
  -p --priority=RANGE     Show only messages within the specified priority                           range
  -e --pager-end          Immediately jump to end of the journal in the                               pager
  -f --follow             Follow the journal
  -n --lines[=INTEGER]    Number of journal entries to show
  --no-tail               Show all lines, even in follow mode
  -r --reverse            Show the newest entries first
  -o --output=STRING      Change journal output mode (short, short-iso,
                          short-precise, short-monotonic, verbose,
                          export, json, json-pretty, json-sse, cat)
  -x --catalog            Add message explanations where available
  --no-full               Ellipsize fields
  -a --all                Show all fields, including long and unprintable
  -q --quiet              Do not show privilege warning
  --no-pager              Do not pipe output into a pager
  -m --merge              Show entries from all available journals
  -D --directory=PATH     Show journal files from directory
  --file=PATH             Show journal file
  --root=ROOT             Operate on catalog files underneath the root ROOT
  --interval=TIME         Time interval for changing the FSS sealing key
  --verify-key=KEY        Specify FSS verification key
  --force                 Force overriding of the FSS key pair with --                               setup-keys

Commands:
  -h --help               Show this help text
  --version               Show package version
  --new-id128             Generate a new 128-bit ID
  --header                Show journal header information
  --disk-usage            Show total disk usage of all journal files
  -F --field=FIELD        List all values that a specified field takes
  --list-catalog          Show message IDs of all entries in the message                             catalog
  --dump-catalog          Show entries in the message catalog
  --update-catalog        Update the message catalog database
  --setup-keys            Generate a new FSS key pair
  --verify                Verify journal file consistency

timedatectl 101

A New Way to Control Time and Date

Read the man page for the timedatectl usage.  See the quick help message below to get most of the details.  Obviously, timedatectl is a pretty easy command to learn.  A few notes.  I am playing with a Raspberry Pi.  It doesn't have a hardware clock.  You can use any timezone listed in '/usr/share/zoneinfo' not just the time zones listed in 'timedatectl list-timezones'.  For example, you can use the 'Etc/GMT' time zones which do not have daylight savings time.  There are new NTP based synchronization tools available in systemd.  These are either 'timesyncd' or 'chronyd'.  The status command provides a lot of information that is nicely formatted.

# timedatectl status
      Local time: Thu 2016-06-23 17:01:54 CDT
  Universal time: Thu 2016-06-23 22:01:54 UTC
        RTC time: n/a
       Time zone: America/Chicago (CDT, -0500)
     NTP enabled: no
NTP synchronized: yes
 RTC in local TZ: no
      DST active: yes
 Last DST change: DST began at
                  Sun 2016-03-13 01:59:59 CST
                  Sun 2016-03-13 03:00:00 CDT
 Next DST change: DST ends (the clock jumps one hour backwards) at
                  Sun 2016-11-06 01:59:59 CDT
                  Sun 2016-11-06 01:00:00 CST

timedatectl Help Message

# timedatectl -h
timedatectl [OPTIONS...] COMMAND ...

Query or change system time and date settings.

  -h                      --help Show this help message
  --version               Show package version
  --no-pager              Do not pipe output into a pager
  --no-ask-password       Do not prompt for password
  -H --host=[USER@]HOST   Operate on remote host
  -M --machine=CONTAINER  Operate on local container
  --adjust-system-clock   Adjust system clock when changing local RTC mode

Commands:
  status                  Show current time settings
  set-time TIME           Set system time
  set-timezone ZONE       Set system time zone
  list-timezones          Show known time zones
  set-local-rtc BOOL      Control whether RTC is in local time
  set-ntp BOOL            Control whether NTP is enabled

Excerpt From the MAN Page

set-local-rtc [BOOL]
Takes a boolean argument. If "0", the system is configured to maintain the RTC in universal time. If "1", it will maintain the RTC in local time instead. Note that maintaining the RTC in the local timezone is not fully supported and will create various problems with time zone changes and daylight saving adjustments. If at all possible, keep the RTC in UTC mode. Note that invoking this will also synchronize the RTC from the system clock, unless --adjust-system-clock is passed (see above). This command will change the 3rd line of /etc/adjtime, as documented in hwclock(8).

set-ntp [BOOL]
Takes a boolean argument. Controls whether NTP based network time synchronization is enabled (if available).

systemctl 101

systemctl

The 'systemctl' command controls the systemd system and service manager.  This is the new way to control services.  It also provides a new way for power management.  You can also control jobs, the environment, and snapshots.

RunLevels, Kernel.sysrq & Ctrl-Alt-Del

The default runlevel is no longer set in /etc/inittab.  Nor can you disable 'ctrl-alt-del' in /etc/inittab.  The runlevel is now controlled by systemd targets.  Not that there are runlevels anymore.

Check and Set the Default Runlevel

Runlevel 3 is now 'multi-user.target'.  And runlevel 5 is now 'graphical.target'.  To see your current setting run 'systemctl get-default'.  And to switch use 'systemctl set-detault <name-of-runlevel>.target'.  See the examples below.

# systemctl get-default
multi-user.target

# ls -la /etc/systemd/system/default.target
lrwxrwxrwx 1 root root 37 May 27 12:00 /etc/systemd/system/default.target -> /lib/systemd/system/multi-user.target

# systemctl set-default graphical.target
Removed symlink /etc/systemd/system/default.target.
Created symlink from /etc/systemd/system/default.target to /lib/systemd/system/graphical.target.

# systemctl set-default multi-user.target
Removed symlink /etc/systemd/system/default.target.
Created symlink from /etc/systemd/system/default.target to /lib/systemd/system/multi-user.target.

Disable Ctrl-Alt-Del

To disable this simply link the target to '/dev/null'.  It appears the target may be in '/etc/systemd/system' on some systems and on others in '/lib/systemd/system'.

# ln -sf /dev/null /lib/systemd/system/ctrl-alt-del.target

# ls -la /lib/systemd/system/ctrl-alt-del.target
lrwxrwxrwx 1 root root 9 Jun 21 21:19 /lib/systemd/system/ctrl-alt-del.target -> /dev/null

The sysrq magic key is still set in the same manner.  Personally, I prefer to explicitly set all network options required by the local security policy in /etc/sysctl.conf.  Some sites will require this to be disabled and some sites will want to enable this network option.

# To Disable kernel.sysrq - /etc/sysctl.conf
kernel.sysrq = 0
# To Enable kernel.sysrq - /etc/sysctl.conf
kernel.sysrq = 1

You may echo commands into '/proc/sysrq-trigger'.  Refer to the Wikipedia article for more information on the Magic SysRq key.

Basic systemctl Commands

The Fedora Project offers a nice cheat sheet that covers the basics.  Here are the commands that will be used most often.  Instead of running 'service <service_name> COMMAND' we now will run 'systemctl COMMAND <service_name>.  Replace COMMAND with start, stop, restart, reload, condrestart, or status.  The example below is truncated.

Example:  systemctl start foo

# systemctl status sshd
* ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: active (running) since Tue 2016-06-21 00:41:12 UTC; 1 day 4h ago
Main PID: 628 (sshd)
   CGroup: /system.slice/ssh.service
       `-628 /usr/sbin/sshd -D

Commands = start, stop, restart, condrestart, reload, & status

Instead of using 'chkconfig' to control how services start at boot, we will now use 'systemctl COMMAND <service_name>'.  And this time COMMAND will be replaced with enable, disable, or is-enabled.

# systemctl enable ssh
Synchronizing state for ssh.service with sysvinit using update-rc.d...
Executing /usr/sbin/update-rc.d ssh defaults
insserv: warning: current start runlevel(s) (empty) of script `ssh' overrides LSB defaults (2 3 4 5).
insserv: warning: current stop runlevel(s) (2 3 4 5) of script `ssh' overrides LSB defaults (empty).
Executing /usr/sbin/update-rc.d ssh enable
Created symlink from /etc/systemd/system/sshd.service to /lib/systemd/system/ssh.service.

Listing Services - .service Units

Previously we could run 'ls /etc/rc.d/init.d' to see all of the available services.  Or run 'chkconfig --list'.  By default systemctl runs the output through less.  To stop systemctl from running the output through a pager add the '--no-pager' flag.  Now to list all of the services and the state of that service run 'systemctl list-unit-files --type=service'.

# systemctl list-unit-files --type=service --no-pager
UNIT FILE                     STATE
alsa-restore.service          static
alsa-utils.service            masked
autologin@.service            disabled
avahi-daemon.service          enabled

The four states are defined below

  • Enabled = The service is configured to start at boot.
  • Disabled = The service is configured NOT to start at boot.
  • Masked = The service is prevented from being started at boot or manually.  It is linked to /dev/null.
  • Static = Installed as a dependency.  Static units cannot be enabled or disabled.  And may not always be executed.  They may start as a dependency of another service.  They may be started manually.

Systemctl Help

# systemctl --help
systemctl [OPTIONS...] {COMMAND} ...

Query or send control commands to the systemd manager.

  -h --help          Show this help
  --version          Show package version
  --system           Connect to system manager
  --user             Connect to user service manager
  -H --host=[USER@]HOST
                     Operate on remote host
  -M --machine=CONTAINER
                     Operate on local container
  -t --type=TYPE     List only units of a particular type
  --state=STATE      List only units with particular LOAD or SUB or ACTIVE                      state
  -p --property=NAME Show only properties by this name
  -a --all           Show all loaded units/properties, including dead/empty
                     ones. To list all units installed on the system, use
                     the 'list-unit-files' command instead.
  -l --full          Don't ellipsize unit names on output
  -r --recursive     Show unit list of host and local containers
  --reverse          Show reverse dependencies with 'list-dependencies'
  --job-mode=MODE    Specify how to deal with already queued jobs, when
                     queueing a new job
  --show-types       When showing sockets, explicitly show their type
  -i --ignore-inhibitors
                     When shutting down or sleeping, ignore inhibitors
  --kill-who=WHO     Who to send signal to
  -s --signal=SIGNAL Which signal to send
  -q --quiet         Suppress output
  --no-block         Do not wait until operation finished
  --no-wall          Don't send wall message before halt/power-off/reboot
  --no-reload        When enabling/disabling unit files, don't reload                            daemon configuration
  --no-legend        Do not print a legend (column headers and hints)
  --no-pager         Do not pipe output into a pager
  --no-ask-password
                    Do not ask for system passwords
  --global          Enable/disable unit files globally
  --runtime         Enable unit files only temporarily until next reboot
  -f --force        When enabling unit files, override existing symlinks
                    When shutting down, execute action immediately
  --preset-mode=    Specifies whether fully apply presets, or only enable,
                    or only disable
  --root=PATH       Enable unit files in the specified root directory
  -n --lines=INTEGER Number of journal entries to show
  -o --output=STRING Change journal output mode (short, short-monotonic,
                     verbose, export, json, json-pretty, json-sse, cat)
  --plain            Print unit dependencies as a list instead of a tree

Unit Commands:
  list-units [PATTERN...]          List loaded units
  list-sockets [PATTERN...]        List loaded sockets ordered by address
  list-timers [PATTERN...]         List loaded timers ordered by next                                          elapse
  start NAME...                    Start (activate) one or more units
  stop NAME...                     Stop (deactivate) one or more units
  reload NAME...                   Reload one or more units
  restart NAME...                  Start or restart one or more units
  try-restart NAME...              Restart one or more units if active
  reload-or-restart NAME...        Reload one or more units if possible,
                                   otherwise start or restart
  reload-or-try-restart NAME...    Reload one or more units if possible,
                                   otherwise restart if active
  isolate NAME                     Start one unit and stop all others
  kill NAME...                     Send signal to processes of a unit
  is-active PATTERN...             Check whether units are active
  is-failed PATTERN...             Check whether units are failed
  status [PATTERN...|PID...]       Show runtime status of one or more units
  show [PATTERN...|JOB...]         Show properties of one or more
                                   units/jobs or the manager
  cat PATTERN...                   Show files and drop-ins of one or more                                      units
  set-property NAME ASSIGNMENT...  Sets one or more properties of a unit
  help PATTERN...|PID...           Show manual for one or more units
  reset-failed [PATTERN...]        Reset failed state for all, one, or more
                                   units
  list-dependencies [NAME]         Recursively show units which are                                            required or wanted by this unit or by                                      which this unit is required or wanted

Unit File Commands:
  list-unit-files [PATTERN...]     List installed unit files
  enable NAME...                   Enable one or more unit files
  disable NAME...                  Disable one or more unit files
  reenable NAME...                 Reenable one or more unit files
  preset NAME...                   Enable/disable one or more unit files
                                   based on preset configuration
  preset-all                       Enable/disable all unit files based on
                                   preset configuration
  is-enabled NAME...               Check whether unit files are enabled

  mask NAME...                     Mask one or more units
  unmask NAME...                   Unmask one or more units
  link PATH...                     Link one or more units files into                                          the search path
  get-default                      Get the name of the default target
  set-default NAME                 Set the default target

Machine Commands:
  list-machines [PATTERN...]    List local containers and host

Job Commands:
  list-jobs [PATTERN...]        List jobs
  cancel [JOB...]               Cancel all, one, or more jobs

Snapshot Commands:
  snapshot [NAME]               Create a snapshot
  delete NAME...                Remove one or more snapshots

Environment Commands:
  show-environment               Dump environment
  set-environment NAME=VALUE...  Set one or more environment variables
  unset-environment NAME...      Unset one or more environment variables
  import-environment NAME...     Import all, one or more environment                                        variables

Manager Lifecycle Commands:
  daemon-reload              Reload systemd manager configuration
  daemon-reexec              Reexecute systemd manager

System Commands:
  is-system-running          Check whether system is fully running
  default                    Enter system default mode
  rescue                     Enter system rescue mode
  emergency                  Enter system emergency mode
  halt                       Shut down and halt the system
  poweroff                   Shut down and power-off the system
  reboot [ARG]               Shut down and reboot the system
  kexec                      Shut down and reboot the system with kexec
  exit                       Request user instance exit
  switch-root ROOT [INIT]    Change to a different root file system
  suspend                    Suspend the system
  hibernate                  Hibernate the system
  hybrid-sleep               Hibernate and suspend the system

systemd 101

Replacing INIT, SysV, & BSD

Personally I tend to think that SYSTEMD is solving a problem that doesn't exist.  However, as I learn more about it I can appreciate the benefits of this style of INIT.  I like the idea of binary logs.  And simplifying the daemon startup process by replacing RC scripts is nice as well.  But from past experience I suspect it will take many years before everyone switches over to 'systemd'.  I can't fathom the amount of hours it will take to redo all of the various support scripts in existence.  Or how many hours it will take to update all of the various ISO 9000 documentation and to re-train the support teams.  All this will probably happen just in time for another new style of INIT to be created.

Systemd Units and Targets

In the past INIT started the system and then stopped.  It tried to be alert enough to notice hot-swappable devices  and other system changes.  Starting processes required the writing of run control (RC) scripts.  This is replaced by systemd.  The systemd process runs at all times.  The scripting and brains to start and run the OS is controlled by the systemd process.  The user just writes configuration files.

To see if you are running systemd run the following command.  If '/sbin/init' is linked to '/lib/systemd/systemd' you are running systemd.

# ls -l $(which init)
lrwxrwxrwx 1 root root 20 Apr 2 14:33 /sbin/init -> /lib/systemd/systemd

Systemd introduces units.  Units are configuration files located in one of the directories listed below.  These unit files are simple text files that relevant to the system init process.  This includes system services, mount points, listening sockets, kernel devices and other items.  Targets are simply a grouping of units.  For example the 'graphical.target' requires the 'multi-user.target' and then starts the display-manager.service (X11).  If required, links to various required units are in the 'foo.target.wants' directory for that target.

Systemd Unit Locations

  • /usr/lib/systemd/system - systemd units distributed with installed packages  (Debian 8 uses /lib/systemd/system)
  • /etc/systemd/system - systemd units created and managed by the sys admin.  This directory takes precedence over the directory with runtime units.
  • /run/systemd/system - systemd units created at run time.  This directory takes precedence over the directory with installed service units.

Listing of Units

This list is from chapter 8 of the RHEL 7 System Administrators Guide.  (PDF Version)

 

Unit Type File Extension Description
Service Unit .service A system service
Target Unit .target A group of systemd units
Automount Unit .automount A file system automount point
Device Unit .device A device file recognized by the kernel
Mount Unit .mount A file system mount point
Path Unit .path A file or directory in a file system
Scope Unit .scope An externally created process
Slice Unit .slice A group of hierarchically organized units that manage system processe.
Snapshot Unit .snapshot A saved state of the systemd manager
Socket Unit .socket An inter-process communication socket
Swap Unit .swap A swap device or a swap file
Timer Unit .timer A systemd timer

The New Commands

There are a number of new commands to learn.  The two main commands are 'systemctl' and 'journalctl'.

The 'systemctl' command controls the systemd system and service manager.  This is the new way to control services.  (aka daemons)  This blog covers the basics of the systemctl command.  Search for the 'systemctl' tag.

The 'journalctl' command helps manage and display the new binary logs.  By default the rsyslog process also runs.  But that can be disabled.  This blog covers the basics of the 'journalctl' command.  Search for the 'journalctl' tag.

This blog also has information about the new 'timedatectl' command.  It is a nice easy way to set the time and date.  Although I still like manually updating the appropriate files.  Search for the 'timedatectl' tag.

For greater detail read the MAN pages for your OS.  The man pages for each command are linked below.

There are other new commands as well.  If you grep for 'ctl' in '/bin', '/usr/bin', '/sbin', and '/usr/sbin' to find more commands.  Some of these commands are listed below.

  • hostnamectl
  • localectl
  • loginctl