Securing the sudo to sudo_logsrvd connection
Using sudo_logsrvd
to centrally collect sudo session recordings from your network is a huge step forward in security: users cannot delete or modify session recordings locally. However, by default, transmission of recordings is not encrypted, making it open to modifications and eavesdropping. Encrypting the connection between sudo
and sudo_logsrvd
can eliminate these problems. Larger environments usually either have in-house PKI tooling in place, or colleagues who know all openssl options off the top of their heads. However, small and medium enterprises often lack the infrastructure or knowledge to work with TLS certificates.
This blog can help you to secure connections between sudo
and sudo_logsrvd
when there is no PKI tooling available to you, or you want to create all the certificates yourself using openssl
. It is based on the sudo_logsrvd
manual, but changed in such a way that all information is entered on the command line. While interactive certificate generation works fine for a single cert, generating multiple client certificates is easier when everything is on the command line.
To collect sudo recordings you need to use at least sudo version 1.9.0. There were many minor bug fixes related to this feature, so it is recommended to use the latest version available. At the time of writing, this is version 1.9.7p2. Another requirement is to have OpenSSL support enabled in sudo
and sudo_logsrvd
. Fedora merged my request, so Rawhide has the latest sudo version with OpenSSL support enabled. OpenSUSE Tumbleweed has an up-to-date version and OpenSSL support is expected to be enabled soon. Sudo in FreeBSD works out of box.
For other distributions you can either try to download a binary package from the sudo website, or compile sudo on your own.
You will also need the openssl
command line utility to generate the certificates. It is installed by default on most systems.
Note: this blog assumes that OpenSSL configuration is stored in the /etc/ssl
directory. If it is not the case, you will have to adjust the path names in configuration files and command line examples.
We do everything under the /etc/ssl/sudo
directory. As a first step we set up a few files and directories and fix their permissions.
mkdir /etc/ssl/sudo
cd /etc/ssl/sudo
mkdir certs csr newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial
Now copy the openssl configuration file over here and open it in your favorite text editor:
cp ../openssl.cnf .
vi openssl.cnf
Edit the openssl.cnf file in the current directory. Most likely it already has a [CA] and a [CA_default] section, similar to this:
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /etc/ssl/sudo
certs = $dir/certs
database = $dir/index.txt
certificate = $dir/cacert.pem
serial = $dir/serial
In this case, all you have to change is to make sure that “dir” points to the newly created /etc/ssl/sudo
directory. Otherwise, copy the example into your openssl.cnf
.
In order to create and sign our own certificates, we need to create a private key and a certificate for the root of the CA. First, create the private key and protect it with a pass phrase:
openssl genrsa -aes256 -out private/cakey.pem 4096
chmod 400 private/cakey.pem
Next, generate the root certificate. While doing it interactively might be easier at first, we provide all values on the command line. You can check the list below to see what the different fields mean:
- “C” stands for country
- “L” for location, usually city name
- “ST” for state (we do not use that here in Hungary, but openssl sometimes complains if it is missing)
- “O” organization
- “OU” organizational unit (or department)
- “CN” stands for common name. In case of a CA, it is the name displayed when you list certificate authorities. In case of client or server certificates, it is the FQDN of the host or its IP address.
Note that from now on you cannot blindly copy and paste command lines from this blog. The command line contains organization and site specific information as well. Change the values according to your environment as necessary.
openssl req -config openssl.cnf -key private/cakey.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out cacert.pem -subj '/C=HU/L=Budapest/ST=Budapest/O=My Home Ltd/OU=sudo/CN=sudo Root CA'
chmod 444 cacert.pem
openssl x509 -noout -text -in cacert.pem
The last command is not strictly necessary. However it helps you to verify if you entered all information as intended. Here is an example:
localhost:/etc/ssl/sudo # openssl x509 -noout -text -in cacert.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
78:af:5a:28:fa:1c:e2:07:2c:44:4a:17:28:60:00:01:5c:86:27:26
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = HU, L = Budapest, ST = Budapest, O = My Home Ltd, OU = sudo, CN = sudo Root CA
Validity
Not Before: Aug 6 11:23:49 2021 GMT
Not After : Aug 1 11:23:49 2041 GMT
Subject: C = HU, L = Budapest, ST = Budapest, O = My Home Ltd, OU = sudo, CN = sudo Root CA
Subject Public Key Info:
[...]
The server and client certificates will be signed by the previously created root CA. Usually, the root CA is not used to sign server/client certificates directly. Instead, intermediate certificates are created and signed with the root CA and the intermediate certs are used to sign CSRs (Certificate Signing Request). In this example we’ll skip this part for simplicity’s sake and sign the CSRs with the root CA.
First, generate the private key without a pass phrase.
openssl genrsa -out private/logsrvd_key.pem 2048
chmod 400 private/logsrvd_key.pem
Next, create a certificate signing request (CSR) for the server’s certificate and sign it. The organization name must match the name given in the root certificate. The common name should be either the server’s IP address or a fully qualified domain name. The abbreviation of field names is the same as in the previous section, you can check them there.
openssl req -config openssl.cnf -key private/logsrvd_key.pem -new -sha256 -out csr/logsrvd_csr.pem -subj '/C=HU/L=Budapest/ST=Budapest/O=My Home Ltd/OU=sudo/CN=172.16.167.164'
openssl ca -config openssl.cnf -days 375 -notext -md sha256 -in csr/logsrvd_csr.pem -out certs/logsrvd_cert.pem
You can verify the results using:
# openssl verify -CAfile cacert.pem certs/logsrvd_cert.pem
certs/logsrvd_cert.pem: OK
If you want to use peer authentication, you also need to create client certificates. Otherwise, you can skip ahead to configuring TLS in sudo_logsrvd
.
Creating the client certificates is practically the same as for sudo_logsrvd
. You only need to change the file names and the CN (Common Name) on the command lines. Here are the command lines for your first sudo
client:
openssl genrsa -out private/client_key.pem 2048
chmod 400 private/logsrvd_key.pem
openssl req -config openssl.cnf -key private/client_key.pem -new -sha256 -out csr/client_csr.pem -subj '/C=HU/L=Budapest/ST=Budapest/O=My Home Ltd/OU=sudo/CN=172.16.167.153'
openssl ca -config openssl.cnf -days 375 -notext -md sha256 -in csr/client_csr.pem -out certs/client_cert.pem
While not strictly part of certificate creation, copying the right files to the right host is important. Here is an example command sequence helping you to figure out which files to copy when you setup a client:
cd ..
tar cvf sudo_client_certs.tgz sudo/cacert.pem sudo/certs/client_cert.pem sudo/private/client_key.pem
scp sudo_client_certs.tgz user@172.16.167.153:
So, we changed to the /etc/ssl
directory, created a tar archive from the three necessary files and copied the file to the host, where we configure sudo to forward session recordings to sudo_logsrvd
through a TLS encrypted connection.
Now that we have the freshly generated certificates available on the server and possibly also on the client, it is time to configure sudo_logsrvd
and sudo
. The configuration examples assume that you use the directory structure from the certificate generation command line examples.
I learned the hard way: /etc/sudo_logsrvd.conf
, the configuration file for sudo_logsrvd
, has several different sections in it. Make sure that you edit the [server]
section when you enable TLS, otherwise you will receive some frightening error messages. The content of some sections is similar, so double-check that you are in the right section.
# Listen on port 30344 for TLS connections to any address.
listen_address = *:30344(tls)
# Path to the certificate authority bundle file in PEM format.
tls_cacert = /etc/ssl/sudo/cacert.pem
# Path to the server's certificate file in PEM format.
tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
# Path to the server's private key file in PEM format.
tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
With these settings you should already be able to receive TLS encrypted connections from sudo
clients. You can configure two additional settings to further secure communications:
- tls_verify -
sudo_logsrvd
will validate its own certificate at startup - tls_checkpeer -
sudo_logsrvd
will validate the certificates of clients that connect to it
If peer authentication is enabled on the client, a copy of cacert.pem must be present on the client system too. And this leads us to client configuration. Here is a minimal configuration:
Defaults log_servers = 172.16.167.164:30344(tls)
Defaults log_output
This configuration enables session recording and sends the results to the given address using TLS encryption. There is no peer verification, but at least the data is not clear text on the wire. There are many more possible configuration options:
Defaults ignore_iolog_errors
Defaults log_servers = 172.16.167.164:30344(tls)
Defaults log_output
Defaults log_input
Defaults log_server_cabundle = /etc/ssl/sudo/cacert.pem
Defaults log_server_peer_cert = /etc/ssl/sudo/certs/client_cert.pem
Defaults log_server_peer_key = /etc/ssl/sudo/private/client_key.pem
Defaults log_server_verify
The names are pretty self-explanatory, but let me give you a quick explanation for each of them.
- By default
sudo
does not authorize commands to execute whensudo_logsrvd
is inaccessible; ignore_iolog_errors makes sure that sudo works even in this situation - log_server_cabundle / log_server_peer_cert / log_server_peer_key point to the various certificates enabling peer authentication
- log_server_verify instructs the client to verify the server’s certificate
If you configured everything properly, using sudo
should not be any different. Just enter commands as usual and they should work just as they did before. The difference is that you should now be able to see your session recordings on the host running sudo_logsrvd
.
Here is the output of sudoreplay
on an openSUSE host running sudo_logsrvd
, showing recordings from sudo
running on a Fedora 34 host:
Aug 3 14:31:50 2021 : czanik : TTY=/dev/pts/0 ; CWD=/home/czanik ; USER=root ; HOST=fedora34.localdomain ; TSID=000015 ; COMMAND=/usr/bin/ls /root/
Aug 6 13:49:17 2021 : czanik : TTY=/dev/pts/0 ; CWD=/home/czanik ; USER=root ; HOST=fedora34.localdomain ; TSID=000016 ; COMMAND=/bin/bash
If you would like to be notified about new posts and sudo news, sign up for the sudo blog announcement mailing list.