Difference between revisions of "SSH"

From Organic Design wiki
(basic ssh usage)
 
(See also: What we know about the xz Utils backdoor that almost infected the world)
 
(32 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Password-protect you private key ==
+
[[File:ssh.jpg|600px|right]]
To add a password to an existing private key, use the following ''openssl'' command:
+
 
 +
== Port forwarding with SSH ==
 +
<onlyinclude>
 +
SSH allows you to forward ports on one machine to another using the SSH pipes.
 +
 
 +
For example, using a local port-forward, you could create a local connection into a remote SQL server that's not available to external connections if you have SSH access to machine with running the SQL server:
 +
<source lang="bash">
 +
ssh -nNTL 3333:localhost:3306 USER@SERVER
 +
</source>
 +
Now you can access the database locally on port 3333.
 +
 
 +
Or in the opposite direction you can use a remote port-forward you could give SSH access to a machine that's behind a firewall or router by putting its SSH port onto a remote machine:
 +
<source lang="bash">
 +
ssh -nNTR 2222:localhost:22 USER@SERVER
 +
</source>
 +
You can now ssh into the local machine from within the remote server on port 2222 instead.
 +
 
 +
Note that by default the forwarded port is only accessible locally, but you can change this behaviour with the ''GatewayPorts'' SSH option.
 +
 
 +
Lets say you're doing some maintenance on your site and you'd like to redirect all the requests on port 80 to another web-server (SERVER) on port 8080. You could set up your temporary web-server on 8080 on a remote server and then after you've stopped the local web-server, forward all requests for port 80 to 8080 on the remote machine with a local port-forward. By using the ''GatewayPorts'' option, the forwarded port 80 is available externally.
 +
<source lang="bash">
 +
ssh -nNTL 80:SERVER:8080 -o GatewayPorts=yes USER@SERVER
 +
</source>
 +
 
 +
This option can be useful for remote forwards too, for example what if we wanted our machine behind the firewall that we want accessible via SSH to be accessible externally? In this case we need to set the ''GatewayPorts'' option in ''sshd_config'' because it applies to the remote machine, not to the one running the command. If it's set to ''yes'' then the forwarded ports will be available externally as well, or you can set it to ''clientspecified'' to restrict the access to an external IP defined in the command:
 +
<source lang="bash">
 +
ssh -nNTR 1.2.3.4:2222:localhost:22 USER@SERVER
 +
</source>
 +
Now the host at ''1.2.3.4'' is able to SSH into our firewalled machine on port 2222 of USER@SERVER. See also [https://askubuntu.com/questions/48129/how-to-create-a-restricted-ssh-user-for-port-forwarding this] post regarding security for port-forwarding accounts.
 +
 
 +
=== Browsing the net through a remote server with SSH ===
 +
Sometimes you need to browse using an IP address that's in another location, for example if the content you want to access is only available to local users or if you're buying something and the prices are based on the buyers location. If you have access to a server in the required location, or someone you know in that location is willing to temporarily set up an SSH server that you can access, the you can use the following syntax to set up a local port that your browser can use as a proxy server.
 +
<source lang="bash">
 +
ssh -fnNTCD 1080 USER@SERVER
 +
</source>
 +
*The '''f''' option means to Fork off into the background after successful connection
 +
*The '''nNT''' options mean to use this SSH session only for tunnelling, prevent reading STDIN, no pseudo terminal and not to use open up a shell session.
 +
*The '''C''' option means to compress the data in the tunnel which is a good idea if you're on a slow connection
 +
*The '''D''' option is the main one that tells SSH to set up a tunnel connected to a local port with the port number specified
 +
 
 +
Next you need to configure your browser to connect via this local port. Chromium allows you to specify the proxy details as a command-line option, so there's no need to change the network configuration and then change it back afterwards. Simply open a shell window and use the following syntax (make sure there are no other Chromium windows open when you do this).
 +
<source lang="bash">
 +
chromium-browser --proxy-server="socks5://localhost:1080"
 +
</source>
 +
 
 +
In [[Firefox]] you need to change the '''Network Proxy''' setting in '''Preferences/General'''. The changes take effect instantly without needing a restart or anything, but you'll need to remember to change the setting back after the SSH connection is closed.
 +
 
 +
[[File:FF-proxy.jpg|400px]]
 +
</onlyinclude>
 +
 
 +
== Useful SSH options and switches ==
 +
*'''f:''' Fork off into the background after successful connection
 +
*'''ClientAliveInterval:''' Set this to the number of seconds of idle time allowed before a ping is sent to keep the connection alive.
 +
*'''GatewayPorts:''' Set to ''yes'' to open forwarded ports for external access instead of only being availabel to ''localhost'', set to ''clientspecified'' to restrict it to a specific IP addresses specified in the command.
 +
*Restrict the server user to only be allowed for port-forwarding by preceding their key with '''command="echo 'This account can only be used for port-forwarding'",no-agent-forwarding,no-X11-forwarding''' in their ''authorized_keys'' file.
 +
 
 +
== Key fingerprints, info and passwords ==
 +
It's common to see an RSA public key shown as just a fingerprint, e.g. ''eb:e9:47:99:b7:3b:46:fe:cf:73:04:ae:40:b8:3a:58''. To generate such a fingerprint from a public key file, do the following:
 +
<source lang="bash">
 +
ssh-keygen -E md5 -lf id_rsa.pub
 +
</source>
 +
 
 +
 
 +
To check what kind of key you have and how many bits long etc, use the following:
 +
<source lang="bash">
 +
ssh-keygen -l -f <PUBLIC_KEY_FILE>
 +
</source>
 +
 
 +
 
 +
To change the password of an existing RSA or DSA key:
 +
<source lang="bash">
 +
ssh-keygen -p -f ~/.ssh/id_dsa
 +
</source>
 +
 
 +
 
 +
Or for a GPG key:
 
<source lang="bash">
 
<source lang="bash">
openssl rsa -des3 -in your.key -out your.encrypted.key
+
gpg --list-keys
 +
gpg --edit-key <KEY-ID>
 +
gpg> passwd
 +
gpg> save
 
</source>
 
</source>
  
Line 23: Line 101:
 
chmod 644 /home/USER/.ssh/authorized_keys
 
chmod 644 /home/USER/.ssh/authorized_keys
 
</source>
 
</source>
 +
  
 
Restart the SSH server and test that you can login from another terminal window before exiting the current session. You now login as your own user, not the ''root'' user, and then use '''sudo bash''' to gain a ''root'' shell.
 
Restart the SSH server and test that you can login from another terminal window before exiting the current session. You now login as your own user, not the ''root'' user, and then use '''sudo bash''' to gain a ''root'' shell.
 
<source lang="bash">
 
<source lang="bash">
 
service ssh restart
 
service ssh restart
 +
</source>
 +
 +
== Enabling password-based logins ==
 +
Normally we'd go out of our way ti disable password login capability, but sometimes you need them temporarily. It's usually just a matter of setting ''PasswordAuthentication'' back to "yes", but it's important to note that password authentication also relies on ''ChallengeResponseAuthentication'', so you need to make sure that is set to "yes" as well. If it's not, then you can spend ages trying to figure out why it's not asking for a password even though "password" is in the list of methods to try!
 +
<source lang="bash">
 +
PasswordAuthentication yes
 +
ChallengeResponseAuthentication yes
 +
</source>
 +
 +
== Password-protect an existing private key ==
 +
To add a password to an existing private key, use the following ''openssl'' command:
 +
<source lang="bash">
 +
openssl rsa -des3 -in your.key -out your.encrypted.key
 +
</source>
 +
 +
== Creating a VPN with SSH ==
 +
This example is sourced from [https://www.perturb.org/display/770_OpenSSH_4_3_VPN_Example.html here], but [https://help.ubuntu.com/community/SSH_VPN this] looks better. OpenSSH has TUN/TAP support since version 4.3 (we're on 7.6 as of late 2018). This means that you can establish an encrypted virtual tunnel between two computers. This tunnel can be used to establish a VPN between these two networks. In the sample network you can establish an SSH connection to 55.56.57.58 but not the other two machines because they're firewalled off. Using an SSH VPN tunnel you can gain access to that entire network (anything that 55.56.57.58 would have access to). To clarify this is not SSH port forwarding. This is full IP forwarding using a tunnel interface.
 +
 +
This is done by creating a tunnel between your home PC (1.2.3.4) and the network gateway PC (55.56.57.58). This is done with the -w command in SSH.
 +
<source lang="bash">
 +
ssh -w0:0 55.56.57.58
 +
</source>
 +
This creates a tun0 interface on both ends of the SSH session.
 +
 +
Once the tunnel is established you will need to put an IP on both sides of the tunnel using the following commands.
 +
<source lang="bash">
 +
ifconfig tun0 10.0.2.1 netmask 255.255.255.252 # IP Address for your Home PC
 +
ifconfig tun0 10.0.2.2 netmask 255.255.255.252 # IP Address for the network gateway PC
 +
</source>
 +
'''Note:''' the ''PermitTunnel'' option must be turned on in your ''sshd_config'' file for this to work.
 +
 +
At this point you should be able to ping both sides of the tunnel from both machines. Now a little Linux routing knowledge comes in handy. You'll need two route statements to do this. One to force access to the network gateway PC to go out eth0 (or whatever your output device is), and the other to tell it to use tun0 for access to the rest of that subnet.
 +
<source lang="bash">
 +
route add -host 55.56.57.58 dev eth0 # tun0?
 +
route add -net 55.56.57.58/24 dev tun0
 +
</source>
 +
 +
Everything will route properly now, but the firewalled machines will not know how to get back to your home PC. A little NAT will fix that right up. You'll need to setup IP Forwarding and NAT on the network gateway PC to masquerade all requests from your home PC.
 +
<source lang="bash">
 +
echo 1 > /proc/sys/net/ipv4/ip_forward
 +
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
 +
</source>
 +
 +
== Troubleshooting ==
 +
=== expecting SSH2_MSG_KEX_ECDH_REPLY ===
 +
Try changing the MTU of the client to 1400 as follows (change ''eth0'' to the appropriate interface):
 +
<source lang="bash">
 +
sudo ip li set mtu 1400 dev eth0
 
</source>
 
</source>
  
 
== See also ==
 
== See also ==
 +
*[[Configure SSH]]
 
*[[SSL]]
 
*[[SSL]]
 
*[[Security]]
 
*[[Security]]
 
*[[Install a new server]]
 
*[[Install a new server]]
 +
*[https://www.digitalocean.com/community/tutorials/how-to-install-and-use-tmux-on-ubuntu-12-10--2 Using TMUX]
 
*[https://martin.kleppmann.com/2013/05/24/improving-security-of-ssh-private-keys.html RSA encrypted key details]
 
*[https://martin.kleppmann.com/2013/05/24/improving-security-of-ssh-private-keys.html RSA encrypted key details]
 +
*[https://blog.cryptographyengineering.com/2015/10/22/a-riddle-wrapped-in-curve/ Should we change our RSA keys to ed25519?]
 +
*[https://www.ssh.com/ssh/port How SSH got its port number]
 +
*[https://arstechnica.com/security/2024/04/what-we-know-about-the-xz-utils-backdoor-that-almost-infected-the-world/ What we know about the xz Utils backdoor that almost infected the world]

Latest revision as of 19:53, 4 April 2024

Ssh.jpg

Port forwarding with SSH

SSH allows you to forward ports on one machine to another using the SSH pipes.

For example, using a local port-forward, you could create a local connection into a remote SQL server that's not available to external connections if you have SSH access to machine with running the SQL server:

ssh -nNTL 3333:localhost:3306 USER@SERVER

Now you can access the database locally on port 3333.

Or in the opposite direction you can use a remote port-forward you could give SSH access to a machine that's behind a firewall or router by putting its SSH port onto a remote machine:

ssh -nNTR 2222:localhost:22 USER@SERVER

You can now ssh into the local machine from within the remote server on port 2222 instead.

Note that by default the forwarded port is only accessible locally, but you can change this behaviour with the GatewayPorts SSH option.

Lets say you're doing some maintenance on your site and you'd like to redirect all the requests on port 80 to another web-server (SERVER) on port 8080. You could set up your temporary web-server on 8080 on a remote server and then after you've stopped the local web-server, forward all requests for port 80 to 8080 on the remote machine with a local port-forward. By using the GatewayPorts option, the forwarded port 80 is available externally.

ssh -nNTL 80:SERVER:8080 -o GatewayPorts=yes USER@SERVER

This option can be useful for remote forwards too, for example what if we wanted our machine behind the firewall that we want accessible via SSH to be accessible externally? In this case we need to set the GatewayPorts option in sshd_config because it applies to the remote machine, not to the one running the command. If it's set to yes then the forwarded ports will be available externally as well, or you can set it to clientspecified to restrict the access to an external IP defined in the command:

ssh -nNTR 1.2.3.4:2222:localhost:22 USER@SERVER

Now the host at 1.2.3.4 is able to SSH into our firewalled machine on port 2222 of USER@SERVER. See also this post regarding security for port-forwarding accounts.

Browsing the net through a remote server with SSH

Sometimes you need to browse using an IP address that's in another location, for example if the content you want to access is only available to local users or if you're buying something and the prices are based on the buyers location. If you have access to a server in the required location, or someone you know in that location is willing to temporarily set up an SSH server that you can access, the you can use the following syntax to set up a local port that your browser can use as a proxy server.

ssh -fnNTCD 1080 USER@SERVER
  • The f option means to Fork off into the background after successful connection
  • The nNT options mean to use this SSH session only for tunnelling, prevent reading STDIN, no pseudo terminal and not to use open up a shell session.
  • The C option means to compress the data in the tunnel which is a good idea if you're on a slow connection
  • The D option is the main one that tells SSH to set up a tunnel connected to a local port with the port number specified

Next you need to configure your browser to connect via this local port. Chromium allows you to specify the proxy details as a command-line option, so there's no need to change the network configuration and then change it back afterwards. Simply open a shell window and use the following syntax (make sure there are no other Chromium windows open when you do this).

chromium-browser --proxy-server="socks5://localhost:1080"

In Firefox you need to change the Network Proxy setting in Preferences/General. The changes take effect instantly without needing a restart or anything, but you'll need to remember to change the setting back after the SSH connection is closed.

FF-proxy.jpg


Useful SSH options and switches

  • f: Fork off into the background after successful connection
  • ClientAliveInterval: Set this to the number of seconds of idle time allowed before a ping is sent to keep the connection alive.
  • GatewayPorts: Set to yes to open forwarded ports for external access instead of only being availabel to localhost, set to clientspecified to restrict it to a specific IP addresses specified in the command.
  • Restrict the server user to only be allowed for port-forwarding by preceding their key with command="echo 'This account can only be used for port-forwarding'",no-agent-forwarding,no-X11-forwarding in their authorized_keys file.

Key fingerprints, info and passwords

It's common to see an RSA public key shown as just a fingerprint, e.g. eb:e9:47:99:b7:3b:46:fe:cf:73:04:ae:40:b8:3a:58. To generate such a fingerprint from a public key file, do the following:

ssh-keygen -E md5 -lf id_rsa.pub


To check what kind of key you have and how many bits long etc, use the following:

ssh-keygen -l -f <PUBLIC_KEY_FILE>


To change the password of an existing RSA or DSA key:

ssh-keygen -p -f ~/.ssh/id_dsa


Or for a GPG key:

gpg --list-keys
gpg --edit-key <KEY-ID>
gpg> passwd
gpg> save

Disable password-based logins

If you want to restrict server logins to keys only, you can disable passwords for SSH access in /etc/ssh/sshd_config:

AllowUsers fred bob sam
PermitRootLogin no
RSAAuthentication yes
PubkeyAuthentication yes
PasswordAuthentication no


And don't forget to add your public RSA key to '~/.ssh/authorized_keys. Note that you'll probably need to create the directory since the account has just been created, and the owner and mode is important.

mkdir /home/USER/.ssh
echo "RSA_KEY" > /home/USER/.ssh/authorized_keys
chown USER:USER -R /home/USER/.ssh
chmod 644 /home/USER/.ssh/authorized_keys


Restart the SSH server and test that you can login from another terminal window before exiting the current session. You now login as your own user, not the root user, and then use sudo bash to gain a root shell.

service ssh restart

Enabling password-based logins

Normally we'd go out of our way ti disable password login capability, but sometimes you need them temporarily. It's usually just a matter of setting PasswordAuthentication back to "yes", but it's important to note that password authentication also relies on ChallengeResponseAuthentication, so you need to make sure that is set to "yes" as well. If it's not, then you can spend ages trying to figure out why it's not asking for a password even though "password" is in the list of methods to try!

PasswordAuthentication yes
ChallengeResponseAuthentication yes

Password-protect an existing private key

To add a password to an existing private key, use the following openssl command:

openssl rsa -des3 -in your.key -out your.encrypted.key

Creating a VPN with SSH

This example is sourced from here, but this looks better. OpenSSH has TUN/TAP support since version 4.3 (we're on 7.6 as of late 2018). This means that you can establish an encrypted virtual tunnel between two computers. This tunnel can be used to establish a VPN between these two networks. In the sample network you can establish an SSH connection to 55.56.57.58 but not the other two machines because they're firewalled off. Using an SSH VPN tunnel you can gain access to that entire network (anything that 55.56.57.58 would have access to). To clarify this is not SSH port forwarding. This is full IP forwarding using a tunnel interface.

This is done by creating a tunnel between your home PC (1.2.3.4) and the network gateway PC (55.56.57.58). This is done with the -w command in SSH.

ssh -w0:0 55.56.57.58

This creates a tun0 interface on both ends of the SSH session.

Once the tunnel is established you will need to put an IP on both sides of the tunnel using the following commands.

ifconfig tun0 10.0.2.1 netmask 255.255.255.252 # IP Address for your Home PC
ifconfig tun0 10.0.2.2 netmask 255.255.255.252 # IP Address for the network gateway PC

Note: the PermitTunnel option must be turned on in your sshd_config file for this to work.

At this point you should be able to ping both sides of the tunnel from both machines. Now a little Linux routing knowledge comes in handy. You'll need two route statements to do this. One to force access to the network gateway PC to go out eth0 (or whatever your output device is), and the other to tell it to use tun0 for access to the rest of that subnet.

route add -host 55.56.57.58 dev eth0 # tun0?
route add -net 55.56.57.58/24 dev tun0

Everything will route properly now, but the firewalled machines will not know how to get back to your home PC. A little NAT will fix that right up. You'll need to setup IP Forwarding and NAT on the network gateway PC to masquerade all requests from your home PC.

echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Troubleshooting

expecting SSH2_MSG_KEX_ECDH_REPLY

Try changing the MTU of the client to 1400 as follows (change eth0 to the appropriate interface):

sudo ip li set mtu 1400 dev eth0

See also