Use application specific nft table by alice945 · Pull Request #1423 · evilsocket/opensnitch (original) (raw)

Closes #1260, fixes #1393.

This patch makes Opensnitch use its own nft table rather than modifying and breaking the existing system ruleset.

Demonstration

The following is a demonstration of how Opensnitch modifies the system ruleset currently and how it does so after this patch is applied.

0 - Initial Ruleset

Since #1393 used Arch Linux's default packaged ruleset as an example, I will also use it as the base system ruleset for this demonstration. Here I simply run nft flush ruleset and nft -f /etc/nftables.conf once.

nft list ruleset > 0.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

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

1.1 - Current, Daemon Started

Here I run systemctl start opensnitchd.service with "Enabled": false in /etc/opensnitchd/system-fw.json. In order for it to function, Opensnitch needs to inject a rule for DNS interception in chain input-filter-inet, and add two rules for outbound connection interception in chain output-mangle-inet.

Note

nft list ruleset > 1.1.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy accept;
        udp sport 53 queue flags bypass to 0
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
    }
}
table inet mangle {
    chain output {
        type route hook output priority mangle; policy accept;
        meta l4proto != tcp ct state related,new queue flags bypass to 0
        tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
    }
}

diff -u 0.nft 1.1.nft

--- 0.nft +++ 1.1.nft @@ -1,6 +1,7 @@ table inet filter { chain input { - type filter hook input priority filter; policy drop; + type filter hook input priority filter; policy accept; + udp sport 53 queue flags bypass to 0 ct state invalid drop comment "early drop of invalid connections" ct state { established, related } accept comment "allow tracked connections" iif "lo" accept comment "allow from loopback" @@ -15,3 +16,10 @@ type filter hook forward priority filter; policy drop; } } +table inet mangle { + chain output { + type route hook output priority mangle; policy accept; + meta l4proto != tcp ct state related,new queue flags bypass to 0 + tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0 + } +}

1.2 - Current, Daemon Running, Firewall Enabled

Here I open opensnitch-ui and enable the main switch in the firewall dialog. Opensnitch should now apply the default firewall configuration at /etc/opensnitchd/system-fw.json.

nft list ruleset > 1.2.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy accept;
        udp sport 53 queue flags bypass to 0
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

    chain forward {
        type filter hook forward priority filter; policy accept;
    }

    chain output {
        type filter hook output priority filter; policy accept;
    }
}
table inet mangle {
    chain output {
        type route hook output priority mangle; policy accept;
        icmp type { echo-reply, destination-unreachable, echo-request } accept
        icmpv6 type { destination-unreachable, echo-request, echo-reply } accept
        meta l4proto != tcp ct state related,new queue flags bypass to 0
        tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
    }

    chain prerouting {
        type filter hook prerouting priority mangle; policy accept;
    }

    chain postrouting {
        type filter hook postrouting priority mangle; policy accept;
    }

    chain forward {
        type filter hook forward priority mangle; policy accept;
    }
}
table inet nat {
    chain filter-prerouting {
        type filter hook prerouting priority filter; policy accept;
    }

    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
    }

    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
    }

    chain input {
        type nat hook input priority srcnat; policy accept;
    }

    chain output {
        type nat hook output priority 100; policy accept;
    }
}

diff -u 1.1.nft 1.2.nft

--- 1.1.nft +++ 1.2.nft @@ -13,13 +13,52 @@ }

 chain forward {

1.3.1 - Current, Daemon Running, Firewall Enabled, Deny Inbound

Here I change the Inbound dropdown in the firewall dialog from Allow to Deny. Opensnitch should now configure chain input-filter-inet with policy drop and apply helpful rules when input is set to drop.

Note

nft list ruleset > 1.3.1.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        udp sport 53 queue flags bypass to 0
        iifname "lo" accept
        ct state established,related accept
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }
}
table inet mangle {
    chain output {
        type route hook output priority mangle; policy accept;
        icmp type { echo-reply, destination-unreachable, echo-request } accept
        icmpv6 type { destination-unreachable, echo-request, echo-reply } accept
        meta l4proto != tcp ct state related,new queue flags bypass to 0
        tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
    }
}
table inet nat {
}

diff -u 1.2.nft 1.3.1.nft

@@ -28,37 +22,6 @@ meta l4proto != tcp ct state related,new queue flags bypass to 0 tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0 }

