NixOS / NixOS/nixpkgs

nixos/mullvad-vpn: mullvad sets up nftables regardless of system settings

Open
#464,331 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

0.kind: bug 2.status: stale 6.topic: nixos
Dominant language
Nix
Stars
26.2k
Forks
20.1k
PR merge metrics
PR metrics pending

Description

Nixpkgs version
  • Unstable (25.11)
Describe the bug

After upgrading my system, mullvad has started setting up nftables with the killswitch enabled by default (for some reason).

This got me stuck without internet even after running sudo iptables -F because apparently it set up nftables even though I did not set networking.nftables.enable = true.

Steps to reproduce

Set services.mullvad-vpn.enable = true

Expected behaviour

mullvad uses iptables as the system is configured to do

Screenshots

No response

Relevant log output
$ sudo nix-shell -p nftables --run 'nft list ruleset' # note I did not have nft in my path
table inet mullvad {
        chain prerouting {
                type filter hook prerouting priority -199; policy accept;
        }

        chain output {
                type filter hook output priority filter; policy drop;
                oif "lo" accept
                ct mark [mark] accept
                udp sport 68 ip daddr 255.255.255.255 udp dport 67 accept
                ip6 saddr [ipv6] udp sport 546 ip6 daddr [ipv6] udp dport 547 accept
                ip6 saddr [ipv6] udp sport 546 ip6 daddr [ipv6] udp dport 547 accept
                ip6 daddr [ipv6] icmpv6 type nd-router-solicit icmpv6 code 0 accept
                ip6 daddr [ipv6] icmpv6 type nd-neighbor-solicit icmpv6 code 0 accept
                ip6 daddr [ipv6] icmpv6 type nd-neighbor-solicit icmpv6 code 0 accept
                ip6 daddr [ipv6] icmpv6 type nd-neighbor-advert icmpv6 code 0 accept
                ip daddr [ipv4] tcp dport 443 meta skuid 0 accept
                udp dport 53 reject
                tcp dport 53 reject with tcp reset
                reject
        }

        chain input {
                type filter hook input priority filter; policy drop;
                iif "lo" accept
                ct mark [mark] accept
                udp sport 67 udp dport 68 accept
                ip6 saddr [ipv6] udp sport 547 ip6 daddr [ipv6] udp dport 546 accept
                ip6 saddr [ipv6] icmpv6 type nd-router-advert icmpv6 code 0 accept
                ip6 saddr [ipv6] icmpv6 type nd-redirect icmpv6 code 0 accept
                ip6 saddr [ipv6] icmpv6 type nd-neighbor-solicit icmpv6 code 0 accept
                icmpv6 type nd-neighbor-advert icmpv6 code 0 accept
                ip saddr [ipv4] tcp sport 443 ct state established meta skuid 0 accept
        }

        chain forward {
                type filter hook forward priority filter; policy drop;
                ct mark [mark] accept
                udp sport 68 ip daddr 255.255.255.255 udp dport 67 accept
                udp sport 67 udp dport 68 accept
                ip6 saddr [ipv6] udp sport 546 ip6 daddr [ipv6] udp dport 547 accept
                ip6 saddr [ipv6] udp sport 546 ip6 daddr [ipv6] udp dport 547 accept
                ip6 saddr [ipv6] udp sport 547 ip6 daddr [ipv6] udp dport 546 accept
                ip6 daddr [ipv6] icmpv6 type nd-router-solicit icmpv6 code 0 accept
                ip6 saddr [ipv6] icmpv6 type nd-router-advert icmpv6 code 0 accept
                ip6 saddr [ipv6] icmpv6 type nd-redirect icmpv6 code 0 accept
                ip6 daddr [ipv6] icmpv6 type nd-neighbor-solicit icmpv6 code 0 accept
                ip6 daddr [ipv6] icmpv6 type nd-neighbor-solicit icmpv6 code 0 accept
                ip6 saddr [ipv6] icmpv6 type nd-neighbor-solicit icmpv6 code 0 accept
                ip6 daddr [ipv6] icmpv6 type nd-neighbor-advert icmpv6 code 0 accept
                icmpv6 type nd-neighbor-advert icmpv6 code 0 accept
                udp dport 53 reject
                tcp dport 53 reject with tcp reset
                reject
        }

        chain mangle {
                type route hook output priority mangle; policy accept;
                meta cgroup [group] ct mark set [mark] meta mark set 0x6d6f6c65
        }

        chain nat {
                type nat hook postrouting priority srcnat; policy accept;
                oif != "lo" ct mark [mark] masquerade
        }
}
Additional context

No response

System metadata
$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 6.17.8-cachyos, NixOS, 25.11 (Xantusia), 25.11.20251112.c5ae371`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.31.2`
 - nixpkgs: `/nix/store/f640ps0hcp7w5jzg18djf8gdhl6r2rnl-source`
Notify maintainers

@arcuru @ymarkus


Note for maintainers: Please tag this issue in your pull request description. (i.e. Resolves #ISSUE.)

I assert that this issue is relevant for Nixpkgs
Is this issue important to you?

Add a 👍 reaction to issues you find important.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the NixOS module behind services.mullvad-vpn.enable and compare its firewall behavior with networking.nftables.enable. Reproduce the issue with nft list ruleset after enabling Mullvad, then verify that Mullvad uses the system-configured firewall backend without enabling nftables unexpectedly.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.