-1

I have a Windows 11 box running IIS on 127.0.0.1 on port 80, which is connected to the Internet through a CGNAT. I also have a VPS from Linode(a VPS supplier). The VPS's IP address is 139.162.19.185. I want to connect to servers/ports on my Windows 11 box from anywhere else on the Internet, via my VPS.

I ran the command below using Windows 11 command prompt in Administrator mode:

ssh -R 80:localhost:80 root@139.162.19.185

When I try to access the SSH tunnel on my VPS using http://139.162.19.185:80, I get connection refused, but when I try to access my localhost using http://127.0.0.1, I see IIS Start homepage.

I have checked the /etc/ssh/sshd_config file, and GatewayPorts and AllowTcpForwarding are both enabled.

UPDATE:

This is the results of netstat -tlnp

root@localhost:~# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:80            0.0.0.0:*               LISTEN      35027/sshd: root@pt
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      434/sshd: /usr/sbin
tcp6       0      0 ::1:80                  :::*                    LISTEN      35027/sshd: root@pt
tcp6       0      0 :::22                   :::*                    LISTEN      434/sshd: /usr/sbin
root@localhost:~#

The results of curl is as follows:

root@localhost:~# curl http://127.0.0.1:80
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Hostname</h2>
<hr><p>HTTP Error 400. The request hostname is invalid.</p>
</BODY></HTML>
root@localhost:~#

Are there any config files I need to edit? I tried some debugging to see whether there are any firewalls on Linode. I installed apache2 and it works fine on port 80, so port 80 is not blocked.

  • On the surface it seems ok. Are you sure there are no firewalls on the Linode box or Linode's platform? – mtak Feb 10 '23 at 07:54
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Feb 10 '23 at 08:01
  • First step to debugging this is to make sure that's an ssh problem, and not something else. So ssh into your Linode host, start some kind of http server on 80, and see if http://139.162.19.185:80 works with that. – dirkt Feb 10 '23 at 08:45
  • You write "when I try to access my localhost using http://127.0.0.1," ,<-- From where? From your 139...185 computer? Run a command to see if it's binding to 127.0.0.1 or 0.0.0.0 Like, for linux, netstat -tlnp (for windows, netstat -aon) – barlop Feb 10 '23 at 10:22
  • "and GatewayPorts and AllowTcpForwarding are both enabled" – Always post exact configuration string(s). GatewayPorts yes and GatewayPorts clientspecified can both be considered "enabled", but they are not equivalent in the context of your problem. – Kamil Maciorowski Feb 10 '23 at 16:23
  • You should be addressing questions people ask you regarding your question. If you don't then it degrades the quality of your own question – barlop Feb 10 '23 at 18:18
  • mtak, yes, there are no firewalls on my Linode. I tried installing apache2 and it ran smoothly on port 80. – Sugumaran Veejakumaran Feb 12 '23 at 08:02

1 Answers1

1

The way you are using the -R option, it means you want the remote side to bind only to the loopback interface. From the ssh manual page:

     -R [bind_address:]port:host:hostport
 ...

         By default, TCP listening sockets on the server will be bound to the loopback interface only.  This may be overridden by
         specifying a bind_address.  An empty bind_address, or the address ‘*’, indicates that the remote socket should listen on
         all interfaces.  Specifying a remote bind_address will only succeed if the server's GatewayPorts option is enabled (see
         sshd_config(5)).

Simplified this means:

  • -R port:host:hostport will bind to loopback only
  • -R :port:host:hostport will bind to all interfaces
  • as will -R *:port:host:hostport and -R 0.0.0.0:port:host:hostport

So in your situation, any of these should work:

ssh -R :80:localhost:80 root@139.162.19.185
ssh -R *:80:localhost:80 root@139.162.19.185
ssh -R 0.0.0.0:80:localhost:80 root@139.162.19.185

*Below my original attempt to explain this behavior based on the documentation text - with some clarifications.

You used the PORT:IP:PORT syntax, which didn't specify a bind_address.

The text specifying a bind_address in the above description refers to there being a : before the remote port(The first port in PORT:IP:PORT). The way you have it in your example, there is no :, which means that you did not specify a bind_address, and according to the man page the remote side will bind only to the loopback interface (default). In order to bind to all interfaces, you need to specify a bind_address (i.e. add a : before the remote port), even if the actual bind_address is an "empty string"! Either an "empty string" or a * would work in this case, but keep in mind that the : is mandatory for it to not be limited to binding to the loopback address only!

Update

