Consider the following situation:
At my home, I have a router (which is connected to internet), server (S) and my main machine (M). S is reachable from the internet (it has static IP), and it is up 24/7, while M is not.
Sometimes, I want to make some app (which listens on some port on M, for example 8888) accessible from outer internet.
For that, I wanted to set up some port on S (2222) to forward to M’s port 8888, so that anybody accessing S:2222 would feel like he was accessing M:8888.
I tried to use ssh port forwarding, my best attempt was as follows:
ssh -L 2222:M:8888 -N M
But that only allows me to access 2222 port from server itself, not from other machines.
Is there some way to do it properly? Preferably, I’d like it to be a simple command, which I would be able to start and shut down with ^C when I don’t need that forwarding anymore.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Yes, this is called GatewayPorts in SSH. An excerpt from ssh_config(5):
GatewayPorts
Specifies whether remote hosts are allowed to connect to local
forwarded ports. By default, ssh(1) binds local port forwardings
to the loopback address. This prevents other remote hosts from
connecting to forwarded ports. GatewayPorts can be used to spec‐
ify that ssh should bind local port forwardings to the wildcard
address, thus allowing remote hosts to connect to forwarded
ports. The argument must be “yes” or “no”. The default is “no”.
And you can use localhost instead of M in the forwarding, as you’re forwarding to the same machine as you’re SSH-ing to — if I understand your question correctly.
So, the command will become this:
ssh -L 2222:localhost:8888 -N -o GatewayPorts=yes hostname-of-M
and will look like this in netstat -nltp:
tcp 0 0 0.0.0.0:2222 0.0.0.0:* LISTEN 5113/ssh
Now anyone accessing this machine at port 2222 TCP will actually talk to localhost:8888 as seen in machine M. Note that this is not the same as plain forwarding to port 8888 of M.
Method 2
There is another way. You may set up port forwarding from S:2222 to W:8888 with iptables. Single command:
iptables -t nat -A PREROUTING -p tcp --dport 2222
-j DNAT --to-destination 1.2.3.4:8888
where 1.2.3.4 is M’s IP address. It is called NAT (Network Address Translation).
Method 3
More alternatives: netcat (traditional) or socat
On the server (S):
socat tcp-listen:2222,reuseaddr,fork tcp:M:8888
or
nc -l -p 2222 -c 'nc M 8888'
Details see in:
Simple way to create a tunnel from one local port to another?
Method 4
Concise answer
The original command is mostly fine, but it doesn’t specify the address to listen on, which results in the process listening on 127.0.0.1 by default.
Change your command from ssh -L 2222:M:8888 -N M to ssh -L S:2222:M:8888 -N M and it should work fine.
Detailed answer
The issue you experience is caused by the use of a short notation in -L – “localPort:remoteHost:remotePort”.
If you use it, ssh listens on 127.0.0.1.
For example:
ssh -L 2222:M:8888 -N M
Will result in something like this (note the address being listened on):
sudo netstat -nlp | grep 2222 tcp 0 0 127.0.0.1:2222 0.0.0.0:* LISTEN 16208/ssh
If you use the full notation (“localAddress:localPort:remoteHost:remotePort”):
ssh -L external-address-of-S:2222:M:8888 -N M
Will result in something like
sudo netstat -nlp | grep 2222 tcp 0 0 external-address-of-S:2222 0.0.0.0:* LISTEN 16208/ssh
P.S. GatewayPorts is a bit more generic solution, but it behaves differently if your server has more than one IP address. This solution lets you pick the IP to listen on (and lets you forward the same port on different IPs to different destinations) while GatewayPorts listens on all of them and forwards them to the same destination. Which one works better for you will depend on your requirements – but both will work for the OP.
P.P.S. I realize it’s a very old question, but it’s still very relevant today (probably more so due to the widespread use of cloud) and I believe it’s missing a simple answer that might help the people who encounter a similar issue.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0