[GH-ISSUE #1976] Linux Client fails to create iptables Masquerade rules in [Synology] #3748

Closed
opened 2026-08-05 00:54:05 -04:00 by saavagebueno · 13 comments
Owner

Originally created by @zzecool on GitHub (May 13, 2024).
Original GitHub issue: https://github.com/netbirdio/netbird/issues/1976

Describe the problem

Running Native Linux Client version 0.27.5 in Synology.
The iptables version is :

iptables v1.8.3 (legacy): Couldn't load match comment':No such file or directory

and cant change.


The Client fails to address the Routes assigned to him either if it is network range or an exit node.
Dirty fix :

If i manual do :

sudo iptables -t nat -A POSTROUTING -o ovs_bond0 -d 192.168.1.0/24 -j MASQUERADE

I can have access to the 192.168.1.0/24 network

or

sudo iptables -t nat -A POSTROUTING -o ovs_bond0 -j MASQUERADE

If i want to make him an Exit node ( access to internet )

ovs_bond0 is my interface


Now for the FORWARD chain that the Native Client is tryhing to use, the Chain is doesnt exist, if i create it it fails on the next set of rules like this :

2024-05-13T17:12:11+03:00 ERRO client/firewall/create_linux.go:48: failed to create iptables manager: running [/sbin/iptables -t filter -C FORWARD -o wt0 -m mark --mark 0x000007e4 -j ACCEPT --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory

Try `iptables -h' or 'iptables --help' for more information.

2024-05-13T17:12:11+03:00 ERRO client/internal/engine.go:315: failed creating firewall manager: running [/sbin/iptables -t filter -C FORWARD -o wt0 -m mark --mark 0x000007e4 -j ACCEPT --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory

Try `iptables -h' or 'iptables --help' for more information.

Not only that but there is a mechanism that deletes the FORWARD chain after a while. So maybe the proper appoach would be to check if iptables is iptables v1.8.3 (legacy) and the system is Synology and use the dirty way on the POSTROUTING chain that exists.

for identifying Synology you can use something like this :

# Check script is running on a Synology NAS
if ! /usr/bin/uname -a | grep -i synology >/dev/null; then
    echo "This script is NOT running on a Synology NAS!"
    echo "Copy the script to a folder on the Synology"
    echo "and run it from there."
    exit 1  # Not a Synology NAS
fi

# Get NAS model
model=$(cat /proc/sys/kernel/syno_hw_version)
#modelname="$model"

# Show script version
#echo -e "$script $scriptver\ngithub.com/$repo\n"
echo "$script $scriptver"

# Get DSM full version
productversion=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION productversion)
buildphase=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION buildphase)
buildnumber=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION buildnumber)
smallfixnumber=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION smallfixnumber)
majorversion=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION majorversion)
minorversion=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION minorversion)

# Show DSM full version and model
if [[ $buildphase == GM ]]; then buildphase=""; fi
if [[ $smallfixnumber -gt "0" ]]; then smallfix="-$smallfixnumber"; fi
echo -e "$model DSM $productversion-$buildnumber$smallfix $buildphase\n"

# Print all the results at the end
echo "Model: $model"
echo "DSM Full Version: $productversion-$buildnumber$smallfix $buildphase"
echo "Major Version: $majorversion"
echo "Minor Version: $minorversion"

Another hint is that WGeasy works out of the box even as docker ( bridge mode )

With the following rules :

$ sudo iptables -L -v -n --line-numbers | grep 172.17.0.22     #( wgeasy ip )

Chain DOCKER
43       0     0 ACCEPT     udp  --  !docker0 docker0  0.0.0.0/0            172.17.0.22          udp dpt:51820
sudo iptables -t nat -L | grep 172.17.0.22     #( wgeasy ip )

Chain DEFAULT_POSTROUTING
MASQUERADE  udp  --  172.17.0.22          172.17.0.22          udp dpt:51820
DNAT       udp  --  anywhere             anywhere             udp dpt:51820to:172.17.0.22:51820

Cause in the config we have : AllowedIPs = 0.0.0.0/0

That way client can decide what networks he will route to, as 0.0.0.0/0 is allowed.