After the comments from @barlop, it seems my explanation was not very clear, so I am trying to clarify things here step by step:

  • The option is defined as -R [bind_address:]port:host:hostport.
  • The whole [bind_address:] part is optional. If it is not present,then the option has the format -R port:host:hostport and the default behavior applies, which means TCP listening sockets on the server will be bound to the loopback interface only.
  • If the [bind_address:] part is present, it means we have the format -R bind_address:port:host:hostport, notice that now the first : is not optional any more. From this moment on, bind_address can take several values, one of the possible values is indeed an empty string! So adding the colon to the option, means we do specify a bind_address this time, albeit an empty one (which, according to the description is taken to mean the remote socket should listen to all interfaces.

I hope this makes it a little more clear, basically not specifying a bind_address and specifying an empty string as bind_address are two different things! The "empty string" bind_address is considered to be a bind address, and refers to using :PORT:IP:PORT syntax without writing in anything there for the address, before the far left colon!.

Here is the output from me testing it (on a different port, but same effect):

See it's SSHing and running netstat -an on the remote machine.

gepa@localhost:~$ ssh -R :5555:localhost:5555 cloud1 netstat -an | grep :5555
tcp        0      0 0.0.0.0:5555            0.0.0.0:*               LISTEN     
tcp6       0      0 :::5555                 :::*                    LISTEN

gepa@localhost:~$ ssh -R 5555:localhost:5555 cloud1 netstat -an | grep :5555 tcp 0 0 127.0.0.1:5555 0.0.0.0:* LISTEN
tcp6 0 0 ::1:5555 :::* LISTEN

Notice how adding a : before the first 5555 makes the remote host listen to all interfaces compared to omitting the :.

BTW, It is far more clear not to use an empty string bind_address and to write $ ssh -R *:5555:localhost:5555 comp or 0.0.0.0:80:localhost:80

Also the reason why the PORT:IP:PORT syntax binds to 127.0.0.1 is for security reasons. So if you do want it to bind non-locally, it's better if you make it very clear e.g. with a wildcard or specifying 0.0.0.0 or specifying a LAN address if only connecting from your LAN.

barlop
  • 23,849
gepa
  • 991
  • 1
  • 3
  • 11
  • where is it that you think he specified a bind address? He wrote PORT:IPADDRESS:PORT.. You say "even if the bind_address is an empty string." Well if the bind_Address is an "empty string". Then what to you would it mean for somebody to NOT specify the bind address?! – barlop Feb 10 '23 at 10:17
  • Also you wrote that (in order to not bind just to the loopback address), "you need to have the : before the remote port, even if the bind_address is an empty string". Yet in this command ssh -R :80:localhost:80 You gave the bind_address as an empty string and told him it'd work – barlop Feb 10 '23 at 10:21
  • i'm not saying your solutions are right/wrong, just remarking on your explanations – barlop Feb 10 '23 at 10:21
  • I said it is confusing, and obviously my explanation is not less confusing :) Basically :80:localhost:80 has an empty string as bind_address, but 80:localhost:80 has no bind_address (i.e. according to the man page terminology, it is not specifying a bind_address, so the default loopback is used). I did try both of these out, and indeed it behaves the way I explained. If I omit the starting :, netstat -anp shows listening to 127.0.0.1:<port>, but if I begin the -R part with a :, it listens to 0.0.0.0:<port>. – gepa Feb 10 '23 at 11:11
  • Or in other words "not specifying a bind_address", and "having an empty string as bind_address" are two different things, that's the weird part, but I believe my understanding (based also on the tests I did), is indeed correct. – gepa Feb 10 '23 at 11:15
  • As I said. i'm not saying your solutions are right/wrong, just remarking on ur explanations. U wrote "specifying a bind_address means you need to have the........" <-- you're suggeseting that he specified a bind address, But he didn't specify a bind address!!!! Then you write(in the same paragraph), " If you leave out the :, you are binding to loopback. " That's technically true but confusingly put. Leaving out the : isn't just leaving out the : it's not specifying a bind address. But the way you stuck that statement in your paragraph makes it sound like he specified a bind address. – barlop Feb 10 '23 at 12:03
  • OK, I think now I understand your point. By having the "specifying a bind_address"-part in backquotes I thought it indicated that I am referring to the text from the man page, but seems to be not. Let me try to rephrase that part... – gepa Feb 10 '23 at 12:24
  • You would be a lot clearer if you said that by writing in the format of PORT:IP:PORT he is binding to 127.0.0.1 And in order to bind to 0.0.0.0 he should write BLAH (then give your examples in place of BLAH)! – barlop Feb 10 '23 at 12:30