Create a template service file at /etc/systemd/system/[email protected]
. 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 [email protected]
systemctl status [email protected]
Or enable it, so it get's started at boot time:
systemctl enable [email protected]
Hi
I think
RestartSec=5
Needs to be greater than
ServerAliveInterval
or andClientAliveInterval
, especially for tunnels.To prevent the possibility of trying to open a failed SSH connection at one end (AA), while the other end (BB) still thinks the connection is alive.
The effect is that the failed end (AA) tries to open a new connection, which is blocked by the half dead connection at the other end (BB).
I think 'RestartSec' should be long enough that both ends know their connection is broken.
Worst case scenario.
ServerAliveInterval = 10
ClientAliveInterval = 3
End AA sends a packet that is received by BB but the connection is blocked before a reply is received by AA.
AA detects a failed linkand will close the connection in 30sec.
BB received the packet from AA and thinks the connection is still open.
After 10sec, BB sends a packet, with no reply.
BB now detects a failed link and will close the connection in 30sec. This is 10sec later than AA.
In that 10s period, AA would try to open a new connection that would fail because it is blocked by BB.
Solution for tunnels
Set:
ExitOnForwardFailure yes
RestartSec
>>ServerAliveInterval
Same applies to
ClientAliveInterval
where: >> means "much greater than"
This will ensure that both ends have killed their ssh connections before trying to re-open them.
The TCP protocol should flag a sent packet missing an
ACK
but I have experienced problems with blocked SSH links.