Originally created by @zzecool on GitHub (May 13, 2024). Original GitHub issue: https://github.com/netbirdio/netbird/issues/1976 **Describe the problem** Running Native Linux Client version 0.27.5 in Synology. The iptables version is : `iptables v1.8.3 (legacy): Couldn't load match comment':No such file or directory` and cant change. ------------------------------------------------------------------------------------------------------------------- The Client fails to address the Routes assigned to him either if it is network range or an exit node. Dirty fix : If i manual do : `sudo iptables -t nat -A POSTROUTING -o ovs_bond0 -d 192.168.1.0/24 -j MASQUERADE` I can have access to the 192.168.1.0/24 network or `sudo iptables -t nat -A POSTROUTING -o ovs_bond0 -j MASQUERADE` If i want to make him an Exit node ( access to internet ) ovs_bond0 is my interface -------------------------------------------------------------------------------------------------------------------- Now for the FORWARD chain that the Native Client is tryhing to use, the Chain is doesnt exist, if i create it it fails on the next set of rules like this : ``` 2024-05-13T17:12:11+03:00 ERRO client/firewall/create_linux.go:48: failed to create iptables manager: running [/sbin/iptables -t filter -C FORWARD -o wt0 -m mark --mark 0x000007e4 -j ACCEPT --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory Try `iptables -h' or 'iptables --help' for more information. 2024-05-13T17:12:11+03:00 ERRO client/internal/engine.go:315: failed creating firewall manager: running [/sbin/iptables -t filter -C FORWARD -o wt0 -m mark --mark 0x000007e4 -j ACCEPT --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory Try `iptables -h' or 'iptables --help' for more information. ``` Not only that but there is a mechanism that deletes the FORWARD chain after a while. So maybe the proper appoach would be to check if iptables is iptables v1.8.3 (legacy) and the system is Synology and use the dirty way on the POSTROUTING chain that exists. for identifying Synology you can use something like this : ``` # Check script is running on a Synology NAS if ! /usr/bin/uname -a | grep -i synology >/dev/null; then echo "This script is NOT running on a Synology NAS!" echo "Copy the script to a folder on the Synology" echo "and run it from there." exit 1 # Not a Synology NAS fi # Get NAS model model=$(cat /proc/sys/kernel/syno_hw_version) #modelname="$model" # Show script version #echo -e "$script $scriptver\ngithub.com/$repo\n" echo "$script $scriptver" # Get DSM full version productversion=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION productversion) buildphase=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION buildphase) buildnumber=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION buildnumber) smallfixnumber=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION smallfixnumber) majorversion=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION majorversion) minorversion=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION minorversion) # Show DSM full version and model if [[ $buildphase == GM ]]; then buildphase=""; fi if [[ $smallfixnumber -gt "0" ]]; then smallfix="-$smallfixnumber"; fi echo -e "$model DSM $productversion-$buildnumber$smallfix $buildphase\n" # Print all the results at the end echo "Model: $model" echo "DSM Full Version: $productversion-$buildnumber$smallfix $buildphase" echo "Major Version: $majorversion" echo "Minor Version: $minorversion" ``` Another hint is that WGeasy works out of the box even as docker ( bridge mode ) With the following rules : ``` $ sudo iptables -L -v -n --line-numbers | grep 172.17.0.22 #( wgeasy ip ) Chain DOCKER 43 0 0 ACCEPT udp -- !docker0 docker0 0.0.0.0/0 172.17.0.22 udp dpt:51820 ``` ``` sudo iptables -t nat -L | grep 172.17.0.22 #( wgeasy ip ) Chain DEFAULT_POSTROUTING MASQUERADE udp -- 172.17.0.22 172.17.0.22 udp dpt:51820 DNAT udp -- anywhere anywhere udp dpt:51820to:172.17.0.22:51820 ``` Cause in the config we have : AllowedIPs = 0.0.0.0/0 That way client can decide what networks he will route to, as 0.0.0.0/0 is allowed.
saavagebueno added the bugclientwaiting-feedbacksynologyacl labels 2026-08-05 00:54:06 -04:00
Author
Owner

@zzecool commented on GitHub (May 21, 2024):

It will be best for a Dev to actually try SYnology on his self to verify everything related.

For that task he can easily use this : https://github.com/vdsm/virtual-dsm

This is a virtual Synology Server running isolated in Docker, so you can test anything you want about itables without any fear of breaking the machine.

You may hijack the mechanism that handles the iptables, or find other more clever way.

Fingers crossed.

