#!/bin/bash # Version: 0.2.1 # Copyright (c) 2022: # Darren 'Tadgy' Austin # Licensed under the terms of the GNU General Public License version 3. # The name of the main external interface. EX_IF="eth0" # The IP ranges from where to accept unfiltered connections # |-- UK Servers --| |---------------------------------- UK2 -----------------------------------| |-- Linode ---| |- L'Servers --| |----- Home -----| UNFILTERED_RANGES_V4=('5.101.171.210/28' '91.109.244.7' '91.109.244.8' '91.109.244.9' '91.109.244.10' '91.109.244.11' '88.80.191.137' '185.176.90.169' 'afterdark.org.uk') # |---- UK Servers -----| |------- UK2 --------| |----------- Linode -----------| |---- LoveServers -----| UNFILTERED_RANGES_V6=('2a01:a500:2981:1::/64' '2a02:2498:1:227::/64' '2a01:7e00::f03c:93ff:fe86:afae' '2a07:4580:b0d:57f::169') start_firewall() { # Disable ICMP redirects. # Note: Redirects are used when a router believes a packet is being routed sub optimally and it would like to inform # the sending host that it should forward subsequent packets to that same destination through a different gateway. echo 0 >"/proc/sys/net/ipv4/conf/$EX_IF/accept_redirects" echo 0 >"/proc/sys/net/ipv6/conf/$EX_IF/accept_redirects" echo 0 >"/proc/sys/net/ipv4/conf/$EX_IF/send_redirects" # Flush old rules. iptables -F ip6tables -F iptables -t nat -F ip6tables -t nat -F iptables -t mangle -F ip6tables -t mangle -F # Delete any custom chains. iptables -X ip6tables -X iptables -t nat -X ip6tables -t nat -X iptables -t mangle -X ip6tables -t mangle -X # Drop invalid packets on all interfaces. iptables -A INPUT -m conntrack --ctstate INVALID -j DROP ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP # Drop unroutable IPs on the external interface. iptables -A INPUT -i "$EX_IF" -s 127.0.0.0/8 -j DROP ip6tables -A INPUT -i "$EX_IF" -s ::1/128 -j DROP # Allow local nets if our IP is in the same range. if [[ "$(ip -br a s "$EX_IF" | awk -e '{printf $3}' | cut -d. -f1)" == "10" ]]; then iptables -A INPUT -i "$EX_IF" -s 10.0.0.0/8 -j ACCEPT else iptables -A INPUT -i "$EX_IF" -s 10.0.0.0/8 -j DROP fi if [[ "$(ip -br a s "$EX_IF" | awk -e '{printf $3}' | cut -d. -f1,2)" == "172.16" ]]; then iptables -A INPUT -i "$EX_IF" -s 172.16.0.0/12 -j ACCEPT else iptables -A INPUT -i "$EX_IF" -s 172.16.0.0/12 -j DROP fi if [[ "$(ip -br a s "$EX_IF" | awk -e '{printf $3}' | cut -d. -f1,2)" == "192.168" ]]; then iptables -A INPUT -i "$EX_IF" -s 192.168.0.0/16 -j ACCEPT else iptables -A INPUT -i "$EX_IF" -s 192.168.0.0/16 -j DROP fi # Allow all loopback traffic. iptables -A INPUT -i lo -j ACCEPT ip6tables -A INPUT -i lo -j ACCEPT # Allow unrestricted access from our IPs. for ENTRY in "${UNFILTERED_RANGES_V4[@]}"; do iptables -A INPUT -i "$EX_IF" -s "$ENTRY" -j ACCEPT done for ENTRY in "${UNFILTERED_RANGES_V6[@]}"; do ip6tables -A INPUT -i "$EX_IF" -s "$ENTRY" -j ACCEPT done # Allow packets of established connections and those related to them. iptables -A INPUT -i "$EX_IF" -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Allow pings. iptables -A INPUT -i "$EX_IF" -p icmp -m icmp --icmp-type echo-request -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p icmpv6 --icmpv6-type echo-request -j ACCEPT iptables -A INPUT -i "$EX_IF" -p icmp --icmp-type echo-reply -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p icmpv6 --icmpv6-type echo-reply -j ACCEPT # Allow certain types of ICMP informational packets. iptables -A INPUT -i "$EX_IF" -p icmp --icmp-type destination-unreachable -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT iptables -A INPUT -i "$EX_IF" -p icmp --icmp-type time-exceeded -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT iptables -A INPUT -i "$EX_IF" -p icmp --icmp-type parameter-problem -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p icmpv6 --icmpv6-type parameter-problem -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p icmpv6 --icmpv6-type neighbour-solicitation -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p icmpv6 --icmpv6-type neighbour-advertisement -j ACCEPT # Allow SSH. iptables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 22,9922 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 22,9922 -m conntrack --ctstate NEW -j ACCEPT # Service: DNS. iptables -A INPUT -i "$EX_IF" -p tcp --syn --dport 53 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn --dport 53 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -i "$EX_IF" -p udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT # Service: HTTP{,S}. iptables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT # Service: FTP. iptables -A INPUT -i "$EX_IF" -p tcp --syn --dport 21 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn --dport 21 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -i "$EX_IF" -p tcp --syn --dport 20 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn --dport 20 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Service: rsync. iptables -A INPUT -i "$EX_IF" -p tcp --syn --dport 873 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn --dport 873 -m conntrack --ctstate NEW -j ACCEPT # Service: SMTP and submission. iptables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 25,587 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 25,587 -m conntrack --ctstate NEW -j ACCEPT # Service: IMAP{,S}. iptables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 143,993 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 143,993 -m conntrack --ctstate NEW -j ACCEPT # Service: POP3{,S}. iptables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 110,995 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 110,995 -m conntrack --ctstate NEW -j ACCEPT # Service: Bittorrent. iptables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 6881:6899 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 6881:6899 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -i "$EX_IF" -p udp -m multiport --dports 6881:6899 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p udp -m multiport --dports 6881:6899 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 49152:65534 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn -m multiport --dports 49152:65534 -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -i "$EX_IF" -p udp -m multiport --dports 49152:65534 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p udp -m multiport --dports 49152:65534 -m conntrack --ctstate NEW -j ACCEPT # Service: tftp. iptables -A INPUT -i "$EX_IF" -p tcp --syn --dport 69 -m conntrack --ctstate NEW -j ACCEPT ip6tables -A INPUT -i "$EX_IF" -p tcp --syn --dport 69 -m conntrack --ctstate NEW -j ACCEPT # Set default policies. iptables -P INPUT DROP ip6tables -P INPUT DROP iptables -P OUTPUT ACCEPT # We don't firewall outgoing connections. ip6tables -P OUTPUT ACCEPT # We don't firewall outgoing connections. iptables -P FORWARD DROP ip6tables -P FORWARD DROP } stop_firewall() { # Set default policies to ACCEPT. iptables -P INPUT ACCEPT ip6tables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT ip6tables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ip6tables -P FORWARD ACCEPT # Flush rules. iptables -F ip6tables -F iptables -t nat -F ip6tables -t nat -F iptables -t mangle -F ip6tables -t mangle -F # Delete any custom chains. iptables -X ip6tables -X iptables -t nat -X ip6tables -t nat -X iptables -t mangle -X ip6tables -t mangle -X # Reset ICMP redirects. cat /proc/sys/net/ipv4/conf/default/accept_redirects >"/proc/sys/net/ipv4/conf/$EX_IF/accept_redirects" cat /proc/sys/net/ipv6/conf/default/accept_redirects >"/proc/sys/net/ipv6/conf/$EX_IF/accept_redirects" cat /proc/sys/net/ipv4/conf/default/send_redirects >"/proc/sys/net/ipv4/conf/$EX_IF/send_redirects" } case "$1" in 'start') start_firewall ;; 'stop') stop_firewall ;; 'restart') stop_firewall sleep 0.5 start_firewall ;; *) echo "Usage: ${BASH_SOURCE[0]} " >&2 exit 1 ;; esac # Unless the system is booting, restart fail2ban to re-create the ban chains. [[ "$PREVLEVEL" != "N" ]] && { [[ -x /etc/rc.d/rc.fail2ban ]] && /etc/rc.d/rc.fail2ban restart >/dev/null } exit 0