#!/bin/bash -x ((EUID == 0 )) || { echo "Need root"; exit 1; } set -euo pipefail confd=/etc/e-router iptables=${IPTABLESCMD:-iptables} source $confd/config set_defaults() { /usr/lib/systemd/scripts/iptables-flush ${iptables} -P FORWARD DROP ${iptables} -P OUTPUT ACCEPT ${iptables} -P INPUT DROP } setup_final(){ if $loginput ; then setup_wandroplog ${iptables} -A INPUT -j WAN-LOG-DROP else ${iptables} -A INPUT -j DROP fi } setup_wandroplog() { ${iptables} -N WAN-LOG-DROP if $debugtcp; then ${iptables} -A WAN-LOG-DROP -p tcp -j LOG --log-prefix "WAN-LOG-DROP TCP: " --log-level 7 ${iptables} -A WAN-LOG-DROP -p tcp -j REJECT --reject-with tcp-reset fi if $debugudp; then ${iptables} -A WAN-LOG-DROP -p udp -j LOG --log-prefix "WAN-LOG-DROP UDP: " --log-level 7 ${iptables} -A WAN-LOG-DROP -p udp -j REJECT --reject-with icmp-port-unreachable fi if $debugicmp; then ${iptables} -A WAN-LOG-DROP -p icmp -j LOG --log-prefix "WAN-LOG-DROP ICMP: " --log-level 7 ${iptables} -A WAN-LOG-DROP -j REJECT --reject-with icmp-proto-unreachable fi } setup_fordroplog() { ${iptables} -N FORWARD-LOG-DROP if $debugtcp; then ${iptables} -A FORWARD-LOG-DROP -p tcp -j LOG --log-prefix "FORWARD-LOG-DROP TCP: " --log-level 7 ${iptables} -A FORWARD-LOG-DROP -p tcp -j REJECT --reject-with tcp-reset fi if $debugudp; then ${iptables} -A FORWARD-LOG-DROP -p udp -j LOG --log-prefix "FORWARD-LOG-DROP UDP: " --log-level 7 ${iptables} -A FORWARD-LOG-DROP -p udp -j REJECT --reject-with icmp-port-unreachable fi if $debugicmp; then ${iptables} -A FORWARD-LOG-DROP -p icmp -j LOG --log-prefix "FORWARD-LOG-DROP ICMP: " --log-level 7 ${iptables} -A FORWARD-LOG-DROP -j REJECT --reject-with icmp-proto-unreachable fi } setup_nat() { ${iptables} -t nat -A POSTROUTING -o ${wan} -s ${locnet} -j MASQUERADE } setup_forward() { ${iptables} -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT ${iptables} -A FORWARD -i ${eth0} -o ${wan} -j ACCEPT while read -r ip public private ; do [[ "$ip" =~ ^[0-9]{1,}.[0-9]{1,}.[0-9]{1,}.[0-9]{1,}$ ]] || continue [[ "$public" =~ ^[0-9]{1,}|[0-9]{1,}:[0-9]{1,}$ ]] || continue [[ "$private" =~ ^[0-9]{1,}|[0-9]{1,}:[0-9]{1,}$ ]] || continue if [[ "$public" =~ ^[0-9]{1,}$ ]] ; then ${iptables} -A PREROUTING -t nat -i ${wan} -p tcp --dport ${public} -j DNAT --to ${ip}:${private} ${iptables} -A FORWARD -i ${wan} -p tcp --syn -d ${ip} --dport ${private} -m conntrack --ctstate NEW --ctproto TCP -j ACCEPT else ${iptables} -A PREROUTING -t nat -i ${wan} -p tcp --dport ${public} -j DNAT --to ${ip} ${iptables} -A FORWARD -i ${wan} -p tcp --syn -d ${ip} --dport ${public} -m conntrack --ctstate NEW --ctproto TCP -j ACCEPT fi done < $confd/FORWARD.tcp while read -r ip public private ; do [[ "$ip" =~ ^[0-9]{1,}.[0-9]{1,}.[0-9]{1,}.[0-9]{1,}$ ]] || continue [[ "$public" =~ ^[0-9]{1,}|[0-9]{1,}:[0-9]{1,}$ ]] || continue [[ "$private" =~ ^[0-9]{1,}|[0-9]{1,}:[0-9]{1,}$ ]] || continue if [[ "$public" =~ ^[0-9]{1,}$ ]] ; then ${iptables} -A PREROUTING -t nat -i ${wan} -p udp --dport ${public} -j DNAT --to ${ip}:${private} ${iptables} -A FORWARD -i ${wan} -p udp -d ${ip} --dport ${private} -m conntrack --ctstate NEW --ctproto UDP -j ACCEPT else ${iptables} -A PREROUTING -t nat -i ${wan} -p udp --dport ${public} -j DNAT --to ${ip} ${iptables} -A FORWARD -i ${wan} -p udp -d ${ip} --dport ${public} -m conntrack --ctstate NEW --ctproto UDP -j ACCEPT fi done < $confd/FORWARD.udp if $logforward ; then setup_fordroplog ${iptables} -A FORWARD -j FORWARD-LOG-DROP else ${iptables} -A FORWARD -j DROP fi } setup_base() { ${iptables} -A INPUT -i lo -j ACCEPT ${iptables} -A INPUT -i ${eth0} -j ACCEPT ${iptables} -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT ${iptables} -A INPUT -m conntrack --ctstate INVALID -j DROP } setup_whitenets() { ipset create -! $whiteset hash:net hashsize 4096 timeout $whitettl maxelem $whitemaxelems while read -r net ; do [[ "$net" =~ ^[0-9]{1,}.[0-9]{1,}.[0-9]{1,}.[0-9]{1,}/[0-9]{1,}$ ]] || continue ipset -! add $whiteset $net timeout 0 done < $confd/WHITE.nets } setup_badips() { ipset create -! $banset hash:ip hashsize 4096 timeout $banttl maxelem $badmaxelems ${iptables} -A INPUT -i ${wan} -p udp -m set --match-set $banset src -m conntrack --ctstate NEW --ctproto UDP -j REJECT --reject-with icmp-port-unreachable ${iptables} -A INPUT -i ${wan} -p tcp -m set --match-set $banset src -m conntrack --ctstate NEW --ctproto TCP -j REJECT --reject-with tcp-reset } setup_scanips() { ipset create -! $scanset hash:ip hashsize 4096 timeout $scanttl maxelem $scanmaxelems ${iptables} -A INPUT -i ${wan} -p udp -m set --match-set $scanset src -m conntrack --ctstate NEW --ctproto UDP -j REJECT --reject-with icmp-port-unreachable ${iptables} -A INPUT -i ${wan} -p tcp -m set --match-set $scanset src -m conntrack --ctstate NEW --ctproto TCP -j REJECT --reject-with tcp-reset } setup_white() { ${iptables} -N FW-FILTERED while read -r port ; do [[ "$port" =~ ^[0-9]{1,}$ ]] || continue ${iptables} -A FW-FILTERED -p udp -m conntrack --ctstate NEW --ctproto UDP --dport $port -j ACCEPT done < $confd/WHITE.udp while read -r port ; do [[ "$port" =~ ^[0-9]{1,}$ ]] || continue ${iptables} -A FW-FILTERED -p tcp -m conntrack --ctstate NEW --ctproto TCP --dport $port -j ACCEPT done < $confd/WHITE.tcp ${iptables} -A INPUT -i ${wan} -p udp -m set --match-set $whiteset src -m conntrack --ctstate NEW --ctproto UDP -j FW-FILTERED ${iptables} -A INPUT -i ${wan} -p tcp -m set --match-set $whiteset src -m conntrack --ctstate NEW --ctproto TCP -j FW-FILTERED ${iptables} -A INPUT -i ${wan} -p icmp --icmp-type 8 -m set --match-set $whiteset src -m conntrack --ctstate NEW --ctproto ICMP -j ACCEPT } setup_public() { ${iptables} -N FW-PUBLIC while read -r port ; do [[ "$port" =~ ^[0-9]{1,}$ ]] || continue ${iptables} -A FW-PUBLIC -p udp -m conntrack --ctstate NEW --ctproto UDP --dport $port -j ACCEPT done < $confd/PUBLIC.udp while read -r port ; do [[ "$port" =~ ^[0-9]{1,}$ ]] || continue ${iptables} -A FW-PUBLIC -p tcp -m conntrack --ctstate NEW --ctproto TCP --dport $port -j ACCEPT done < $confd/PUBLIC.tcp ${iptables} -A INPUT -i ${wan} -p udp -m conntrack --ctstate NEW --ctproto UDP -j FW-PUBLIC ${iptables} -A INPUT -i ${wan} -p tcp -m conntrack --ctstate NEW --ctproto TCP -j FW-PUBLIC } setup_cast() { ${iptables} -N FW-CAST ${iptables} -A FW-CAST -m pkttype --pkt-type broadcast -j ACCEPT ${iptables} -A FW-CAST -m pkttype --pkt-type multicast -j ACCEPT ${iptables} -A INPUT -i ${wan} -j FW-CAST } main () { defaultHooks="set_defaults setup_whitenets setup_nat setup_forward setup_base setup_badips setup_white setup_public setup_scanips setup_cast setup_final" hookarray=(${hooks:-$defaultHooks}) for hook in "${hookarray[@]}" ; do $hook done } main