1.3.2 - Current, Daemon Running, Firewall Enabled, Deny Outbound

Here I change the Inbound dropdown in the firewall dialog back from Deny to Allow, and instead change Outbound from Allow to Deny. Opensnitch should now restore chain input-filter-inet, configure chain output-mangle-inet with policy drop and apply helpful rules when output is set to drop.

Note

nft list ruleset > 1.3.2.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy accept;
        udp sport 53 queue flags bypass to 0
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

    chain forward {
        type filter hook forward priority filter; policy accept;
    }

    chain output {
        type filter hook output priority filter; policy accept;
    }
}
table inet mangle {
    chain output {
        type route hook output priority mangle; policy drop;
        icmp type { echo-reply, destination-unreachable, echo-request } accept
        icmpv6 type { destination-unreachable, echo-request, echo-reply } accept
        ct state established,related accept
        meta l4proto != tcp ct state related,new queue flags bypass to 0
        tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
    }

    chain prerouting {
        type filter hook prerouting priority mangle; policy accept;
    }

    chain postrouting {
        type filter hook postrouting priority mangle; policy accept;
    }

    chain forward {
        type filter hook forward priority mangle; policy accept;
    }
}
table inet nat {
    chain filter-prerouting {
        type filter hook prerouting priority filter; policy accept;
    }

    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
    }

    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
    }

    chain input {
        type nat hook input priority srcnat; policy accept;
    }

    chain output {
        type nat hook output priority 100; policy accept;
    }
}

diff -u 1.3.1.nft 1.3.2.nft

--- 1.3.1.nft +++ 1.3.2.nft @@ -1,9 +1,7 @@ table inet filter { chain input { - type filter hook input priority filter; policy drop; + type filter hook input priority filter; policy accept; udp sport 53 queue flags bypass to 0 - iifname "lo" accept - ct state established,related accept ct state invalid drop comment "early drop of invalid connections" ct state { established, related } accept comment "allow tracked connections" iif "lo" accept comment "allow from loopback" @@ -13,15 +11,55 @@ meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited counter packets 0 bytes 0 } + + chain forward { + type filter hook forward priority filter; policy accept; + } + + chain output { + type filter hook output priority filter; policy accept; + } } table inet mangle { chain output { - type route hook output priority mangle; policy accept; + type route hook output priority mangle; policy drop; icmp type { echo-reply, destination-unreachable, echo-request } accept icmpv6 type { destination-unreachable, echo-request, echo-reply } accept + ct state established,related accept meta l4proto != tcp ct state related,new queue flags bypass to 0 tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0 } + + chain prerouting { + type filter hook prerouting priority mangle; policy accept; + } + + chain postrouting { + type filter hook postrouting priority mangle; policy accept; + } + + chain forward { + type filter hook forward priority mangle; policy accept; + } } table inet nat { + chain filter-prerouting { + type filter hook prerouting priority filter; policy accept; + } + + chain prerouting { + type nat hook prerouting priority dstnat; policy accept; + } + + chain postrouting { + type nat hook postrouting priority srcnat; policy accept; + } + + chain input { + type nat hook input priority srcnat; policy accept; + } + + chain output { + type nat hook output priority 100; policy accept; + } }

diff -u 1.2.nft 1.3.2.nft

--- 1.2.nft +++ 1.3.2.nft @@ -22,9 +22,10 @@ } table inet mangle { chain output { - type route hook output priority mangle; policy accept; + type route hook output priority mangle; policy drop; icmp type { echo-reply, destination-unreachable, echo-request } accept icmpv6 type { destination-unreachable, echo-request, echo-reply } accept + ct state established,related accept meta l4proto != tcp ct state related,new queue flags bypass to 0 tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0 }

1.4 - Current, Daemon Stopped

Here I exit opensnitch-ui and run systemctl stop opensnitchd.service. Opensnitch should now be completely disabled, and the initially configured ruleset should be restored.

Note

nft list ruleset > 1.4.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy accept;
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }
}
table inet mangle {
}
table inet nat {
}

diff -u 1.3.2.nft 1.4.nft

diff -u 0.nft 1.4.nft

2.1 - Patched, Daemon Started

From here on I repeat the same procedure done in the previous section, this time with the patch applied.

Note

