I am setting up a homelab server with Tailscale, and I am also trying to learn new stuff along the way. I’ve never worked with xtables/nftables, so I wanted to try it out instead of ufw.

My goals for the setup were:

  • Tailscale manages its own traffic (aka everything on tailscale0). Otherwise:
    • all outgoing traffic is allowed
    • forwarding is not allowed
    • incoming is not allowed, unless it’s port 22 from my local LAN (for quick at-home debugging)
    • ICMP is allowed for pinging

I’ve scouted Arch Linux wiki and nftables wiki and have made this config:

flush ruleset

table inet my_chain {
    set LANv4 {
        type ipv4_addr
        flags interval

        elements = { 192.168.1.0/24 }
    }

    set LANv6 {
        type ipv6_addr
        flags interval

        elements = { fe80::/64 }
    }

    chain my_lan_input {
        tcp dport ssh accept comment "Accept SSH on port 22"
    }

    chain my_input {
        type filter hook input priority filter; policy drop;

        iif lo accept comment "Accept localhost traffic"
        ct state invalid drop comment "Drop invalid connections"
        ct state established,related accept comment "Accept traffic originated from us"

        meta l4proto ipv6-icmp accept comment "Accept ICMPv6"
        meta l4proto icmp accept comment "Accept ICMP"

        ip6 saddr @LANv6 jump my_lan_input comment "Connections from private IPv6 address ranges"
        ip saddr @LANv4 jump my_lan_input comment "Connections from private IPv4 address ranges"
    }

    chain my_forward {
        type filter hook forward priority filter; policy drop;
    }

    chain my_output {
        type filter hook output priority filter; policy accept;
    }
}

I put this config in /etc/nftables.conf, set TS_DEBUG_FIREWALL_MODE=nftables, and restarted my machine. After booting, Tailscale added its own chains, as expected:

$ sudo nft list tables
table inet my_chain
table ip filter
table ip nat
table ip6 filter
table ip6 nat

But now, I can’t connect to my machine over HTTP(S) from Tailscale; When I go to the node’s address in the browser, I get a timeout. I’ve tried setting the priority of my chain to filter + 1, but to no avail. How do I make this work?

(I realise this is more a networking question than a Tailscale one, but maybe someone had faced a similar situation)