2

Problem description:

I have a rather complicated issue where I can't seem to figure out how to effectively tackle it; Suppose there's the following setup:

There is 1 linux machine, connected to 3 sets of networks, let's call them A, B, and C.

The linux machine can get through the internet through network A. It has a private ip address on this network, but NO NAT is enabled on it; e.g. any other machines that are routed through this network which have a public ip given out by it can connect to the internet through it, but the computer in question cannot do so.

Network B is a public ip network set; a set of several public networks. By default, packets from B are either routed back into B, and for all other destinations not in B are routed via A.

Network C is, like A, also a network where the machine has a private address. However, here NAT is enabled. Network C can be used to communicate with the internet, but devices on network B are not allowed to route through C, they have to route through A.

Currently, the linux machine can't talk to the internet. I want it to be able to do so (e.g. ping www.stackoverflow.com to not return timeout).

How to tell linux to use another gateway for its own traffic, and only its own traffic (source or destination == localhost)?

Important

I do not want to route all the traffic to the internet over just one network. The traffic coming/going to the internet needs to use two networks, depending on source: Everything from the linux machine over one network (C), everything that it routes (that isn't on one of its local ranges), it routes over the other one (A).

Tentative solution

First, I thought to just add 'from/to localhost' to the ip rule table, yet this is not allowed. What's the easiest way to allow this router to use another router on network C as its gateway, but only from traffic originating from the machine itself?

Essentially, what I'd want is something that would be equivalent to the example below, if that would actually work in the naïve, intuitive way:

0: from all lookup local
32000: from localhost lookup myroute
32100: from all lookup main 
32767: from all lookup default
5
  • The traffic isn’t originating from localhost because that’s the loopback connection.
    – Daniel B
    Commented Aug 14, 2017 at 8:44
  • Confusing terminology aside, my intent should be clear; traffic originating from the machine itself: I want it to pick the IP in network C by default as its own IP, but it's trying to go through A (which fails). Traffic coming from B: route through A.
    – aphid
    Commented Aug 14, 2017 at 8:46
  • Whatever the solution is, it doesn't involve rerouting the loopback device. If I understand you correctly, you want to use network C as the default route, and NATing your Linux box on C already works. So use something like ip route add default dev eth-for-network-C via .... If that doesn't work, please edit your question with the output of ip addr and ip route.
    – dirkt
    Commented Aug 14, 2017 at 10:39
  • @dirkt. This is not the correct answer and the only answer I've found online so far. When doing a plain 'route everything via X' that would include the traffic coming via network B, when what I want is; the computer itself uses a gateway in C, but everything which comes from network B sent via the gateway of A. This box is an actual router, not just an endpoint.
    – aphid
    Commented Aug 14, 2017 at 14:00
  • No, traffic coming via network B is only forwarded to network C if you enable forwarding, and normally this is disabled. If you want to use the computer both as forwarding router and as normal machine, then yes, policy routing helps (or you can use iptables). But you still need the default route to network C, and it still has nothing to do with "forwarding localhost". Localhost is the address of the computer itself via the loopback device ("network D", if you want), and nothing else.
    – dirkt
    Commented Aug 14, 2017 at 16:33

2 Answers 2

2

I tested the following configuration with two network namespaces, and two veth pairs:

+-- Main --+
|          | 192.168.2.21/24
|    wlan0 | ------------------- ...
|          |
|          | 10.0.0.254/24   10.0.0.1/24 +-- NS0 --+
|   veth0a | --------------------------- | veth0b  |
|          |                             +---------+
|          |
|          | 10.0.1.254/24   10.0.1.1/24 +-- NS1 --+
|   veth1a | --------------------------- | veth1b  |
|          |                             +---------+
+----------+

The goal is to route all traffic from Main to wlan0 (network C), while routing everything from veth0 (network A) through veth1 (network B).

There's a normal default route on wlan0, acquired via DHCP:

$ ip route
default via 192.168.2.1 dev wlan0 
...

Forwarding is enabled:

echo "1" | sudo tee /proc/sys/net/ipv4/ip_forward

We add a default route for veth1a in a new table, assuming 10.0.1.1 is the gateway:

sudo ip route add 10.0.1.0/24 table 250 dev veth1a src 10.0.1.254
sudo ip route add default table 250 dev veth1a via 10.0.1.1

All traffic from and to veth0a (10.0.0.0/24) uses this table:

sudo ip rule add from 10.0.0.0/24 table 250
sudo ip rule add to 10.0.0.0/24 table 250

If somebody behind veth1b (10.0.1.0/24) has the stupid idea to try to use us as a gateway, prevent forwarding to wlan0 and forward right back using the same table. This will usually generate ICMP error packets:

sudo ip rule add from 10.0.1.0/24 table 250
sudo ip rule add to 10.0.1.0/24 table 250

Adapt to your setup as necessary.

No localhost was even remotely mentioned anywhere.

-2

Try ip ru add from 0.0.0.0

I tested on my router, locally originated connections match the rule, routed connections don't.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .