#3463·gluetun

Bug:Title: Kernelspace WireGuard implementation causes VPN-side NAT mapping to expire during idle UDP traffic (breaks torrent DHT), userspace does not

Author: RDHoworthCreated Sep 8, 2026Updated Sep 9, 2026
LabelsCategory: Wireguard 🔐Category: Investigation 🔍

Is this urgent?

No

Host OS

Ubuntu Server 26,04 LTS

CPU arch

x86_64

VPN service provider

Privado

What are you using to run the container

docker-compose

What is the version of Gluetun

2026-09-01T23:04:47.130Z

What's the problem

When using a custom WireGuard provider (Privado, no official port forwarding), switching gluetun's WireGuard implementation from userspace to kernelspace (the current auto default when the kernel module is available) causes inbound UDP traffic to silently stop being deliverable after a period of low outbound traffic on a given port — specifically breaking BitTorrent DHT for qBittorrent running via network_mode: service:gluetun.

With WIREGUARD_IMPLEMENTATION=userspace, DHT node counts remain stable over many hours of idle periods. With auto/kernelspace, DHT node counts gradually decay to 0 and never recover without a full container restart.

Steps to reproduce Run gluetun with VPN_SERVICE_PROVIDER=custom, VPN_TYPE=wireguard, connected to a provider with no official port forwarding (Privado in my case) Run qBittorrent (linuxserver image) with network_mode: service:gluetun Leave the client mostly idle (no active downloads) for several hours Observe DHT node count in qBittorrent's WebUI gradually drop to 0 and never recover Restart the stack — DHT briefly repopulates, then decays again over time Expected behavior

DHT node count should remain stable during idle periods, consistent with behavior observed when WIREGUARD_IMPLEMENTATION=userspace is explicitly set.

Actual behavior

Only occurs with kernelspace WireGuard (auto default, confirmed via logs: Using available kernelspace implementation). Setting WIREGUARD_IMPLEMENTATION=userspace explicitly resolves the issue completely — DHT nodes remain populated after several hours of no activity.

Environment gluetun image: qmcgaw/gluetun:latest (please note actual version tag/commit if you can get it — see note below) VPN_SERVICE_PROVIDER: custom VPN_TYPE: wireguard Provider: Privado (no official port forwarding support) Host: [add: OS / kernel version, e.g. Ubuntu 24.04, kernel 6.x] qBittorrent image: lscr.io/linuxserver/qbittorrent:latest

Additional context

This regression appeared after rebuilding the Docker host and re-pulling :latest images — the same WireGuard keys, same VPN server, and same compose configuration had worked reliably for months prior on an older gluetun version, which (as far as I can tell) was always using the userspace implementation since kernelspace detection didn't exist yet.

My working theory: kernelspace WireGuard's NAT/conntrack refresh behavior for the tunnel differs from the userspace implementation in a way that causes the VPN provider's exit-server NAT mapping for sparse/low-frequency UDP traffic (like DHT) to expire, whereas userspace's behavior keeps it alive. This isn't caught by gluetun's own healthcheck since the WireGuard tunnel to the VPN server itself never drops — only inbound reachability for certain traffic patterns is affected.

Workaround

Setting WIREGUARD_IMPLEMENTATION=userspace explicitly fixes the issue.

Share your logs (at least 10 lines)

plain
========================================
========================================
=============== gluetun ================
========================================
=========== Made with ❤️ by ============
======= https://github.com/qdm12 =======
========================================
========================================

Running version latest built on 2026-09-01T23:04:47.130Z (commit 0fef7b2) on Linux 7.0.0-31-generic (x86_64)

 Need help? ☕ Discussion? https://github.com/qdm12/gluetun/discussions/new/choose
 Bug? ✨ New feature? https://github.com/qdm12/gluetun/issues/new/choose
 Email? [email protected]
 Help me? https://www.paypal.me/qmcgaw https://github.com/sponsors/qdm12