nft list ruleset > 2.1.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
    }
}
table inet opensnitch {
    chain intercept_dns {
        type filter hook input priority filter - 1; policy accept;
        udp sport 53 queue flags bypass to 0
    }

    chain intercept_con {
        type route hook output priority mangle + 1; policy accept;
        meta l4proto != tcp ct state related,new queue flags bypass to 0
        tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
    }
}

diff -u 0.nft 2.1.nft

--- 0.nft +++ 2.1.nft @@ -15,3 +15,15 @@ type filter hook forward priority filter; policy drop; } } +table inet opensnitch { + chain intercept_dns { + type filter hook input priority filter - 1; policy accept; + udp sport 53 queue flags bypass to 0 + } + + chain intercept_con { + type route hook output priority mangle + 1; policy accept; + meta l4proto != tcp ct state related,new queue flags bypass to 0 + tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0 + } +}

2.2 - Patched, Daemon Running, Firewall Enabled

Note

nft list ruleset > 2.2.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
    }
}
table inet opensnitch {
    chain intercept_dns {
        type filter hook input priority filter - 1; policy accept;
        udp sport 53 queue flags bypass to 0
    }

    chain intercept_con {
        type route hook output priority mangle + 1; policy accept;
        meta l4proto != tcp ct state related,new queue flags bypass to 0
        tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
    }

    chain filter_forward {
        type filter hook forward priority filter; policy accept;
    }

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

    chain filter_input {
        type filter hook input priority filter; policy accept;
    }

    chain filter_prerouting {
        type filter hook prerouting priority filter; policy accept;
    }

    chain mangle_prerouting {
        type filter hook prerouting priority mangle; policy accept;
    }

    chain mangle_postrouting {
        type filter hook postrouting priority mangle; policy accept;
    }

    chain nat_prerouting {
        type nat hook prerouting priority dstnat; policy accept;
    }

    chain nat_postrouting {
        type nat hook postrouting priority srcnat; policy accept;
    }

    chain nat_input {
        type nat hook input priority srcnat; policy accept;
    }

    chain nat_output {
        type nat hook output priority 100; policy accept;
    }

    chain mangle_output {
        type filter hook output priority mangle; policy accept;
        icmp type { echo-reply, destination-unreachable, echo-request } accept
        icmpv6 type { destination-unreachable, echo-request, echo-reply } accept
    }

    chain mangle_forward {
        type filter hook forward priority mangle; policy accept;
    }
}

diff -u 2.1.nft 2.2.nft

--- 2.1.nft +++ 2.2.nft @@ -26,4 +26,54 @@ meta l4proto != tcp ct state related,new queue flags bypass to 0 tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0 } + + chain filter_forward { + type filter hook forward priority filter; policy accept; + } + + chain filter_output { + type filter hook output priority filter; policy accept; + } + + chain filter_input { + type filter hook input priority filter; policy accept; + } + + chain filter_prerouting { + type filter hook prerouting priority filter; policy accept; + } + + chain mangle_prerouting { + type filter hook prerouting priority mangle; policy accept; + } + + chain mangle_postrouting { + type filter hook postrouting priority mangle; policy accept; + } + + chain nat_prerouting { + type nat hook prerouting priority dstnat; policy accept; + } + + chain nat_postrouting { + type nat hook postrouting priority srcnat; policy accept; + } + + chain nat_input { + type nat hook input priority srcnat; policy accept; + } + + chain nat_output { + type nat hook output priority 100; policy accept; + } + + chain mangle_output { + type filter hook output priority mangle; policy accept; + icmp type { echo-reply, destination-unreachable, echo-request } accept + icmpv6 type { destination-unreachable, echo-request, echo-reply } accept + } + + chain mangle_forward { + type filter hook forward priority mangle; policy accept; + } }

2.3.1 - Patched, Daemon Running, Firewall Enabled, Deny Inbound

