summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2018-12-20 02:04:25 +0100
committerGuilhem Moulin <guilhem@fripost.org>2018-12-22 13:22:43 +0100
commitfc337924c7e66258319c6b6d538660240cfeda5e (patch)
treef0e96885c014ee7bc0083e93c1c8385aa53faed2
parent57273eb0ab62acbc38a327f50ccfd1ac5cc415da (diff)
firewall: gracefully close invalid connections.
This is useful when an ESTABLISHED connection is seen as NEW because the client was offline for some time. For instance, clients now gracefully close existing SSH connections immediately after resuming from a suspend state, rather that waiting for the TCP timeout.
-rwxr-xr-xroles/common/files/usr/local/sbin/update-firewall.sh16
1 files changed, 12 insertions, 4 deletions
diff --git a/roles/common/files/usr/local/sbin/update-firewall.sh b/roles/common/files/usr/local/sbin/update-firewall.sh
index 36c12c6..8ef3ab9 100755
--- a/roles/common/files/usr/local/sbin/update-firewall.sh
+++ b/roles/common/files/usr/local/sbin/update-firewall.sh
@@ -237,41 +237,41 @@ run() {
iptables -A INPUT -i $if -s "$ip" -j DROP
iptables -A INPUT -i $if -d "$ip" -j DROP
done
elif [ "$f" = 6 ]; then
# Martian IPv6 packets: ULA (RFC 4193) and site local addresses
# (RFC 3879).
for ip in fc00::/7 fec0::/10; do
iptables -A INPUT -i $if -s "$ip" -j DROP
iptables -A INPUT -i $if -d "$ip" -j DROP
done
fi
# DROP INVALID packets immediately.
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP
# DROP bogus TCP packets.
iptables -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
- iptables -A INPUT -p tcp \! --syn -m state --state NEW -j DROP
+ iptables -A INPUT -p tcp \! --syn -m state --state NEW -j REJECT --reject-with tcp-reset
# Allow all input/output to/from the loopback interface.
local localhost=$(inet46 $f '127.0.0.1/8' '::1/128')
iptables -A INPUT -i lo -s "$localhost" -d "$localhost" -j ACCEPT
iptables -A OUTPUT -o lo -s "$localhost" -d "$localhost" -j ACCEPT
if [ "$f" = 4 ] && [ "$ipsec" = y ]; then
# Allow local access to our virtual IP
ip -4 -o route show table 220 dev $if \
| sed -nr 's/.*\ssrc\s+([[:digit:].]{7,15})(\s.*)?$/\1/p' \
| while read ips; do
iptables -A INPUT -i lo -s "$ips" -d "$ips" -j ACCEPT
iptables -A OUTPUT -o lo -s "$ips" -d "$ips" -j ACCEPT
done
fi
# Prepare fail2ban. We make fail2ban insert its rules in a
# dedicated chain, so that it doesn't mess up the existing rules.
[ $fail2ban -eq 1 ] && iptables -A INPUT -i $if -j fail2ban
if [ "$f" = 4 ]; then
@@ -282,69 +282,77 @@ run() {
for t in 'echo-reply' 'destination-unreachable' 'echo-request'; do
iptables -A INPUT -p icmp -m icmp --icmp-type $t -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type $t -j ACCEPT
done
elif [ $f = 6 ]; then
iptables -A INPUT -p icmpv6 -j ACCEPT
iptables -A OUTPUT -p icmpv6 -j ACCEPT
fi
########################################################################
# ACCEPT new connections to the services we provide, or to those we want
# to connect to.
sed -re 's/#.*//; /^\s*$/d' -e "s/^(in|out|inout)$f?(\s.*)/\1\2/" \
/etc/iptables/services | \
grep -Ev '^(in|out|inout)\S\s' | \
while read dir proto dport sport; do
# We add two entries per config line: we need to accept the new
# connection, and latter the reply.
- local stNew=NEW,ESTABLISHED
- local stEst=ESTABLISHED
+ local stNew=NEW,ESTABLISHED,RELATED
+ local stEst=ESTABLISHED,RELATED
# In-Out means full-duplex
[[ "$dir" =~ ^inout ]] && stEst="$stNew"
local iptNew= iptEst= optsNew= optsEst=
case "$dport" in
*,*|*:*) optsNew="--match multiport --dports $dport"
optsEst="--match multiport --sports $dport";;
?*) optsNew="--dport $dport"
optsEst="--sport $dport";;
esac
case "$sport" in
*,*|*:*) optsNew+=" --match multiport --sports $sport"
optsEst+=" --match multiport --dports $sport";;
?*) optsNew+=" --sport $sport"
optsEst+=" --dport $sport";;
esac
case "$dir" in
in|inout) iptNew="-A INPUT -i"; iptEst="-A OUTPUT -o";;
out) iptNew="-A OUTPUT -o"; iptEst="-A INPUT -i";;
*) fatal "Error: Unknown direction: '$dir'."
esac
iptables $iptNew $if -p $proto $optsNew -m state --state $stNew -j ACCEPT
iptables $iptEst $if -p $proto $optsEst -m state --state $stEst -j ACCEPT
done
- iptables -A OUTPUT -o $if -j REJECT
+
+ iptables -A OUTPUT -o $if -p tcp -j REJECT --reject-with tcp-reset
+ iptables -A OUTPUT -o $if -p udp -j REJECT --reject-with port-unreach
+ if [ "$f" = "4" ]; then
+ iptables -A OUTPUT -o $if -p icmp -j REJECT --reject-with icmp-host-unreachable
+ iptables -A OUTPUT -o $if -j REJECT --reject-with icmp-host-prohibited
+ else
+ iptables -A OUTPUT -o $if -j REJECT
+ fi
########################################################################
commit
local rv1=0 rv2=0 persistent=/etc/iptables/rules.v$f
local oldz=$(mktemp --tmpdir current-rules.v$f.XXXXXX)
# Reset the counters. They are not useful for comparing and/or
# storing persistent ruleset. (We don't use sed -i because we want
# to restore the counters when reverting.)
sed -r -e '/^:/ s/\[[0-9]+:[0-9]+\]$/[0:0]/' \
-e 's/^\[[0-9]+:[0-9]+\]\s+//' \
"$old" >"$oldz"
ip netns exec $netns $ipt-restore <"$new" || ipt-revert
for table in ${tables[$f]}; do
ip netns exec $netns $ipt-save -t $table
done >"$new"