<!-- gh-comment-id:2123329450 --> @zzecool commented on GitHub (May 21, 2024): It will be best for a Dev to actually try SYnology on his self to verify everything related. For that task he can easily use this : https://github.com/vdsm/virtual-dsm This is a virtual Synology Server running isolated in Docker, so you can test anything you want about itables without any fear of breaking the machine. You may hijack the mechanism that handles the iptables, or find other more clever way. Fingers crossed.
Author
Owner

@mlsmaycon commented on GitHub (May 22, 2024):

Hello @zzecool thanks for reporting this issue and sharing the virtual dsm project. We will have a look at it and report soon.

<!-- gh-comment-id:2125063995 --> @mlsmaycon commented on GitHub (May 22, 2024): Hello @zzecool thanks for reporting this issue and sharing the virtual dsm project. We will have a look at it and report soon.
Author
Owner

@mlsmaycon commented on GitHub (May 22, 2024):

Actually, can you confirm if it works on userspace mode too? see steps to enabled here: https://github.com/netbirdio/netbird/issues/1983#issuecomment-2125059066

<!-- gh-comment-id:2125068196 --> @mlsmaycon commented on GitHub (May 22, 2024): Actually, can you confirm if it works on userspace mode too? see steps to enabled here: https://github.com/netbirdio/netbird/issues/1983#issuecomment-2125059066
Author
Owner

@zzecool commented on GitHub (May 22, 2024):

Hello @zzecool thanks for reporting this issue and sharing the virtual dsm project. We will have a look at it and report soon.

@mlsmaycon Yes that will be great. The underlying mechanism in Synology not only deleting the FORWARD chain, it flushes every rule that has been added manually not by using their GUI firewall rule. The think is that this tool is useless for our case as it doesnt support masquerade etc.

Lets hope for a clean solution but a dirty will also be acceptable.

<!-- gh-comment-id:2125131541 --> @zzecool commented on GitHub (May 22, 2024): > Hello @zzecool thanks for reporting this issue and sharing the virtual dsm project. We will have a look at it and report soon. @mlsmaycon Yes that will be great. The underlying mechanism in Synology not only deleting the FORWARD chain, it flushes every rule that has been added manually not by using their GUI firewall rule. The think is that this tool is useless for our case as it doesnt support masquerade etc. Lets hope for a clean solution but a dirty will also be acceptable.
Author
Owner

@seehma commented on GitHub (Jun 18, 2024):

Hi, this ticket is now one month old. was there any progress? we also have a similar usecase and it would be cool to make it via our internal syno nas. regards m.

<!-- gh-comment-id:2176217698 --> @seehma commented on GitHub (Jun 18, 2024): Hi, this ticket is now one month old. was there any progress? we also have a similar usecase and it would be cool to make it via our internal syno nas. regards m.
Author
Owner

@fear commented on GitHub (Jul 31, 2024):

+1 from me :). Having the same Problem

<!-- gh-comment-id:2260891776 --> @fear commented on GitHub (Jul 31, 2024): +1 from me :). Having the same Problem
Author
Owner

@martijnw1986 commented on GitHub (Oct 11, 2024):

My Synology NAS is the only always-on Linux cliënt in my home. I've been pulling my hairs out for two days why I can't access my home network. I don't want to buy new hardware just because there's an issue with Netbird on Synology but if this doesn't get resolved, it seems like the only option.

<!-- gh-comment-id:2407396794 --> @martijnw1986 commented on GitHub (Oct 11, 2024): My Synology NAS is the only always-on Linux cliënt in my home. I've been pulling my hairs out for two days why I can't access my home network. I don't want to buy new hardware just because there's an issue with Netbird on Synology but if this doesn't get resolved, it seems like the only option.
Author
Owner

@Christopher87R commented on GitHub (Nov 30, 2024):

Any update on this issue?
It seems that Nidbrid does not make any iptables entries at all.

<!-- gh-comment-id:2509132228 --> @Christopher87R commented on GitHub (Nov 30, 2024): Any update on this issue? It seems that Nidbrid does not make any iptables entries at all.
Author
Owner

@nazarewk commented on GitHub (Apr 28, 2025):

Hello @zzecool,

We're currently reviewing our open issues and would like to verify if this problem still exists in the latest NetBird version.

Could you please confirm if the issue is still there?

