Skip to content

Bug: Gluetun does not allow NDP packets through the firewall #3475

Description

@ranile

Is this urgent?

None

Host OS

Debian Trixie

CPU arch

x86_64

VPN service provider

ProtonVPN

What are you using to run the container

docker run

What is the version of Gluetun

Running version latest built on 2026-09-01T01:11:28.450Z (commit bc5e219) on Linux 6.12.100+deb13-amd64 (x86_64)

What's the problem 🤔

it's impossible to talk to gluetun on an IPv6-only network. The firewall blocks NDP so neighbor solicitation packets never go through and no service can reach gluetun (errors as "host unreachable").

Running this in another container in the gluetun network name solves the issue:

R="INPUT -i eth0 -p ipv6-icmp --icmpv6-type neighbour-solicitation -d ff02::1:ff00:0/104 -j ACCEPT"
while ip6tables -C $$R 2>/dev/null || ip6tables -I $$R; do sleep 10; done

It's fine in an IPv4 or dual stack network because ARP is used for neighbor discovery in v4: ARP. In v6 networks, NDP is used and that must be allowed through IP firewalls (NDP uses multicast IP address)

I briefly mentioned this in #3157 (comment) but I figured I should open an issue for it as well, since it is still a bug in both main and nftables implementation

Share your logs (at least 10 lines)

2026-09-14T20:43:47+08:00 INFO [routing] default route found: interface eth0, gateway 2001:db8::1, assigned IP 2001:db8::2 and family v6
2026-09-14T20:43:47+08:00 INFO [routing] local ethernet link found: eth0
2026-09-14T20:43:47+08:00 INFO [routing] local ipnet found: 2001:db8::/112
2026-09-14T20:43:47+08:00 INFO [routing] local ipnet found: fe80::/64
2026-09-14T20:43:47+08:00 INFO [firewall] enabling...
2026-09-14T20:43:47+08:00 INFO [firewall] enabled successfully
2026-09-14T20:43:47+08:00 INFO [storage] merging by most recent 26611 hardcoded servers and 26667 servers read from manifest file /gluetun/servers/manifest.json
2026-09-14T20:43:47+08:00 INFO [storage] Using protonvpn servers from file (marked as preferred)
2026-09-14T20:43:48+08:00 INFO Alpine version: 3.23.5
2026-09-14T20:43:48+08:00 INFO OpenVPN version: 2.6.20
2026-09-14T20:43:48+08:00 INFO Firewall version: iptables v1.8.11
docker compose exec -it gluetun ip6tables -S # without gluetun-ndp container
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -d 2001:db8::/112 -i eth0 -j ACCEPT
-A INPUT -d fe80::/64 -i eth0 -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -s 2001:db8::2/128 -d 2001:db8::/112 -o eth0 -j ACCEPT
-A OUTPUT -d ff02::1:ff00:0/104 -o eth0 -j ACCEPT
-A OUTPUT -s 2001:db8::2/128 -d fe80::/64 -o eth0 -j ACCEPT
-A OUTPUT -d 2a02:6ea0:d101:2282::10/128 -o eth0 -p udp -m udp --dport 51820 -j ACCEPT
-A OUTPUT -o tun0 -j ACCEPT

Share your configuration

gluetun:
    image: qmcgaw/gluetun:latest
    container_name: gluetun
    restart: unless-stopped
    networks: [media]
    sysctls:
      - net.ipv6.conf.all.disable_ipv6=0
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    environment:
      TZ: "${TZ}"
      VPN_SERVICE_PROVIDER: protonvpn
      VPN_TYPE: wireguard
      WIREGUARD_PRIVATE_KEY: "${PROTON_WG_PRIVATE_KEY}"
      SERVER_COUNTRIES: "${PROTON_COUNTRIES}"
      VPN_PORT_FORWARDING: "on"
      VPN_PORT_FORWARDING_PROVIDER: protonvpn
      WIREGUARD_ADDRESSES: 10.2.0.2/32,2a07:b944::2:2/128
      DNS_UPSTREAM_IPV6: "on"
      FIREWALL_OUTBOUND_SUBNETS: "2001:db8::/112"
      VPN_PORT_FORWARDING_UP_COMMAND: '/bin/sh -c ''wget -qO- --post-data="json={\"listen_port\":{{PORTS}}}" http://127.0.0.1:${QBT_PORT}/api/v2/app/setPreferences'''
      HTTPPROXY: "on"
      HTTPPROXY_LISTENING_ADDRESS: ":${HTTPPROXY_PORT}"
      HTTPPROXY_STEALTH: "on"
      HTTPPROXY_LOG: "off"
    volumes:
      - ${APPDATA_DIR}/gluetun:/gluetun

# workaround for this issue
  gluetun-ndp:
    image: qmcgaw/gluetun:latest
    container_name: gluetun-ndp
    restart: unless-stopped
    network_mode: "service:gluetun"
    depends_on:
      gluetun:
        condition: service_healthy
    cap_add:
      - NET_ADMIN
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        R="INPUT -i eth0 -p ipv6-icmp --icmpv6-type neighbour-solicitation -d ff02::1:ff00:0/104 -j ACCEPT"
        while ip6tables -C $$R 2>/dev/null || ip6tables -I $$R; do sleep 10; done

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions