NFTables use scripts to create tables and chains

To hardcode table and chain creation and deletion makes it impossible
for existing firewall infrastructures to integrate miniupnpd.
NFTables will either reevaluate packets through miniupnpd or
it will delete existing tables when there are already custom chains in it.

Signed-off-by: Sven Auhagen <sven.auhagen@voleatech.de>
This commit is contained in:
Sven Auhagen 2021-08-18 16:51:06 +01:00
parent d4849fa08e
commit 3129683cb3
10 changed files with 199 additions and 90 deletions

View File

@ -78,7 +78,7 @@
#upnp_nattable_name=
# chain names for netfilter and netfilter nft
# netfilter : default are MINIUPNPD, MINIUPNPD, MINIUPNPD-POSTROUTING
# netfilter nft : default are forward, prerouting, postrouting
# netfilter nft : default are miniupnpd, prerouting_miniupnpd, postrouting_miniupnpd
#upnp_forward_chain=forwardUPnP
#upnp_nat_chain=UPnP
#upnp_nat_postrouting_chain=UPnP-Postrouting

View File

@ -19,3 +19,59 @@ Please run 'netfilter_nft/scripts/nft_init.sh' to add miniupnpd chain.
##FAQ
I will add this section when I get question.
Comments and Questions are welcome ;)
###Custom Chains
NFTables is very flexible but it comes with some restrictions because of that. If there is a second filter chain than all packets that were passed before with the miniupnpd chain will be reevaluated. This also means that if the chain is a drop chain you loose the packets. In that case you really want to use a custom chain and jump to it in your filter chain. miniupnpd should save all accept rules in that custom chain.
For NAT it is the same, a second chain will also evaluate the packets again and therefore it is possible that a second SNAT or DNAT is performed.
The following is used in miniupnpd for a table setup but it can be customized:
table inet filter {
chain forward {
type filter hook forward priority 0;
policy drop;
# miniupnpd
jump miniupnpd
# Add other rules here
}
# miniupnpd
chain miniupnpd {
}
chain prerouting {
type nat hook prerouting priority -100;
policy accept;
# miniupnpd
jump prerouting_miniupnpd
# Add other rules here
}
chain postrouting {
type nat hook postrouting priority 100;
policy accept;
# miniupnpd
jump postrouting_miniupnpd
# Add other rules here
}
chain prerouting_miniupnpd {
}
chain postrouting_miniupnpd {
}
}
and the following config settings can be used to change the tables and chains
upnp_table_name=filter
upnp_nattable_name=filter
upnp_forward_chain=miniupnpd
upnp_nat_chain=prerouting_miniupnpd
upnp_nat_postrouting_chain=postrouting_miniupnpd

View File

@ -75,54 +75,12 @@ init_redirect(void)
/* requires elevated privileges */
result = nft_mnl_connect();
/* 'inet' family */
if (result == 0) {
result = table_op(NFT_MSG_NEWTABLE, NFPROTO_INET, nft_table);
}
if (result == 0) {
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_INET, nft_table,
nft_forward_chain, FILTER_CHAIN_TYPE, NF_INET_FORWARD, NF_IP_PRI_FILTER - 25);
}
if (result == 0 && strcmp(nft_nat_table, nft_table) != 0) {
result = table_op(NFT_MSG_NEWTABLE, NFPROTO_INET, nft_nat_table);
}
if (result == 0) {
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_INET, nft_nat_table,
nft_prerouting_chain, NAT_CHAIN_TYPE, NF_INET_PRE_ROUTING, NF_IP_PRI_NAT_DST);
}
if (result == 0) {
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_INET, nft_nat_table,
nft_postrouting_chain, NAT_CHAIN_TYPE, NF_INET_POST_ROUTING, NF_IP_PRI_NAT_SRC);
}
return result;
}
void
shutdown_redirect(void)
{
int result;
/* 'inet' family */
result = chain_op(NFT_MSG_DELCHAIN, NFPROTO_INET, nft_table,
nft_forward_chain, FILTER_CHAIN_TYPE, NF_INET_FORWARD, NF_IP_PRI_FILTER - 25);
if (result == 0) {
result = chain_op(NFT_MSG_DELCHAIN, NFPROTO_INET, nft_table,
nft_prerouting_chain, NAT_CHAIN_TYPE, NF_INET_PRE_ROUTING, NF_IP_PRI_NAT_DST);
}
if (result == 0) {
result = chain_op(NFT_MSG_DELCHAIN, NFPROTO_INET, nft_nat_table,
nft_postrouting_chain, NAT_CHAIN_TYPE, NF_INET_POST_ROUTING, NF_IP_PRI_NAT_SRC);
}
if (result == 0) {
result = table_op(NFT_MSG_DELTABLE, NFPROTO_INET, nft_nat_table);
}
if (result == 0 && strcmp(nft_nat_table, nft_table) != 0) {
result = table_op(NFT_MSG_DELTABLE, NFPROTO_INET, nft_nat_table);
}
nft_mnl_disconnect();
}

View File

@ -63,11 +63,11 @@
#define RULE_CACHE_INVALID 0
#define RULE_CACHE_VALID 1
const char * nft_table = "miniupnpd";
const char * nft_nat_table = "miniupnpd";
const char * nft_prerouting_chain = "prerouting";
const char * nft_postrouting_chain = "postrouting";
const char * nft_forward_chain = "forward";
const char * nft_table = "filter";
const char * nft_nat_table = "filter";
const char * nft_prerouting_chain = "prerouting_miniupnpd";
const char * nft_postrouting_chain = "postrouting_miniupnpd";
const char * nft_forward_chain = "miniupnpd";
static struct mnl_socket *mnl_sock = NULL;
static uint32_t mnl_portid = 0;

