Firslty my setup is an Ubuntu laptop and an Ubuntu server.

I have a program on my local laptop which needs to access a certain web-service, (lets call it http://someserver.com/someservice123). Now this service has a firewall which only allows access from my server's IP.

Is there some type of SSH tunnel I could use between my laptop and server so that when a python script on my laptop sends a request to http://someserver.com/someservice123 that service sees the request coming from my server's IP?

I know it would look something like:

ssh -N -R 80:localhost:80 user@myserver

but I'm not sure exactly.

  • You could use an SSH tunnel as others have suggested, and also edit your /etc/hosts file so that someserver.com resolves to – jwbensley Oct 30 '12 at 13:09

What you want is not a reverse tunnel but a regular tunnel.

ssh -L 80:someserver.com:80 user@myserver

This will create a listening socket on port 80 of your laptop (localhost) that will go to someserver.com through the SSH server on myserver.

I usually combine tunnels with the options -CfN, -C will enable compression (speeds things up a bit), -f sends the SSH to the background once the authentication is complete (so you still have a chance to enter the password if needed), -N will make sure no command is executed on the SSH server (it's not really safe to have an SSH running in the background that could hypothetically be used send commands to the server, it's a bit of healthy paranoia/a good practice).

If you don't care about having a very secure connection between your laptop and myserver, you can also change the cipher to something fast, like blowfish using -c blowfish, or arcfour128 (which is faster still).

So what I would use is this:

ssh -CfNc arcfour128 -L 80:someserver.com:80 user@myserver

Which will give you nice, fast tunnel that goes straight into the background instead of leaving an open command prompt on your server.

Keep in mind that if you send it to the background, when you want to break the tunnel, you'll have to first find the process id by doing something like ps -ef | grep ssh and kill the correct process id.

  • That sounds good but doesn't seem to work for me, when I run 'ssh -L 80:someserver.com:80 user@myserver' I'm taken to myserver as if I used a normal ssh login. When I add the -f option the service is still blocked from my python script. Also I needed sudo since 80 is a special port – user143278 Oct 30 '12 at 10:23
  • The point you make about port 80 requiring root permissions is valid, ports below 1024 are considered privileged and you need root permissions to listen on them. What you said about being taken to your server after running the ssh command is normal. Your tunnel will still be open on your own laptop. You can verify this by running netstat -an | grep*LISTEN on your laptop (not in the terminal that now shows a prompt on your server). If that shows a line similar to tcp 0 0* LISTEN, your tunnel is open. – Kenny Rasschaert Oct 30 '12 at 13:07
  • Hmmm I the netstat command works as you said so my tunnel is open, however the service is still responding that my IP is invalid. btw - in the command 'ssh -L 80:someserver.com:80 ...' Does this only send packets through to someserver.com, What if I wanted to tunnel any http request to any url through my server? – user143278 Oct 30 '12 at 14:25
  • One option to tunnel any http request would be to set up a SOCKS proxy with the -D flag, but this would require you to modify your application (see xhochy's answer). Another option would be to use something like SSHuttle (github.com/apenwarr/sshuttle) or some sort of VPN solution. – Kenny Rasschaert Oct 30 '12 at 17:24

You could use the SOCKS proxy that ssh provides. Connect via

ssh -D 9999 user@myserver

and then you could use this SOCKS proxy in your python script as described in How can I use a SOCKS 4/5 proxy with urllib2:

import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "", 9999)
socket.socket = socks.socksocket

(Put this code at the top of your script)


My suggestion would be to use:

ssh -L 8080:localhost:80 user@server

This way, you don't run afoul with port 80 being a privileged port, by connecting your program to http://localhost:8080/. Also, I would use options -C for compression, -f for backgrounding, and -N for not opening a terminal.
So ssh -CfN -L 8080:localhost:80 user@server should do the

Following up on your comment, please allow me to quote from tutorialspoint.com:

A simple client:

import socket               # Import socket module
s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 8080                # Reserve a port for your service.
s.connect((host, port))

As you are using Python's means of connecting to networks, I am assuming there is a connect() statement in your code.

(Follow the link for more in-depth info.) ;-)

  • In this case I'll have to work out how to send my script calls through port 8080, I don't understand ports so well but I assume that if I run for example wget 'some-url' then this is sent through my port 80 – user143278 Oct 30 '12 at 14:22
  • wget is an http client, so it always defaults to port 80 unless otherwise specified. – Rainbow Code Oct 30 '12 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.