0

I have this port forwarding solution for testing purposes. There is a distant server named box and a local machine named tower, on two separate networks. box is accessible through the internet.

On tower, I run the following command:

ssh -R 80:localhost:80 box.sleblanc

This connects to box and setups a socket on port 80 that will access a web service on tower, port 80. When a connection is established with box:80, I find that it appears to the web service in the logs as coming from 127.0.0.1. I find this annoying as I cannot reliably distinguish between the connections that are legitimately from my localhost as opposed to those that come from via the proxy.

By setting the BindAddress option to something different (e.g. 192.168.0.100) the connections to the proxy actually show up as that address instead, which solves my problem, but it forces my service to run on a network address other than localhost.

I found that running curl --interface 127.0.0.2 localhost:80 will produce requests from the IP address 127.0.0.2, which fulfills my requirement of being able to distinguish between legitimately local requests versus proxied requests, however, when setting BindAddress to 127.0.0.2, SSH can no longer reach box, as the 127.0.0.0/8 network is not routeable.

Ultimately, my question is: how can I bind the SSH client to multiple different addresses, so that the client can connect to an Internet host while the remote port redirection will come from an unrouteable address other than 127.0.0.1? That is, strictly bind connections to the remote forwarded port to the local address 127.0.0.2?


Toying with socat, I discovered this solution:

% socat TCP4-Listen:1234,fork TCP:127.0.0.1:80,bind=127.0.0.2 &
% ssh -R 80:127.0.0.1:1234 box.sleblanc

This sets up a socket on that listens to incoming connections on port 1234 and forwards them to 127.0.0.1:80 by binding to the local address 127.0.0.2. It works exactly as intended, but I am wondering if there is a way to streamline this into the SSH command.

  • You would need ssh to bind on a specified interface when creating the local sockets for -R, but I see no way to specify this in man ssh. So if you want to do this with ssh only, you'll likely have to modify the code to provide this option (and submit a patch). You can also connect the remote box to your local box with a different kind of tunnel which preserves IP addresses. – dirkt Mar 16 at 19:47
  • On a Linux system, this hack (on tower) will "fix" ssh: iptables -t nat -I POSTROUTING -s 127.0.0.1 -d 127.0.0.2 -j SNAT --to-source 127.0.0.2 – A.B Mar 16 at 22:49
  • @A.B, interesting. This rewrites packets addressed to 127.0.0.2 so that they show up as coming from 127.0.0.2 instead of 127.0.0.1, is that so? – sleblanc Mar 16 at 23:39
  • yes. even tested it (using.. socat with -d -d of course) before commenting. But your question doesn't specify the OS – A.B Mar 16 at 23:41
  • GNU plus Linux. – sleblanc Mar 17 at 2:25

Your Answer

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

Browse other questions tagged or ask your own question.