MikroTik Solutions

Bridged Container VETH
Login

Bridged Container VETH

Motivation

The recommended container networking setup in MikroTik’s docs has you putting your containers on a secondary software bridge under a separate subnet, then setting up a source NAT scheme to convert those in-container IP addresses to LAN-side addresses. This has a number of downsides:

  1. NAT has inherent issues and limitations.

  2. If the container host is a router, it may have another NAT layer above this, which then means that if the container is exposed to the outer network (e.g. port-forwarded to the Internet) you’ve likely bought yourself one or more of the common double NAT problems.

  3. NAT takes a tiny amount of processing power to manage. Your RouterOS device and configuration may allow it to be hardware-offloaded, but even then, there are cases where we want zero overhead, as when the container is running a speed test program.

Given this list, you may be wondering why MikroTik recommends that you put a container’s veth behind NAT in the first place?

It’s my belief that it is because Docker does this,1 and although RouterOS’s container feature is not based on any Docker code, they’ve mimicked this aspect of its design without considering whether that makes sense on a router or a switch, where we have complete control over the local network design. The NAT default on Docker has better justification since it is running on a desktop or server computer with a preexisting network setup, and they want it to “just work” out of the box.

That logic may play to some extent as a RouterOS container default, but it is my opinion that if you’re going to run a container on a router or a switch, you’d best be thinking about network configuration details regardless.

Solution

The alternative is simpler to configure and doesn’t have any of these problems:

$ ssh myrouter
> /interface/veth
  add address=192.168.88.2/24 gateway=192.168.88.1 name=veth1
> /interface bridge port
  add bridge=bridge1 interface=veth1

That is, we put veth1 directly on the bridge, giving it an IP in the same scheme as the rest of the bridged ports. We’re using RouterOS’s default LAN-side IP scheme of 192.168.88.0/24 for the purposes of this example, but it can be anything you like.

Consequences

I’m aware of two potential pitfalls with this scheme.

Random MAC on the Bridge

One falls out of the fact that each veth interface gets a random MAC address each time it starts up. If you run that bridge in auto-mac mode, there’s a chance on each reboot that the OS will choose to give this random MAC to the bridge, because auto-mac apparently uses the lowest-numbered MAC available, meaning you can never reliably predict whether the VETH will even be the bridge MAC, much less what that MAC will end up being.

That in turn can play havoc with configurations requiring a predictable MAC address, such as when assigning RouterOS device IPs with static DHCP reservations.

If you’re going to put veth interfaces on the bridge, I recommend turning off its auto-mac setting.

Multiple MACs over a Single WiFi Link

The default assumption with WiFi is that each client presents a single MAC address to uniquely identify itself as the endpoint of a connection. It is how the AP gets reply packets back to a specific client.

This is quite unlike with wired Ethernet switching, where a given port might be plugged into a deep fan-out of other Ethernet switches, each with their own multiplicity of clients. You can expect even a cheap consumer-grade switch to have at least an 8192 entry MAC table, because yes, there can reasonably be thousands of MACs visible to a 5-port switch.

WiFi, though, is a point-to-point medium designed with the assumption that each client presents one wireless MAC to the AP, uniquely identifying itself. When you bridge a container to a WiFi network using this article's technique, it presents the veth's random MAC address to the AP as a second client MAC, which is liable to confuse it. The typical symptom is that the bridged client becomes very slow due to the AP thrashing about trying to work out how to get reply packets back over a link that presents two different client MACs.

Do not attempt to apply this article's solution over WiFi. Either follow MikroTik's stock advice of interposing a NAT layer — thus hiding the container's random veth MAC behind the router's actual WiFi-facing MAC — or switch to wired Ethernet.

License

This work is © 2024 by Warren Young and is licensed under CC BY-NC-SA 4.0


  1. ^ …evidenced by their use of 172.17.0.0/24 for this, a subset of Docker’s default NAT IP scheme.