Advanced Routing

  • By Llama (LMA) Charmers
Channel Revision Published Runs on
latest/stable 23 01 Nov 2023
Ubuntu 22.04 Ubuntu 20.04
latest/candidate 30 03 May 2024
Ubuntu 22.04 Ubuntu 20.04
latest/edge 30 03 May 2024
Ubuntu 22.04 Ubuntu 20.04
juju deploy advanced-routing
Show information

Platform:

Ubuntu
22.04 20.04

Understanding the configuration options

The charm builds a routing configuration on units based on the configuration options provided to it. The configuration uses the policy routing rules specified to build multiple route tables, and select which one to use based on rule matching.

Let’s use an example to illustrate; a unit with two network interfaces, one for ‘internal’ traffic, and one that listens on a public facing IP address for traffic to it’s specific application. The default gateway is found via eth0 which is for ‘internal’ traffic, but doesn’t allow traffic to the entire Internet. On the network with the ‘public’ interface is a gateway/firewall that has routes to the clients wanting to connect to our host.

On the Juju unit we’re looking at, the /etc/netplan/50-cloud-init.yaml contains a ‘gateway’ setting only for eth0 (the default gateway) and does not add a gateway for eth1.

Our network config looks like this:

  • eth0: IP address 192.168.0.20/24, gateway 192.168.0.1 (default gateway)
  • eth1: IP address 10.0.0.50/24, gateway 10.0.0.1 (not configured)
  • Default gateway set up by the host network config: 192.168.0.1

The route table at the start looks like this:

# ip route
default via 192.168.0.1 dev eth0 proto static
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.20
10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.50

Now, consider that a client connects to 192.168.0.20. The traffic arrives on eth0, and the reply goes out via eth0 and 192.168.0.1. No problem.

Next a packet arrives from, e.g., 1.2.3.4, addressed to 10.0.0.50, on eth1. The reply needs to go via a router that has a route to that address, but the route table states that the default route is via eth0 192.168.0.1, which would block that traffic. We need to tell the kernel that the response must go via eth1, and use 10.0.0.1 as the next hop, rather than use this asymmetric path.

We can fix this using policy routing rules. In this case, we want to define a new rule and a route table to match it (let’s call that ‘public’).

We want to define the rule such that replies to traffic addressed to our eth1 IP address is sent via the gateway accessed via eth1. We can specify this with a ‘from’ address rule, where the network we state ‘from’ is the network that has the address on eth1 - i.e., the reply is ‘from’ our eth1 address, going outwards.

In this case, we want to say:

# ip rule list
0:      from all lookup local
101:    from 10.0.0.0/24 lookup public
32766:  from all lookup main
32767:  from all lookup default

# ip route show table main
default via 192.168.0.1 dev eth0 proto static
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.20
10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.50

# ip route show table public
default via 10.0.0.1 dev eth1 proto static

Reading this, we see that traffic ‘from’ 10.0.0.0/24, i.e. from our host address 10.0.0.50 heading anywhere outwards, will be selected to use the ‘public’ route table, which uses 10.0.0.1 as the next hop. Other traffic will use the ‘main’ table which uses 192.168.0.1.

To translate this into a configuration for the charm:

settings:
  advanced-routing-config:
    value: |-
      [ {
          "type": "table",
          "table": "public"
      }, {
          "type": "route",
          "default_route": true,
          "gateway": "10.0.0.1",
          "table": "public",
          "metric": 101,
          "device": "eth1"
      }, {
          "type": "rule",
          "from-net": "10.0.0.0/24",
          "table": "public",
          "priority": 101
      } ]
  enable-advanced-routing:
    value: true

Help improve this document in the forum (guidelines). Last updated 7 months ago.