2026-09-07T13:05:04Z WARN You are using the old environment variable VPN_ENDPOINT_IP, please consider changing it to OPENVPN_ENDPOINT_IP
2026-09-07T13:05:04Z WARN You are using the old environment variable VPN_ENDPOINT_PORT, please consider changing it to OPENVPN_ENDPOINT_PORT
2026-09-07T13:05:04Z WARN You are using the old environment variable VPN_ENDPOINT_IP, please consider changing it to WIREGUARD_ENDPOINT_IP
2026-09-07T13:05:04Z WARN You are using the old environment variable VPN_ENDPOINT_PORT, please consider changing it to WIREGUARD_ENDPOINT_PORT
2026-09-07T13:05:04Z INFO [routing] default route found: interface eth0, gateway 172.19.0.1, assigned IP 172.19.0.2 and family v4
2026-09-07T13:05:04Z INFO [routing] local ethernet link found: eth0
2026-09-07T13:05:04Z INFO [routing] local ipnet found: 172.19.0.0/16
2026-09-07T13:05:04Z INFO [firewall] enabling...
2026-09-07T13:05:04Z INFO [firewall] enabled successfully
2026-09-07T13:05:04Z INFO [storage] writing servers data files to /gluetun/servers/ with 26611 hardcoded servers
2026-09-07T13:05:04Z INFO Alpine version: 3.23.5
2026-09-07T13:05:04Z INFO OpenVPN version: 2.6.20
2026-09-07T13:05:04Z INFO Firewall version: iptables v1.8.11
2026-09-07T13:05:04Z INFO Settings summary:
├── VPN settings:
|   ├── VPN provider settings:
|   |   ├── Name: custom
|   |   └── Server selection settings:
|   |       ├── VPN type: wireguard
|   |       └── Wireguard selection settings:
|   |           ├── Endpoint IP address: 91.148.228.128
|   |           ├── Endpoint port: 51820
|   |           └── Server public key: =
|   ├── Wireguard settings:
|   |   ├── Private key: qKg...l8=
|   |   ├── Interface addresses:
|   |   |   └── 100.64.141.217/32
|   |   ├── Allowed IPs:
|   |   |   ├── 0.0.0.0/0
|   |   |   └── ::/0
|   |   ├── Persistent keepalive interval: 10s
|   |   ├── Network interface: tun0
|   |   |   └── MTU: use path MTU discovery
|   |   └── Implementation: userspace
|   └── Path MTU discovery:
|       ├── ICMP addresses:
|       |   ├── 1.1.1.1
|       |   └── 8.8.8.8
|       └── TCP addresses:
|           ├── 1.1.1.1:443
|           ├── 8.8.8.8:443
|           ├── 1.1.1.1:53
|           ├── 8.8.8.8:53
|           ├── [2606:4700:4700::1111]:53
|           ├── [2001:4860:4860::8888]:53
|           ├── [2606:4700:4700::1111]:443
|           └── [2001:4860:4860::8888]:443
├── DNS settings:
|   ├── Upstream resolver type: dot
|   ├── Upstream resolvers:
|   |   └── Cloudflare
|   ├── Caching: yes
|   ├── IPv6: no
|   ├── Update period: every 24h0m0s
|   └── DNS filtering settings:
|       ├── Block malicious: yes
|       └── Block ads: no
├── Firewall settings:
|   ├── Enabled: yes
|   ├── Iptables settings:
|   |   └── Log level: info
|   ├── Input ports:
|   |   ├── 8080
|   |   └── 54321
|   └── Outbound subnets:
|       └── 192.168.111.0/24
├── Log settings:
|   └── Log level: info
├── IPv6 settings:
|   └── Check addresses:
|       ├── [2001:4860:4860::8888]:53
|       └── [2606:4700:4700::1111]:53
├── Metrics settings:
|   └── Type: noop
├── Health settings:
|   ├── Server listening address: 127.0.0.1:9999
|   ├── Target addresses:
|   |   ├── cloudflare.com:443
|   |   └── github.com:443
|   ├── Small health check type: ICMP echo request
|   |   └── ICMP target IPs:
|   |       ├── 1.1.1.1
|   |       └── 8.8.8.8
|   └── Restart VPN on healthcheck failure: yes
├── SOCKS5 proxy server settings:
|   └── Enabled: no
├── Shadowsocks server settings:
|   └── Enabled: no
├── HTTP proxy settings:
|   └── Enabled: no
├── Control server settings:
|   ├── Listening address: :8000
|   ├── Logging: yes
|   └── Authentication file path: /gluetun/auth/config.toml
├── Storage settings:
|   └── Servers directory path: /gluetun/servers/
├── OS Alpine settings:
|   ├── Process UID: 1000
|   └── Process GID: 1000
├── Public IP settings:
|   ├── IP file path: /tmp/gluetun/ip
|   ├── Public IP data base API: ipinfo
|   └── Public IP data backup APIs:
|       ├── ifconfigco
|       ├── ip2location
|       └── cloudflare
└── Version settings:
    └── Enabled: yes
