At the office we get access to the web via a SOCKS server which is started with the command:
ssh localhost -f -N -D *:8888.

This server has 2 IPs (but only one network card):
eth0 xx.yy.zz.1
eth0:1 xx.yy.zz.2

So the browsers are configured to use the socks proxy xx.yy.zz.2:8888

When I check what is the IP that websites see, it gives me xx.yy.zz.1 (the server's default IP).
But I want it to be the other one (xx.yy.zz.2).

How can I bind the outgoing connections to the second IP?

Could this be solved with iptables?
May be there is a way to tell which are the packets originating from a given SSH tunnel and then modify their destination IP?

Another idea that crosses my mind, is there some sort of wrapper command that force another command to bind to a given IP?


The SSH protocol has no way for clients to tell the server to bind to a certain address when doing a dynamic port forwarding, so no, you can't tell your SSH client to do it. You can't tell the OpenSSH server to do it either. It will blindly use getaddrinfo to connect to your remote host.

The only way to fix is to configure your server so it does what you want. Unfortunately, there is no way you can tell from the routing or iptables which connection was made by the OpenSSH server. The problem is hard: OpenSSH may open connection, but may also spawn a shell which can spawn other process which also can open connections. Distinguishing from the two cases is hard. It would be much easier if OpenSSH would just set a mark or anything, but it doesn't.

So your solutions are limited:

  • Use a separate SOCKS server that allows you to configure the bind address.

  • Configure your kernel so that it uses xx.yy.zz.2 by default for all outgoing connection, or for the actual destination IPs that are used if they are known in advance.

    To assign a source address when there is none, the kernel looks at the used route entry for your destination address, and if it has a preferred source address, it will use it. Else it will pick some address that look best for the task. Whatever it chooses can be checked by the ip route get (destination) command, after the src token:

    $ ip route get via (maybe your gateway) dev eth0 src xx.yy.zz.1 [...]

    You may modify your routing table with the ip route command to add preferred source addresses with ip route change [...] src xx.yy.zz.2 You may even add more specific route going though the same gateway, but with a different preferred source address.

  • Put OpenSSH into a network namespace that only handles the xx.yy.zz.2 address. This solution is way overkill and may change the configuration of many services on your server, since it essentially isolates your two adresses. This solution will involve many changes in your system, especially regarding the way the sshd daemon and your socks server is started.

Unrelated to all of this: "interfaces aliases" (e.g. eth0:1) are deprecated on Linux. They still work as backward compatibility for historic tools like ifconfig, but you should really get rid of them and use the native functionality of the kernel to get multiple addresses per interfaces. Stop using ifconfig, route and use ip addr and ip route instead.

Use ip addr add ... dev eth0 to add an address to the eth0 interface. You can add as many addresses as you want. Use ip addr to list them all. See the manual page of ip addr and ip route to get more information.

  • Would it be possible to use the LD_PRELOAD trick to overwrite the getaddrinfo function with a custom one? – GetFree Apr 4 '14 at 13:29
  • Yes, but it wouldn't change anything. getaddrinfo only returns parameter to use when creating your socket, and it does not return a bind parameter. What you need to intercept is the socket() or connect() call, to bind the socket to what you want, or to set a firewall mark so that the kernel can pick the preferred source address that you want. – BatchyX Apr 4 '14 at 18:00
  • I found this page daniel-lange.com/archives/… where they point to two working examples of that. I tried one of them (the one that supports x86_64) but it doesn't seem to work. I'll try adding some debug messages to the code to see what's going on. – GetFree Apr 4 '14 at 18:31
  • I realized that the LD_PRELOAD trick is never going to work, since the SSH command is just the client program that makes the connection to the SSH server. And it's the server the one that forwards the packets. So forcing the client to bind to a given IP won't make any difference. – GetFree Apr 9 '14 at 16:58

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.