made minor adjustments to ssh port forwarding guide

This commit is contained in:
davidovski 2022-01-17 20:17:40 +00:00
parent d286833b1e
commit e9532e8173
1 changed files with 24 additions and 9 deletions

View File

@ -1,6 +1,8 @@
# Permanent SSH Forwarding (Tutorial)
Take this situation: you have a cheap (or even free), low-powered remote server and a considerably better homeserver with more storage and power. For certain services that require more power, you'd obviously want to run them on that homeserver. However, what if you don't want to, *or can't*, directly open ports onto your home network, or you if you simply want to keep all of your site on one IP? This is where SSH port forwarding comes in handy: using ssh to forward the open port from a service from your local server to the remote one, where it can be exposed to the rest of the internet.
Take this situation: you have a cheap (or even free), low-powered remote server and a considerably better homeserver with more storage and power. For certain services that require more power, you'd obviously want to run them on that homeserver.
However, what if you don't want to, *or can't*, directly open ports onto your home network, or you if you simply want to keep all of your site to one IP? This is where SSH port forwarding comes in handy: using ssh to forward the open port from a service from your local server to the remote one, where it can be exposed to the rest of the internet.
...
@ -12,19 +14,28 @@ SSH remote port forwarding is built right into ssh itself, and is quite simple:
ssh -R 5505:localhost:4404 user@remote.host
```
When this command is run on the local server, it will create an ssh connection to the remote server, as per usual. Additionally, it will open the port 5505 on the remote server, which will forward all traffic to port 4404 on the local server. This command by itself is already everything you'd need to forward most ports easily to your remote server, of course, remember to open the port on your remote server's firewall, if applicable.
When this command is run on the local server, it will:
+ create an ssh connection to the remote server, as per usual
+ open the port 5505 on the remote server,
+ all traffic on this port will be forwarded to port 4404 on the local server.
However to ensure that that port is exposed properly on the remote server, you'd want to make sure that it is listening to all external traffic. You can fix this by setting `GatewayPorts yes` in `/etc/ssh/sshd_config` on the remote server. (don't forget to restart sshd after editing the config)
This command by itself is already everything you'd need to forward most ports easily to your remote server, of course, remember to open the port on your remote server's firewall, if applicable.
However to ensure that that port is exposed properly on the remote server, you'd want to make sure that it is listening to all external traffic.
You can fix this by setting `GatewayPorts yes` in `/etc/ssh/sshd_config` on the remote server. (don't forget to restart sshd after editing the config)
## Persistent ssh forwarding
The above is all well and good, but you'd need to keep an interactive ssh connection up at all times (not impossible with a tool like `screen` or `tmux`), so it isn't the most ideal solution. To get around this, you can create a service to run on the local server to forward requested ports to the remote server.
The above is all well and good, but you'd need to keep an interactive ssh connection up at all times, so the above isn't the most ideal solution.
To begin, I'd recommend creating two users, one on each server. For sake of example, lets all them `bridge`, though any other names like `tunnel` or whatever would work too. I'd recommend to avoid giving these users passwords, that way they can only be signed in through key based authentication. Of course you will still be able to log into them as root using `su - bridge`
To get around this, you can create a service to run on the local server to forward requested ports from the remote server.
Next you should create an ssh keypair on the local server(`ssh-keygen`) and place the contents of your public key into `.ssh/authorized_keys`. This will make sure that only the local server will be able to ssh into the remote using that key.
To begin, I'd recommend creating two users, one on each server. For sake of example, lets all them `bridge`. I'd recommend to avoid giving these users passwords, that way they can only be accessed through key based authentication. Of course you will still be able to log into them as root using `su - bridge`
Then, create a script for your ssh port forwarding. I placed mine directly in the home folder of my bridge user of my local server, though it only matters that the bridge user can execute it. In your script you *must* use the `-nT` flag on your ssh command. These will allow you to run this script as a service, by preventing a virtual terminal being allocated. (read `man ssh` for more info)
Next you should create an ssh keypair on the local server (`ssh-keygen`) and place the contents of your public key into `.ssh/authorized_keys` on the remote. This will make sure only the local server can ssh into the remote using that key.
Then, create a script for your ssh port forwarding. I placed mine directly in the home folder on my local server, though it only matters that the bridge user can execute it. In your script you *must* use the `-nT` flag on your ssh command. These will allow you to run this script as a service, by preventing a virtual terminal being allocated. (read `man ssh` for more info)
Here is my example of a script that you could use:
@ -61,11 +72,15 @@ Then enable and start the service with: `systemd --user enable tunnel.service` a
## Forwarding ports smaller than 1024
As you may know, TCP/IP port numbers below 1024 are special in that normal users are not able to open, and hence forward from on the remote server. To bypass this, you can change your services to run at different ports, though this may not always be possible, for example with ports 80 and 443 for http and https respectively. One solution to this is run a server on the remote that will proxy requests from port 80 to a different port (say port 8080).
As you may know, TCP/IP port numbers below 1024 are special in that normal users are not able to open, and hence forward from on the remote server.
One solution to this is run a server on the remote that will proxy requests from port 80 to a different port (say port 8080).
This can be achieved using `socat`.
Say you forwarded traffic from port 8080 on the remote to port 80 on the local, you could then, on the remote server run `sudo socat TCP-LISTEN:80,fork TCP:localhost:8080` to listen to traffic on port 80 and forward it to 8080, which will forward back to the local server. Here is an example of this in practice, forwarding port 80 and 443, by forwarding ports 8080 and 8443:
Say you forwarded traffic from port 8080 on remote to port 80 on local, you could then, on the remote server, run `sudo socat TCP-LISTEN:80,fork TCP:localhost:8080` to listen to traffic on port 80 and forward it to 8080, which will forward back to the local server.
Here is an example of this in practice, forwarding port 80 and 443, by forwarding ports 8080 and 8443:
/usr/bin/ssh -nT -R 8443:localhost:443 -R 8080:localhost:80 -i $IDENTITY_FILE -p $SSH_PORT $DEST "(sudo socat TCP-LISTEN:80,fork TCP:localhost:8080) & sudo socat TCP-LISTEN:443,fork TCP:localhost:8443"