2026-09-07T13:05:04Z INFO [routing] default route found: interface eth0, gateway 172.19.0.1, assigned IP 172.19.0.2 and family v4
2026-09-07T13:05:04Z INFO [routing] adding route for 0.0.0.0/0
2026-09-07T13:05:04Z INFO [firewall] setting allowed subnets...
2026-09-07T13:05:04Z INFO [routing] default route found: interface eth0, gateway 172.19.0.1, assigned IP 172.19.0.2 and family v4
2026-09-07T13:05:04Z INFO [routing] adding route for 192.168.111.0/24
2026-09-07T13:05:04Z INFO [firewall] setting allowed input port 8080 through interface eth0...
2026-09-07T13:05:04Z INFO [firewall] setting allowed input port 54321 through interface eth0...
2026-09-07T13:05:04Z INFO [healthcheck] listening on 127.0.0.1:9999
2026-09-07T13:05:04Z INFO [http server] http server listening on [::]:8000
2026-09-07T13:05:04Z INFO [firewall] allowing VPN connection...
2026-09-07T13:05:04Z INFO [wireguard] Connecting to 91.148.228.128:51820
2026-09-07T13:05:04Z INFO [vpn] wireguard setup is complete. Note wireguard is a silent protocol and it may or may not work, without giving any error message. Typically i/o timeout errors indicate the wireguard connection is not working.
2026-09-07T13:05:04Z INFO [MTU discovery] finding maximum MTU, this can take up to 6 seconds
2026-09-07T13:05:04Z INFO [MTU discovery] reverting VPN interface tun0 MTU to 1320 (due to: ICMP path MTU discovery: finding IPv4 next hop MTU to 1.1.1.1: checking next-hop-mtu found: ICMP Next Hop MTU is too high: 1480 is larger than physical link MTU 1440)
2026-09-07T13:05:04Z INFO [dns] DNS server listening on [::]:53
2026-09-07T13:05:04Z INFO [dns] ready and using DNS server with dot upstream resolvers
2026-09-07T13:05:04Z INFO [dns] downloading hostnames and IP block lists
2026-09-07T13:05:05Z INFO [ip getter] Public IP address is 91.148.228.133 (United Kingdom, England, Manchester - source: ipinfo+ifconfig.co+ip2location+cloudflare)
2026-09-07T13:05:05Z INFO [vpn] You are running on the bleeding edge of latest!
2026-09-07T13:05:05Z INFO [dns] leak check report: 104.23.169.40 (20%), 172.71.101.98 (20%), 104.23.167.42 (10%), 104.23.171.40 (10%), 141.101.75.86 (10%), 162.159.112.43 (10%), 172.70.45.99 (10%), 172.71.181.105 (10%)

