Skip to content

A VPN protects you only while it is up. When the tunnel drops because of a Wi-Fi hiccup, a server restart or a laptop waking from sleep, the operating system quietly goes back to the normal connection, and anything that retries in that moment leaves with your real address. A kill switch closes that gap by blocking the normal route whenever the tunnel is not there.

On Windows or a phone, the kill switch is a checkbox. On Linux, linux vpn kill switch means something different: a firewall rule you write yourself. That sounds heavier than it is. This article shows three ways to build one, explains which traffic you must still allow so you do not cut your own legs off, and gives a safe way to test. The background idea is covered in what a VPN kill switch is; here we only build and verify it.

What a kill switch really is on Linux

Linux filters packets in the kernel using netfilter, and tools such as nftables, iptables and ufw are different front-ends to the same engine. A kill switch is one policy written in that engine:

  1. Allow traffic on the loopback interface.
  2. Allow traffic out of the VPN interface, such as wg0 or tun0.
  3. Allow the small amount of traffic that builds the tunnel: packets to the VPN server's address and port.
  4. Allow the things you deliberately want outside, such as your local printer network, if any.
  5. Drop or reject everything else that tries to leave.

There is nothing magic in it. If the tunnel disappears, rule 2 matches nothing, rule 5 catches the rest, and applications simply time out instead of connecting in the open. Because the policy is a firewall rule, it keeps working whether the tunnel is managed by wg-quick, NetworkManager or a plain OpenVPN command.

Decide what you want to block

Pick your level before you write anything.

Approach Blocks Strength Risk
wg-quick PostUp rule Everything not going through the WireGuard interface, while it is up Lives in the config file; appears and disappears with the tunnel Does not protect before the tunnel starts or after it is brought down
Permanent nftables policy Everything except tunnel, server and exceptions, at all times Protects boot, sleep and reconnect gaps You must manage exceptions, and a mistake can disconnect you
ufw default deny outgoing Same idea with a friendlier tool Easy to read and persists across reboots Needs several allow rules; easy to forget DHCP
Per-application control A single program only Useful for one app Other apps still leak

Be clear on one trade-off. A rule that exists only while the tunnel is up cannot protect the moments around it. A permanent policy protects those moments but means the computer has no internet at all until you start the tunnel. For a laptop used on public Wi-Fi, many people accept that; for a household machine others prefer the lighter rule.

Method 1: rules inside wg-quick

WireGuard's own documentation describes a pair of lines you can put in the interface section of the config. They add the rule when the tunnel comes up and remove it when it goes down.

[Interface]
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT && ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT && ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT

How to read it: reject any output packet that is not going out of the tunnel interface (%i), is not marked as the tunnel's own encrypted traffic (the fwmark WireGuard sets), and is not for a local address. The tunnel's own packets to the server carry that mark, so they pass.

Limits worth knowing: this works with wg-quick, not with a NetworkManager-imported WireGuard profile, and distributions that use the nft backend for iptables behave the same way. Because the rule is removed in PreDown, running wg-quick down returns you to normal internet access, which is correct when you chose to disconnect but means a crash that skips PreDown can leave the rule behind. Check with sudo iptables -S OUTPUT.

Method 2: a permanent nftables policy

nftables lets you describe the whole policy in one readable file. Replace the capitals with your values.

table inet killswitch {
  chain output {
    type filter hook output priority 0; policy accept;
    oif "lo" accept
    oifname "wg0" accept
    ip daddr SERVER_IP udp dport 51820 accept
    ip daddr 192.168.1.0/24 accept
    udp dport { 67, 68 } accept
    counter drop
  }
}

Load it with sudo nft -f killswitch.nft, and remove it with sudo nft delete table inet killswitch. Notes on each line:

  • oif "lo" keeps local services such as the DNS stub working.
  • oifname "wg0" allows everything that goes out through the tunnel. Use tun0 for OpenVPN.
  • The SERVER_IP line lets the encrypted packets reach the VPN server. Use an address, not a hostname, because the name must be resolved outside the tunnel before it works.
  • The local subnet line is optional: it keeps your printer and NAS reachable. Remove it if you do not want that.
  • DHCP ports let the machine renew its address on Wi-Fi. Without them the connection dies after the lease expires.
  • counter drop ends the chain and shows how many packets were blocked, which is useful when you test.

Because the table is named inet, it covers both IPv4 and IPv6. IPv6 traffic that is not going out through the tunnel is dropped, which prevents the quiet IPv6 leak many people overlook. IPv6 is defined in RFC 8200, and many networks use it by default today, so do not skip this.

Method 3: ufw, for people who prefer simple commands

ufw suits desktops that already use it.

sudo ufw default deny outgoing
sudo ufw default deny incoming
sudo ufw allow out on wg0
sudo ufw allow out to SERVER_IP port 51820 proto udp
sudo ufw allow out 67/udp
sudo ufw allow out to 192.168.1.0/24
sudo ufw enable

ufw already handles loopback in its default rules. Check the result with sudo ufw status verbose. Disable it with sudo ufw default allow outgoing and sudo ufw disable if you need to recover. ufw rules persist across reboots, which is good for protection and bad if you forget they are there and wonder why a new network does not work. Another change: a laptop that moves to a network with a captive portal needs the portal page to load before the tunnel can start, so you may have to relax the rule briefly.

Allow the things that must pass

Most lockouts come from forgetting one of these.

  1. The VPN server itself. Without a rule for its address and port, the tunnel can never start.
  2. DHCP. The machine asks the router for an address by UDP ports 67 and 68.
  3. Local network access. Only if you want it; otherwise leave it out.
  4. Hostnames used by the config. If the config uses a name, resolve it to an address first and write the address.
  5. Captive portals. Hotel and cafe networks need a page to load before the tunnel will work. Plan a manual relaxation step.
  6. Fallback access. On a remote machine, an SSH session from a specific address may need its own allow rule, or you lose the session as soon as the policy loads.

