ssh¶
Reverse ssh tunnel¶
Let’s say you have a RaspberryPi without a static IP and a server with a static IP, and you want to ssh from the server to your RaspberryPi.
Run the following command on RaspberryPi:
It will bring localhost:22
of RaspberryPi to <ip-of-server>:32003
, so that you can ssh to
RaspberryPi with ssh localhost -p 32003
Consider creating a restricted ssh user for port-forwarding (only).
SSH port forwarding: bastions and ProxyJump
’s¶
Sometimes there are “bastion” hosts: in order to ssh to host2
, you have first have to ssh to an intermediate host1
.
There is proper support for this workflow in ssh: read more about -J
, -W
flags and ProxyCommand
here.
Arbitrary port forwarding¶
Suppose you have a web-server on host2
, and this host is unreachable directly from your machine (localhost
).
The only way to reach host2
is through intermediate host - host1
. And you want to be able to open pages from host2
from a browser running on your localhost
.
To achieve this, just run it:
(wherehost2
is directly unreachable host, host1
- intermediate host)
Once you run it, you can navigate to http://localhost:12345
in your browser.
Agent forwarding¶
You might want to maintain and use a single SSH key, regardless of how many nested SSH sessions there are. By default, the key of the current localhost is used. Agent forwarding makes it possible to use a single ssh key, forwarding it from one remote host to another. (1)
-
Both ssh-agent as well as gpg-agent implement ssh-agent protocol. This secction describes only ssh-agent.
See Generating ssh keys -> GPG keys for more info about gpg for ssh.
-
Ensure local ssh config allows in:
-
Ensure remote server allows it:
- Check configuration is fine:
/usr/sbin/sshd -t
- And restart sshd:
service ssh restart
-
Start ssh-agent automatically:
Escape characters¶
ssh
has these escape characters:
~.
— disconnect (useful if it hang).~^Z
— background ssh.~#
— list forwarded connections.~?
— display a list of escape characters.-
~C
— open command line.Currently this allows the addition of port forwardings using the -L, -R and -D options. It also allows the cancellation of existing portforwardings with
-KL[bind_address:]port
for local,-KR[bind_address:]port
for remote and-KD[bind_address:]port
for dynamic port-forwardings.!command
allows the user to execute a local command if thePermitLocalCommand
option is enabled in ssh_config.
Getting ssh fingerprint¶
When you ssh to a host first time, you are supposed to verify its key fingerprint.
You can obtain host’s fingerprint in this way:
Prevent dropping idle connections¶
The problem is that there is something (usually a firewall or load-balancer), which is dropping idle sessions. If you configure session keepalives, the keepalives will prevent network devices from considering the session as idle.
Hardenining — Publickey-only auth, disable passwords¶
Protocol 2
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
MaxAuthTries 3
PermitRootLogin no
Or, for specific user:
and then: sudo systemctl restart sshd
A very nice tutorial on hardening SSH Server that includes things like putting SSH in TOR.
SSH + 2FA¶
You can use various 2FA apps (such as Google Authenticator) with SSH.
sshfs¶
auto-reconnect¶
sshfs
allows you to mount remote computer’s filesystem over network. But sometimes the connection gets broken.
To mitigate it, you can mount in such way:
fstab¶
Example of fstab
for sshfs
:
sshfs#<login>@<server>:/remote/path/ /local/path fuse IdentityFile=/home/<login>/.ssh/id_ecdsa,idmap=user,allow_other 0 0
Generating ssh keys¶
Elliptic curves¶
Read more about ed25519.
Keeping keys on a harware token (aka Yubikey)¶
Advantages of Yubikeys (in comparison with storing ssh keys on a filesystem)
- Keys are never stored on filesystem of your PC.
- It is nearly impossible to extract (private) keys from Yubikey (and impossible without your noticing it).
- Yubikey has a hardware-backed max PIN entry counter (for example, your LUKS password can be brute-forced arbitrarily long, but Yubikey limits the number of attempts to 3).
- Yubikeys are “detachable” and can be stored in a safe/remote place.
- You do not need to insert it physically in a USB because there are NFC versions.
There are several ways to make ssh work with keys on a Yubikey:
FIDO/U2F-backed ssh keys security concerns
Note, however, that FIDO/U2F has different security properties:
- Often, only touch is neede to use the key, unlike gpg, where you have to enter PIN code and and which limits number of failed attempts.
- It is likely that touch will be needed for each ssh-connection (which might be a problem, if you are using ssh in a loop/script), unlike gpg, which caches your PIN for some time.
Recent ssh versions can generate FIDO/U2F token-backed keys. This options is good when you do not need/want to create “proxy” GPG keys and if remote host (where you are going to ssh to, for example github) supports such keys.
In order to generate ssh keys directly on FIDO/U2F token, use -t ed25519-sk
or -t ecdsa-sk
:
-O verify-required
makes the token require PIN (safer but more annoying)-O resident
will put key handle to token. Without the option, the token alone is not usable.
The idea is that you create GPG keys, put them on a Yubikey, and ask gpg-agent
to “pretend” to be ssh-agent
.
This option is good when you already have gpg keys.
-
Setup Yubikey as a SmartCard (optional):
- Buy an appropriate NFC card-reader
(for example
HID Identity OMNIKEY 5422 Internal USB 2.0 Grey Smart Card Reader
). - Blacklist standard Linux drivers (source: 1, 2):
- Install
libnfc
:sudo apt install libnfc-bin pcsc-tools
- Verify it works: (re-)plug the NFC reader, put your Yubikey on it, scan with:
pcsc_scan
and rungpg --card-edit
.
- Buy an appropriate NFC card-reader
(for example
-
Create GPG keys locally and move them to a Yubikey.
- You can use DrDuh’s guide.
- Or you can use a script that automates it.
-
Setup ssh<—>gpg interaction (main source):
-
Enable ssh support in
gpg-agent
config: -
Restart
gpg-agent
:gpgconf --kill gpg-agent
-
Specify which key should be used for ssh: add keygrip of the “Auth GPG key” to
~/.gnupg/sshcontrol
:- Get its keygrip:
gpg -K --with-keygrip
- Put it in ~/.gnupg/sshcontrol:
echo 87A342B1561ADD416AD21... > ~/.gnupg/sshcontrol
- Get its keygrip:
-
Tell SSH to use
gpg-agent
’s socket:
-
-
Verify it works.
ssh-add -L
should show you public ssh-keys (backed by Yubikey & gpg).