Skip to content

Commit

Permalink
Create ipv6-rules.sh
Browse files Browse the repository at this point in the history
  • Loading branch information
RiccardoMasutti authored Dec 11, 2022
1 parent 005fc9b commit b3ba4dc
Showing 1 changed file with 183 additions and 0 deletions.
183 changes: 183 additions & 0 deletions files/ipv6-rules.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#!/bin/bash
# set -x


function addCommon() {
ip6tables -P INPUT DROP
ip6tables -P OUTPUT ACCEPT

# allow loopback
ip6tables -A INPUT --in-interface lo -m comment --comment "$(date -R)" -j ACCEPT
ip6tables -A INPUT -p udp --source fe80::/10 --dst ff02::1 -j ACCEPT

# make sure NEW incoming tcp connections are SYN packets
ip6tables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP

# do not touch established connections
ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# ssh
local port=$(grep -m 1 -E "^Port\s+[[:digit:]]+$" /etc/ssh/sshd_config | awk '{ print $2 }')
local addr=$(grep -m 1 -E "^ListenAddress\s+.+$" /etc/ssh/sshd_config | awk '{ print $2 }' | grep -F ':')
ip6tables -A INPUT -p tcp --dst ${addr:-"::/0"} --dport ${port:-22} -j ACCEPT

## ratelimit ICMP echo
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-request -m limit --limit 6/s -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-request -j DROP
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
}


function __fill_trustlist() {
(
echo "2a0c:dd40:1:b::42 2a0c:dd40:1:b::43 2a0c:dd40:1:b::44 2a0c:dd40:1:b::45 2a0c:dd40:1:b::46 2607:f018:600:8:be30:5bff:fef1:c6fa"
echo "2001:638:a000:4140::ffff:189 2001:678:558:1000::244 2001:67c:289c::9 2001:858:2:2:aabb:0:563b:1526 2607:8500:154::3 2610:1c0:0:5::131 2620:13:4000:6000::1000:118"

getent ahostsv6 snowflake-01.torproject.net. snowflake-02.torproject.net. | awk '{ print $1 }' | sort -u
if jq --help &>/dev/null; then
curl -s 'https://onionoo.torproject.org/summary?search=flag:authority' -o - | jq -cr '.relays[].a | select(length > 1) | .[1]' | tr -d '][' | sort -u
else
{ echo " please install package jq to fetch the latest Tor authority ips" >&2 ; }
fi
) | xargs -r -n 1 -P 20 ipset add -exist $trustlist
}


function __create_ipset() {
local name=$1
local seconds=$2

local cmd="ipset create -exist $name hash:ip family inet6 timeout $(( seconds )) maxelem $(( 2**20 ))"
if ! $cmd 2>/dev/null; then
content=$(ipset list -s $name | sed -e '1,8d')
if ! ipset destroy $name; then
{ echo " ipset does not work, cannot continue" >&2 ; }
exit 1
fi
$cmd
{ echo $content | xargs -r -n 3 -P 20 ipset add -exist $name ; } &
fi
}


function addTor() {
local trustlist="tor-trust6"
local hashlimit="-m hashlimit --hashlimit-mode srcip,dstport --hashlimit-srcmask 128 --hashlimit-htable-size $(( 2**20 )) --hashlimit-htable-max $(( 2**20 ))"

ipset create -exist $trustlist hash:ip family inet6
__fill_trustlist &

for relay in $*
do
read -r orip orport <<< $(sed -e 's,]:, ,' <<< $relay | tr '[' ' ')
if [[ $orip = "::" ]]; then
orip+="/0"
{ echo " please consider to set CONFIGURED_RELAYS6" >&2 ; }
fi

local synpacket="ip6tables -A INPUT -p tcp --dst $orip --dport $orport --syn"
local ddoslist="tor-ddos6-$orport"
__create_ipset $ddoslist "24*60*60"

# rule 1
$synpacket -m set --match-set $trustlist src -j ACCEPT

# rule 2
$synpacket $hashlimit --hashlimit-htable-expire $(( 60*1000 )) --hashlimit-name tor-ddos-$orport --hashlimit-above 6/minute --hashlimit-burst 5 -j SET --add-set $ddoslist src --exist
$synpacket -m set --match-set $ddoslist src -j DROP

# rule 3
$synpacket $hashlimit --hashlimit-htable-expire $(( 120*1000 )) --hashlimit-name tor-rate-$orport --hashlimit-above 1/hour --hashlimit-burst 1 -j DROP

# rule 4
$synpacket -m connlimit --connlimit-mask 128 --connlimit-above 3 -j DROP

# rule 5
$synpacket -j ACCEPT
done
}


function addLocalServices() {
local addr
local port

for service in ${ADD_LOCAL_SERVICES6:-}
do
read -r addr port <<< $(sed -e 's,]:, ,' <<< $service | tr '[' ' ')
if [[ $addr = "::" ]]; then
addr+="/0"
fi
ip6tables -A INPUT -p tcp --dst $addr --dport $port -j ACCEPT
done
}


function addHetzner() {
local sysmon="hetzner-sysmon6"

ipset create -exist $sysmon hash:ip family inet6
{
(
getent ahostsv6 pool.sysmon.hetzner.com | awk '{ print $1 }' | sort -u
echo "2a01:4f8:0:a101::5:1 2a01:4f8:0:a101::6:1 2a01:4f8:0:a101::6:2 2a01:4f8:0:a101::6:3 2a01:4f8:0:a112::c:1"
) | xargs -r -n 1 -P 20 ipset add -exist $sysmon
} &
ip6tables -A INPUT -m set --match-set $sysmon src -j ACCEPT
}


function clearAll() {
ip6tables -P INPUT ACCEPT
ip6tables -P OUTPUT ACCEPT

ip6tables -F
ip6tables -X
ip6tables -Z
}


function printFirewall() {
date -R
echo
ip6tables -nv -L INPUT
}


function getConfiguredRelays6() {
grep -h -e "^ORPort *" /etc/tor/torrc* | grep -v ' NoListen' |
grep -P "^ORPort\s+\[[0-9a-f]*:[0-9a-f:]*:[0-9a-f]*\]:\d+\s*" |
awk '{ print $2 }'
}


function bailOut() {
trap - INT QUIT TERM EXIT

{ echo "Something went wrong, stopping ..." >&2 ; }
clearAll
exit 1
}


#######################################################################
set -eu
export LANG=C.utf8
export PATH=/usr/sbin:/usr/bin:/sbin/:/bin

trap bailOut INT QUIT TERM EXIT
case ${1:-} in
start) clearAll
addCommon
addHetzner
addLocalServices
addTor ${CONFIGURED_RELAYS6:-$(getConfiguredRelays6)}
;;
stop) clearAll
ipset list -t | grep -P "^Name: tor-(conn|ddos)6-\d+$" | cut -f2 -d' ' | xargs -r -n 1 ipset flush 2>/dev/null
;;
*) printFirewall
;;
esac
trap - INT QUIT TERM EXIT

0 comments on commit b3ba4dc

Please sign in to comment.