SSH From the Inside
I need SSH access to a particulr machine (schoolsvr) which is behind a NAT. I only need to enable access from a single client (homesvr), which has a public IP address of its own. Both machines are running sshd. I can access homesvr from a shell on schoolsvr, but not vise-versa.
If I had admin access on schoolsvr’s gateway, I could alter the NAT to forward some unused port (say, 12345) to schoolsvr:22, which would allow me to SSH to schoolsvr using the gateway’s public IP and port 12345. Unfortunately, I dons’t have admin access to the gateway.
How do I enable SSH access to schoolsvr?
The solution is to open an SSH tunnel from schoolsvr, which I can access from
a shell on homesvr. To achieve this, I use the OpenSSH client program’s
option to bind an SSH tunnel to a non-standard port on homesvr. Consider the
nick@schoolsvr$ ssh -R 12345:localhost:22 nick@homesvr nick@homesvr's password: nick@homesvr$
This command connects to homesvr via the standard SSH port (22) and binds that connection to the specified bind port (12345). This port remains bound until the SSH session is terminated. Now all SSH traffic directed to port 12345 on homesvr will be forwarded to port 22. When I get back to homesvr, I can open a new SSH session with schoolsvr using the following command:
nick@homesvr$ ssh -p 12345 localhost nick@localhost's password: nick@schoolsvr$
I’m in! I can terminate this session when I am finished, and the original tunnel remains open until I kill it on schoolsvr.
This command can be set up in /etc/inittab (or an Upstart config file,
depending on your system configuration) with the
respawn action, which would
ensure that the tunnel is open upon boot and will be automatically reopened upon
termination. Note that such a setup requires the appropriate SSH keys to be
configured on both machines, as an init process can’t enter a password.
Because each half of the connection is done using SSH, this setup is completely secure. Of course, anyone with physical access to schoolsvr would have full control over the open login to homesvr. To prevent this, I can modify the original command as follows:
nick@schoolsvr$ ssh -nNT -R 12345:localhost:22 nick@homesvr &
-n option redirects standard input from /dev/null. The
-N option is
specifically designed for port-forwarding applications such as this, and tells
SSH not to bother preparing a command stream for this connection. The
option tells the remote host not to bother allocating a pseudo-tty for this
connection. These three options eliminate the possibility of using this open
tunnel to execute any other processes on schoolsvr. Additionally, I appended
an ampersand (
&) to send the process to the background. Now I can close the
shell in which I ran the command without killing the process.
While not as elegant as a true NAT-based port forwarding solution, reverse SSH tunnels are a fast, secure way to connect two remote machines for general use. When used with discretion, they can be a real time-saver.
What do you think of this solution? Did I leave anything out? Let me know in the comments.