Update lxc-net to support nftables

Closes #3093
Closes #3602

Add support for nftables firewall rules if `nft` command line
interface is available in the system

Signed-off-by: Pablo Correa Gómez <ablocorrea@hotmail.com>
This commit is contained in:
Pablo Correa Gómez 2021-05-27 15:43:31 +02:00 committed by Christian Brauner
parent d41b0293f5
commit 71def1ad00
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D
2 changed files with 105 additions and 31 deletions

View File

@ -18,6 +18,7 @@ LXC_DHCP_MAX="253"
LXC_DHCP_CONFILE=""
LXC_DHCP_PING="true"
LXC_DOMAIN=""
LXC_USE_NFT="true"
LXC_IPV6_ADDR=""
LXC_IPV6_MASK=""
@ -26,8 +27,15 @@ LXC_IPV6_NAT="false"
[ ! -f $distrosysconfdir/lxc ] || . $distrosysconfdir/lxc
use_iptables_lock="-w"
iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
use_nft() {
[ -n "$NFT" ] && nft list ruleset > /dev/null 2>&1 && [ "$LXC_USE_NFT" = "true" ]
}
NFT="$(which nft)"
if ! use_nft; then
use_iptables_lock="-w"
iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
fi
_netmask2cidr ()
{
@ -51,6 +59,58 @@ _ifup() {
ip link set dev ${LXC_BRIDGE} up
}
start_ipv6() {
LXC_IPV6_ARG=""
if [ -n "$LXC_IPV6_ADDR" ] && [ -n "$LXC_IPV6_MASK" ] && [ -n "$LXC_IPV6_NETWORK" ]; then
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 0 > /proc/sys/net/ipv6/conf/${LXC_BRIDGE}/autoconf
ip -6 addr add dev ${LXC_BRIDGE} ${LXC_IPV6_ADDR}/${LXC_IPV6_MASK}
LXC_IPV6_ARG="--dhcp-range=${LXC_IPV6_ADDR},ra-only --listen-address ${LXC_IPV6_ADDR}"
fi
}
start_iptables() {
start_ipv6
if [ -n "$LXC_IPV6_ARG" ] && [ "$LXC_IPV6_NAT" = "true" ]; then
ip6tables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_IPV6_NETWORK} ! -d ${LXC_IPV6_NETWORK} -j MASQUERADE
fi
iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
iptables $use_iptables_lock -I FORWARD -i ${LXC_BRIDGE} -j ACCEPT
iptables $use_iptables_lock -I FORWARD -o ${LXC_BRIDGE} -j ACCEPT
iptables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE
iptables $use_iptables_lock -t mangle -A POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
}
start_nftables() {
start_ipv6
NFT_RULESET=""
if [ -n "$LXC_IPV6_ARG" ] && [ "$LXC_IPV6_NAT" = "true" ]; then
NFT_RULESET="${NFT_RULESET}
add table ip6 lxc;
flush table ip6 lxc;
add chain ip6 lxc postrouting { type nat hook postrouting priority 100; };
add rule ip6 lxc postrouting ip saddr ${LXC_IPV6_NETWORK} ip daddr != ${LXC_IPV6_NETWORK} counter masquerade;
"
fi
NFT_RULESET="${NFT_RULESET};
add table inet lxc;
flush table inet lxc;
add chain inet lxc input { type filter hook input priority 0; };
add rule inet lxc input iifname ${LXC_BRIDGE} udp dport { 53, 67 } accept;
add rule inet lxc input iifname ${LXC_BRIDGE} tcp dport { 53, 67 } accept;
add chain inet lxc forward { type filter hook forward priority 0; };
add rule inet lxc forward iifname ${LXC_BRIDGE} accept;
add rule inet lxc forward oifname ${LXC_BRIDGE} accept;
add table ip lxc;
flush table ip lxc;
add chain ip lxc postrouting { type nat hook postrouting priority 100; };
add rule ip lxc postrouting ip saddr ${LXC_NETWORK} ip daddr != ${LXC_NETWORK} counter masquerade"
nft "${NFT_RULESET}"
}
start() {
[ "x$USE_LXC_BRIDGE" = "xtrue" ] || { exit 0; }
@ -91,24 +151,11 @@ start() {
_ifup
LXC_IPV6_ARG=""
if [ -n "$LXC_IPV6_ADDR" ] && [ -n "$LXC_IPV6_MASK" ] && [ -n "$LXC_IPV6_NETWORK" ]; then
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 0 > /proc/sys/net/ipv6/conf/${LXC_BRIDGE}/autoconf
ip -6 addr add dev ${LXC_BRIDGE} ${LXC_IPV6_ADDR}/${LXC_IPV6_MASK}
if [ "$LXC_IPV6_NAT" = "true" ]; then
ip6tables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_IPV6_NETWORK} ! -d ${LXC_IPV6_NETWORK} -j MASQUERADE
fi
LXC_IPV6_ARG="--dhcp-range=${LXC_IPV6_ADDR},ra-only --listen-address ${LXC_IPV6_ADDR}"
if use_nft; then
start_nftables
else
start_iptables
fi
iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
iptables $use_iptables_lock -I FORWARD -i ${LXC_BRIDGE} -j ACCEPT
iptables $use_iptables_lock -I FORWARD -o ${LXC_BRIDGE} -j ACCEPT
iptables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE
iptables $use_iptables_lock -t mangle -A POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
LXC_DOMAIN_ARG=""
if [ -n "$LXC_DOMAIN" ]; then
@ -144,24 +191,47 @@ start() {
FAILED=0
}
stop_iptables() {
iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE
iptables $use_iptables_lock -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
if [ "$LXC_IPV6_NAT" = "true" ]; then
ip6tables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_IPV6_NETWORK} ! -d ${LXC_IPV6_NETWORK} -j MASQUERADE
fi
}
stop_nftables() {
# Adding table before removing them is just to avoid
# delete error for non-existent table
NFT_RULESET="add table inet lxc;
delete table inet lxc;
add table ip lxc;
delete table ip lxc;
"
if [ "$LXC_IPV6_NAT" = "true" ]; then
NFT_RULESET="${NFT_RULESET};
add table ip6 lxc;
delete table ip6 lxc;"
fi
nft "${NFT_RULESET}"
}
stop() {
[ "x$USE_LXC_BRIDGE" = "xtrue" ] || { exit 0; }
[ -f "${varrun}/network_up" ] || [ "$1" = "force" ] || { echo "lxc-net isn't running"; exit 1; }
if [ -d /sys/class/net/${LXC_BRIDGE} ]; then
_ifdown
iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE
iptables $use_iptables_lock -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
if [ "$LXC_IPV6_NAT" = "true" ]; then
ip6tables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_IPV6_NETWORK} ! -d ${LXC_IPV6_NETWORK} -j MASQUERADE
_ifdown
if use_nft; then
stop_nftables
else
stop_iptables
fi
pid=`cat "${varrun}"/dnsmasq.pid 2>/dev/null` && kill -9 $pid

View File

@ -198,6 +198,10 @@ LXC_DHCP_MAX="253"
# container 'mail1' always get ip address 10.0.3.100.
#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf
# Whether to use nftables (if available) to configure required network rules.
# Set to any value != "true" to force iptables backend instead.
LXC_USE_NFT="true"
# Uncomment the next line if you want lxcbr0's dnsmasq to resolve the .lxc
# domain. You can then add "server=/lxc/10.0.3.1' (or your actual $LXC_ADDR)
# to /etc/dnsmasq.conf, after which 'container1.lxc' will resolve on your