Use this to create an encrypted connection between a local/remote box.
*** Local forwarding
Forwards a port from the client machine to the server machine. The ssh client listens for connections on a configured port, tunnels the connection to the server, and the server then connects to the destination address/port.
For example, I want that every client connecting to my IP address 192.168.1.157 on port 8080 to be tunneled to my server on pzolo.info and then have the connection sent to icanhazip.com on port 80:
root@twickenham:~# ssh -L 192.168.1.157:8080:icanhazip.com:80 email@example.com firstname.lastname@example.org's password:
Now we can see that the ssh client is listening on port 8080 and also has an established connectin, the tunnel, to the server:
root@twickenham:/home/ptosiani# lsof -P | grep 3703 | grep TCP ssh 3703 root 3u IPv4 40524 0t0 TCP 192.168.1.157:60542->pzolo.info:22 (ESTABLISHED) ssh 3703 root 4u IPv4 35436 0t0 TCP 192.168.1.157:8080 (LISTEN)
This is what we see in a packet capture when a client on the network connects to 192.168.1.157:8080:
17:49:47.131557 IP 192.168.1.168.52691 > 192.168.1.157.8080: Flags [S], seq 697753369, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0 [...] GET / HTTP/1.1 Host: 192.168.1.157:8080 Connection: keep-alive [...] 17:49:47.133320 IP 192.168.1.157.60542 > 184.108.40.206.22: Flags [P.], seq 2537745498:2537745598, ack 3952728736, win 501, options [nop,nop,TS val 3200931444 ecr 4168325949], length 100 # # Then on the server # 16:49:47.160112 IP pzolo.info.59848 > dedi4.de.icanhazip.com.http: Flags [P.], seq 1:508, ack 1, win 502, length 507: HTTP: GET / HTTP/1.1 E..#:.@.@.......t.7j...Pm5h..[5;P.......GET / HTTP/1.1 Host: 192.168.1.157:8080 Connection: keep-alive Cache-Control: max-age=0 # # Response on the client shows the IP addrss of the server # HTTP/1.1 200 OK Server: nginx Date: Sun, 26 Jul 2020 16:49:47 GMT Content-Type: image/vnd.microsoft.icon Content-Length: 16 Connection: close X-SECURITY: This site DOES NOT distribute malware. Get the facts. https://goo.gl/1FhVpg X-RTFM: Learn about this site at http://bit.ly/icanhazip-faq and do not abuse the service. Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET 220.127.116.11
In this post I'll show practical examples on how to verify that we are connecting to the correct SSH endpoint and how to exchange keys for password-less authentication.
When we try to connect to an SSH server for the first time, we get a warning about the authenticity of the host we are about to connect, followed by a fingerprint and a question.. but where does the signature comes from? and how can we be certain that it comes from the right host?
root@chromeos:~# ssh 192.168.1.200 The authenticity of host '192.168.1.200 (192.168.1.200)' can't be established. ECDSA key fingerprint is SHA256:DqEhLL8M8YjVJk8XDIdlOJQ235faGOjkL8MmZ+yPxWM. Are you sure you want to continue connecting (yes/no)?
In older versions of the ssh client we used to get an MD5 fingerprint
root@chromeos:~# ssh -o FingerprintHash=md5 192.168.1.200 The authenticity of host '192.168.1.200 (192.168.1.200)' can't be established. ECDSA key fingerprint is MD5:8a:4a:b9:84:81:f8:0f:de:cb:89:be:85:42:1a:5c:30. Are you sure you want to continue connecting (yes/no)?
In this example we are getting the ECDSA (Elliptic Curve Digital Signature Algorithm) fingerprint, but we could specify a different key algorithm
root@chromeos:~# ssh -o HostKeyAlgorithms=ssh-rsa 192.168.1.200 The authenticity of host '192.168.1.200 (192.168.1.200)' can't be established. RSA key fingerprint is SHA256:4skDV2xIXiQLwe0EsAdCmUjXm8CteDN2DGQcrx61lQk. Are you sure you want to continue connecting (yes/no)?
A full list of supported key algorithms is available by running the following command:
root@chromeos:~# ssh -Q key ssh-ed25519 email@example.com ssh-rsa ssh-dss ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 firstname.lastname@example.org email@example.com firstname.lastname@example.org email@example.com firstname.lastname@example.org
These fingerprints are generated in the client, from the public keys in the server. In this case, the server has:
root@raspberrypi:/etc/ssh# ll ssh_host_*pub -rw-r--r-- 1 root root 606 Sep 26 01:24 ssh_host_dsa_key.pub -rw-r--r-- 1 root root 178 Sep 26 01:24 ssh_host_ecdsa_key.pub -rw-r--r-- 1 root root 98 Sep 26 01:24 ssh_host_ed25519_key.pub -rw-r--r-- 1 root root 398 Sep 26 01:24 ssh_host_rsa_key.pub
To verify that we are connecting to the right server, we need to compare the public key in the server and the one that we are receiving in the client.
root@raspberrypi:/etc/ssh# cat ssh_host_ecdsa_key.pub ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFfsub7U+Sb6h4obExzsxzXanqzVfE4sNozlkl2Bu0j/f5ZomIv5ieY+5oTZvutW/e/eLrZ6LL5McNJJ8WR2eIo= root@raspberrypi
Then we can get the full key in the client
root@chromeos:~# ssh-keyscan -t ecdsa 192.168.1.200 # 192.168.1.200:22 SSH-2.0-OpenSSH_7.9p1 Raspbian-10+deb10u1 192.168.1.200 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFfsub7U+Sb6h4obExzsxzXanqzVfE4sNozlkl2Bu0j/f5ZomIv5ieY+5oTZvutW/e/eLrZ6LL5McNJJ8WR2eIo=
And finally, to go full circle, and check that the digest of the key is the same as the one we get in the question, we can use key-gen
root@chromeos:~# ssh-keyscan -t ecdsa 192.168.1.200 | ssh-keygen -lf - # 192.168.1.200:22 SSH-2.0-OpenSSH_7.9p1 Raspbian-10+deb10u1 256 SHA256:DqEhLL8M8YjVJk8XDIdlOJQ235faGOjkL8MmZ+yPxWM 192.168.1.200 (ECDSA)
Your client keeps a list of all the hosts where the authenticity has been verified. When we answer the question with yes, we add this new host to the list.
root@chromeos:~# tail -n1 .ssh/known_hosts |1|ZCjQ5DVz31CIjAcqJlhL6/PBce0=|1Bzfnbf0BUBYmsmSYHXtmIICRqY= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFfsub7U+Sb6h4obExzsxzXanqzVfE4sNozlkl2Bu0j/f5ZomIv5ieY+5oTZvutW/e/eLrZ6LL5McNJJ8WR2eIo=
We can see the public ECDSA key of the server in that output. But what are those strings that precede the key? This is the result of an ssh option called HashKnownHosts. When the option is enabled, instead of storing the IP address or hostname, we take this value, add some salt to it, and then hash it. So, what we have is:
Before moving to this step, make sure you have a backup of your private key, and if possible a "paper key" version. Change the following values on the sshd config, and restart the service:
sudo sed -i 's/PasswordAuthentication.*/PasswordAuthentication no/g' /etc/ssh/sshd_config sudo sed -i 's/ChallengeResponseAuthentication.*/ChallengeResponseAuthentication no/g' /etc/ssh/sshd_config