Subject: [alpine-aports] [PATCH] testing/nftables: new aport

From: Sören Tempel <[email-masked]>
Date: Mon, 7 Sep 2015 23:52:17 +0200

Might need some additional testing. Especially the OpenRC service wasn't
tested to extensively by myself.
---
 .../nftables/01-fix-object-order-via-nft--f.patch  |  50 +++++++
 testing/nftables/APKBUILD                          |  70 +++++++++
 testing/nftables/nftables.confd                    |  19 +++
 testing/nftables/nftables.initd                    | 166 +++++++++++++++++++++
 4 files changed, 305 insertions(+)
 create mode 100644 testing/nftables/01-fix-object-order-via-nft--f.patch
 create mode 100644 testing/nftables/APKBUILD
 create mode 100644 testing/nftables/nftables.confd
 create mode 100644 testing/nftables/nftables.initd

diff --git a/testing/nftables/01-fix-object-order-via-nft--f.patch b/testing/nftables/01-fix-object-order-via-nft--f.patch
new file mode 100644
index 0000000..6092032
--- /dev/null
+++ b/testing/nftables/01-fix-object-order-via-nft--f.patch
@@ -0,0 +1,50 @@
+From 454ffab9cc695b9618324a6a0a4dead6d5289f8d Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <[email-masked]>
+Date: Sat, 14 Feb 2015 21:41:23 +0100
+Subject: rule: fix object order via nft -f
+
+The objects need to be loaded in the following order:
+
+	#1 tables
+	#2 chains
+	#3 sets
+	#4 rules
+
+We have to make sure that chains are in place by when we add rules with
+jumps/gotos. Similarly, we have to make sure that the sets are in place
+by when rules reference them.
+
+Without this patch, you may hit ENOENT errors depending on your ruleset
+configuration.
+
+Signed-off-by: Pablo Neira Ayuso <[email-masked]>
+
+diff --git a/src/rule.c b/src/rule.c
+index feafe26..8d76fd0 100644
+--- a/src/rule.c
++++ b/src/rule.c
+@@ -658,14 +658,19 @@ static int do_add_table(struct netlink_ctx *ctx, const struct handle *h,
+ 	if (netlink_add_table(ctx, h, loc, table, excl) < 0)
+ 		return -1;
+ 	if (table != NULL) {
++		list_for_each_entry(chain, &table->chains, list) {
++			if (netlink_add_chain(ctx, &chain->handle,
++					      &chain->location, chain,
++					      excl) < 0)
++				return -1;
++		}
+ 		list_for_each_entry(set, &table->sets, list) {
+ 			handle_merge(&set->handle, &table->handle);
+ 			if (do_add_set(ctx, &set->handle, set) < 0)
+ 				return -1;
+ 		}
+ 		list_for_each_entry(chain, &table->chains, list) {
+-			if (do_add_chain(ctx, &chain->handle, &chain->location,
+-					 chain, excl) < 0)
++			if (netlink_add_rule_list(ctx, h, &chain->rules) < 0)
+ 				return -1;
+ 		}
+ 	}
+-- 
+cgit v0.10.2
+
diff --git a/testing/nftables/APKBUILD b/testing/nftables/APKBUILD
new file mode 100644
index 0000000..0679b5b
--- /dev/null
+++ b/testing/nftables/APKBUILD
@@ -0,0 +1,70 @@
+# Contributor: Sören Tempel <[email-masked]>
+# Maintainer: Sören Tempel <[email-masked]>
+pkgname=nftables
+pkgver=0.4
+pkgrel=0
+pkgdesc="Netfilter tables userspace tools"
+url="http://netfilter.org/projects/nftables/"
+arch="all"
+license="GPL2"
+depends=""
+depends_dev="libmnl-dev libnftnl-dev gmp-dev readline-dev ncurses-dev"
+makedepends="$depends_dev bison flex"
+install=""
+subpackages="" # -doc would require docbook2x which isn't packaged yet
+source="http://netfilter.org/projects/$pkgname/files/$pkgname-$pkgver.tar.bz2
+	nftables.confd
+	nftables.initd
+	01-fix-object-order-via-nft--f.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+	cd "$_builddir"
+
+	update_config_sub || return 1
+	sed -i '1i#include "config.h"' src/proto.c
+
+	local i=
+	for i in $source; do
+		case $i in
+		*.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+		esac
+	done
+}
+
+build() {
+	cd "$_builddir"
+	./configure \
+		--build=$CBUILD \
+		--host=$CHOST \
+		--prefix=/usr \
+		--sysconfdir=/etc \
+		--mandir=/usr/share/man \
+		--infodir=/usr/share/info \
+		--localstatedir=/var \
+		|| return 1
+	make || return 1
+}
+
+package() {
+	cd "$_builddir"
+	make DESTDIR="$pkgdir" install || return 1
+
+	install -Dm755 "$srcdir"/$pkgname.initd \
+		"$pkgdir"/etc/init.d/$pkgname || return 1
+	install -Dm644 "$srcdir"/$pkgname.confd \
+		"$pkgdir"/etc/conf.d/$pkgname || return 1
+}
+
+md5sums="09b686c489ff10db670ca60dbed7ff43  nftables-0.4.tar.bz2
+00f7dc61bcc1f7c2e48ebeaeb8b6b6b5  nftables.confd
+f5703f86eb2129cdece8c230cc036bd7  nftables.initd
+c0a18f43a5ce02cb61c9e0071725529a  01-fix-object-order-via-nft--f.patch"
+sha256sums="f6ca69b75c68915f9f3a3972274ec68354dfbbcfc0b9fc55c813a0525c351d3c  nftables-0.4.tar.bz2
+d5e3077345dfea02849a70aea220396322a10c3808f0303b988119adbc56fdbd  nftables.confd
+293d5a0ef687c69fffdce912a833cf5812272c0baae9f59d603ada8efa5828a6  nftables.initd
+ab5068a30e4a0df72b589aec500a4a6a1c3a5ab50ee73fad034eee676eabe9bb  01-fix-object-order-via-nft--f.patch"
+sha512sums="0932cf987da602285fbf7c7f61328b0d74d687889c2d4a5bd2bd7fe11e8b99433bc5ee53ebbddadf2c90e40acdcb28f6babf07e11feedff815c571c3b782dffc  nftables-0.4.tar.bz2
+8370abcdc89fcd9da5dc7d1620be6afb4633b8bcd0a8a120b464cc1a7e1fab6f34956c293da3f6d3cbe1f7a2e03038fd0c94a614137ae5657d29ffdb5f3fa144  nftables.confd
+ec43cc630b45ea2726044b30925e04f16fdb48ff2ee1871c112fde5b406f47c75b53ce05db4dfab8558156da96e9bf484ebab1f00f5cda20bbe8597c63b178fe  nftables.initd
+9b7b51c55681fc25bb53fef6bf38e125377a3b32bdf6e9c8c7056a72deb7f24b7b6e2dcccb3065645e69675848585c6051e8992d9179f1609fbe1d873cb3bddf  01-fix-object-order-via-nft--f.patch"
diff --git a/testing/nftables/nftables.confd b/testing/nftables/nftables.confd
new file mode 100644
index 0000000..e83a4b9
--- /dev/null
+++ b/testing/nftables/nftables.confd
@@ -0,0 +1,19 @@
+# /etc/conf.d/nftables
+
+# Location in which nftables initscript will save set rules on 
+# service shutdown
+NFTABLES_SAVE="/var/lib/nftables/rules-save"
+
+# Options to pass to nft on save
+SAVE_OPTIONS="-n"
+
+# Save state on stopping nftables
+SAVE_ON_STOP="yes"
+
+# If you need to log nftables messages as soon as nftables starts,
+# AND your logger does NOT depend on the network, then you may wish
+# to uncomment the next line.
+# If your logger depends on the network, and you uncomment this line
+# you will create an unresolvable circular dependency during startup.
+# After commenting or uncommenting this line, you must run 'rc-update -u'.
+#rc_use="logger"
diff --git a/testing/nftables/nftables.initd b/testing/nftables/nftables.initd
new file mode 100644
index 0000000..c726393
--- /dev/null
+++ b/testing/nftables/nftables.initd
@@ -0,0 +1,166 @@
+#!/sbin/runscript
+# Copyright 2014 Nicholas Vinson
+# Copyright 1999-2014 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+extra_commands="clear list panic save"
+extra_started_commands="reload"
+
+depend() {
+    need localmount #434774
+    before net
+}
+
+checkkernel() {
+    if ! nft list tables >/dev/null 2>&1; then
+        eerror "Your kernel lacks nftables support, please load"
+        eerror "appropriate modules and try again."
+        return 1
+    fi
+    return 0
+}
+
+checkconfig() {
+    if [ ! -f ${NFTABLES_SAVE} ]; then
+        eerror "Not starting nftables.  First create some rules then run:"
+        eerror "rc-service nftables save"
+        return 1
+    fi
+    return 0
+}
+
+getfamilies() {
+    local families
+    for l3f in ip arp ip6 bridge inet; do
+        if nft list tables ${l3f} > /dev/null 2>&1; then
+            families="${families}${l3f} "
+        fi
+    done
+    echo ${families}
+}
+
+clearNFT() {
+    local l3f line table chain
+
+    for l3f in $(getfamilies); do
+        nft list tables ${l3f} | while read line; do
+            table=$(echo ${line} | sed "s/table[ \t]*//")
+            nft flush table ${l3f} ${table}
+            nft list table ${l3f} ${table} | while read l; do
+                chain=$(echo $l | grep -o 'chain [^[:space:]]\+' |\
+                        cut -d ' ' -f2)
+                if [ -n "${chain}" ]; then
+                    nft flush chain ${l3f} ${table} ${chain}
+                    nft delete chain ${l3f} ${table} ${chain}
+                fi
+            done
+            nft delete table ${l3f} ${table}
+        done
+    done
+}
+
+addpanictable() {
+    local l3f=$1
+    nft add table ${l3f} panic
+    nft add chain ${l3f} panic input \{ type filter hook input priority 0\; \}
+    nft add chain ${l3f} panic output \{ type filter hook output priority 0\; \}
+    nft add chain ${l3f} panic forward \{ type filter hook forward priority 0\; \}
+    nft add rule ${l3f} panic input drop
+    nft add rule ${l3f} panic output drop
+    nft add rule ${l3f} panic forward drop
+}
+
+start_pre() {
+    checkkernel || return 1
+    checkconfig || return 1
+	return 0
+}
+
+start() {
+    ebegin "Loading nftables state and starting firewall"
+    clearNFT
+    nft -f ${NFTABLES_SAVE}
+    eend $?
+}
+
+stop() {
+    if yesno ${SAVE_ON_STOP:-yes}; then
+        save || return 1
+    fi
+
+    ebegin "Stopping firewall"
+    clearNFT
+    eend $?
+}
+
+reload() {
+    checkkernel || return 1
+    # checkrules || return 1
+    ebegin "Flushing firewall"
+    clearNFT
+
+    start
+}
+
+clear() {
+    clearNFT
+}
+
+list() {
+    local l3f
+
+    for l3f in $(getfamilies); do
+        nft list tables ${l3f} | while read line; do
+            line=$(echo ${line} | sed "s/table/table ${l3f}/")
+            echo "$(nft list ${line})"
+        done
+    done
+}
+
+save() {
+    ebegin "Saving nftables state"
+    checkpath -q -d "$(dirname "${NFTABLES_SAVE}")"
+    checkpath -q -m 0600 -f "${NFTABLES_SAVE}"
+
+    local l3f line tmp_save="${NFTABLES_SAVE}.tmp"
+
+    touch "${tmp_save}"
+    for l3f in $(getfamilies); do
+        nft list tables ${l3f} | while read line; do
+            line=$(echo ${line} | sed "s/table/table ${l3f}/")
+            # The below substitution fixes an issue where nft -n output may not
+            # always be parsable by nft -f.  For example, nft -n might print
+            #
+            #     ip6 saddr ::1 ip6 daddr ::1 counter packets 0 bytes 0 accept
+            #
+            # but nft -f refuses to parse that string with error:
+            #
+            #     In file included from internal:0:0-0:
+            #     /var/lib/nftables/rules-save:1:1-2: Error: Could not process rule:
+            #     Invalid argument
+            #     table ip6 filter {
+            #     ^^
+            echo "$(nft ${SAVE_OPTIONS} list ${line} |\
+                    sed 's/\(::[0-9a-fA-F]\+\)\([^/]\)/\1\/128\2/g')" >> "${tmp_save}"
+        done
+    done
+    mv "${tmp_save}" "${NFTABLES_SAVE}"
+}
+
+panic() {
+    checkkernel || return 1
+    if service_started ${RC_SVCNAME}; then
+        rc-service ${RC_SVCNAME} stop
+    fi
+
+    ebegin "Dropping all packets"
+    clearNFT
+
+    local l3f
+    for l3f in $(getfamilies); do
+        case ${l3f} in
+            ip) addpanictable ${l3f} ;;
+            ip6) addpanictable ${l3f} ;;
+        esac
+    done
+}
-- 
2.5.1

---
Unsubscribe:  [email-masked]
Help:         [email-masked]
---