nft list ruleset > 2.3.1.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
    }
}
table inet opensnitch {
    chain intercept_dns {
        type filter hook input priority filter - 1; policy accept;
        udp sport 53 queue flags bypass to 0
    }

    chain intercept_con {
        type route hook output priority mangle + 1; policy accept;
        meta l4proto != tcp ct state related,new queue flags bypass to 0
        tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
    }

    chain filter_forward {
        type filter hook forward priority filter; policy accept;
    }

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

    chain filter_input {
        type filter hook input priority filter; policy drop;
        iifname "lo" accept
        ct state established,related accept
    }

    chain filter_prerouting {
        type filter hook prerouting priority filter; policy accept;
    }

    chain mangle_prerouting {
        type filter hook prerouting priority mangle; policy accept;
    }

    chain mangle_postrouting {
        type filter hook postrouting priority mangle; policy accept;
    }

    chain nat_prerouting {
        type nat hook prerouting priority dstnat; policy accept;
    }

    chain nat_postrouting {
        type nat hook postrouting priority srcnat; policy accept;
    }

    chain nat_input {
        type nat hook input priority srcnat; policy accept;
    }

    chain nat_output {
        type nat hook output priority 100; policy accept;
    }

    chain mangle_output {
        type filter hook output priority mangle; policy accept;
        icmp type { echo-reply, destination-unreachable, echo-request } accept
        icmpv6 type { destination-unreachable, echo-request, echo-reply } accept
    }

    chain mangle_forward {
        type filter hook forward priority mangle; policy accept;
    }
}

diff -u 2.2.nft 2.3.1.nft

--- 2.2.nft +++ 2.3.1.nft @@ -36,7 +36,9 @@ }

 chain filter_input {

2.3.2 - Patched, Daemon Running, Firewall Enabled, Deny Outbound

nft list ruleset > 2.3.2.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
    }
}
table inet opensnitch {
    chain intercept_dns {
        type filter hook input priority filter - 1; policy accept;
        udp sport 53 queue flags bypass to 0
    }

    chain intercept_con {
        type route hook output priority mangle + 1; policy accept;
        meta l4proto != tcp ct state related,new queue flags bypass to 0
        tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0
    }

    chain filter_forward {
        type filter hook forward priority filter; policy accept;
    }

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

    chain filter_input {
        type filter hook input priority filter; policy accept;
    }

    chain filter_prerouting {
        type filter hook prerouting priority filter; policy accept;
    }

    chain mangle_prerouting {
        type filter hook prerouting priority mangle; policy accept;
    }

    chain mangle_postrouting {
        type filter hook postrouting priority mangle; policy accept;
    }

    chain nat_prerouting {
        type nat hook prerouting priority dstnat; policy accept;
    }

    chain nat_postrouting {
        type nat hook postrouting priority srcnat; policy accept;
    }

    chain nat_input {
        type nat hook input priority srcnat; policy accept;
    }

    chain nat_output {
        type nat hook output priority 100; policy accept;
    }

    chain mangle_output {
        type filter hook output priority mangle; policy drop;
        icmp type { echo-reply, destination-unreachable, echo-request } accept
        icmpv6 type { destination-unreachable, echo-request, echo-reply } accept
        ct state established,related accept
    }

    chain mangle_forward {
        type filter hook forward priority mangle; policy accept;
    }
}

diff -u 2.3.1.nft 2.3.2.nft

--- 2.3.1.nft +++ 2.3.2.nft @@ -36,9 +36,7 @@ }

 chain filter_input {

@@ -70,9 +68,10 @@ }

 chain mangle_output {

diff -u 2.2.nft 2.3.2.nft

--- 2.2.nft +++ 2.3.2.nft @@ -68,9 +68,10 @@ }

 chain mangle_output {

2.4 - Patched, Daemon Stopped

Note

nft list ruleset > 2.4.nft

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        ct state invalid drop comment "early drop of invalid connections"
        ct state { established, related } accept comment "allow tracked connections"
        iif "lo" accept comment "allow from loopback"
        ip protocol icmp accept comment "allow icmp"
        meta l4proto ipv6-icmp accept comment "allow icmp v6"
        tcp dport 22 accept comment "allow sshd"
        meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited
        counter packets 0 bytes 0
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
    }
}
table inet opensnitch {
}

diff -u 2.3.2.nft 2.4.nft

--- 2.3.2.nft +++ 2.4.nft @@ -16,65 +16,4 @@ } } table inet opensnitch { - chain intercept_dns { - type filter hook input priority filter - 1; policy accept; - udp sport 53 queue flags bypass to 0 - }

diff -u 0.nft 2.4.nft

--- 0.nft +++ 2.4.nft @@ -15,3 +15,5 @@ type filter hook forward priority filter; policy drop; } } +table inet opensnitch { +}