LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices


Reply
  Search this Thread
Old 12-10-2014, 12:12 PM   #1
aristosv
Member
 
Registered: Dec 2014
Posts: 263

Rep: Reputation: 3
Reverse SSH Tunnel Question


I have a Linux machine behind a firewall. I found that if I use Reverse SSH Tunnel I am able to access it without opening ports on the Firewall. So I tried it like shown below and it works.

Code:
server$ ssh -R 9091:localhost:22 client.example.egg
client$ ssh -p 9091 localhost
My problem is that when the Linux machine is restarted, the server$ command has to be entered again, in order for me to be able to access it from the client$

I could put the command in cron @reboot, but it prompts for a password.

Is there a way I can automate this thing?

Thanks
 
Old 12-10-2014, 12:50 PM   #2
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
You need to set up passwordless ssh keys from the server to the client.

On the server:
Code:
$ ssh-keygen -t dsa # keep pressing enter until you get back to the command prompt
$ cat ~/.ssh/id_dsa.pub | ssh user@client "cat - >> ~/.ssh/authorized_keys"
On the client:
Code:
$ chmod 750 ~
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys
Once you've done this, you should be able to ssh from the server to the client without entering a password, which will let the server set up its own reverse ssh tunnel back to the cilent.

However, if you need this to be reliable, then you can't stop there. What happens if there's a network interruption and the connection breaks, or if you reboot the client? I have a few systems that do what you're planning on here, and I wrote a small bash script that records the PID of the ssh process and keeps tabs on it, restarting it if it ever goes down. I also an option to the ssh command to make sure it fails on error, instead of hanging.

The whole thing looks something like this:
Code:
#!/bin/bash

user=$1
rip=$2
rport=$3
lport=$4

while [[ 1 ]]; do
   if [ -e $HOME/$lport.pid ]; then
      pid=$(cat $HOME/$lport.pid)
   else
      pid=1
   fi

   ps | grep $lport | grep $pid | grep -v rssh_tunnel | grep -q ssh
   if [[ $? -ne 0 ]]; then
      echo $(date) opening reverse tunnel from $rip:$rport to 127.0.0.1:$lport
      ssh -o "ExitOnForwardFailure yes" -R $rport:127.0.0.1:$lport $user@$rip -N &
      echo $! > $HOME/$lport.pid
   fi

   sleep 60
done
And you call it like:
Code:
nohup rssh_tunnel user remoteIP remotePort localPort &> $HOME/rssh.out &

Last edited by suicidaleggroll; 12-10-2014 at 12:56 PM.
 
1 members found this post helpful.
Old 12-10-2014, 01:25 PM   #3
aristosv
Member
 
Registered: Dec 2014
Posts: 263

Original Poster
Rep: Reputation: 3
Thanks for all the info. How will my command change if i have multiple servers behind firewalls connecting to my client? Will changing the port number be enough?
 
Old 12-10-2014, 01:34 PM   #4
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
You just need to change the port to use on the client.

edit: of course you'll also need to repeat the two "server" steps I mentioned (ssh-keygen and cat | ssh) for each machine that needs to log into the client without a password. The chmod commands that are run on the client only need to be done once after the first authorized_keys entry has been made.

Last edited by suicidaleggroll; 12-10-2014 at 01:47 PM.
 
Old 12-11-2014, 11:22 AM   #5
aristosv
Member
 
Registered: Dec 2014
Posts: 263

Original Poster
Rep: Reputation: 3
I must be doing something wrong with this process.

I run the command below, to create the keys

On machine1, which is behind the firewall I run this:
Code:
$ ssh-keygen -t dsa # keep pressing enter until you get back to the command prompt
$ cat ~/.ssh/id_dsa | ssh root@my.remote.host "cat - >> ~/.ssh/authorized_keys"
On machine2, which is my machine I run this:
Code:
$ chmod 750 ~
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys
Then on machine1 I run this to create the tunnel.
Code:
ssh -R 5001:localhost:22 root@my.remote.host
Then on machine2 I run this:
Code:
/usr/bin/ssh root@localhost -p 5001
And I connect on machine 1 from machine 2 successfully!

My problem is that, as soon as I close the terminal on the machine 1, the connection is dropped.

So I though I would add this command on a startup script on machine 1, so it will run at startup and create the tunnel on boot.

Code:
ssh -R 5001:localhost:22 root@my.remote.host
The issue is that it prompts for a password. And the whole idea of creating the keys is not to use passwords, correct?

What did I do wrong?

Last edited by aristosv; 12-11-2014 at 11:27 AM.
 
Old 12-11-2014, 12:04 PM   #6
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
Four things

