1

I have nftables setup to reject packets that don't match my allow block (nft list ruleset added below), but the packets are being dropped instead.

For context, I have a service that listens on port 8080 that only localhost should have access to (for now). My setup allows that but clients are timing out with their requests instead of getting a reject.

This is the ruleset I'm using (slightly truncated for brevity), including the traces I've used for debugging:

# nft list ruleset
table inet firewall {
    set allowed_protocols {
            type inet_proto
            elements = { icmp, ipv6-icmp }
    }

    set allowed_interfaces {
            type ifname
            elements = { "lo" }
    }

    set allowed_tcp_dports {
            type inet_service
            elements = { 22, 80, 443 }
    }

    chain allow {
            ct state established,related accept
            meta l4proto @allowed_protocols accept
            iifname @allowed_interfaces accept
            meta nftrace set 1
            tcp dport @allowed_tcp_dports accept
    }

    chain input {
            type filter hook input priority 20; policy accept;
            jump allow
            meta nftrace set 1
            reject
    }

    chain forward {
            type filter hook forward priority 20; policy accept;
            jump allow
            meta nftrace set 1
            reject
    }
}

From my trace, I can see packets being dropped instead:

trace id 36f72c1b inet firewall allow rule meta nftrace set 1 (verdict continue)
trace id 36f72c1b inet firewall allow verdict continue
trace id 36f72c1b inet firewall input rule meta nftrace set 1 (verdict continue)
trace id 36f72c1b inet firewall input rule reject (verdict drop)

It explicitly reads reject but then decided to drop anyway. Any idea what the cause for this is?

ricekab
  • 123
  • 5

1 Answers1

1

Seeing verdict drop in the trace is normal. The reject still sends the proper ICMP error, not simply dropping the packet. You can fire up Wireshark and look at them if you wish to be sure. Yes, this is confusing.

Michael Hampton
  • 244,070
  • 43
  • 506
  • 972
  • I don't know why I didn't think of checking the trace on the client side. Feeling kind of stupid now. Thanks for the answer! – ricekab Sep 03 '20 at 08:53
  • Would you happen to know how I can translate this into an immediate failure when doing a request instead of a timeout? For example, when I `curl` the endpoint it waits for a timeout but I'd like it to immediately fail on rejection. – ricekab Sep 03 '20 at 08:55
  • 1
    @ricekab You already should get an immediate failure if you try to hit a firewalled port. Better pop open Wireshark again and take a closer look. – Michael Hampton Sep 03 '20 at 18:37
  • I should've been more clear - I do see the ICMP reject coming in on Wireshark. It is when I hit the endpoint using a client, like `curl` or `python-requests`, that they're waiting for timeouts. It seems the clients don't get informed about the reject message so they'll just retry and timeout as they normally would. – ricekab Sep 04 '20 at 13:21
  • 1
    @ricekab Do you have a local firewall interfering with ICMP? – Michael Hampton Sep 04 '20 at 16:22