Reverse SSH tunnel from a firewalled host

You have an SSH server A behind a firewall that you wish to connect to. You have no control over the firewall but has an account on an open SSH server B on the internet outside the firewall. You can setup a reverse tunnel from A to B so that you can connect to A through B from anywhere.

In the SSH configuration file A:~/.ssh/config, add the following section

Host b-tun
	HostName B
	ServerAliveInterval 30
	ExitOnForwardFailure yes
	RemoteForward 8822 localhost:22

Afterward, you can create the reverse tunnel on A by running ssh -Nf b-tun. and login with your credential on B or setup key authentication for automatic login. If the tunnel has been created successfully, you can now connect to the port 8822 of localhost on B to login to A, e.g., ssh -p 8822 localhost. If you have access to the nc command on B, you can add the section below to the ~/.ssh/config on a machine outside the firewall:

Host A
	ProxyCommand ssh -qax B 'nc -w 600 localhost 8822'
	ServerAliveInterval 30

You will then be able to connect to A with a simple ssh A on that machine.

You can also make the creation of the reverse tunnel automatic by creating a systemd unit, say, ~/.config/systemd/user/b-tun.service with the content

[Unit]
Description=Create SSH tunnel through B
After=network-online.target

[Service]
Type=idle
ExecStart=/usr/bin/ssh -N b-tun
RestartSec=39
Restart=always

[Install]
WantedBy=default.target

and start the process with systemctl --user start b-tun.service. You may need to enable unattended job for the user on A with loginctl enable-linger user as the root on A. To make the service start on boot automatically, you need to enable it with systemctl --user enable b-tun.service.

Dovecot 2.3.18 failed to load certificate with OpenSSL 3.0

This problem prevents user login with SSL to the Dovecot IMAP server. The errors in the journal look like this:

... imap-login: Error: Failed to initialize SSL server context: Can't load SSL certificate (ssl_cert setting): error:25066067:DSO support routines:dlfcn_load:could not load the shared library: filename(libproviders.so): libproviders.so: cannot open shared object file: No such file or directory, error:25070067:DSO support routines:DSO_load:could not load the shared library, error:0E07506E:configuration file routines:module_load_dso:error loading dso: module=providers, path=providers, error:0E076071:configuration file routines:module_run:unknown module name: module=providers: ...

A fix/workaround was found at Bug#1011051: libssl3: upgrade to libssl3 broke my dovecot setup. By commenting out the line “providers = provider_sect” in the configuration file “/etc/ssl/openssl.cnf”, the service is restored. Hope this will be resolved properly in the near future.

Authenticate through Client Certificate

This post documents how to setup using a client certificate in accessing a private web page.

The involved components are as follows:

  • Web server: Apache 2.4
  • Browser: Firefox 98

Steps:

  1. Generate CA certificate: see the previous post
  2. Configure web server to require client certificates signed by the CA
    • Add SSLVerifyClient require to the protected Location
    • Add SSLCACertificateFile to point to the CA certificate
  3. Generate a personal certificate: also described in the previous post
  4. Sign the personal certificate with CA certificate: ditto
  5. Import personal certificate into browser
    Settings → Privacy & Security → Certificates → View Certificates… → Your Certificates → Import…
  6. Configure browser to enable post-handshake authentication (Only needed if you get “…Cannot perform Post-Handshake Authentication” error. Usually happens when securing only a sub path instead of the entire server.)
    For Firefox (98)
    1. Go to the URL about:config
    2. Find and enable security.tls.enable_post_handshake_auth
  7. All set! Go ahead and test it out…

Self-signed CA certificate

It’s useful for signing certificates for internal use. Here is a quick way for setting up a self-signed CA using the openssl command in Linux.

mkdir ca
cd ca
openssl req -nodes -new -x509 -keyout ca.key -out ca.crt -subj "/C=TW/ST=Taiwan/L=Taipei/O=ccdw.org/OU=sam/CN=sam.ccdw.org/emailAddress=root@sam.ccdw.org"

Server certificate

To create a server certificate signing request along with a new server key:

openssl req -nodes -new -keyout server.key -out server.csr -subj "/C=TW/ST=Taiwan/L=Taipei/O=ccdw.org/OU=server/CN=server.ccdw.org/emailAddress=server@ccdw.org"

To sign the server certificate:

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650

The resulting key can certificate of the server can be combine into a PEM file:

cat server.key server.crt > server.pem

Client certificate

To create a client certificate signing request along with a new client key:

openssl req -nodes -new -keyout client.key -out client.csr -subj "/C=TW/ST=Taiwan/L=Taipei/O=ccdw.org/OU=client/CN=Good Client/emailAddress=good@client.ccdw.org"

To sign the client certificate:

openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAserial ca.srl -out client.crt -days 1000

The browser usually needs the certificate in PKCS#12 format. To convert the format of the certificate:

openssl pkcs12 -export -out client.pfx -inkey client.key -in client.crt

The .pfx file can then be imported into a browser.