1) You can't just run "ssh -R 5001:localhost:22 root@my.remote.host". This will run ssh in the foreground, which is why as soon as you close the terminal it disconnects. If you want to be able to launch it in the background then you need to use nohup.

2) I don't understand why it prompts you for a password the second time but not the first. It's the exact same command. Are you running it as the same user?

3) Did you miss the second half of my post? Sticking a single ssh command in a script at startup is not sufficient. As soon as you get a network interruption or the client machine is restarted, the connection will drop, and you will have no way of getting it back. This is why I posted that script to babysit the connection and re-open it if it ever closes.

4) You should NOT be connecting to root on the client machine to set up the tunnel! Connect to an unprivileged user, preferably one inside a chroot jail. You shouldn't even be able to ssh into EITHER of these machines as root, period, much less with passwordless ssh keys.

Last edited by suicidaleggroll; 12-11-2014 at 12:08 PM.
 
Old 12-11-2014, 12:31 PM   #7
aristosv
Member
 
Registered: Dec 2014
Posts: 263

Original Poster
Rep: Reputation: 3
1. What if i use -f? Will the result be the same?

2. It prompts for a password the first time also. Sorry i didnt mention that.

3. I am not worried about network interruptions. The remote machine is automatically rebooted every 24 hours, so if it gets disconnected, it should be ok again on reboot. Plus, the services its running, dont depend on the tunnel im creating. The tunnel is just in case i need to connect, to configure something new, maybe once a month.

4. I understand that i should not be using the root user, but these machines im trying to tunnel dont host any critical data. Plus, currently im just doing a proof of concept. The final configuration on these machines will propably not use the root user.

I just need to add something to the startup scrpts im running on these machines, to get the tunnel up and running. Ive also looked into sshpass, but im not sure it can create the tunnel. If it did though, it would be a simpler solution i think.
 
Old 12-11-2014, 12:36 PM   #8
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
1) Why don't you try it and see? I don't recall if ssh's built in "background" flags will allow you to close the terminal without severing the connection.

2) Then something is off in the key exchange. It could be that your client is not configured to allow ssh keys, or something else. Ignore the reverse tunnel for now and just use regular ssh connections until you get the password issue sorted out. You can try adding -vvv to the ssh command to print verbose debugging information, and look at /var/log/secure (or equivalent) on the client.

Actually nevermind, the command you ran is not the same as the one I posted. It needs to be
Code:
$ cat ~/.ssh/id_dsa.pub | ssh user@client "cat - >> ~/.ssh/authorized_keys"
NOT
Code:
$ cat ~/.ssh/id_dsa | ssh root@my.remote.host "cat - >> ~/.ssh/authorized_keys"
You need to send the public key (the id_dsa.pub file), not the private key. Clear out that entry in your client's authorized_keys file and copy the public one over instead.

You haven't told us yet what distro(s) you're using. The proper way of adding a command at startup can vary dramatically between different distros and even different versions of the same distro.

Last edited by suicidaleggroll; 12-11-2014 at 12:38 PM.
 
Old 12-11-2014, 12:41 PM   #9
aristosv
Member
 
Registered: Dec 2014
Posts: 263

Original Poster
Rep: Reputation: 3
I would love to try and see, but I don't have access on the remote machine, since I couldn't get the tunnel up and running. So I have to wait until tomorrow, when someone get's in the office, so they can run the command for me

I have a very small working window every day, so I am trying to gather as much information as I can before trying again. I'll give it a try with the -vvv option, to try and figure out what's wrong.

The distro's are both debian.
 
Old 12-11-2014, 12:53 PM   #10
descendant_command
Senior Member
 
Registered: Mar 2012
Posts: 1,878

Rep: Reputation: 644Reputation: 644Reputation: 644Reputation: 644Reputation: 644Reputation: 644
The autossh package might be of use.
 
Old 12-12-2014, 08:16 AM   #11
allend
LQ 5k Club
 
Registered: Oct 2003
Location: Melbourne
Distribution: Slackware64-15.0
Posts: 6,409

Rep: Reputation: 2775Reputation: 2775Reputation: 2775Reputation: 2775Reputation: 2775Reputation: 2775Reputation: 2775Reputation: 2775Reputation: 2775Reputation: 2775Reputation: 2775
Quote:
I would love to try and see, but I don't have access on the remote machine, since I couldn't get the tunnel up and running. So I have to wait until tomorrow, when someone get's in the office, so they can run the command for me
The trick here is to have a cron job that runs a script to set up the reverse secure shell tunnel. NB. Root privileges are required for this.
The script I use to connect to my home machine via a dynamic DNS address is shown below. It is adapted from that shown here. http://www.brandonhutchinson.com/ssh_tunnelling.html
(I really should get around to changing from using 'netstat' to using 'ss'.)
Code:
#!/bin/sh

