Skip to content

Recipe: deployment with mutual TLS authentication using self‐signed certificates

Snawoot edited this page Jan 4, 2025 · 3 revisions

This guide explains deployment of secure (HTTP-over-TLS) proxy server on any mainstream Linux distro. In the configuration presented below both client and server authenticate each other using self-signed certificates. Such configuration does not require domain name to be attached to the server and doesn't depend on any external certificate authority.

Note

It is also possible to make server authenticate itself using globally trusted certificates from well-known authorities (e.g. Let's Encrypt) as usual for public HTTPS sites. In that case such certificate and key go in place of server certificate and clients are not required to use self-signed CA cert to verify peer. Clients, however, are still required to present certificate from self-signed CA to authenticate against server.

For sake of example we assume server has IP address 203.0.113.99.

Step 1. Establish your own certificate authority and generate certificates

It is possible to use any utility of your choice to generate certificates. In this guide we will use mkcert tool.

Tip

You can use any machine to generate certificates. It doesn't have to be the server or client machine. In general it's better to keep only required certificates and keys on each machine.

Run following commands to generate certificates:

export CAROOT=.
mkcert 203.0.113.99 # server certificate
mkcert -client client1 # client certificate

Following files will appear in your working directory:

Filename Used by client Used by server Description
203.0.113.99-key.pem NO YES server private key
203.0.113.99.pem NO YES server end-entity certificate
client1-client-key.pem YES NO client private key
client1-client.pem YES NO client end-entity certificate
rootCA-key.pem NO NO certificate authority private key
rootCA.pem YES YES certificate authority root certificate

Step 2. Install dumbproxy on your server

Assuming amd64 processor architecture, for other cases get binary here. Run command:

curl -Lo /usr/local/bin/dumbproxy \
	'https://github.com/SenseUnit/dumbproxy/releases/download/v1.20.1/dumbproxy.linux-amd64' \
	&& chmod +x /usr/local/bin/dumbproxy

Check if installation was successful. Command /usr/local/bin/dumbproxy -version should output v1.20.1.

Step 3. Configure dumbproxy

Put files rootCA.pem, 203.0.113.99.pem and 203.0.113.99-key.pem into files /etc/dumbproxy-ca.pem, /etc/dumbproxy.pem and /etc/dumbproxy-key.pem on server respectively.

Create file /etc/default/dumbproxy with following content:

OPTIONS=-auth cert:// \
	-cafile /etc/dumbproxy-ca.pem \
	-cert /etc/dumbproxy.pem \
	-key /etc/dumbproxy-key.pem \
	-bind-address :443

Place following content info file /etc/systemd/system/dumbproxy.service:

[Unit]
Description=Dumb Proxy
Documentation=https://github.com/SenseUnit/dumbproxy/
After=network.target network-online.target
Requires=network-online.target

[Service]
EnvironmentFile=/etc/default/dumbproxy
User=root
Group=root
ExecStart=/usr/local/bin/dumbproxy $OPTIONS
TimeoutStopSec=5s
PrivateTmp=true
ProtectSystem=full
LimitNOFILE=20000

[Install]
WantedBy=default.target

Finally, apply systemd configuration:

systemctl daemon-reload

Step 4. Run dumbproxy

Enable autostart:

systemctl enable dumbproxy

Start service:

systemctl start dumbproxy

Check if proxy is operational using this command:

curl --proxy https://203.0.113.99 \
	--proxy-cacert rootCA.pem \
	--proxy-cert client1-client.pem \
	--proxy-key client1-client-key.pem \
	https://api.ipify.org ; echo

It should output server's IP address.

Important

You can stop at this point and use proxy directly with any Chrome-like browser. In order to do that, you'll have to install client certificates and CA into browser. It is more convenient to import client certificates in browser if cert and key is packed int PKCS12 bundle. To achieve that generate client certificates like this: mkcert -client -pkcs12 my-chrome-browser. The import password will be set to changeit.

But if you need generic plaintext HTTP proxy compatible with the most of applications, you'll need an adapter to handle mTLS. In that case read further.

Step 5. Install steady-tun on your client

See installation options here.

Step 6. Run steady-tun

Ensure steady-tun is running as follows:

steady-tun -dsthost 203.0.113.99 -dstport 443 -cafile rootCA.pem -cert client1-client.pem -key client1-client-key.pem

Autostart configuration depends on your OS choice and is left to reader's discretion.

Now proxy server is available as plain HTTP proxy on local port 127.0.0.1:57800. You can test it with following command:

curl --proxy http://127.0.0.1:57800 https://api.ipify.org ; echo