#!/bin/bash

% if not node.metadata.get('iptables/enabled', True):
exit 0
% endif

lock_try=0
while ! mkdir /run/bw-iptables.lock >/dev/null 2>&1
do
    ((lock_try++))
    if (( lock_try == 10 ))
    then
        echo 'FATAL: iptables-enforce: Could not get lock!' >&2
        exit 1
    fi
    sleep 1
done
trap 'rmdir /run/bw-iptables.lock' EXIT

iptables_both()
{
    iptables "$@"
    ip6tables "$@"
}

iptables_both -P INPUT DROP
iptables_both -P OUTPUT ACCEPT
iptables_both -P FORWARD DROP
iptables_both -F
iptables_both -X
iptables_both -t nat -F
iptables_both -t nat -X
iptables_both -t nat -Z
iptables_both -t filter -F
iptables_both -t filter -X
iptables_both -t filter -Z
iptables_both -t mangle -F
iptables_both -t mangle -X
iptables_both -t mangle -Z

# Workaround for CVE-2019-11477, CVE-2019-11478 and CVE-2019-11479
# https://www.openwall.com/lists/oss-security/2019/06/17/5
# https://people.canonical.com/~ubuntu-security/cve/2019/CVE-2019-11477.html
iptables_both -I INPUT -p tcp -m tcpmss --mss 1:500 -j DROP

# Dummy rules to make sure the conntrack table(s) will be updated.
iptables_both -I INPUT -m state --state NEW,ESTABLISHED,RELATED
iptables_both -I OUTPUT -m state --state NEW,ESTABLISHED,RELATED
iptables_both -I FORWARD -m state --state NEW,ESTABLISHED,RELATED

# open up local loopback
iptables_both -A INPUT -i lo -j ACCEPT

# Set Up counting rules
% for ip in sorted(ipv4):
iptables -A INPUT -d ${ip}
iptables -A OUTPUT -s ${ip}
% endfor

% for ip in sorted(ipv6):
ip6tables -A INPUT -d ${ip}
ip6tables -A OUTPUT -s ${ip}
% endfor

iptables -A INPUT -p ICMP --icmp-type timestamp-request -j DROP
iptables -A INPUT -p ICMP --icmp-type timestamp-reply -j DROP
# allow ICMP -- answers for IPv4 are covered by conntrack
iptables -A INPUT -p icmp -j ACCEPT

# ICMP6 is used for so many things, we should under no circumstances
# ignore it and thus should not rely on any conntrack heuristics.
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT

# Allow incoming answers. Install this first (before the larger ruleset
# from /etc/network/iptables-rules.d/), so that iptables can match/exit
# early.
iptables_both -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

shopt -s nullglob
for i in /etc/iptables-rules.d/*
do
    . "$i"
done

cat /etc/sysctl.d/*.conf /etc/sysctl.conf | sysctl -e -p -