Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Setup a secure (SSH) tunnel as a systemd service. #systemd #ssh #ssh-tunnel #ssh-forward

README

Create a template service file at /etc/systemd/system/secure-tunnel@.service. The template parameter will correspond to the name of target host:

[Unit]
Description=Setup a secure tunnel to %I
After=network.target

[Service]
Environment="LOCAL_ADDR=localhost"
EnvironmentFile=/etc/default/secure-tunnel@%i
ExecStart=/usr/bin/ssh -NT -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -L ${LOCAL_ADDR}:${LOCAL_PORT}:localhost:${REMOTE_PORT} ${TARGET}

# Restart every >2 seconds to avoid StartLimitInterval failure
RestartSec=5
Restart=always

[Install]
WantedBy=multi-user.target

We need a configuration file (inside /etc/default) for each target host we will be creating tunnels for. For example, let's assume we want to tunnel to a host named jupiter (probably aliased in /etc/hosts). Create the file at /etc/default/secure-tunnel@jupiter:

TARGET=jupiter
LOCAL_ADDR=0.0.0.0
LOCAL_PORT=20022
REMOTE_PORT=22

Note that for the above to work we need to have allready setup a password-less SSH login to target (e.g. by giving access to a non-protected private key).

Now we can start the service instance:

systemctl start secure-tunnel@jupiter.service
systemctl status secure-tunnel@jupiter.service

Or enable it, so it get's started at boot time:

systemctl enable secure-tunnel@jupiter.service
@erikbgithub

This comment has been minimized.

Copy link

commented May 8, 2017

Thanks man, you just saved me like 4 hours of reading systemd docs!

Edit: If this blogpost is your source, maybe a reference is also polite. (not my blog, just reading what others say about the same topic)

Also, maybe the network-online.target is more interesting?

@drmalex07

This comment has been minimized.

Copy link
Owner Author

commented Sep 5, 2017

Thanks @erikbgithub. No, the article you mention was not my source (just the official docs of systemd).

@comperem

This comment has been minimized.

Copy link

commented Dec 3, 2017

Super helpful.

I think this is what worked for my restart failures:
RestartSec=5

@derkosak

This comment has been minimized.

Copy link

commented Mar 1, 2018

+1, really useful.
As the blogpost mentioned by @erikbgithub, for flexibility you might want to allow configuration of the SSH key file and for the remote user. I added -l ${REMOTE_USER} -i ${KEY_FILE} to the command in ExecStart and the defaults file.

@willjian

This comment has been minimized.

Copy link

commented Mar 13, 2018

Very helpful
Thanks @drmalex07 so much

@renxida

This comment has been minimized.

Copy link

commented Mar 22, 2018

I've been using this to connect to lab computers for a while. Awesome config file. Thank you so much.

I just tried using it on a public computer but it didn't work, so I made a root-free version:

https://github.com/renxida/labtunnel

It also includes install/uninstall scripts.

@sanludhi

This comment has been minimized.

Copy link

commented Mar 24, 2018

I was struggling... thanks for saving so much of time ... it worked perfectly fine

@sanludhi

This comment has been minimized.

Copy link

commented Aug 10, 2018

How to forward multiple ports

@htfy96

This comment has been minimized.

Copy link

commented Sep 21, 2018

Maybe it's better to set it as a user service

@dhruv

This comment has been minimized.

Copy link

commented Nov 7, 2018

Thank you for this!

@sunnyszy

This comment has been minimized.

Copy link

commented Nov 12, 2018

I also think it's better to exec in user mode. But my machine systemctl has bug when running --user, so I add user permission in service file

@linuxmalaysia

This comment has been minimized.

@maykel535

This comment has been minimized.

Copy link

commented Jan 31, 2019

I used the -R instead -L because did not works...

@siliconhippy

This comment has been minimized.

Copy link

commented Jan 31, 2019

Can this be modified to set up reverse SSH for multiple hosts behind firewalls, with as much automation as possible?

E.g., the port #s on the middleman machine represent each individual host, with the port #s left as variable in the host script. This variable port# determined at client- middleman login time and displayed, from within a pool of port #s.

The keygen should be done on middleman machine, and the public keys copied to target host machines apriori.

@LuoLee

This comment has been minimized.

Copy link

commented May 16, 2019

Helpful a lot, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.