# Script to start a reverse ssh tunnel to a remote host
# It is intended that this script runs periodically as a cron job.

# $REMOTE_USER is the user name on the remote system
REMOTE_USER=<remote user name>
# $REMOTE_HOST is the name of the remote system
REMOTE_HOST=<remote host name>
# command to get REMOTE_HOST IP - Internal DNS can be slow to update
REMOTE_HOST_IP=$(dig @8.8.8.8 $REMOTE_HOST +short)
# $REMOTE_CONNECT_PORT is the port number to connect to on the remote system
REMOTE_CONNECT_PORT=<port on remote host that accepts SSH connection>
# $REMOTE_LOGIN_PORT is the remote port number that will be used to tunnel
# back to this system
REMOTE_LOGIN_PORT=<port on local host that accepts remote SSH connection>
# $ID_FILE is the identity file on local host to use to authenticate
ID_FILE="/path/to/id_file"

# $COMMAND is the command used to create the reverse ssh tunnel
COMMAND="ssh -q -N -f -p $REMOTE_CONNECT_PORT -R :$REMOTE_LOGIN_PORT:localhost:22 -o ServerAliveInterval=60 -o TCPKeepAlive=no -i $ID_FILE $REMOTE_USER@$REMOTE_HOST_IP"

# Is the tunnel up? Perform two tests:

# 1. Check for relevant process ($COMMAND)
pgrep -fx "$COMMAND" || $COMMAND

# 2. Test tunnel by looking at "netstat" output on $REMOTE_HOST
ssh -p $REMOTE_CONNECT_PORT -i $ID_FILE $REMOTE_USER@$REMOTE_HOST_IP 'netstat -atn' 2>&1 \
  | grep "tcp.*:$REMOTE_LOGIN_PORT.*LISTEN" \
  > /dev/null
if [ $? -ne 0 ] ; then
   pkill -fx "$COMMAND"
   $COMMAND
fi
 
1 members found this post helpful.
Old 02-01-2015, 09:47 AM   #12
aristosv
Member
 
Registered: Dec 2014
Posts: 263

Original Poster
Rep: Reputation: 3
@suicidaleggroll

This is working perfectly. I set everything up as per your instructions and now I have a tunnel, and even if one of the two machines is restarted, the tunnel is re-established. Thanks for that.

Today for the first time I did a "more rssh.out" and it showed me the following:

Code:
Sun Feb 1 17:44:02 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Like I said, its working, but I am worried if this error will cause an issue in the future.
Any ideas on what could be causing this error?

Thanks
 
Old 02-02-2015, 11:35 AM   #13
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
Usually that error means the port is already open. Were you trying to open a second tunnel with the same port? Perhaps the first tunnel (from before a reboot maybe) hadn't closed on the server side yet?
 
Old 02-02-2015, 12:07 PM   #14
aristosv
Member
 
Registered: Dec 2014
Posts: 263

Original Poster
Rep: Reputation: 3
I wasn't trying to create a tunnel manually. I don't know if the script is trying on reboot. How can i troubleshoot this? It seems that its trying every one minute.

Code:
Mon Feb 2 19:52:33 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Mon Feb 2 19:53:51 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 19:54:51 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 19:55:51 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 19:56:52 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 19:57:52 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 19:58:52 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 19:59:52 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 20:00:52 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 20:01:53 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 20:02:53 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 20:03:53 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
Mon Feb 2 20:04:53 EET 2015 opening reverse tunnel from my_host_here:5001 to 127.0.0.1:22
Error: remote port forwarding failed for listen port 5001
 
Old 02-02-2015, 01:01 PM   #15
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
What is the script you are using? It appears to be trying to re-open the tunnel every minute, even though it has already been successfully opened. The script I posted earlier has a ps command to check if the tunnel is already open, this check is apparently failing on your machine. It's probably because that ps command is grepping for the name of the script itself, so if you named your script differently and didn't update the ps command it will fail.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
SSH Reverse Tunnel - ~/.ssh/config - PHP marcelp1 Linux - Newbie 1 05-28-2014 12:49 AM
[SOLVED] ssh reverse tunnel vib150 Linux - Networking 16 10-27-2013 09:22 PM
[SOLVED] Reverse SSH tunnel edan Linux - Security 3 07-14-2010 09:37 PM
SSH reverse tunnel (lo only? why not eth0) Dinomight Linux - Networking 3 08-17-2006 09:44 PM
Reverse SSH Tunnel sniggleflop Linux - Security 1 10-13-2002 01:24 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 12:58 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration