diff --git a/net b/net index ece39b4..2551ccc 100755 --- a/net +++ b/net @@ -26,6 +26,93 @@ find_next_subnet() { echo "172.$i" } +nft_rev() { + local family + local table + local chain + local protocol + local field + local port + local policy + + local filter + local remove + + source "$NET_CONF_FILE" + + family="$3" + table="$4" + chain="$5" + if [[ "$chain" = 'INPUT' ]]; then + protocol="$6" + field="$7" + port="$8" + policy="$9" + + filter=" + .nftables[] | select(.rule) | .rule + | select(.family|test(\"$family\")) + | select(.table|test(\"$table\")) + | select(.chain|test(\"$chain\")) + | select(.expr[0]?.match?.op) + | select(.expr[0]?.match?.left?.payload?.protocol) + | select(.expr[0]?.match?.left?.payload?.field) + | select(.expr[0]?.match?.right) + | select(.expr[1]?.$policy == null) + | select(.expr[0].match.op == \"==\") + | select(.expr[0].match.left.payload.protocol == \"$protocol\") + | select(.expr[0].match.left.payload.field == \"$field\") + | select(.expr[0].match.right == $port) + | .handle + " + remove=" + echo nft delete rule $table $chain handle \$handle + nft delete rule $table $chain handle \$handle + " + elif [[ "$chain" = 'FORWARD' ]]; then + key="$6" + ifname="$7" + policy="${13}" + + filter=" + .nftables[] | select(.rule) | .rule + | select(.family|test(\"$family\")) + | select(.table|test(\"$table\")) + | select(.chain|test(\"$chain\")) + | select(.expr[0]?.match?.op) + | select(.expr[0]?.match?.left?.meta?.key) + | select(.expr[0]?.match?.right) + | select(.expr[2]?.$policy == null) + | select(.expr[0].match.op == \"==\") + | select(.expr[0].match.left.meta.key == \"$key\") + | select(.expr[0].match.right == \"$ifname\") + | .handle + " + remove=" + echo nft delete rule $table $chain handle \$handle + nft delete rule $table $chain handle \$handle + " + else + echo "Warning: Don't know how to reverse 'nft $@'" 1>&2 + nft "$@" + return 0 + fi + set +u + if [[ -z "$restore_nft_file" ]]; then + restore_nft_file="$(mktemp)" + echo "#!/usr/bin/env sh" > "$restore_nft_file" + chmod 700 "$restore_nft_file" + chown root:root "$restore_nft_file" + echo "restore_nft_file=$restore_nft_file" >> "$NET_CONF_FILE" + fi + set -u + + echo "handle=\"\$(nft --json list ruleset | jq '$filter')\"" >> "$restore_nft_file" + echo "$remove" >> "$restore_nft_file" + + nft "$@" +} + create() { local next_subnet @@ -61,21 +148,21 @@ create() { echo "nft_ruleset='$(nft -s list ruleset)'" >> "$NET_CONF_FILE" # dhcp - nft add rule ip filter INPUT udp dport 67 accept - nft add rule ip filter INPUT tcp dport 67 accept + nft_rev add rule ip filter INPUT udp dport 67 accept + nft_rev add rule ip filter INPUT tcp dport 67 accept # dns - nft add rule ip filter INPUT udp dport 53 accept - nft add rule ip filter INPUT tcp dport 53 accept + nft_rev add rule ip filter INPUT udp dport 53 accept + nft_rev add rule ip filter INPUT tcp dport 53 accept # scream - nft add rule ip filter INPUT udp dport 4010 accept - nft add rule ip filter INPUT tcp dport 4010 accept + nft_rev add rule ip filter INPUT udp dport 4010 accept + nft_rev add rule ip filter INPUT tcp dport 4010 accept # forward bridge - nft add rule ip filter FORWARD iifname "$bridge_name" \ + nft_rev add rule ip filter FORWARD iifname "$bridge_name" \ counter packets 0 bytes 0 accept - nft add rule ip filter FORWARD oifname "$bridge_name" \ + nft_rev add rule ip filter FORWARD oifname "$bridge_name" \ counter packets 0 bytes 0 accept - nft add rule ip nat POSTROUTING oifname "$(default_route)" \ + nft_rev add rule ip nat POSTROUTING oifname "$(default_route)" \ counter masquerade } @@ -85,8 +172,10 @@ delete() { kill "$dnsmasq_pid" ip link del "$tap_name" ip link del "$bridge_name" - nft flush ruleset - nft -f - <<< "$nft_ruleset" + # nft flush ruleset + # nft -f - <<< "$nft_ruleset" + "$restore_nft_file" + rm "$restore_nft_file" rm "$NET_CONF_FILE" }