From 02d346a522d7f8199a80a5bd0b17534d04a3f65f Mon Sep 17 00:00:00 2001 From: David Runge Date: Sun, 25 Sep 2016 22:04:23 +0200 Subject: content/blog/201502-ssh-tunnel-and-postfix.rst: Updating to rst. --- content/blog/201502-ssh-tunnel-and-postfix.rst | 247 +++++++++++++++++++++++++ content/blog/ssh-tunnel-and-postfix.md | 179 ------------------ 2 files changed, 247 insertions(+), 179 deletions(-) create mode 100644 content/blog/201502-ssh-tunnel-and-postfix.rst delete mode 100644 content/blog/ssh-tunnel-and-postfix.md (limited to 'content/blog') diff --git a/content/blog/201502-ssh-tunnel-and-postfix.rst b/content/blog/201502-ssh-tunnel-and-postfix.rst new file mode 100644 index 0000000..b0d7422 --- /dev/null +++ b/content/blog/201502-ssh-tunnel-and-postfix.rst @@ -0,0 +1,247 @@ +SSH tunnel with single hop, using systemd-networkd and autossh +############################################################## + +:date: 2015-02-01 20:00 +:modified: 2015-02-01 20:00 +:tags: archlinux, autossh, ssh, tunnel, systemd, systemd.network, postfix, TUN +:category: admin +:slug: ssh-tunnel-with-single-hop-using-systemd-networkd-and-autossh +:summary: HOWTO on setting up a SSH tunnel with the help of a systemd-networkd between two machines, with no direct access to each other and modifying Postfix to use that tunnel. +:authors: David Runge + +| Recently I had the pleasure of setting up a :abbr:`SSH (Secure Shell)` tunnel between two virtual machines that share no route and are located in two different subnets. +| They can however reach each other via SSH, hopping their host. +| Let's assume the following setup: + +* **client1** (Arch Linux) has *10.0.5.2/24* +* **client2** (Arch Linux) has *10.0.6.2/24* +* **host** (Debian) is *10.0.5.1/24* to **client1** and *10.0.6.1/24* to **client2** + +| As I needed the two clients to be able to send mail to each other and reach each others' services, I did some digging and opted for a SSH connection using :abbr:`TUN (network TUNnel (virtual-network kernel devices))` devices (aka. "poor man's :abbr:`VPN (Virtual Private Network)`"). +| The following is needed to set this up: + +* root access on both virtual machines (**client1** & **client2**) +* a user account on the **host** system +* SSH (|openssh| assumed) installed on all three machines + +Connect the clients +___________________ + +Change sshd_config +------------------ + +| The following two settings have to be made in each clients */etc/ssh/sshd_config* (to allow root login and the creation of TUN devices): + + .. code:: apache + + PermitRootLogin yes + PermitTunnel yes + +| I hope it is needless to say, that permitting root access via SSH has its caveats. You should make sure to set a very secure password, or only allow SSH keys for login. +| + +Generate and exchange keys +-------------------------- + +| Generate SSH keys on **client1** (you can of course use other key types, if your OpenSSH installation allows and supports it): + + .. code:: bash + + ssh-keygen -t rsa -b 4096 -C "$(whoami)@$(hostname)-$(date -I)" + +| Here you can choose between setting a password for the key (to unlock the key with *ssh-add* yourself) or not setting one (to be able to use the key on system boot with an automated service). +| Add them to your user at **host** like this: + + .. code:: bash + + ssh-copy-id -i .ssh/id_rsa user@host + +| Also add it to */root/.ssh/authorized_keys* on **client2**. +| + +Use ProxyCommand to connect +--------------------------- + +| To make a first connection between the clients, one can use the following settings in */root/.ssh/config* of **client1** to hop **host** and connect to **client2**: + + .. code:: apache + + Host client2 + ProxyCommand ssh user@10.0.5.1 -W 10.0.6.2:%p + ForwardAgent yes + User root + ServerAliveInterval 120 + Compression yes + ControlMaster auto + ControlPath ~/.ssh/socket-%r@%h:%p + +| The *ForwardAgent yes* setting here is especially interesting, as it forwards the SSH key of **client1** to **client2**. +| On **client1** a simple + + .. code:: bash + + ssh client2 -v + +| should now directly connect to **client2** by hopping **host**. +| + +Tunneling +_________ + +Start the tunnel +---------------- + +| Now to the fun part: Creating the tunnel. +| OpenSSH supports a feature similar to VPN, that creates a TUN device on both ends of the connection. As the "direct" (hopping **host**) connection between **client1** and **client2** has been setup already, let's try the tunnel: + + .. code:: bash + + ssh -w5:5 client2 -v + +| The *-w* switch will create a TUN device (*tun5* to be exact) on each client. +| Now, to start the tunnel without executing a remote command (*-N*), compression of the data (*-C*) and disabling pseudo-tty allocation (*-T*), one can use the following: + + .. code:: bash + + ssh -NCTv -w5:5 client2 + +Setting up the TUN devices +-------------------------- + +| A short + + .. code:: bash + + ip a s + +| on **client1** and **client2** shows, that the *tun5* devices have been created on both clients. However they don't feature a link yet. +| This can be achieved by setting up a |systemd_network| with the help of |systemd-networkd|. By placing a *.network* file in */etc/systemd/network/*, the TUN device will be configured as soon as it shows up. +| Here I chose the *10.0.10.0/24* subnet, but you could use any other private subnet (that's still available in your setup). +| On **client1** (*/etc/systemd/network/client1-tun.network*): + + .. code:: ini + + [Match] + Name=tun5 + Host=client1 + + [Network] + Address=10.0.10.1/24 + + [Address] + Address=10.0.10.1/24 + Peer=10.0.10.2/24 + +| On **client2** (*/etc/systemd/network/client2-tun.network*): + + .. code:: ini + + [Match] + Name=tun5 + Host=client2 + + [Network] + Address=10.0.10.2/24 + + [Address] + Address=10.0.10.2/24 + Peer=10.0.10.1/24 + +| After adding the files a restart of the **systemd-networkd** service on both machines is necessary. + + .. code:: bash + + systemctl restart systemd-networkd + +| Now starting the tunnel again should give a fully working point-to-point :abbr:`TCP (Transmission Control Protocol)` connection between the two (virtual) machines using the TUN devices. +| If you need a more complex setup (i.e. to access the other clients' subnet), you will have to apply some routes (either using |netfilter| or |systemd-networkd|), depending on your individual setup. +| + +Hosts +_____ + +| To make both hosts know about each other by hostname (and domain, if any), too, those can be added to the clients' */etc/hosts* files. +| On **client1** (*/etc/hosts*): + + .. code:: bash + + 10.0.10.2 client2.org client2 + +| On **client2** (*/etc/hosts*): + + .. code:: bash + + 10.0.10.1 client1.org client1 + +Postfix +_______ + +| If using |postfix| as :abbr:`MTA (Message Transfer Agent)`, the service has to be configured to use */etc/hosts* before resolving to your networks DNS resolving. +| On **client1** and **client2** (*/etc/postfix/main.cf*): + + .. code:: ini + + lmtp_host_lookup = native + smtp_host_lookup = native + ignore_mx_lookup_error = yes + +Autossh and system boot +_______________________ + +| Wrapping it all up, it's usually intended to have a tunnel service be started on system boot. SSH tunnels are supposedly known for their poor connectivity. One way to get around this issue is to manage them with |autossh| . +| A simple |systemd_service| file can then be used to manage this behavior. +| On **client1** (*/etc/systemd/system/tunnel@.service*): + + .. code:: ini + + [Unit] + Description=AutoSSH tunnel to a host + After=network.target + + [Service] + Environment="AUTOSSH_GATETIME=0" + ExecStart=/usr/bin/autossh -M 0 -NCTv -o ServerAliveInterval=45 -o ServerAliveCountMax=2 -o TCPKeepAlive=yes -w 5:5 %I + + [Install] + WantedBy=multi-user.target + +| Enable the service with + + .. code:: bash + + systemctl enable tunnel@client2 + +| Start the service with + + .. code:: bash + + systemctl start tunnel@client2 + + +.. |openssh| raw:: html + + OpenSSH + +.. |systemd_network| raw:: html + + systemd network + +.. |systemd-networkd| raw:: html + + systemd-networkd + +.. |netfilter| raw:: html + + netfilter + +.. |systemd_service| raw:: html + + systemd service + +.. |autossh| raw:: html + + autossh + +.. |postfix| raw:: html + + postfix diff --git a/content/blog/ssh-tunnel-and-postfix.md b/content/blog/ssh-tunnel-and-postfix.md deleted file mode 100644 index 2f09db8..0000000 --- a/content/blog/ssh-tunnel-and-postfix.md +++ /dev/null @@ -1,179 +0,0 @@ -Title: SSH tunnel with single hop, using systemd network and autossh -Date: 2015-02-01 20:00 -Modified: 2015-02-01 20:00 -Tags: archlinux, autossh, ssh, tunnel, systemd, systemd.network, postfix, TUN -Slug: ssh-tunnel-with-single-hop-using-systemd-network-and-autossh -Authors: David Runge -Summary: Howto on setting up a SSH tunnel with the help of a systemd .network file between two machines, with no direct access to each other and modifying Postfix to use that tunnel. -Category: admin - -Recently I had the pleasure of setting up a SSH tunnel between two virtual machines that share no route and are located in two different subnets. -They can however reach each other via SSH, hopping their host. -Let's assume the following setup: - -* **client1** (Arch Linux) has *10.0.5.2/24* -* **client2** (Arch Linux) has *10.0.6.2/24* -* **host** (Debian) is *10.0.5.1/24* to **client1** and *10.0.6.1/24* to **client2** - -As I needed the two clients to be able to send mail to each other and reach each others' services, I did some digging and opted for a SSH connection using TUN devices (aka. *"poor man's VPN"*). -The following is needed to set this up: - -* root access on both virtual machines (**client1** & **client2**) -* a user account on the **host** system -* SSH ([OpenSSH](http://www.openssh.com/) assumed) installed on all three machines - -# Connect the clients - -## Change sshd_config -The following two settings have to be made in each clients */etc/ssh/sshd_config* (to allow root login and the creation of TUN devices): - - #!aconf - PermitRootLogin yes - PermitTunnel yes - -I hope it is needless to say, that permitting root access via SSH has its caveats. You should make sure to set a very secure password, or only allow SSH keys for login. - -## Generate and exchange keys -Generate SSH keys on **client1** (you can of course use other key types, if your OpenSSH installation allows and supports it): - - :::bash - ssh-keygen -t rsa -b 4096 -C "$(whoami)@$(hostname)-$(date -I)" - -Here you can choose between setting a password for the key (to unlock the key with *ssh-add* yourself) or not setting one (to be able to use the key on system boot with an automated service). -Add them to your user at **host** like this: - - :::bash - ssh-copy-id -i .ssh/id_rsa user@host - -Also add it to */root/.ssh/authorized_keys* on **client2**. - -## Use ProxyCommand to connect -To make a first connection between the clients, one can use the following settings in */root/.ssh/config* of **client1** to hop **host** and connect to **client2**: - - #!aconf - Host client2 - ProxyCommand ssh user@10.0.5.1 -W 10.0.6.2:%p - ForwardAgent yes - User root - ServerAliveInterval 120 - Compression yes - ControlMaster auto - ControlPath ~/.ssh/socket-%r@%h:%p - -The *ForwardAgent yes* setting here is especially interesting, as it forwards the SSH key of **client1** to **client2**. -On **client1** a simple - - :::bash - ssh client2 -v -should now directly connect to **client2** by hopping **host**. - -# Tunneling -## Start the tunnel -Now to the fun part: Creating the tunnel. -OpenSSH supports a VPN-like feature, that creates a TUN device on both ends of the connection. As the "direct" (hopping **host**) connection between **client1** and **client2** has been setup already, let's try the tunnel: - - :::bash - ssh -w5:5 client2 -v - -The *-w* switch will create a TUN device (*tun5* to be exact) on each client. -Now, to start the tunnel without executing a remote command (*-N*), compression of the data (*-C*) and disabling pseudo-tty allocation (*-T*), one can use the following: - - :::bash - ssh -NCTv -w5:5 client2 - -## Setting up the TUN devices -A short - - :::bash - ip a s - -on **client1** and **client2** shows, that the *tun5* devices have been created on both clients. However they don't feature a link yet. -This can be achieved by setting up a [systemd.network](http://www.freedesktop.org/software/systemd/man/systemd.network.html) with the help of [systemd-networkd](http://www.freedesktop.org/software/systemd/man/systemd-networkd.service.html). By placing a *.network* file in */etc/systemd/network/*, the TUN device will be configured as soon as it shows up. -Here I chose the *10.0.10.0/24* subnet, but you could use any other private subnet (that's still available in your setup). -On **client1** (*/etc/systemd/network/client1-tun.network*): - - #!ini - [Match] - Name=tun5 - Host=client1 - - [Network] - Address=10.0.10.1/24 - - [Address] - Address=10.0.10.1/24 - Peer=10.0.10.2/24 - -On **client2** (*/etc/systemd/network/client2-tun.network*): - - #!ini - [Match] - Name=tun5 - Host=client2 - - [Network] - Address=10.0.10.2/24 - - [Address] - Address=10.0.10.2/24 - Peer=10.0.10.1/24 - -After adding the files a restart of the **systemd-networkd** service on both machines is necessary. - - :::bash - systemctl restart systemd-networkd - -Now starting the tunnel again should give a fully working point-to-point TCP connection between the two (virtual) machines using the TUN devices. -If you need a more complex setup (i.e. to access the other clients' subnet), you will have to apply some routes (either using [Netfilter](http://www.netfilter.org/) or [systemd.network](http://www.freedesktop.org/software/systemd/man/systemd.network.html)), depending on your individual setup. - -# Hosts -To make both hosts know about each other by hostname (and domain, if any), too, those can be added to the clients' */etc/hosts* files. -On **client1** (*/etc/hosts*): - - 10.0.10.2 client2.org client2 -On **client2** (*/etc/hosts*): - - 10.0.10.1 client1.org client1 - -# Postfix -If using [postfix](http://www.postfix.org/) as MTA, the service has to be configured to use */etc/hosts* before resolving to your networks DNS resolving. -On **client1** and **client2** (*/etc/postfix/main.cf*): - - #!ini - lmtp_host_lookup = native - smtp_host_lookup = native - ignore_mx_lookup_error = yes - -# Autossh and system boot -Wrapping it all up, it's usually intended to have a tunnel service be started on system boot. SSH tunnels are supposedly known for their poor connectivity. One way to get around this issue is to manage them with [autossh](http://www.harding.motd.ca/autossh/). -A simple [systemd service](http://www.freedesktop.org/software/systemd/man/systemd.service.html) file can then be used to manage this behavior. -On **client1** (*/etc/systemd/system/tunnel@.service*): - - #!ini - [Unit] - Description=AutoSSH tunnel to a host - After=network.target - - [Service] - Environment="AUTOSSH_GATETIME=0" - ExecStart=/usr/bin/autossh -M 0 -NCTv -o ServerAliveInterval=45 -o ServerAliveCountMax=2 -o TCPKeepAlive=yes -w 5:5 %I - - [Install] - WantedBy=multi-user.target - -Enable the service with - - :::bash - systemctl enable tunnel@client2 - -Start the service with - - :::bash - systemctl start tunnel@client2 - - -*[SSH]: Secure Shell -*[MTA]: Message Transfer Agent -*[TCP]: Transmission Control Protocol -*[TUN]: network TUNnel (virtual-network kernel devices) -*[VPN]: Virtual Private Network -- cgit v1.2.3-70-g09d2