#!/bin/sh # # firewall script # # PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin IPT4=/sbin/iptables IPT6=/sbin/ip6tables NAME=firewall DESC="packet filter" PUBIF="{{ firewall_public_interface | default(ansible_default_ipv4.interface | default('eth0')) }}" FIREWALL_DOCKER_SAFE="{{ firewall_docker_safe | default(true) | ternary('1', '0') }}" #PRIVATEIF=eth1 case "$1" in start) echo -n "Initializing $DESC. \n" ### IPv4 ### echo " \033[33mIPv4 : \033[0m" HAS_DOCKER4=0 if [ "$FIREWALL_DOCKER_SAFE" = "1" ] && $IPT4 -S DOCKER >/dev/null 2>&1; then HAS_DOCKER4=1 fi # Reset only chains managed by this role. $IPT4 -F INPUT $IPT4 -F OUTPUT $IPT4 -F ADMIN >/dev/null 2>&1 || true $IPT4 -X ADMIN >/dev/null 2>&1 || true if [ "$HAS_DOCKER4" -eq 0 ]; then $IPT4 -F FORWARD $IPT4 -P FORWARD DROP else echo " * Docker detected, preserving IPv4 FORWARD chain : \033[32m[OK] \033[0m" fi # DROP all incomming traffic $IPT4 -P INPUT DROP $IPT4 -P OUTPUT DROP echo " * Deny all input and output IPv4 connections : \033[32m[OK] \033[0m" # Unlimited access to loopback $IPT4 -A INPUT -j ACCEPT -i lo $IPT4 -A OUTPUT -j ACCEPT -o lo echo " * Accept all loopback connections : \033[32m[OK] \033[0m" # Allow full outgoing connection but no incomming stuff $IPT4 -A INPUT -j ACCEPT -m state --state ESTABLISHED,RELATED $IPT4 -A OUTPUT -j ACCEPT -m state --state NEW,ESTABLISHED,RELATED -m comment --comment "Authorize all established output access" echo " * Don't break IPv4 established connections : \033[32m[OK] \033[0m" # Allow incoming ICMP ping pong stuff $IPT4 -A INPUT -j ACCEPT -p icmp --icmp-type echo-request $IPT4 -A OUTPUT -j ACCEPT -p icmp --icmp-type echo-reply echo " * Accept request & reply ICMP requests : \033[32m[OK] \033[0m" ## Protection rules # Drop excessive RST packets $IPT4 -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT echo " * IPv4 protection rules : \033[32m[OK] \033[0m" # Admin chain $IPT4 -N ADMIN {% for source in firewall_admin_sources %} $IPT4 -A ADMIN -s {{ source.cidr }} -j ACCEPT -m comment --comment "{{ source.comment }}" {% endfor %} echo " * Creating admin chain : \033[32m[OK] \033[0m" # Custom rules {% for rule in firewall_admin_rules_ipv4 %} $IPT4 -A INPUT -j ADMIN -p {{ rule.proto }} --dport {{ rule.dport }}{% if rule.proto == 'tcp' %} --syn{% endif %} -m comment --comment "{{ rule.comment }}" {% endfor %} {% for port in firewall_public_tcp_ports_ipv4 %} $IPT4 -A INPUT -j ACCEPT -p tcp --dport {{ port }} -m comment --comment "IPv4 tcp/{{ port }}" {% endfor %} echo " * Custom IPv4 rules : \033[32m[OK] \033[0m" # REJECT everything else $IPT4 -A INPUT -j REJECT --reject-with tcp-reset -p tcp $IPT4 -A INPUT -j REJECT -p udp echo " * Reject everything else : \033[32m[OK] \033[0m" ### IPv6 ### echo " \033[33mIPv6 : \033[0m" HAS_DOCKER6=0 if [ "$FIREWALL_DOCKER_SAFE" = "1" ] && $IPT6 -S DOCKER >/dev/null 2>&1; then HAS_DOCKER6=1 fi # Reset only chains managed by this role. $IPT6 -F INPUT $IPT6 -F OUTPUT if [ "$HAS_DOCKER6" -eq 0 ]; then $IPT6 -F FORWARD $IPT6 -P FORWARD DROP else echo " * Docker detected, preserving IPv6 FORWARD chain : \033[32m[OK] \033[0m" fi # DROP all incomming traffic $IPT6 -P INPUT DROP $IPT6 -P OUTPUT DROP echo " * Deny all input and output IPv6 connections : \033[32m[OK] \033[0m" # Unlimited access to loopback $IPT6 -A INPUT -j ACCEPT -i lo $IPT6 -A OUTPUT -j ACCEPT -o lo echo " * Accept all loopback connections : \033[32m[OK] \033[0m" # Allow full outgoing connection but no incomming stuff $IPT6 -A INPUT -j ACCEPT -m state --state ESTABLISHED,RELATED $IPT6 -A OUTPUT -j ACCEPT -m state --state NEW,ESTABLISHED,RELATED -m comment --comment "Authorize all established output access" echo " * Don't break IPv6 established connections : \033[32m[OK] \033[0m" # Allow incoming ICMP ping pong stuff #$IPT6 -A INPUT -j ACCEPT -p icmpv6 --icmpv6-type echo-request #$IPT6 -A OUTPUT -j ACCEPT -p icmpv6 --icmpv6-type echo-reply $IPT6 -A INPUT -j ACCEPT -p icmpv6 $IPT6 -A OUTPUT -j ACCEPT -p icmpv6 echo " * Accept request & reply ICMP requests : \033[32m[OK] \033[0m" ## Protection rules # Drop excessive RST packets $IPT6 -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT echo " * IPv6 protection rules : \033[32m[OK] \033[0m" # Custom rules {% for port in firewall_public_tcp_ports_ipv6 %} $IPT6 -A INPUT -j ACCEPT -p tcp --dport {{ port }} --syn -m comment --comment "IPv6 tcp/{{ port }}" {% endfor %} echo " * Custom IPv6 rules : \033[32m[OK] \033[0m" # REJECT everything else $IPT6 -A INPUT -j REJECT --reject-with tcp-reset -p tcp $IPT6 -A INPUT -j REJECT -p udp echo " * Reject everything else : \033[32m[OK] \033[0m" # Log everything else #$IPT6 -A INPUT -i $PUBIF -j LOG --log-prefix "Firewall IPv6 : " ;; stop) echo -n "Resetting $DESC. \n" HAS_DOCKER4=0 if [ "$FIREWALL_DOCKER_SAFE" = "1" ] && $IPT4 -S DOCKER >/dev/null 2>&1; then HAS_DOCKER4=1 fi HAS_DOCKER6=0 if [ "$FIREWALL_DOCKER_SAFE" = "1" ] && $IPT6 -S DOCKER >/dev/null 2>&1; then HAS_DOCKER6=1 fi ### IPv4 ### $IPT4 -F INPUT $IPT4 -F OUTPUT $IPT4 -F ADMIN >/dev/null 2>&1 || true $IPT4 -X ADMIN >/dev/null 2>&1 || true if [ "$HAS_DOCKER4" -eq 0 ]; then $IPT4 -F FORWARD $IPT4 -P FORWARD ACCEPT else echo " * Docker detected, preserving IPv4 FORWARD chain : \033[32m[OK] \033[0m" fi $IPT4 -P INPUT ACCEPT $IPT4 -P OUTPUT ACCEPT echo " * Cleaning IPv4 chains and rules : \033[32m[OK] \033[0m" ### IPv6 ### $IPT6 -F INPUT $IPT6 -F OUTPUT if [ "$HAS_DOCKER6" -eq 0 ]; then $IPT6 -F FORWARD $IPT6 -P FORWARD ACCEPT else echo " * Docker detected, preserving IPv6 FORWARD chain : \033[32m[OK] \033[0m" fi $IPT6 -P INPUT ACCEPT $IPT6 -P OUTPUT ACCEPT echo " * Cleaning IPv6 chains and rules : \033[32m[OK] \033[0m" echo ;; restart|force-reload) $0 stop $0 start ;; status) echo "\033[33mIPv4 chains and rules : \033[0m" $IPT4 -L -n -v echo echo "\033[33mIPv6 chains and rules : \033[0m" $IPT6 -L -n -v ;; *) echo "Usage: firewall {start|stop|restart|force-reload|status}" >&2 exit 1 ;; esac exit 0