2026-09-08T01:00:00Z WARN Caught OS signal terminated, shutting down
2026-09-08T01:00:00Z INFO updater ticker: terminated ✔️
2026-09-08T01:00:00Z INFO http server: terminated ✔️
2026-09-08T01:00:00Z INFO dns ticker: terminated ✔️
2026-09-08T01:00:00Z INFO control: terminated ✔️
2026-09-08T01:00:00Z INFO updater: terminated ✔️
2026-09-08T01:00:00Z INFO tickers: terminated ✔️
2026-09-08T01:00:00Z INFO HTTP health server: terminated ✔️
2026-09-08T01:00:00Z ERROR [wireguard] Failed to load updated MTU of device: failed to get MTU of TUN device: no such device
2026-09-08T01:00:00Z INFO vpn: terminated ✔️
2026-09-08T01:00:00Z INFO shadowsocks proxy: terminated ✔️
2026-09-08T01:00:00Z INFO http proxy: terminated ✔️
2026-09-08T01:00:00Z INFO dns: terminated ✔️
2026-09-08T01:00:00Z INFO other: terminated ✔️
2026-09-08T01:00:00Z INFO [routing] routing cleanup...
2026-09-08T01:00:00Z INFO [routing] default route found: interface eth0, gateway 172.19.0.1, assigned IP 172.19.0.2 and family v4
2026-09-08T01:00:00Z INFO [routing] deleting route for 0.0.0.0/0
2026-09-08T01:00:00Z INFO [routing] deleting route for 192.168.111.0/24
                         @@@
                         @@@@
                        @@@@@@
                       @@@@.@@                       @@@@@@@@@@
                       @@@@.@@@                   @@@@@@@@==@@@@
                      @@@.@..@@                @@@@@@@=@..==@@@@
            @@@@      @@@.@@.@@              @@@@@@===@@@@.=@@@
           @...-@@   @@@@.@@.@@@  @@@     @@@@@@=======@@@=@@@@
           @@@@@@@@  @@@.-%@.+@@@@@@@@  @@@@@%============@@@@
                     @@@.--@..@@@@.-@@@@@@@==============@@@@
              @@@@  @@@-@--@@.@@.---@@@@@==============#@@@@@
              @@@   @@@.@@-@@.@@--@@@@@===============@@@@@@
                   @@@@.@--@@@@@@@@@@================@@@@@@@
                   @@@..--@@*@@@@@@================@@@@+*@@
                   @@@.---@@.@@@@=================@@@@--@@
                  @@@-.---@@@@@@================@@@@*--@@@
                  @@@.:-#@@@@@@===============*@@@@.---@@
                  @@@.-------.@@@============@@@@@@.--@@@
                 @@@..--------:@@@=========@@@@@@@@.--@@@
                 @@@.-@@@@@@@@@@@========@@@@@  @@@.--@@
                 @@.@@@@===============@@@@@ @@@@@@---@@@@@@
                @@@@@@@==============@@@@@@@@@@@@*@---@@@@@@@@
                @@@@@@=============@@@@@ @@@...------------.*@@@
                @@@@%===========@@@@@@ @@@..------@@@@.-----.-@@@
                @@@@@@.=======@@@@@@  @@@.-------@@@@@@-.------=@@
               @@@@@@@@@===@@@@@@     @@.------@@@@   @@@@.-----@@@
               @@@==@@@=@@@@@@@      @@@.-@@@@@@@       @@@@@@@--@@
               @@@@@@@@@@@@@         @@@@@@@@                @@@@@@@
                @@@@@@@@             @@@@                       @@@@
                                                                       
2026-09-08T01:00:00Z INFO Shutdown successful
========================================
========================================
=============== gluetun ================
========================================
=========== Made with ❤️ by ============
======= https://github.com/qdm12 =======
========================================

Share your configuration

yaml
Environment
gluetun version: latest, built 2026-09-01T23:04:47.130Z, commit 0fef7b2
Host kernel: Linux 7.0.0-31-generic (x86_64)
Alpine base: 3.23.5
VPN_SERVICE_PROVIDER: custom
VPN_TYPE: wireguard
Provider: Privado (no official port forwarding support)
qBittorrent image: lscr.io/linuxserver/qbittorrent:latest

Compose File:
services:
  gluetun:
    image: qmcgaw/gluetun:latest
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    ports:
      - 9980:8080 # qBittorrent Web UI
      - 54321:54321 # Torrent listening port (TCP)
      - 54321:54321/udp # Torrent listening port (UDP)
    environment:
      - WIREGUARD_IMPLEMENTATION=userspace
      - VPN_SERVICE_PROVIDER=custom
      - VPN_TYPE=wireguard
      - WIREGUARD_PRIVATE_KEY=
      - WIREGUARD_PUBLIC_KEY=
      - WIREGUARD_ADDRESSES=100.64.141.217/32
      - VPN_ENDPOINT_IP=91.148.228.128
      - VPN_ENDPOINT_PORT=51820
      - WIREGUARD_PERSISTENT_KEEPALIVE_INTERVAL=10s
      - HTTPPROXY=off
      - SHADOWSOCKS=off
      - FIREWALL_OUTBOUND_SUBNETS=192.168.111.0/24
      - FIREWALL_INPUT_PORTS=8080,54321
    restart: unless-stopped
  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    network_mode: service:gluetun
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/London
      - WEBUI_PORT=8080
    volumes:
      - /opt/docker/appdata/qbittorrent:/config
      - /mnt/DataStore:/downloads
    depends_on:
      gluetun:
        condition: service_healthy
        restart: true
    restart: unless-stopped
networks: {}