View File

@ -0,0 +1,40 @@
#! /bin/sh
NFT=$(which nft) || {
echo "Can't find nft" >&2
exit 1
}
TABLE="filter"
NAT_TABLE="filter"
CHAIN="miniupnpd"
PREROUTEING_CHAIN="prerouting_miniupnpd"
POSTROUTEING_CHAIN="postrouting_miniupnpd"
while getopts ":t:n:c:p:r:" opt; do
case $opt in
t)
TABLE=$OPTARG
;;
n)
NAT_TABLE=$OPTARG
;;
c)
CHAIN=$OPTARG
;;
p)
PREROUTEING_CHAIN=$OPTARG
;;
r)
POSTROUTEING_CHAIN=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done

View File

@ -1,5 +1,10 @@
#!/bin/sh
nft delete chain miniupnpd forward
nft delete chain miniupnpd postrouting
nft delete chain miniupnpd prerouting
. $(dirname "$0")/miniupnpd_functions.sh
# Prerouting
$NFT delete chain inet $NAT_TABLE $PREROUTEING_CHAIN
# Postrouting
$NFT delete chain inet $NAT_TABLE $POSTROUTEING_CHAIN
# Filter
$NFT delete chain inet $TABLE $CHAIN

View File

@ -1,8 +1,10 @@
#!/bin/sh
. $(dirname "$0")/miniupnpd_functions.sh
# Prerouting
nft list chain inet miniupnpd prerouting
$NFT list chain inet $NAT_TABLE $PREROUTEING_CHAIN
# Postrouting
nft list chain inet miniupnpd postrouting
$NFT list chain inet $NAT_TABLE $POSTROUTEING_CHAIN
# Filter
nft list chain inet miniupnpd forward
$NFT list chain inet $TABLE $CHAIN

View File

@ -1,5 +1,7 @@
#!/bin/sh
nft flush chain inet miniupnpd prerouting
nft flush chain inet miniupnpd postrouting
nft flush chain inet miniupnpd filter
. $(dirname "$0")/miniupnpd_functions.sh
$NFT flush chain inet $TABLE $CHAIN
$NFT flush chain inet $NAT_TABLE $PREROUTEING_CHAIN
$NFT flush chain inet $NAT_TABLE $POSTROUTEING_CHAIN

View File

@ -5,16 +5,71 @@
# 'add' doesn't raise an error if the object already exists. 'create' does.
#
#opts="--echo"
. $(dirname "$0")/miniupnpd_functions.sh
echo "create table"
nft ${opts} add table inet miniupnpd
$NFT --check list table inet $TABLE > /dev/null 2>&1
if [ $? -eq "0" ]
then
echo "Table $TABLE already exists"
exit 0
fi
echo "create NAT chain table"
nft ${opts} add chain inet miniupnpd preouting
echo "Creating nftables structure"
echo "create pcp peer chain in table"
nft ${opts} add chain inet miniupnpd postrouting
cat > /tmp/miniupnpd.nft <<EOF
table inet $TABLE {
chain forward {
type filter hook forward priority 0;
policy drop;
echo "create filter chain in table"
nft ${opts} add chain inet miniupnpd forward
# miniupnpd
jump $CHAIN
# Add other rules here
}
# miniupnpd
chain $CHAIN {
}
EOF
if [ "$TABLE" != "$NAT_TABLE" ]
then
cat >> /tmp/miniupnpd.nft <<EOF
}
table inet $NAT_TABLE {
EOF
fi
cat >> /tmp/miniupnpd.nft <<EOF
chain prerouting {
type nat hook prerouting priority -100;
policy accept;
# miniupnpd
jump $PREROUTEING_CHAIN
# Add other rules here
}
chain postrouting {
type nat hook postrouting priority 100;
policy accept;
# miniupnpd
jump $POSTROUTEING_CHAIN
# Add other rules here
}
chain $PREROUTEING_CHAIN {
}
chain $POSTROUTEING_CHAIN {
}
}
EOF
$NFT -f /tmp/miniupnpd.nft

View File

@ -5,31 +5,22 @@
# Do not disturb other existing structures in nftables, e.g. those created by firewalld
#
nft --check list table inet miniupnpd > /dev/null 2>&1
if [ $? -eq "0" ]; then
{
# table exists, so first remove the nat chains we added
nft --check list chain inet miniupnpd prerouting > /dev/null 2>&1
if [ $? -eq "0" ]; then
echo "Remove nat chain from miniupnpd table"
nft delete chain inet miniupnpd prerouting
fi
nft --check list chain inet miniupnpd postrouting > /dev/null 2>&1
if [ $? -eq "0" ]; then
echo "Remove pcp peer chain from miniupnpd table"
nft delete chain inet miniupnpd postrouting
fi
# remove the filter chain we added
nft --check list chain inet miniupnpd forward > /dev/null 2>&1
if [ $? -eq "0" ]; then
echo "Remove filter chain from miniupnpd table"
nft delete chain inet miniupnpd forward
fi
. $(dirname "$0")/miniupnpd_functions.sh
$NFT --check list table inet $TABLE > /dev/null 2>&1
if [ $? -eq "0" ]
then
# then remove the table itself
echo "Remove miniupnpd table"
nft delete table inet miniupnpd
}
$NFT delete table inet $TABLE
fi
if [ "$TABLE" != "$NAT_TABLE" ]
then
$NFT --check list table inet $TABLE > /dev/null 2>&1
if [ $? -eq "0" ]; then
# then remove the table itself
echo "Remove miniupnpd nat table"
$NFT delete table inet $NAT_TABLE
fi
fi