We may close this issue temporarily if we don't hear back from you within 2 weeks, but feel free to reopen it with updated information.

Thanks for your contribution to improving the project!

<!-- gh-comment-id:2835669979 --> @nazarewk commented on GitHub (Apr 28, 2025): Hello @zzecool, We're currently reviewing our open issues and would like to verify if this problem still exists in the [latest NetBird version](https://github.com/netbirdio/netbird/releases). Could you please confirm if the issue is still there? We may close this issue temporarily if we don't hear back from you within **2 weeks**, but feel free to reopen it with updated information. Thanks for your contribution to improving the project!
Author
Owner

@mlsmaycon commented on GitHub (Jun 1, 2025):

closing issue due to no recent feedback. Feel free to open a new one if the issue persist or reopen if this was a feature request.

<!-- gh-comment-id:2927892676 --> @mlsmaycon commented on GitHub (Jun 1, 2025): closing issue due to no recent feedback. Feel free to open a new one if the issue persist or reopen if this was a feature request.
Author
Owner

@MarkSteadAus commented on GitHub (Oct 25, 2025):

I can confirm on the current version (0.59.8) NetBird does not create any iptables entries at all.
No packets are routed to/from the wt0 interface so communication is impossible.
It is using the userspace interface and the tun module is installed/active.

<!-- gh-comment-id:3446160912 --> @MarkSteadAus commented on GitHub (Oct 25, 2025): I can confirm on the current version (0.59.8) NetBird does not create any iptables entries at all. No packets are routed to/from the wt0 interface so communication is impossible. It is using the userspace interface and the tun module is installed/active.
Author
Owner

@crazy-matt commented on GitHub (Dec 10, 2025):

@mlsmaycon I can confirm the issue is still there on v0.60.7. Found those logs:

