if (binop->op == OP_AND && (expr->op == OP_NEQ || expr->op == OP_EQ) &&
right->dtype->basetype &&
- right->dtype->basetype->type == TYPE_BITMASK) {
- switch (right->etype) {
- case EXPR_VALUE:
- if (!mpz_cmp_ui(right->value, 0)) {
- /* Flag comparison: data & flags != 0
- *
- * Split the flags into a list of flag values and convert the
- * op to OP_EQ.
- */
- expr_free(right);
-
- expr->left = expr_get(binop->left);
- expr->right = binop_tree_to_list(NULL, binop->right);
- switch (expr->op) {
- case OP_NEQ:
- expr->op = OP_IMPLICIT;
- break;
- case OP_EQ:
- expr->op = OP_NEG;
- break;
- default:
- BUG("unknown operation type %d\n", expr->op);
- }
- expr_free(binop);
- } else if (binop->right->etype == EXPR_VALUE &&
- right->etype == EXPR_VALUE &&
- !mpz_cmp(right->value, binop->right->value)) {
- /* Skip flag / flag representation for:
- * data & flag == flag
- * data & flag != flag
- */
- ;
- } else {
- *exprp = flagcmp_expr_alloc(&expr->location, expr->op,
- expr_get(binop->left),
- binop_tree_to_list(NULL, binop->right),
- expr_get(right));
- expr_free(expr);
- }
+ right->dtype->basetype->type == TYPE_BITMASK &&
+ right->etype == EXPR_VALUE &&
+ !mpz_cmp_ui(right->value, 0)) {
+ /* Flag comparison: data & flags != 0
+ *
+ * Split the flags into a list of flag values and convert the
+ * op to OP_EQ.
+ */
+ expr_free(right);
+
+ expr->left = expr_get(binop->left);
+ expr->right = binop_tree_to_list(NULL, binop->right);
+ switch (expr->op) {
+ case OP_NEQ:
+ expr->op = OP_IMPLICIT;
break;
- case EXPR_BINOP:
- *exprp = flagcmp_expr_alloc(&expr->location, expr->op,
- expr_get(binop->left),
- binop_tree_to_list(NULL, binop->right),
- binop_tree_to_list(NULL, right));
- expr_free(expr);
+ case OP_EQ:
+ expr->op = OP_NEG;
break;
default:
- break;
+ BUG("unknown operation type %d\n", expr->op);
}
+ expr_free(binop);
} else if (binop->left->dtype->flags & DTYPE_F_PREFIX &&
binop->op == OP_AND && expr->right->etype == EXPR_VALUE &&
expr_mask_is_prefix(binop->right)) {
tcp flags cwr;ok
tcp flags != cwr;ok
tcp flags == syn;ok
-tcp flags fin,syn / fin,syn;ok
-tcp flags != syn / fin,syn;ok
+tcp flags fin,syn / fin,syn;ok;tcp flags & (fin | syn) == fin | syn
+tcp flags != syn / fin,syn;ok;tcp flags & (fin | syn) != syn
tcp flags & syn != 0;ok;tcp flags syn
tcp flags & syn == 0;ok;tcp flags ! syn
tcp flags & (syn | ack) != 0;ok;tcp flags syn,ack
# it should be possible to transform this to: tcp flags syn
tcp flags & syn == syn;ok
tcp flags & syn != syn;ok
-tcp flags & (fin | syn | rst | ack) syn;ok;tcp flags syn / fin,syn,rst,ack
-tcp flags & (fin | syn | rst | ack) == syn;ok;tcp flags syn / fin,syn,rst,ack
-tcp flags & (fin | syn | rst | ack) != syn;ok;tcp flags != syn / fin,syn,rst,ack
-tcp flags & (fin | syn | rst | ack) == (syn | ack);ok;tcp flags syn,ack / fin,syn,rst,ack
-tcp flags & (fin | syn | rst | ack) != (syn | ack);ok;tcp flags != syn,ack / fin,syn,rst,ack
-tcp flags & (syn | ack) == (syn | ack);ok;tcp flags syn,ack / syn,ack
+tcp flags & (fin | syn | rst | ack) syn;ok;tcp flags & (fin | syn | rst | ack) == syn
+tcp flags & (fin | syn | rst | ack) == syn;ok
+tcp flags & (fin | syn | rst | ack) != syn;ok
+tcp flags & (fin | syn | rst | ack) == syn | ack;ok
+tcp flags & (fin | syn | rst | ack) != syn | ack;ok
+tcp flags & (syn | ack) == syn | ack;ok
tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr;ok;tcp flags == 0xff
tcp flags { syn, syn | ack };ok
tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack };ok
--- /dev/null
+table inet filter {
+ map if_input {
+ type ifname : verdict
+ elements = { "eth0" : jump public_input,
+ "eth1" : jump home_input,
+ "eth2.10" : jump home_input,
+ "eth2.20" : jump home_input }
+ }
+
+ map if_forward {
+ type ifname : verdict
+ elements = { "eth0" : jump public_forward,
+ "eth1" : jump trusted_forward,
+ "eth2.10" : jump voip_forward,
+ "eth2.20" : jump guest_forward }
+ }
+
+ map if_output {
+ type ifname : verdict
+ elements = { "eth0" : jump public_output,
+ "eth1" : jump home_output,
+ "eth2.10" : jump home_output,
+ "eth2.20" : jump home_output }
+ }
+
+ set ipv4_blacklist {
+ type ipv4_addr
+ flags interval
+ auto-merge
+ }
+
+ set ipv6_blacklist {
+ type ipv6_addr
+ flags interval
+ auto-merge
+ }
+
+ set limit_src_ip {
+ type ipv4_addr
+ size 1024
+ flags dynamic,timeout
+ }
+
+ set limit_src_ip6 {
+ type ipv6_addr
+ size 1024
+ flags dynamic,timeout
+ }
+
+ chain PREROUTING_RAW {
+ type filter hook prerouting priority raw; policy accept;
+ meta l4proto != { icmp, tcp, udp, ipv6-icmp } counter packets 0 bytes 0 drop
+ tcp flags syn jump {
+ tcp option maxseg size 1-500 counter packets 0 bytes 0 drop
+ tcp sport 0 counter packets 0 bytes 0 drop
+ }
+ rt type 0 counter packets 0 bytes 0 drop
+ }
+
+ chain PREROUTING_MANGLE {
+ type filter hook prerouting priority mangle; policy accept;
+ ct state vmap { invalid : jump ct_invalid_pre, related : jump rpfilter, new : jump ct_new_pre, untracked : jump ct_untracked_pre }
+ }
+
+ chain ct_invalid_pre {
+ counter packets 0 bytes 0 drop
+ }
+
+ chain ct_untracked_pre {
+ icmpv6 type { mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } return
+ counter packets 0 bytes 0 drop
+ }
+
+ chain ct_new_pre {
+ jump rpfilter
+ tcp flags & (fin | syn | rst | ack) != syn counter packets 0 bytes 0 drop
+ iifname "eth0" meta nfproto vmap { ipv4 : jump blacklist_input_ipv4, ipv6 : jump blacklist_input_ipv6 }
+ }
+
+ chain rpfilter {
+ ip saddr 0.0.0.0 ip daddr 255.255.255.255 udp sport 68 udp dport 67 return
+ ip6 saddr :: ip6 daddr . icmpv6 type { ff02::1:ff00:0/104 . nd-neighbor-solicit, ff02::16 . mld2-listener-report } return
+ fib saddr . iif oif 0 counter packets 0 bytes 0 drop
+ }
+
+ chain blacklist_input_ipv4 {
+ ip saddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } counter packets 0 bytes 0 drop
+ ip saddr @ipv4_blacklist counter packets 0 bytes 0 drop
+ }
+
+ chain blacklist_input_ipv6 {
+ icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 return
+ udp sport 547 ip6 saddr fe80::/64 return
+ ip6 saddr { ::/3, 2001::/32, 2001:2::/48, 2001:3::/32, 2001:10::-2001:2f:ffff:ffff:ffff:ffff:ffff:ffff, 2001:db8::/32, 2002::/16, 3000::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } counter packets 0 bytes 0 drop
+ ip6 saddr @ipv6_blacklist counter packets 0 bytes 0 drop
+ }
+
+ chain INPUT {
+ type filter hook input priority filter; policy drop;
+ iif "lo" accept
+ ct state established,related accept
+ iifname vmap @if_input
+ log prefix "NFT REJECT IN " flags ip options flags ether limit rate 5/second burst 10 packets reject
+ }
+
+ chain public_input {
+ icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 ip6 hoplimit 255 accept
+ udp sport 547 udp dport 546 ip6 saddr fe80::/64 accept
+ fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop
+ counter packets 0 bytes 0 drop
+ }
+
+ chain home_input {
+ icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+ icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+ udp sport 68 udp dport 67 accept
+ udp sport 546 udp dport 547 iifname { "eth1", "eth2.10", "eth2.20" } accept
+ fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop
+ icmp type echo-request accept
+ icmpv6 type echo-request accept
+ tcp dport 22 iifname "eth1" accept
+ meta l4proto { tcp, udp } th dport 53 jump {
+ ip6 saddr != { fd00::/8, fe80::/64 } counter packets 0 bytes 0 reject with icmpv6 port-unreachable
+ accept
+ }
+ udp dport 123 accept
+ tcp dport 8443 accept
+ }
+
+ chain FORWARD_MANGLE {
+ type filter hook forward priority mangle; policy accept;
+ oifname "eth0" jump {
+ ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
+ tcp flags & (syn | rst) == syn tcp option maxseg size set rt mtu
+ }
+ }
+
+ chain blacklist_output_ipv4 {
+ ip daddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } goto log_blacklist
+ ip daddr @ipv4_blacklist goto log_blacklist
+ }
+
+ chain blacklist_output_ipv6 {
+ icmpv6 type . ip6 daddr { nd-router-solicit . ff02::2, nd-neighbor-solicit . ff02::1:ff00:0/104, nd-neighbor-advert . fe80::/64, nd-neighbor-advert . ff02::1, nd-neighbor-advert . ff02::1:ff00:0/104, mld2-listener-report . ff02::16 } return
+ udp dport 547 ip6 daddr ff02::1:2 return
+ ip6 daddr { ::/3, 2001::/32, 2001:2::/48, 2001:3::/32, 2001:10::-2001:2f:ffff:ffff:ffff:ffff:ffff:ffff, 2001:db8::/32, 2002::/16, 3000::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } goto log_blacklist
+ ip6 daddr @ipv6_blacklist goto log_blacklist
+ }
+
+ chain log_blacklist {
+ log prefix "NFT BLACKLIST " flags ip options flags ether limit rate 5/minute burst 10 packets drop
+ counter packets 0 bytes 0 drop
+ }
+
+ chain FORWARD {
+ type filter hook forward priority filter; policy drop;
+ ct state established,related accept
+ fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop
+ iifname vmap @if_forward
+ log prefix "NFT REJECT FWD " flags ip options flags ether limit rate 5/second burst 10 packets reject
+ }
+
+ chain public_forward {
+ udp dport { 5060, 7078-7097 } oifname "eth2.10" jump {
+ ip6 saddr { 2001:db8::1-2001:db8::2 } accept
+ meta nfproto ipv6 log prefix "NFT DROP SIP " flags ip options flags ether limit rate 5/second burst 10 packets drop
+ }
+ counter packets 0 bytes 0 drop
+ }
+
+ chain trusted_forward {
+ oifname "eth0" accept
+ icmp type echo-request accept
+ icmpv6 type echo-request accept
+ ip daddr { 192.168.3.30, 192.168.4.40 } tcp dport vmap { 22 : accept, 80 : drop, 443 : accept }
+ ip daddr 192.168.2.20 jump {
+ tcp dport { 80, 443, 515, 631, 9100 } accept
+ udp dport 161 accept
+ }
+ }
+
+ chain voip_forward {
+ icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } oifname "eth0" accept
+ ip6 daddr { 2001:db8::1-2001:db8::2 } jump {
+ udp dport { 3478, 5060 } accept
+ udp sport 7078-7097 accept
+ tcp dport 5061 accept
+ }
+ tcp dport 587 ip daddr 10.0.0.1 accept
+ tcp dport 80 oifname "eth0" counter packets 0 bytes 0 reject
+ }
+
+ chain guest_forward {
+ oifname "eth0" accept
+ }
+
+ chain OUTPUT {
+ type filter hook output priority filter; policy drop;
+ oif "lo" accept
+ ct state vmap { invalid : jump ct_invalid_out, established : accept, related : accept, untracked : jump ct_untracked_out }
+ oifname vmap @if_output
+ log prefix "NFT REJECT OUT " flags ip options flags ether limit rate 5/second burst 10 packets reject
+ }
+
+ chain ct_invalid_out {
+ counter packets 0 bytes 0 drop
+ }
+
+ chain ct_untracked_out {
+ icmpv6 type { mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } return
+ counter packets 0 bytes 0 drop
+ }
+
+ chain public_output {
+ ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
+ icmp type { destination-unreachable, echo-request, time-exceeded, parameter-problem } accept
+ icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
+ icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+ icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+ udp dport 547 ip6 saddr fe80::/64 ip6 daddr ff02::1:2 accept
+ udp dport { 53, 123 } accept
+ tcp dport { 443, 587, 853 } accept
+ }
+
+ chain home_output {
+ icmp type { destination-unreachable, echo-request, time-exceeded, parameter-problem } accept
+ icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
+ icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+ icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+ udp sport 547 udp dport 546 ip6 saddr fe80::/64 oifname { "eth1", "eth2.10", "eth2.20" } accept
+ udp sport 67 udp dport 68 ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } accept
+ tcp dport 22 ip daddr 192.168.1.10 accept
+ }
+
+ chain POSTROUTING_SRCNAT {
+ type nat hook postrouting priority srcnat; policy accept;
+ ip saddr { 192.168.1.0-192.168.4.255 } oifname "eth0" masquerade
+ }
+}