Skip to content
View in the app

A better way to browse. Learn more.

Unraid

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Macvlan container with internal DNAT (e.g. VirtualDSM) unreachable from external clients on 7.2.x — caused by kernel default `bridge-nf-call-iptables=1`

Featured Replies

If you run a Docker container on a **macvlan** network that performs **its own internal DNAT** to a second IP/VM (the VirtualDSM/`vdsm/virtual-dsm` pattern is the textbook case), external LAN clients may get TCP RST / "connection refused" on the published ports, while access from the Unraid host itself or from other containers still works. Root cause is the Linux kernel default `net.bridge.bridge-nf-call-iptables=1`, which routes L2 bridge traffic through host netfilter/conntrack and bypasses the container-internal DNAT. Fix: set the three `bridge-nf-call-*` sysctls to `0`.

---

## Environment where I hit this

- Unraid 7.2.6, kernel 6.12.87-Unraid, Docker 29.3.1
- Container: `vdsm/virtual-dsm` on a macvlan network attached to `br0`
- VirtualDSM container has its own IP on the LAN (e.g. `192.168.20.8`) and internally DNATs to the DSM VM on `172.30.20.x`

A second host (Unraid 7.2.4, kernel 6.12.54, Docker 27.5.1) showed the same kernel default but no symptoms — because it only uses `ipvlan`/`bridge`, no macvlan-with-internal-DNAT containers.

## Symptom

From external LAN clients (and via VPN) to the macvlan container IP:
- `curl https://192.168.20.8:5001` → immediate TCP RST / "Connection refused"
- ICMP to the same IP works
- From the Unraid host itself or from another container on the same host: works fine
- From the DSM VM outwards: works fine

So L3 reachability is OK, only inbound TCP to published ports is broken — and only from *external* clients.

## Root cause

When the `br_netfilter` kernel module is loaded (Docker triggers this), the kernel sets these defaults:

```
net.bridge.bridge-nf-call-iptables   = 1
net.bridge.bridge-nf-call-ip6tables  = 1
net.bridge.bridge-nf-call-arptables  = 1
```

With macvlan-on-bridge, incoming L2 frames destined for the wrapper container's MAC/IP first traverse the **host's** netfilter chains and create a **host-side conntrack entry**. The host has no DNAT rule for the wrapper IP, so the connection is tracked as a plain "to-local" flow.

The wrapper container's internal DNAT (its own iptables rule that rewrites `192.168.20.8:5001` → `172.30.20.x:5001`) then never sees a fresh first packet — the host-side conntrack short-circuits the path, and the packet ends up in the wrapper's network namespace as if it were addressed to the wrapper itself. Since nothing inside the wrapper is listening on `:5001`, the kernel sends a RST.

Local-host and inter-container traffic doesn't trip this path, which is why those work.

## Fix

Live:

```bash
sysctl -w net.bridge.bridge-nf-call-iptables=0 \
           net.bridge.bridge-nf-call-ip6tables=0 \
           net.bridge.bridge-nf-call-arptables=0
```

Persistent — add **before** the `/usr/local/sbin/emhttp` line in `/boot/config/go`:

```bash
# Disable bridge netfilter so external traffic to macvlan containers
# is not intercepted by host iptables/conntrack
sysctl -w net.bridge.bridge-nf-call-iptables=0 \
           net.bridge.bridge-nf-call-ip6tables=0 \
           net.bridge.bridge-nf-call-arptables=0
```

After applying: external clients reach `https://192.168.20.8:5001` immediately (HTTP 200, ~250 ms in my case).

## Is this a security risk?

In a normal Unraid setup: **no real impact.**

- Docker `bridge` networking (the default for most containers) uses PREROUTING DNAT in the `nat` table — that path is independent of `bridge-nf-call` and continues to work unchanged.
- `ipvlan` does not use bridge_nf at all.
- The only thing you "lose" is the ability to filter **bridged L2 traffic** via host `iptables` (e.g. `FORWARD` rules applied to gemacvlan'd containers). Macvlan containers are by design directly on the LAN and were never meaningfully filtered by host iptables anyway — segmentation for them belongs on the switch/router (VLANs/ACLs) or inside the container.
- Many other distros / orchestrators (Proxmox guidance for some setups, several Kubernetes CNIs) explicitly require `bridge-nf-call-iptables=0`.

## Why I think this is worth a default change

- Unraid actively promotes macvlan/ipvlan as the "Custom" network option in the Docker UI.
- The kernel default was reasonable in a pre-container world but is now a footgun for exactly the use case Unraid encourages.
- There is no Unraid-shipped sysctl override, and nothing in the macvlan UI hints at this requirement.
- VirtualDSM is a very popular community template; many users will hit this without knowing where to look (the symptom looks like a firewall/router problem, not a host-kernel-default problem).

Would be great if Limetech either flipped the default in a future release or added a one-liner to the Docker/Network settings docs.

## How to check if you're affected

```bash
# Are you running br_netfilter with the dangerous defaults?
sysctl net.bridge.bridge-nf-call-iptables \
       net.bridge.bridge-nf-call-ip6tables \
       net.bridge.bridge-nf-call-arptables

# Do you have any macvlan-with-internal-DNAT containers?
docker network ls --filter driver=macvlan
```

If both are "yes" → you'll hit this the moment such a container is deployed (VirtualDSM, some NAS-in-VM wrappers, some IoT bridges).

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.