0

I have a VPS with 2 usable IP addresses. I would like to use one of them to receive connections on, and use the other when the server is establishing a connection. So if the starter of the connection is not the VPS, it will use IP Address A and if it is, it will use IP Address B.

VPS is running Ubuntu 16.04

how would I go about doing this? Thank you!

  • You can force routing in some cases with a local system/server firewall, but in general this isn't done unless there is a dependency with a separate network firewall exception. In almost all cases, outbound connections should be allowed to use whichever interface the OS finds appropriate/available. – pmdba Apr 21 '21 at 03:09
  • I can think of setting up policy routing with `ip rule` and an alternate route table, like set up rules for ports that services listen on. (It won't be strictly based on the connection "state" but might make even more sense.) Note that the rules should be matching against `sport`. – Tom Yan Apr 21 '21 at 10:42
  • Also if it's just two IPs on the assigned to the same interface, you might not even need to do anything as often the program will reply with the source address set to the original destination address, AFAIK. – Tom Yan Apr 21 '21 at 10:50

1 Answers1

2

When Linux makes outgoing connection, it first tries to use whichever address application requested on socket creation. If it didn't requested anything particular (or requested 0.0.0.0), it looks for a hint in the route.

You may set a route to have such hint to any address you have assigned, this is done with src keyword of ip command:

ip route add DESTINATION via GATEWAY src PREFERRED_SRC_ADDRESS

For example, on my machine I have two addresses, 192.168.168.4/24 and 192.168.168.6/24 (output is stripped down for clarity):

muon ~ # ip addr
...
3: br0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 ... state UP ...
    inet 192.168.168.4/24 brd 192.168.168.255 scope global br0
    inet 192.168.168.6/24 scope global secondary br0
...

To use 192.168.168.6 for outgoing routes I have either to tell all programs to bind to it explicitely, for example:

ssh -b 192.168.168.6 dst-address

or set up my default route so it will be chosen by default:

ip route add default via 192.168.168.1 src 192.168.168.6

(Default route doesn't have a hint by default; system uses "connected" hint in that case.) Also notice, some src will already be in the "connected" route, spawned from the ip address add command and defined by the netmask:

192.168.168.0/24 dev br0 proto kernel scope link src 192.168.168.4

That's because .4 address was "primary" on this system, and .6 was added afterwards. These two routes is all I have in the main table, so now I'll connect from .4 to machines in the same LAN (when I go through "connected" route) and from .6 to the machines outside of it (when I go through "default" route). I may update this route too to use .6 address in it:

ip route change 192.168.168.0/24 dev br0 src 192.168.168.6

To use .4 address now I must bind to it excplicitly, for example, with ssh -b, or setup additional routes with "longer prefix" to certain systems for which I want to use .4 address.

All the time machine is accessible for incoming connections to both IP addresses. If I want it to accept connections to only one of them, I may simply block unwanted connections in the firewall.

Nikita Kipriyanov
  • 8,033
  • 1
  • 21
  • 39