For the SSH case in particular, read the warning in the command-line guide.

Test it safely

Never load a new kill switch and walk away. Use a timer so a bad rule removes itself.

  1. Open two terminals. In the first, schedule removal: sleep 300; sudo nft delete table inet killswitch (or the ufw undo commands).
  2. In the second, load the rules.
  3. With the tunnel up, check that ordinary traffic works: curl -s https://example.org -o /dev/null -w "%{http_code}\n".
  4. Bring the interface down without removing the rules: sudo ip link set wg0 down.
  5. Try curl again. It should fail or time out. That is the kill switch working.
  6. Check that DNS also fails to resolve outside the tunnel: resolvectl query example.org should not return an answer through your Wi-Fi link.
  7. Bring the tunnel up again and confirm recovery. If the timer fires first, repeat with a longer wait.

Then follow the wider checks in how to test a VPN, including a public-address check and IPv6.

Making it persistent, and removing it

To load nftables rules at boot, save the file where your distribution expects it (often /etc/nftables.conf) and enable the nftables service. On systems that use ufw, ufw enable is persistent already. For wg-quick hook rules, enabling wg-quick@wg0 adds them on every start.

Document how to remove it. A note taped inside the notes app saying "sudo nft delete table inet killswitch" saves a stressful evening. If you sell, lend or hand on the machine, remove the policy first.

A quick scenario shows why the exceptions matter. Mei uses a permanent nftables policy on a laptop. At home everything works. At a hotel the Wi-Fi shows a login page, but the page cannot load because the policy blocks everything except the tunnel, and the tunnel cannot start without internet. She keeps a second file with a relaxed policy and a one-line command to swap it in, finishes the portal login, then swaps the strict policy back and starts the tunnel. The extra file took two minutes to write and saved her from a locked laptop in a hotel lobby.

Limits and honest caveats

  • A kill switch stops leaks when the tunnel fails. It does not make you anonymous and does not protect accounts from phishing.
  • Applications that already hold a connection open may take a moment to fail. Short timeouts are normal.
  • Policies that rely on a fwmark, like Method 1, are specific to WireGuard. For OpenVPN, use the interface-based policy.
  • Some desktop tools, VMs and containers have their own networks and may bypass your OUTPUT rules; check their traffic too.
  • Do not copy rules from the internet that you do not understand. A line that drops traffic is easy to write and hard to debug.

Summary

On Linux a kill switch is a firewall policy: allow loopback, the tunnel interface, the packets that reach the VPN server and the few exceptions you want, and drop the rest. Use wg-quick hooks for a light, tunnel-bound rule, nftables for a permanent policy that covers IPv4 and IPv6, or ufw if you prefer simple commands. Test with a self-removing timer, confirm that bringing the tunnel down really stops traffic, and write down how to undo it. If you prefer a desktop app with a prepaid pass, see the download page and the pricing page.

Frequently asked questions

Does Linux have a built-in VPN kill switch?

Not as a single switch in the kernel or the desktop. A Linux kill switch is a firewall rule that only lets traffic leave through the VPN interface, plus the packets needed to reach the VPN server. You build it with nftables, iptables, ufw or the hooks in wg-quick.

Will a kill switch lock me out of my own network?

It can if you forget to allow loopback, DHCP, your local network or the VPN server address. Always test with a timer that removes the rules automatically, and keep console access on remote machines.

Do I need separate rules for IPv6?

Yes. If the tunnel does not carry IPv6, traffic to IPv6 sites can leave outside it. Either block IPv6 output the same way as IPv4 or disable IPv6 on the physical interface.

Does a kill switch stop DNS leaks too?

It stops DNS packets from leaving through the normal interface, because all output except the tunnel is blocked. You still need the tunnel's DNS settings to be correct so lookups succeed inside the tunnel.

Can I use the same rules for OpenVPN?

The nftables and ufw approaches work for any tunnel interface such as tun0, as long as you allow the OpenVPN server address and port. The wg-quick hook lines apply only to WireGuard.

About the author

Bob Kanokphon Thongdee, founder of XPASS VPN

Bob Kanokphon Thongdee

  • Founder of XPASS VPN
  • Co-founder of eSIMonline.asia
  • More than 7 years in online marketing
  • Founder of Cojourney Visa and Cojourney Travel

Need a VPN for a short trip or a busy month?

XPASS sells prepaid passes for a set number of days. You pay once and nothing renews automatically.

See passes

Keep reading

VPN Security

What Is a VPN Kill Switch?

A kill switch stops your device from quietly falling back to an unprotected connection when the VPN drops. Here is how the idea works and how to check it.

12 min read

Device Guides

How to Use a VPN Kill Switch on Windows

The built-in Windows VPN has no kill switch toggle. Learn how to look for one in your app, what a manual firewall approach involves, and how to test the result.

10 min read

VPN Security

How to Test a VPN: Leaks, Speed and Kill Switch

A VPN is only useful if it does what it claims. This guide shows how to test any VPN yourself: leaks, kill switch, speed, latency, IPv6 and the app's own behaviour.

9 min read

VPN Security

IPv6 Leaks and VPNs: A Practical Guide

A hands-on guide to IPv6 leaks with a VPN: why two address families create a gap, how to test, how to read the result, and the fixes to try in order.

10 min read

VPN Security

WireGuard vs OpenVPN Explained

WireGuard and OpenVPN both build encrypted tunnels, but they differ in design, complexity and flexibility. Here is a plain comparison and how to think about the choice.

9 min read