2025-12-09T22:30:29Z INFO client/firewall/create_linux.go:70: creating an iptables firewall manager
2025-12-09T22:30:29Z WARN client/firewall/create_linux.go:49: failed to create native firewall: init firewall: router init: create containers: add static nat rules: add outbound masquerade rule: running [/sbin/iptables -t nat -A NETBIRD-RT-NAT -m mark --mark 0x1bd21 ! -o lo -j MASQUERADE --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory
Try `iptables -h' or 'iptables --help' for more information.
2025-12-10T07:01:02Z INFO client/internal/statemanager/manager.go:412: cleaning up state iptables_state
2025-12-10T07:01:36Z INFO client/firewall/create_linux.go:70: creating an iptables firewall manager
2025-12-10T07:01:36Z WARN client/firewall/create_linux.go:49: failed to create native firewall: init firewall: router init: create containers: add static nat rules: add outbound masquerade rule: running [/sbin/iptables -t nat -A NETBIRD-RT-NAT -m mark --mark 0x1bd21 ! -o lo -j MASQUERADE --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory
Try `iptables -h' or 'iptables --help' for more information.
2025-12-10T12:07:31Z INFO client/internal/statemanager/manager.go:412: cleaning up state iptables_state
2025-12-10T12:07:34Z INFO client/firewall/create_linux.go:70: creating an iptables firewall manager
2025-12-10T12:07:34Z WARN client/firewall/create_linux.go:49: failed to create native firewall: init firewall: router init: create containers: add static nat rules: add outbound masquerade rule: running [/sbin/iptables -t nat -A NETBIRD-RT-NAT -m mark --mark 0x1bd21 ! -o lo -j MASQUERADE --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory
Try `iptables -h' or 'iptables --help' for more information.
<!-- gh-comment-id:3636902974 --> @crazy-matt commented on GitHub (Dec 10, 2025): @mlsmaycon I can confirm the issue is still there on v0.60.7. Found those logs: ``` 2025-12-09T22:30:29Z INFO client/firewall/create_linux.go:70: creating an iptables firewall manager 2025-12-09T22:30:29Z WARN client/firewall/create_linux.go:49: failed to create native firewall: init firewall: router init: create containers: add static nat rules: add outbound masquerade rule: running [/sbin/iptables -t nat -A NETBIRD-RT-NAT -m mark --mark 0x1bd21 ! -o lo -j MASQUERADE --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory Try `iptables -h' or 'iptables --help' for more information. 2025-12-10T07:01:02Z INFO client/internal/statemanager/manager.go:412: cleaning up state iptables_state 2025-12-10T07:01:36Z INFO client/firewall/create_linux.go:70: creating an iptables firewall manager 2025-12-10T07:01:36Z WARN client/firewall/create_linux.go:49: failed to create native firewall: init firewall: router init: create containers: add static nat rules: add outbound masquerade rule: running [/sbin/iptables -t nat -A NETBIRD-RT-NAT -m mark --mark 0x1bd21 ! -o lo -j MASQUERADE --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory Try `iptables -h' or 'iptables --help' for more information. 2025-12-10T12:07:31Z INFO client/internal/statemanager/manager.go:412: cleaning up state iptables_state 2025-12-10T12:07:34Z INFO client/firewall/create_linux.go:70: creating an iptables firewall manager 2025-12-10T12:07:34Z WARN client/firewall/create_linux.go:49: failed to create native firewall: init firewall: router init: create containers: add static nat rules: add outbound masquerade rule: running [/sbin/iptables -t nat -A NETBIRD-RT-NAT -m mark --mark 0x1bd21 ! -o lo -j MASQUERADE --wait]: exit status 2: iptables v1.8.3 (legacy): Couldn't load match `mark':No such file or directory Try `iptables -h' or 'iptables --help' for more information. ```
Author
Owner

@crazy-matt commented on GitHub (Dec 10, 2025):

For anyone finding this issue on a google search, extending the boot-up task documented here as below worked:

#!/bin/sh

TAG="Netbird Init"
log() {
  /usr/syno/bin/synologset1 sys "$1" 0x11100000 "$TAG: $2"
}

# Create the necessary file structure for /dev/net/tun
if [ ! -c /dev/net/tun ]; then
  if [ ! -d /dev/net ]; then
    mkdir -m 755 /dev/net
  fi
  mknod /dev/net/tun c 10 200
  chmod 0755 /dev/net/tun
fi

# Load the tun module if not already loaded
if ! lsmod | grep -q "^tun\s"; then
  insmod /lib/modules/tun.ko
  log info "tun module loaded"
fi

# Netbird workaround for missing libxt_mark.so
# Issue https://github.com/netbirdio/netbird/issues/1976
TIMEOUT=120
ELAPSED=0
INTERVAL=5
NETBIRD_CIDR="100.64.0.0/16"

while [ $ELAPSED -lt $TIMEOUT ]; do
  if ip link show wt0 >/dev/null 2>&1; then
    iptables -t nat -A POSTROUTING -s ${NETBIRD_CIDR} -o bond0 -j MASQUERADE
    log info "Netbird iptables rules applied successfully after ${ELAPSED}s"
    exit 0
  fi

  sleep $INTERVAL
  ELAPSED=$((ELAPSED + INTERVAL))
done

log warn "Netbird wt0 interface not found after ${TIMEOUT}s"
exit 1
<!-- gh-comment-id:3637892506 --> @crazy-matt commented on GitHub (Dec 10, 2025): For anyone finding this issue on a google search, extending the boot-up task documented [here](https://docs.netbird.io/get-started/install/synology#reboot-script) as below worked: ``` #!/bin/sh TAG="Netbird Init" log() { /usr/syno/bin/synologset1 sys "$1" 0x11100000 "$TAG: $2" } # Create the necessary file structure for /dev/net/tun if [ ! -c /dev/net/tun ]; then if [ ! -d /dev/net ]; then mkdir -m 755 /dev/net fi mknod /dev/net/tun c 10 200 chmod 0755 /dev/net/tun fi # Load the tun module if not already loaded if ! lsmod | grep -q "^tun\s"; then insmod /lib/modules/tun.ko log info "tun module loaded" fi # Netbird workaround for missing libxt_mark.so # Issue https://github.com/netbirdio/netbird/issues/1976 TIMEOUT=120 ELAPSED=0 INTERVAL=5 NETBIRD_CIDR="100.64.0.0/16" while [ $ELAPSED -lt $TIMEOUT ]; do if ip link show wt0 >/dev/null 2>&1; then iptables -t nat -A POSTROUTING -s ${NETBIRD_CIDR} -o bond0 -j MASQUERADE log info "Netbird iptables rules applied successfully after ${ELAPSED}s" exit 0 fi sleep $INTERVAL ELAPSED=$((ELAPSED + INTERVAL)) done log warn "Netbird wt0 interface not found after ${TIMEOUT}s" exit 1 ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#3748