diff options
author | Guilhem Moulin <guilhem@fripost.org> | 2018-12-20 02:04:25 +0100 |
---|---|---|
committer | Guilhem Moulin <guilhem@fripost.org> | 2018-12-22 13:22:43 +0100 |
commit | fc337924c7e66258319c6b6d538660240cfeda5e (patch) | |
tree | f0e96885c014ee7bc0083e93c1c8385aa53faed2 | |
parent | 57273eb0ab62acbc38a327f50ccfd1ac5cc415da (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-x | roles/common/files/usr/local/sbin/update-firewall.sh | 16 |
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" |