From 947f31f496906bf18f009bd845dde72d5606282d Mon Sep 17 00:00:00 2001 From: Justin Wind Date: Sun, 1 Oct 2017 11:24:54 -0700 Subject: [PATCH] initial router config --- router.sh | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100755 router.sh diff --git a/router.sh b/router.sh new file mode 100755 index 0000000..2ff05af --- /dev/null +++ b/router.sh @@ -0,0 +1,294 @@ +#!/bin/bash + +set -e + +# some system-specific config... + +EXT=173.164.216.234 +EXT_IF=eth2 + +INT='192.168.0.0/24' +INT_IF=eth5 + +EXT6_IF=he6 +INT6_IF=eth5 +SUBNET6='2001:470:1f05:cb8::/64' + +UPLINK=11232 #kbit +BURST=15 #k + +# note that behavior between v4 and v6 is slightly different + +### +## +# +IPTABLES=$(which iptables) +IP6TABLES=$(which ip6tables) +IPSET=$(which ipset) +TC=$(which tc) +SYSCTL=/usr/sbin/sysctl +F2B_CTL="/etc/init.d/fail2ban" + +if [ "commit" != "$1" ]; then + IPTABLES="echo ${IPTABLES}" + IP6TABLES="echo ${IP6TABLES}" + IPSET="echo ${IPSET}" + TC="echo ${TC}" + SYSCTL="echo ${SYSCTL}" + F2B_CTL="echo ${F2B_CTL}" +fi + +# fail2ban writes its own chains, don't flush tables before shutting it down +f2b_needs_attention=0 +if f2b_pid=$(cat /var/run/fail2ban/fail2ban.pid) +then + f2b_comm=`ps -o comm= -p ${f2b_pid}` + if [ $? -eq 0 ]; then + if [ "fail2ban-server" = "${f2b_comm}" ]; then + f2b_needs_attention=1 + fi + fi +fi + +function sysctl_set(){ + if [ "$2" != $($SYSCTL -ne "$1") ] + then + echo "setting $1 to $2" + $SYSCTL -w "$1"="$2" + fi +} + +# system config +# enable forwarding +sysctl_set net.ipv4.ip_forward 1 +sysctl_set net.ipv6.conf.all.forwarding 1 +# disable routing triangulation; queries go out same interface +sysctl_set net.ipv4.conf.all.rp_filter 1 +# log malformed packets +#${SYSCTL} -w net.ipv4.conf.all.log_martians=1 +sysctl_set net.ipv4.conf.all.log_martians 0 +# disable redirects +sysctl_set net.ipv4.conf.all.send_redirects 0 +sysctl_set net.ipv4.conf.all.accept_redirects 0 +# disable source routed packets +sysctl_set net.ipv4.conf.all.accept_source_route 0 +# do syncookies +sysctl_set net.ipv4.tcp_syncookies 1 + +if [ ${f2b_needs_attention} -eq 1 ]; then + ${F2B_CTL} stop +fi + +# flush tables +${IPTABLES} -F +${IPTABLES} -F INPUT +${IPTABLES} -F OUTPUT +${IPTABLES} -F FORWARD +${IPTABLES} -F -t mangle +${IPTABLES} -F -t nat +${IPTABLES} -X + +$IP6TABLES -F +$IP6TABLES -F INPUT +$IP6TABLES -F OUTPUT +$IP6TABLES -F FORWARD +$IP6TABLES -F -t mangle +$IP6TABLES -X + +# default policies +$IPTABLES -P INPUT DROP +$IPTABLES -P OUTPUT ACCEPT +$IPTABLES -P FORWARD ACCEPT + +$IP6TABLES -P INPUT DROP +$IP6TABLES -P OUTPUT DROP +$IP6TABLES -P FORWARD DROP + +# clear and reset traffic control +( +set +e +if $TC qdisc del dev ${EXT_IF} +then + echo "removed existing qdisc" +else + echo "new qdisc" +fi +if $TC qdisc add dev ${EXT_IF} root handle 1: htb default 30 +then + echo "qdisc root exists" +else + echo "new qdisc root" +fi +$TC class add dev ${EXT_IF} parent 1: classid 1:1 htb rate ${UPLINK}kbit burst ${BURST}k +$TC class add dev ${EXT_IF} parent 1:1 class 1:10 htb rate ${UPLINK}kbit burst ${BURST}k prio 1 +$TC class add dev ${EXT_IF} parent 1:1 class 1:20 htb rate ${UPLINK}kbit burst ${BURST}k prio 2 +$TC class add dev ${EXT_IF} parent 1:1 class 1:30 htb rate $(expr 9 \* ${UPLINK} / 10)kbit burst ${BURST}k prio 3 +$TC class add dev ${EXT_IF} parent 1:1 class 1:40 htb rate $(expr 5 \* ${UPLINK} / 10)kbit burst ${BURST}k prio 4 +$TC class add dev ${EXT_IF} parent 1:1 class 1:50 htb rate $(expr 5 \* ${UPLINK} / 10)kbit burst $(expr 2 \* ${BURST} / 3)k prio 5 + +for x in $(seq 5) +do + $TC qdisc add dev ${EXT_IF} parent 1:${x}0 handle ${x}0: sfq perturb 10 + $TC filter add dev ${EXT_IF} parent 1: prio 0 protocol ip handle ${x} fw flowid 1:${x}0 +done +) + +SHAPE_CHAIN='SHAPER-OUT' +# shaper marking +$IPTABLES -t mangle -X ${SHAPE_CHAIN} +$IPTABLES -t mangle -N ${SHAPE_CHAIN} +$IP6TABLES -t mangle -X ${SHAPE_CHAIN} +$IP6TABLES -t mangle -N ${SHAPE_CHAIN} + +function shape() { + local PRIO=$1 + shift + if ! $IPTABLES -t mangle -C ${SHAPE_CHAIN} "$@" -j MARK --set-mark ${PRIO} >/dev/null 2>&1 + then + $IPTABLES -t mangle -A ${SHAPE_CHAIN} "$@" -j MARK --set-mark ${PRIO} + fi + if ! $IP6TABLES -t mangle -C ${SHAPE_CHAIN} "$@" -j MARK --set-mark ${PRIO} >/dev/null 2>&1 + then + $IP6TABLES -t mangle -A ${SHAPE_CHAIN} "$@" -j MARK --set-mark ${PRIO} + fi +} + +# prioritize small and responsive things +shape 1 -p icmp +shape 1 -p ipv6-icmp +shape 1 -p udp +#shape 1 -p tcp -m length :64 +#shape 1 -p tcp --syn -m length 40:68 +#shape 1 -p tcp --tcp-flags ALL ACK -m length --length 40:100 +shape 1 -p tcp --tcp-flags ALL RST +shape 1 -p tcp --tcp-flags ALL ACK,RST +shape 1 -p tcp --tcp-flags ALL ACK,FIN + +# favor ssh +shape 2 -p tcp --dport 22 + +# defavor ftp +shape 4 -p tcp --dport 20 +shape 4 -p tcp --dport 115 + +# bulk bittorrent +shape 5 -p tcp --dport 8881:8899 +shape 5 -p tcp --sport 8881:8899 + +# default everything else to middle +shape 3 -m mark --mark 0 + +# tag traffic +$IPTABLES -t mangle -I POSTROUTING -o ${EXT_IF} -j ${SHAPE_CHAIN} + + +# reserve a special place in hell for some people +$IPTABLES -N xenophobe +$IPTABLES -A xenophobe -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN +$IPTABLES -A xenophobe -j REJECT --reject-with icmp-port-unreachable + +$IP6TABLES -N xenophobe +$IP6TABLES -A xenophobe -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN +$IP6TABLES -A xenophobe -j REJECT --reject-with icmp6-port-unreachable + +# create ipsets for v4 and v6 +for s in xenophobe sinokorea +do + $IPSET create "$s" -exist hash:net counters + $IPSET create "$s"6 -exist hash:net family inet6 counters +done +for s in trusted +do + $IPSET create "$s" -exist hash:net + $IPSET create "$s"6 -exist hash:net family inet6 +done + +# create ipsets shared by v4 and v6 +for s in allowed_udp allowed_tcp +do + $IPSET create "$s" -exist bitmap:port range 0-65535 +done + + +### +## +# + +# allow local traffics +$IPTABLES -A INPUT -i lo -j ACCEPT +$IP6TABLES -A INPUT -i lo -j ACCEPT +$IP6TABLES -A OUTPUT -o lo -j ACCEPT + +# allow anything out to v6 +$IP6TABLES -A OUTPUT -o ${EXT6_IF} -j ACCEPT + +# allow all internal traffic in +$IP6TABLES -I INPUT -i ${INT6_IF} -j ACCEPT + +# allow icmp +$IPTABLES -A INPUT -p icmp -j ACCEPT +$IP6TABLES -A INPUT -p ipv6-icmp -j ACCEPT +$IP6TABLES -A OUTPUT -p ipv6-icmp -j ACCEPT +$IP6TABLES -A FORWARD -p ipv6-icmp -j ACCEPT + +# drop source-route headered v6 +$IP6TABLES -A INPUT -m rt --rt-type 0 -j DROP || echo "MISSING RT MATCH" 1>&2 + +# drop bad packets; these are all illegal combinations +for flags in 'ALL FIN,URG,PSH' 'ALL ALL' 'ALL SYN,RST,ACK,FIN,URG' 'ALL NONE' 'SYN,RST SYN,RST' 'SYN,FIN SYN,FIN' +do + $IPTABLES -A INPUT -p tcp --tcp-flags ${flags} -j DROP +done + +# allow trusted things +$IPTABLES -A INPUT -m set --match-set trusted src -j ACCEPT +$IP6TABLES -A INPUT -m set --match-set trusted6 src -j ACCEPT + +# drop sketchy things +$IPTABLES -A INPUT -m set --match-set xenophobe src -j xenophobe +$IP6TABLES -A INPUT -m set --match-set xenophobe6 src -j xenophobe + +# drop asia from ssh and smtp +$IPTABLES -A INPUT -m set --match-set sinokorea src -m multiport -p tcp --dports ssh,smtp -j xenophobe +$IP6TABLES -A INPUT -m set --match-set sinokorea6 src -m multiport -p tcp --dports ssh,smtp -j xenophobe + +# don't forward packets in +$IPTABLES -A FORWARD -i ${EXT_IF} -m conntrack --ctstate NEW,INVALID -j DROP + +# forward from internal site subnet +$IP6TABLES -A FORWARD -i ${INT6_IF} -o ${EXT6_IF} -s ${SUBNET6} -m conntrack --ctstate NEW -j ACCEPT + +# allow things we've dealt with +$IPTABLES -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +$IP6TABLES -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +$IP6TABLES -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + +# accept ipv6 link-local +$IP6TABLES -A INPUT -s fe80::/10 -j ACCEPT +$IP6TABLES -A OUTPUT -s fe80::/10 -j ACCEPT + +# accept ipv6 multicast +$IP6TABLES -A INPUT -s ff00::/8 -j ACCEPT +$IP6TABLES -A OUTPUT -s ff00::/8 -j ACCEPT + +# many:1 NAT +$IPTABLES -t nat -A POSTROUTING -o ${EXT_IF} -j SNAT --to ${EXT} + +# accept internal network traffic +$IPTABLES -A INPUT -i ${INT_IF} -j ACCEPT + +# accept list of external ports +$IPTABLES -A INPUT -i ${EXT_IF} -p tcp -m set --match-set allowed_tcp dst -j ACCEPT +$IPTABLES -A INPUT -i ${EXT_IF} -p udp -m set --match-set allowed_udp dst -j ACCEPT +$IP6TABLES -A INPUT -i ${EXT6_IF} -p tcp -m set --match-set allowed_tcp dst -j ACCEPT +$IP6TABLES -A INPUT -i ${EXT6_IF} -p udp -m set --match-set allowed_udp dst -j ACCEPT + +# load rules +# inserts, so stack order matters +./sinokorea.sh +./xenophobe.sh +./trusted.sh + +if [ ${f2b_needs_attention} -eq 1 ]; then + ${F2B_CTL} start +fi -- 2.45.2