How to use SSH for various administrative tasks
With SSH many are familiar for a long time, but, like we, not everyone suspects about what opportunities are hidden behind these magical three letters. I would like to share my little experience of using SSH to solve various administrative tasks.
Table of contents:
- Local TCP forwarding
- Remote TCP forwarding
- TCP forwarding chain through several nodes
- TCP forwarding ssh connection
- SSH VPN Tunnel
- Briefly about non-password access
- Conclusion (links)
1) Local TCP forwarding
Let’s start with a simple – local TCP forwarding:
If on “host1” Windows
We have a remote server “host2” with some application, say, a PostgreSQL server that accepts TCP connections on port 5432. It is quite logical that this server is equipped with a firewall that does not allow direct connections from outside to port 5432, but there is Access via SSH (by default port 22, I recommend changing it. It is required to connect from our workplace “host1” client application to the PostgreSQL server on “host2”.
To do this, type “host1” in the console:
Host1 # ssh -L 9999: localhost: 5432 host2
Now on “host1” we can connect to the PostgreSQL server via local port 9999:
host1# psql -h localhost -p 9999 -U postgres
For example, in PuTTy this is done like this:
Go to the settings tree: Connection → SSH → Tunnels.
Next, in the “Source port” field, drive 9999, in the “Destination” – localhost: 5432, and click Add.
Do not forget to save the session settings, if necessary.
- How it works
After successfully connecting to the SSH server on host2, on host1, the SSH client starts listening on port 9999. When connecting to port 9999 to host1, the SSH server on host2 establishes a connection to localhost (which is for Itself “host2”) to port 5432 and transmits over this connection the data received by the ssh client to “host1” on port 9999.
IMPORTANT! All the connections shown in the diagrams are separate TCP connections (sessions).
Port forwarding, as a rule, is already included in the ssh default settings.
/ Etc / ssh / sshd_config:
AllowTcpForwarding yes
- We can also connect to the application not on the “host2” itself, but on any machine available to it:
To do this, when port forwarding, instead of “localhost”, specify the host name, for example, “host3”:
Host1 # ssh -L 9999: host3: 5432 host2
It is important to note here that “host3” should be known (if it’s a name, not an IP address) and is available for the host2 machine.
- You can also give access to any other host (via “host1A”) to the service on “host3” through “host1”:
To do this, you need to insert the IP address of the interface on the ssh connection command on which the local port 9999 will be raised:
Ssh -L 0.0.0.0:9999:host3:5432 host2
In this example, port 9999 will be opened on all interfaces available on the “host1” IPv4.
2) Remote TCP forwarding
But what if, for example, “host2” does not have a white IP address, is it behind NAT or are all its incoming connections closed? Or, for example, on “host2” is Windows and there is no way to put an SSH server?
- For this case, there is Remote TCP forwarding:
Now we need to establish an ssh connection in the opposite direction – from “host2” to “host1”. Those. Our administrative workstation will be an SSH server and will be accessible via SSH with “host2”, and on “host2” you will need to connect to the SSH client:
Ssh -R 9999: localhost: 5432 host1
If on “host2” Windows
For example, in PuTTy this is done like this:
Go to the settings tree: Connection → SSH → Tunnels.
Next, in the “Source port” field, drive 9999, in the “Destination” – localhost: 5432, and below select “Remote”, and click Add.
Do not forget to save the session settings, if necessary.
- How it works
After a successful connection, the SSH server starts listening on port 9999 on host1. When connecting to port 9999 to host1, the SSH client on host2 establishes a connection to localhost (which is host2 itself) to port 5432 and transmits over this connection the data received by the ssh server on “host1” to port 9999.
Also, you will have additional security problems with “host1” if you do not trust the host2 node. However, this is beyond the scope of this article.
And, of course, you somehow (by yourself or with help) should initiate the ssh connection from host2 by typing the above command, and host1 should have a white IP address and an open port of SSH.
After installing the ssh connection, everything works in the same way as the previous chapter.
3) TCP forwarding chain through several nodes
In closed networks, it often happens that the site we need is not directly accessible. Those. We can go to the desired host only on a chain, for example, host1 → host2 → host3 → host4:
Host1 # ssh host2 Host2 # ssh host3 Host3 # ssh host4 Host4 # echo hello host4
This can happen, for example, if these nodes are gateways, or if gateways are only available to neighbor subnets.
- In this case, we can also do TCP forwarding along the chain:
Here ports 9991, 9992, 9993 are chosen for clarity, in practice, one can use the same port (for example, 9999) if it is free on all nodes.
- Total you need to execute the following chain of commands:
Host1 # ssh -L 9991: localhost: 9992 host2
Host2 # ssh -L 9992: localhost: 9993 host3
Host3 # ssh -L 9993: localhost: 5432 host4
- How it works
After successful execution of the above commands, the following is performed on the nodes:
- On “host1”: port 9991 opens, when connected to, the data is redirected via the ssh connection to port 9992 to “host2”;
- On “host2”: opens port 9992, when connected to, the data is redirected via ssh connection to port 9993 to “host3”;
- On “host3”: opens port 9993, when connected to, the data is redirected via ssh connection to port 5432 to “host4”;
Thus, when connecting to port 9991 to “host1”, the data is redirected along the chain to “host4” on port 5432.
IMPORTANT! All the connections shown in the diagrams are separate TCP connections (sessions).
4) TCP forwarding ssh connection
Sometimes you need to connect to ssh with a server that is not directly accessible, and access is possible only through the chain of ssh servers (see the previous chapter). Now we have the necessary knowledge to do the following:
Host1 # ssh -L 2222: localhost: 2222 host2 Host2 # ssh -L 2222: host4: 22 host3
Thus, on port 2222 on “host1”, we now have forwarded to port SSH (22) to “host4”. We can connect:
Host1 # ssh -p 2222 localhost Host4 # echo hello host4
It would seem, why is it needed? For example, here’s why:
# Copy the file to host4 Host1 # scp -P 2222 / local / path / to / some / file localhost: / path / on / host4 # Copy the file from host4 Host1 # scp -P 2222 localhost: / path / on / host4 / local / path / to / some / file # Make another great TCP forwarding on host4 Host1 # ssh -p 2222 -L 9999: localhost: 5432 localhost Host1 # psql -h localhost -p 9999 -U postgres # Note that the port for the ssh command is given by the -p switch in lowercase, # And for the scp -P command in uppercase
Well, in general, great that now “host4” is so close
Conclusion: you can do TCP forwarding a large level of nesting.
Remarks about RSA fingerprint
In some cases, SCP does not work until you first go through ssh -p 2222 localhost and do not accept the RSA fingerprint of the remote server.
If you use the same port (2222) to access different remote servers, there will be errors RSA fingerprint, which remained from the previous server. It will need to be removed from ~ / .ssh / known_hosts.
5) SSH VPN Tunnel
TCP port forwarding is a great opportunity. But what if we need more? Access via UDP, access to multiple ports and hosts, access to dynamic ports? The answer is obvious – VPN. And almighty SSH since version 4.3 and here will come to our rescue.
Running ahead I will say: this SSH functionality works well if you need a temporary solution for some administrative tasks. To build a persistent VPN, this option is far from the most suitable, because it assumes TCP-over-TCP, which will have a bad effect on the connection speed.
More about TCP forwarding
TCP port forwarding with SSH, if it is sufficient, will in many cases benefit from VPN performance, since TCP port forwarding transfers only application data, not the source packets, along with the headers, see the link: http://blog.backslasher.net/ssh-openvpn-tunneling.html
Configuring the SSH server:
PermitTunnel in the sshd settings is disabled by default, it should be included in / etc / ssh / sshd_config:
PermitTunnel yes
or
PermitTunnel point-to-point
IMPORTANT: superuser rights are required to raise the new network interface of the tunnel and on the ssh client and on the ssh server. You can argue for a long time about how unsafe, but in most cases, on the ssh-server, it’s enough to configure:
PermitRootLogin without-password
Thus, you can not log in as root with a password, but only by other means, for example, by using the RSA key, which is much safer.
Restart sshd:
Sudo service sshd restart # centos
or
/etc/init.d/ssh restart # (debian / ubuntu)
The tunnel rises when using the magic key -w:
Host1 # sudo ssh -w 5: 5 root @ host2
Where 5: 5 – the number of the interface on the local machine and on the remote, respectively. Here, you may be confused that ifconfig does not display “tun5” in the interface list. This is because it is in a “down” state, but if you call “ifconfig -a” or “ifconfig tun5”, then the interface will be visible:
Host1 # ifconfig tun5 Tun5 Link encap: UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 POINTOPOINT NOARP MULTICAST MTU: 1500 Metric: 1 RX packets: 0 errors: 0 dropped: 0 overruns: 0 frame: 0 TX packets: 0 errors: 0 dropped: 0 overruns: 0 carrier: 0 Collisions: 0 txqueuelen: 500 RX bytes: 0 (0.0 b) TX bytes: 0 (0.0 b)
Assign interfaces to IP addresses and raise them:
Host1 # sudo ifconfig tun5 192.168.150.101/24 pointopoint 192.168.150.102 Host2 # sudo ifconfig tun5 192.168.150.102/24 pointopoint 192.168.150.101
If there is a firewall, do not forget to allow connections from the interface tun5:
Host1 # # save the original firewall rules Host1 # sudo iptables-save> /tmp/iptables.rules.orig Host1 # sudo iptables -I INPUT 1 -i tun5 -j ACCEPT Host2 # # save the original firewall rules Host2 # sudo iptables-save> /tmp/iptables.rules.orig Host2 # sudo iptables -I INPUT 1 -i tun5 -j ACCEPT
On host1, this is not necessary, here it is only done so that ping works in both directions.
Enjoying the ping:
Host1 # ping 192.168.150.102 Host2 # ping 192.168.150.101
If we consider an earlier example with PostgreSQL, then now the scheme will be:
And the command to connect to the PostgreSQL server will look like this:
Host1 # psql -h 192.168.150.102 -U postgres
Well and further it is possible to do any of these sites by a gateway if it is necessary to provide access not to one node, but to a network. For example:
Host2 # # resolve IP forwarding Host2 # sudo sysctl -w net.ipv4.ip_forward = 1 Host2 # # resolve IP forwarding with host1 Host2 # sudo iptables -I FORWARD 1 -s 192.168.150.101 -j ACCEPT Host2 # # resolve IP forwarding to host1 Host2 # sudo iptables -I FORWARD 1 -d 192.168.150.101 -j ACCEPT Host2 # # mask the IP address host1 Host2 # sudo iptables -t nat -A POSTROUTING -s 192.168.150.101 -j MASQUERADE Host1 # # Suppose host2 has access to the 192.168.2.x network, where we need to get from host1 Host1 # # Register host2 as a gateway to the network 192.168.2.x Host1 # sudo ip route add 192.168.2.0/24 via 192.168.150.2 Host1 # # Enjoying network access with host1 Host1 # ping 192.168.2.1
After the end of the work, do not forget to return net.ipv4.ip_forward and the firewall to its original state.
Host1 # sudo iptables-restore </tmp/iptables.rules.orig Host2 # sudo iptables-restore </tmp/iptables.rules.orig
Under the spoiler, a more interesting case with a temporary Internet expanding.
Suppose you need to configure the server in a closed network where Internet access is prohibited, but nevertheless, you have a loophole there – access through one ssh server or a chain of ssh servers. Suppose you need Internet access to configure the server. Then it’s easier to set up temporary access to the Internet on the server that needs to be configured than to ask the service staff to do it.
Suppose there is an access through ssh from your working machine host1 to server host2, from it – to host3, and already from there – to the host4 you need. Then do TCP forwarding for ssh (if with host1 you can connect to host4 right away, skip this step):
Host1 # ssh -L 2222: localhost: 2222 host2 Host2 # ssh -L 2222: host4: 22 host3
Next, connect to host4 and raise interface tun5:
Host1 # sudo ssh -p 2222 -w 5: 5 root @ localhost Host1 # # or if host4 is available immediately: sudo ssh -w 5: 5 root @ host4 Host1 # sudo ifconfig tun5 192.168.150.101/24 pointopoint 192.168.150.102 Host4 # sudo ifconfig tun5 192.168.150.102/24 pointopoint 192.168.150.101
We look at the routing table on host4, let’s see the following:
Host4 # route -n Kernel IP routing table Destination Gateway GenMask Flags Metric Ref Use Iface 192.168.150.0 0.0.0.0 255.255.255.0 U 0 0 0 tun5 192.168.56.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0 0.0.0.0 192.168.56.254 0.0.0.0 UG 0 0 0 eth0
IMPORTANT! Next, we most likely want to make the default route tun5 the interface with the gateway 192.168.150.101, through which the Internet will be available. Therefore, at this stage, it is important to know exactly which routes to add to replace the default route. This is important because quite often the routes to individual networks are not registered separately, but simply specify the default route (0.0.0.0/0) with the gateway through which all the internetworking traffic passes. Moreover, it is likely that your ssh connection to the server also uses the default gateway.
For simplicity, in this example, suppose that there are no routes other than 192.168.56.0/24 for the server to function normally and that the previous ssh host host3 has an IP address from the same network.
Remember and write somewhere the original routing table with the default gateway:
Host4 # route -n> routes.orig
We configure our host1 to work as a gateway to the Internet for host4:
Host1 # # resolve IP forwarding Host1 # sudo sysctl -w net.ipv4.ip_forward = 1 Host1 # # save the original firewall rules Host1 # sudo iptables-save> /tmp/iptables.rules.orig Host1 # # resolve IP forwarding with host4 Host1 # sudo iptables -I FORWARD 1 -s 192.168.150.102 -j ACCEPT Host1 # # resolve IP forwarding to host4 Host1 # sudo iptables -I FORWARD 1 -d 192.168.150.102 -j ACCEPT Host1 # # mask the IP address host4 Host1 # sudo iptables -t nat -A POSTROUTING -s 192.168.150.102 -j MASQUERADE
We change the route by default on host4 (CAUTION, see warning above!):
Host4 # sudo ip route replace default via 192.168.150.101 Host4 # route -n Kernel IP routing table Destination Gateway GenMask Flags Metric Ref Use Iface 192.168.150.0 0.0.0.0 255.255.255.0 U 0 0 0 tun5 192.168.56.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0 0.0.0.0 192.168.150.101 0.0.0.0 UG 0 0 0 tun5
We check that there is the Internet:
Host4 # ping 8.8.8.8
Excellent. It remains to configure DNS. There are many ways to do this, the easiest way is to edit the /etc/resolve.conf file and add the lines there:
Nameserver 8.8.8.8 Nameserver 8.8.4.4
After that, the Internet should be fully accessible:
Host4 # ping ya.ru
After the termination of work we do not forget to return all in an initial condition:
Host1 # # restore firewall rules on host1 Host1 # sudo iptables-restore </tmp/iptables.rules.orig Host1 # # do not forget to restore also the value of net.ipv4.ip_forward Host2 # # restore the default route to host4: Host2 # sudo ip route replace defau
6) Briefly on access without a password
I think that everyone already knows that password authentication is not about us. But just in case, I’ll write a brief guide to setting up RSA authentication:
1. On the client computers, the user generates his own RSA key:
Client1 # ssh-keygen -t rsa
By default, the private key is stored in ~ / .ssh / id_rsa, and the public key is stored in ~ / .ssh / id_rsa.pub. Keep the secret key as the apple of your eye and do not give it to anyone, do not copy it anywhere.
When creating the key, you can set a password (passphrase), to which the key will be encrypted.
2. The public keys of the client should be stored on the ssh server in the ~ / .ssh / authorized_keys file (~ this is the user’s home directory that you will log into), each on a separate line. To not do this manually, on each client you can use the command:
Ssh-copy-id user @ sshserver
If the user is a username on the server, ssh server is the name or IP address of the ssh server.
File permissions ~ / .ssh / authorized_keys
3. Make sure that you can enter the server by key without entering a password (not to be confused with a passphrase):
Ssh user @ sshserver
I recommend not to close at least one active ssh session with the server until the final configuration is completed and make sure that everything works.
4. Disable the SSH server to enter the password in the / etc / ssh / sshd_config file:
PasswordAuthentication no
The ability to enter a public key is usually already enabled by default:
PubkeyAuthentication yes
Usually, I also disable the following two options:
GSSAPIAuthentication no UseDNS no
In some cases, this allows you to speed up the connection process (for example, when the server does not have Internet access).
5. Restart sshd:
Restarting the sshd service
or
Restarting /etc/init.d/ssh
In the case of errors, it is useful to view the log/var / log / secure or use the -v, –vv, or –vvv options to display a detailed log of the connection:
Ssh -vvv user @ sshserver
7) Links
help.ubuntu.com/community/SSH_VPN
blog.backslasher.net/ssh-openvpn-tunneling.html