0

From my basic understanding of SSH port forwarding, the SSH client software opens a listening socket on an IP:PORT, say 185.68.93.141:80. So if I go to my web browser and access somewebsite.com that resolves to 185.68.93.141, then my web browser will open a socket to talk to 185.68.93.141:80.

Alas, unbeknownst to the browser, it is not talking to the webserver, but the SSH client. The SSH client will send it over the SSH connection (through port 22, which is the only one allowed through the NAT and firewall) and the SSH server will relay it to localhost:80.

However, as I know from experience and a few google searches, you cannot bind a listening socket to an external IP. You get some "IP not valid in this context" error.

So, how does this actually work?

  • At first glance your basic understanding seems very wrong. You cannot bind to arbitrary (foreign) IP address. Please include full ssh command with -L, -R or -D and then we can tell you how this works (or doesn't, if the command makes no sense). – Kamil Maciorowski May 24 '18 at 15:40
  • @KamilMaciorowski I know you can't bind to a foreign ip address, that's what doesn't add up. Something in the other part of the process must be wrong. I'm not running a particular ssh command, I'm just trying to understand how it works. Let me change the question a bit: If I have a remote host that supports SSH running a web server, but the port 80 is not exposed, can I configure the SSH client so that when someone opens a web browser on the local machine it can access the web server on the remote machine? – freejuices May 24 '18 at 15:50
  • In your example, is 185.68.93.141 the address of some interface of the remote machine you ssh to? – Kamil Maciorowski May 24 '18 at 16:00
  • @KamilMaciorowski It's the address of the router. The remote machine would be behind the router with some local IP address, that would be the address of the interface on the remote mahcine – freejuices May 24 '18 at 16:07
1

Assumptions:

  • There is a remote server behind NAT, the public IP is 185.68.93.141 but because of NAT the server is not directly available.
  • The server runs sshd on port 22 and httpd on port 80.
  • 185.68.93.141:22 is forwarded to the server, so we can ssh in (like ssh 185.68.93.141).
  • 185.68.93.141:80 is not forwarded to the server.

Goal:

  • Reach the remote httpd from the outside.

Possible approaches:

  1. ssh -L 5678:localhost:80 185.68.93.141

    (Note: the localhost above means localhost in the context of the remote server). Now every connection to localhost:5678 on the local computer will reach localhost:80 (127.0.0.1:80) of the remote server. The remote httpd will "see" the connection from the remote server itself. Your local browser should visit http://localhost:5678. There are few obstacles:

    • The remote httpd may reject the connection because the URL used is not what it expects, let's say it expects http://example.com. You can fix this by redirecting example.com to 127.0.0.1 on the local side either by supplying your own DNS service or by modifying /etc/hosts. Even then you need to connect to http://example.com:5678 though.
    • You may want to use the port 80 instead of 5678 on the local side (so with the above trick the URL to use is the desired http://example.com) but probably your local OS won't allow you to open ports with numbers lower than 1024, unless you're root (or Administrator etc.). Running ssh as root is not recommended.
  2. ssh -D 5678 185.68.93.141

    In this case you need to set up your local browser to use SOCKS4 or SOCKS5 dynamic proxy at localhost:5678 (127.0.0.1:5678). Connections to any site it visits is established by the sshd on the remote side in behalf of the browser. Your browser is "seen" as if it connected from the remote server. Now all you have to do is to use URL that works when connecting from the remote server to its own httpd (but if it's http://localhost or similar then keep in mind your local browser may have an option like "don't use proxy for local addresses").

    More information here.

If you want to use 185.68.93.141 (or somewebsite.com that resolves to 185.68.93.141) as the main part of the URL in your local browser and still reach the remote sshd despite the lack of port 80 forwarding on 185.68.93.141, then you need to make the browser connect according to the above rules somehow. Sole ssh has no means to intercept traffic from browser that doesn't cooperate.

  • Thank you for taking the time to answer. That made if much more clear. Do you think I should edit the original question to change it into the question that's in the comments? – freejuices May 24 '18 at 17:19
  • @freejuices Yes, this is a good idea; but please pay attention and don't make the existing answers appear off-topic afterwards. – Kamil Maciorowski May 24 '18 at 17:24
1

The SSH client is binding to a port on localhost. The browser sends the request to the SSH client. The client forwards the request to the SSH server (outside the firewall). The SSH server connects to the URL. The SSH server doesn't have to bind to a port (other than 22), because in this context it is acting as a client, and the remote web server will pick up its default IP address.

Also, the reason that the browser is connecting to localhost instead of the IP address on the URL is due to the browser proxy settings. When you set up a proxy, the browser always connects to the proxy IP address (probably localhost in this case) and tells the proxy server the real address that you want to connect to.

1

Taking your question from the comments:

If I have a remote host that supports SSH running a web server, but the port 80 is not exposed, can I configure the SSH client so that when someone opens a web browser on the local machine it can access the web server on the remote machine?

If the SSH on the remote host is listening on 22 and you can access it, what you can do is connect using a local port forwarding. For instance, considering a Linux client:

ssh remotehost -L 81:localhost:80

After running the previous command you should see a new listening socket on port 81 (you can check with netstat -latn | grep 81).

As a result, local port 81 will be forwarded to remotehost:80.

You can now browse on your client machine http://localhost:81 and you will see the web server.

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.