Email over ssh

The method described here was tested on openSUSE Leap 15.5; on Ubuntu and other linux distributions this installation of the software will be different. For the method described here you need root access to your linux system.

Using NetworkManager and dnsmasq

Sending email using smtp.science.ru.nl, port 587 is possible on campus, or using eduVPN. If you have ssh access to lilo7.science.ru.nl it is possible to use dnsmasq to redirect smtp.science.ru.nl to 127.0.0.1 (localhost) and use ssh port forwarding to forward port 587 on localhost to lilo7.science.ru.nl. As a result, a mail client, e.g. thunderbird should work with the same settings as on campus.

Install software

Install software and start NetworkManager:

# (zypper is the OpenSUSE package manager)
zypper install NetworkManager NetworkManager-dns-dnsmasq
zypper install dnsmasq
# Note: do not use systemd to manage dnsmasq
# NetworkManager will directly call the binary /usr/sbin/dnsmasq

# Switch to NetworkManager in YaST (the openSUSE setup tool)
YaST / System / Network Settings / Global Options
General Network Settings/ Network Setup Method / Network Manager
# or by hand (systemctl is a systemd command used by many linux distributions)
systemctl enable NetworkManager
systemctl start NetworkManager
# Check
systemctl status NetworkManager
cat /etc/resolv.conf
# will show something like:
search home
nameserver 127.0.0.1

Configure NetworkManager (as root):

cd /etc/NetworkManager
mkdir conf.d
mkdir dnsmasq.d
# create file conf.d/my.conf with these two lines:

[main]
dns=dnsmasq

# create dnsmasq.d/my.conf with:

address=/smtp.science.ru.nl/127.0.0.1
cache-size=1000

# Restart NetworkManager

systemctl restart NetworkManager

The cache-size entry is not essential, but it may speed up domainname lookup. To test use:

dig smpt.science.ru.nl +short
# this should return: 127.0.0.1

Port forwarding can be started by hand with:

ssh -L 587:localhost:587 lilo7.science.ru.nl
# or with
ssh -N -L 587:localhost:587 lilo7.science.ru.nl
# where the -N flag means "Do not execute a remote command"

When you give the ssh command you have to enter your passphrase when prompted. By using an ssh-agent you will only have to enter your passphrase once.

The port-forwarding can also be started when booting the system by adding a systemd unit. It may seem this would require entering your passphrase at boot time or using ssh keys without passphrase, but the solution described here requires neither.

The trick is to let the user that knows the passphrase use an ssh-agent with a fixed location of the ssh-agent socket, e.g., at $XDG_RUNTIME_DIR/ssh-agent.sock:

# Check whether your linux defines:
echo $XDG_RUNTIME_DIR
# I get:
/run/user/15010
# the number 15010 is my user id, which you can also find with
id -u

# In your .bashrc define a location for a ssh-agent socket:
export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent.sock
# if $XDG_RUNTIME_DIR is not defined you can use another directory,
# as long as you (the user, not only root) has r/w access to that
# directory

The user should start the ssh-agent with this socket, this can also be done in your .bashrc

export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent.sock
ssh-agent -a "$SSH_AUTH_SOCK"

To let the ssh-agent know the passphrase use:

ssh-add
# enter the passphrase when prompted
# check with
ssh-add -l
# this should show a hash of your passphrase, like
256 SHA256:IXZCIzWssOhp1sf3HiT0RUwPZLTKFGnrT2Q1ZDAMua4 user@host.nl (ED25519)

A root process can now setup port forwarding with ssh to lilo7.science.ru.nl, since it can read the ssh-agent socket /run/user/15010/ssh-agent.sock.

The systemd configuration is found here:

cd /etc/systemd/system

To add a unit create a file emailtunnel.socket (as root) with:

[Unit]
Description=Open an SSH connection in order to send an email.

[Socket]
ListenStream=127.0.0.1:587
# Start one SSH connection per TCP connection to 587.
Accept=true

[Install]
WantedBy=sockets.target

Also create, in the same directory, a file emailtunnel@.service with:

[Unit]
Description=An SSH tunnel

[Service]
# The SSH_AUTH_SOCK should be what was set by the user with the
# passphrase as explained above
Environment="SSH_AUTH_SOCK=/run/user/15010/ssh-agent.sock"
Type=simple
ExecStart=/usr/bin/ssh gerritg@lilo7.science.ru.nl -- nc smtp.science.ru.nl 587
StandardInput=socket
StandardOutput=socket
StandardError=journal

To load/test/start/start at reboot/ these units use:

# After changing files in /etc/systemd/system you need:
systemctl daemon-reload

# check for messages:
systemctl status
journalctl -xau emailtunnel.socket

# if ok, start it
sytemctl start emailtunnel.socket

# to switch the unit off
sytemctl stop emailtunnel.socket

# to start this unit at boot time
systemctl enable emailtunnel.socket

Now, make sure to give the ssh-agent your passphrase before you try sending e-mail with ssh-add (see above). In thunderbird click on buttons until you finally find the settings for Outgoing Server (SMTP). You need to set:

Description: sending email with science mail account
Server Name: smtp.science.ru.nl
Port:        587
Connection security:   STARTTLS
Authentication method: Normal password
Username:              gerritg
# replace gerritg by your science username

Now when you send an e-mail with thunderbird, dnsmasq (started by NetworkManager will redirect smtp.science.ru.nl to localhost, and the systemd socket defined in /etc/systemd/system/emailtunnel.socket will connect port 587 to the ssh forwarding command defined in /etc/systemd/system/emailtunnel@.service, which will get the passphrase from the ssh-agent from the socket $SSH_AUTH_SOCK defined in /etc/systemd/system/emailtunnel@.service.

If you have thunderbird working on campus, it should now be possible to simply copy your entire .thunderbird directory to your linux desktop at home or a laptop with:

rsync -avz lilo7.science.ru.nl:.thunderbird ~/

and have thunderbird working.

Note that reading e-mail from imap.science.ru.nl works off-campus in the same way as on-campus and does not require eduVPN or ssh port forwarding.