firewall/firewall.sh

482 lines
13 KiB
Bash
Raw Normal View History

2024-09-23 15:44:35 -06:00
#!/bin/bash
2024-09-24 09:42:31 -06:00
DATE="$(date +%d/%b/%Y:%H:%M -d '1 minute ago')"
2024-09-23 22:44:50 -06:00
MY_IP=($(redis-cli --raw SMEMBERS my_ip))
2024-09-23 15:44:35 -06:00
ATTACK_THRESHOLD="50"
NGINX_ACCESS="/tmp/access.log"
2024-09-24 09:51:37 -06:00
ACCESS="/tmp/minute.log"
2024-09-24 17:44:34 -06:00
HTTP_LIMIT="100"
RATE_LIMITED_HTTP="30"
2024-09-24 21:10:18 -06:00
MODULES="/opt/firewall/modules"
2024-09-24 17:51:03 -06:00
grep $DATE $NGINX_ACCESS >$ACCESS
2024-09-23 15:44:35 -06:00
#Firewall Port Configuration
#
2024-09-23 22:27:53 -06:00
declare -A portConfig
2024-09-23 15:44:35 -06:00
portConfig["https"]="443"
portConfig["http"]="80"
portConfig["cups"]="631"
portConfig["WireGuard"]="57692"
portConfig["AdGuard-1"]="3000"
portConfig["AdGuard-2"]="8082"
portConfig["AdGuard-3"]="853"
portConfig["Uptime"]="4001"
portConfig["DNS-1"]="53"
portConfig["DNS-2"]="67"
portConfig["DNS-3"]="68"
portConfig["CUPS-1"]="631"
portConfig["CUPS-2"]="5353"
#portConfig["Bitcoin-1"]="8333"
#portConfig["Bitcoin-2"]="8332"
#portConfig["Bitcoin-3"]="8333"
#portConfig["Bitcoin-4"]="4050"
#portConfig["KDE-Connect"]="1714-1764"
#portConfig["Lightning-1"]="10009"
#portConfig["Lightning-1"]="9735"
#portConfig["Lightning-2"]="8080"
#portConfig["Lightning-3"]="28334"
#portConfig["Lightning-4"]="28333"
#portConfig["Lightning-5"]="19998"
#portConfig["Lightning-6"]="29000"
portConfig["SyncThing-1"]="22000"
portConfig["SyncThing-2"]="8384"
portConfig["SyncThing-3"]="21027"
#portConfig["NFS-1"]="2049"
#portConfig["NFS-2"]="111"
portConfig["Jellyfin-1"]="8096"
portConfig["Jellyfin-1"]="7359"
portConfig["SSH"]="22"
MACHINES=(127.0.0.1)
VIRT_BRIDGE="virbr0"
#### NFT CONFIG ####
#
NFT='/usr/bin/nft'
NFT_CACHE='/tmp/nft.cache'
2024-09-23 22:08:38 -06:00
TMP_BLOCK=($(redis-cli --raw SMEMBERS tmp_block))
2024-09-23 23:04:37 -06:00
#Redis DB
2024-09-23 15:44:35 -06:00
#
2024-09-23 22:08:38 -06:00
SAVED_BOTS=($(redis-cli --raw SMEMBERS bots))
CRAWLER_DB=($(redis-cli --raw SMEMBERS crawlers))
SAFE_TRAFFIC=($(redis-cli --raw SMEMBERS safe_traffic))
2024-09-23 15:44:35 -06:00
RULE_SET='/opt/firewall/nft.rules'
MENU_TOP="=============================FireWall================================="
MENU_BOTTOM="====================================================================="
nft list table filter >$NFT_CACHE
2024-09-23 22:27:53 -06:00
ipBlockParser() {
if [[ "$1" == *":"* ]]; then
$NFT insert rule ip6 filter input position 0 ip6 saddr $1 drop
else
$NFT insert rule ip filter input position 0 ip saddr "$1" drop
fi
2024-09-23 15:44:35 -06:00
}
2024-09-23 22:27:53 -06:00
portOpenParser() {
if [[ "$1" == "443" || "$1" == "80" ]]; then
2024-09-24 17:51:03 -06:00
echo "Skipping $1"
2024-09-23 22:27:53 -06:00
else
$NFT add rule ip filter input position 0 tcp dport $1 accept
$NFT add rule ip filter input position 0 udp dport $1 accept
$NFT add rule ip6 filter input position 0 tcp dport $1 accept
$NFT add rule ip6 filter input position 0 udp dport $1 accept
fi
2024-09-23 15:44:35 -06:00
}
2024-09-23 22:27:53 -06:00
ipDeleteParser() {
if [[ "$1" == *":"* ]]; then
2024-09-24 17:44:34 -06:00
$NFT delete rule ip6 filter input handle $HANDLE &>/dev/null
2024-09-23 22:27:53 -06:00
else
2024-09-24 17:44:34 -06:00
$NFT delete rule ip filter input handle $HANDLE &>/dev/null
2024-09-23 22:27:53 -06:00
fi
2024-09-24 17:51:03 -06:00
redis-cli SREM tmp_block $i
redis-cli SREM bots $i
2024-09-23 15:44:35 -06:00
}
blockCountry() {
2024-09-24 17:51:03 -06:00
DATA=($(redis-cli SMEMBERS country_ip))
2024-09-23 22:56:04 -06:00
for i in "${DATA[@]}"; do
2024-09-23 15:44:35 -06:00
echo "Blocking $i"
2024-09-23 22:56:04 -06:00
ipBlockParser $i
2024-09-23 15:44:35 -06:00
done
}
wireguard-networking() {
$NFT add table nat
$NFT add chain nat postrouting
$NFT add rule nat postrouting oif wg0 iif enp11s0
$NFT add rule nat postrouting oif enp11s0 iif wg0
$NFT add rule nat postrouting masquerade
$NFT add rule filter forward iifname wg0 oif enp11s0 accept
$NFT add rule filter forward iifname enp11s0 oif wg0 accept
$NFT add rule ip filter input ip saddr 192.168.5.0/24 accept
}
attacker-protection() {
watch
2024-09-24 21:34:13 -06:00
bash $MODULES/module-nostr.sh "$i" "$DATE"
2024-09-23 15:44:35 -06:00
bot-search
}
bot-search() {
2024-09-24 21:37:55 -06:00
echo "Searching for Web Crawalers...."
2024-09-24 09:51:37 -06:00
CRAWLERS=($(grep $DATE $ACCESS | grep -vi $MY_IP | grep -Evi 'Guro|spank|report|rape|block' | grep -Ff <(printf '%s\n' "${CRAWLER_DB[@]}") | grep -Fivf <(printf '%s\n' "${SAFE_TRAFFIC[@]}") | cut -d "-" -f1 | sort -u))
2024-09-23 15:44:35 -06:00
echo
echo "Processing Web Crawler list into NFT....."
echo
for i in "${CRAWLERS[@]}"; do
CHECK=$(cat $NFT_CACHE | grep $i)
if [ "$CHECK" = "" ]; then
ipBlockParser $i
2024-09-23 22:08:38 -06:00
redis-cli SADD bots $i
2024-09-23 15:44:35 -06:00
else
echo
echo "Skipping Duplicate IP $i"
echo
fi
done
}
basic-security() {
$NFT flush ruleset
$NFT -f /opt/firewall/ipv4-filter.nft
$NFT -f /opt/firewall/ipv6-filter.nft
$NFT add rule filter input icmp type echo-request drop
$NFT rule filter output accept
$NFT rule filter forward accept
$NFT insert rule filter input ct state established accept
$NFT insert rule filter input iif lo accept
2024-09-23 22:27:53 -06:00
for i in "${!portConfig[@]}"; do
echo "Enabling Port for: $i"
2024-09-23 15:44:35 -06:00
portOpenParser "${portConfig[$i]}"
done
2024-09-24 17:44:34 -06:00
#$NFT add rule filter input drop
#$NFT add rule ip6 filter input drop
2024-09-23 15:44:35 -06:00
}
virtualization() {
ip link del virbr0
killall dnsmasq
/usr/bin/systemctl restart libvirtd
/usr/bin/virsh net-start default
/usr/bin/systemctl restart pleroma
$NFT insert rule filter input iif $VIRT_BRIDGE accept
}
trust() {
for i in "${MACHINES[@]}"; do
$NFT add rule filter input ip saddr $i accept
done
}
import-saved() {
2024-09-23 22:08:38 -06:00
for i in "${SAVED_BOTS[@]}"; do
2024-09-23 22:27:53 -06:00
ipBlockParser $i
2024-09-23 15:44:35 -06:00
done
}
start() {
basic-security
if [[ $HOSTNAME == *"nas"* ]]; then
sysctl -w net.ipv4.conf.all.forwarding=1
import-saved
blockCountry
wireguard-networking
docker restart uptime-kuma
2024-09-23 22:27:53 -06:00
#Docker
2024-09-23 15:44:35 -06:00
$NFT insert rule filter input iif docker0 accept
2024-09-24 17:44:34 -06:00
#HTTP Rate Limit
2024-09-24 22:43:29 -06:00
bash $MODULES/module-rate-limit.sh $HTTP_LIMIT
2024-09-24 17:44:34 -06:00
2024-09-23 15:44:35 -06:00
else
virtualization
fi
2024-09-24 21:56:54 -06:00
message "Starting Firewall"
2024-09-23 15:44:35 -06:00
}
research() {
2024-09-23 22:27:53 -06:00
STATS=($(redis-cli --raw SMEMBERS tmp_block | sort -u))
2024-09-23 15:44:35 -06:00
for i in "${STATS[@]}"; do
echo $MENU_TOP
echo " [Researching $i] "
echo
2024-09-23 22:08:38 -06:00
DATA=$(grep $i $NGINX_LOG | grep -Fivf <(printf '%s\n' "${SAFE_TRAFFIC[@]}"))
2024-09-23 15:44:35 -06:00
echo "$DATA"
echo
echo $MENU_BOTTOM
echo
read -p 'Press Enter to Continue ' -e
done
}
automaticStatus() {
status
sleep 30
automaticStatus
}
status() {
clear
2024-09-24 09:51:37 -06:00
sleep 2
2024-09-24 17:44:34 -06:00
RATE=$(cat $NFT_CACHE | grep 443 | cut -d ' ' -f14)
2024-09-24 09:51:37 -06:00
DATE="$(date +%d/%b/%Y:%H:%M -d '1 minute ago')"
STATS=$(grep $DATE $ACCESS | grep -vi $MY_IP | wc -l)
GET=$(grep $DATE $ACCESS | grep -vi $MY_IP | grep GET | wc -l)
POST=$(grep $DATE $ACCESS | grep -vi $MY_IP | grep POST | wc -l)
PUT=$(grep $DATE $ACCESS | grep -vi $MY_IP | grep -i PUT | wc -l)
NOT_FOUND=$(grep $DATE $ACCESS | grep -vi $MY_IP | grep 404 | wc -l)
GATEWAY=$(grep $DATE $ACCESS | grep -vi $MY_IP | grep 502 | wc -l)
SUCCESS=$(grep $DATE $ACCESS | grep -vi $MY_IP | grep 200 | wc -l)
CRAWL=$(grep $DATE $ACCESS | grep -vi $MY_IP | grep -Ff <(printf '%s\n' "${CRAWLER_DB[@]}") | wc -l)
2024-09-23 15:44:35 -06:00
echo $MENU_TOP
echo "Attack Threshold: $ATTACK_THRESHOLD"
echo "Firewall Rules: $($NFT list table filter | wc -l)"
2024-09-24 17:44:34 -06:00
echo "Rate Limit: $RATE"
2024-09-23 15:44:35 -06:00
echo
echo "Traffic Last Minute: $STATS"
echo " GET: $GET"
echo " PUT: $PUT"
echo " POST: $POST"
echo " Crawlers: $CRAWL"
echo
echo "Query Stats:: "
echo " 200: $SUCCESS"
echo " 404: $NOT_FOUND"
echo " 502: $GATEWAY"
echo
#echo "Dropped Traffic: $($NFT list table filter | grep -Ei 'log counter packets' | cut -d ' ' -f6)"
echo
echo "Rate-limited IP's:"
2024-09-23 22:08:38 -06:00
echo
redis-cli --raw SMEMBERS tmp_block | sort -u
2024-09-23 15:44:35 -06:00
echo $MENU_BOTTOM
}
stop() {
#forgive
2024-09-24 17:44:34 -06:00
#$NFT -s list ruleset | tee $RULE_SET
2024-09-23 15:44:35 -06:00
$NFT flush ruleset
$NFT -f /usr/share/nftables/ipv4-filter.nft
$NFT add rule filter input icmp type echo-request accept
$NFT rule filter input accept
$NFT rule filter output accept
$NFT rule filter forward accept
$NFT insert rule filter input ct state established accept
$NFT insert rule filter input iif lo accept
$NFT -f /opt/firewall/ipv6-filter.nft
# $NFT add rule ip6 filter input icmpv6 type nd-neighbor-solicit accept
# $NFT add rule ip6 filter input icmpv6 type nd-router-advert accept
message "Stopping Firewall"
}
forgive() {
2024-09-23 22:08:38 -06:00
IP=($(redis-cli --raw SMEMBERS tmp_block | sort -u))
2024-09-23 15:44:35 -06:00
echo $IP
for i in "${IP[@]}"; do
HANDLE=$(nft -n -a list ruleset | grep $i | grep handle | cut -d '#' -f2 | cut -d ' ' -f3)
echo "Removing: $i Handle: $HANDLE"
ipDeleteParser $HANDLE
done
echo "Clearing old $TMP_BLOCK"
2024-09-23 22:08:38 -06:00
redis-cli DEL tmp_blocked
2024-09-24 22:43:29 -06:00
bash $MODULES/module-rate-limit.sh $HTTP_LIMIT
2024-09-23 15:44:35 -06:00
}
watch() {
echo "Scanning $DATE"
echo
2024-09-24 09:51:37 -06:00
IP=($(grep $DATE $ACCESS | grep -Fivf <(printf '%s\n' "${SAFE_TRAFFIC[@]}") | grep -Fivf <(printf '%s\n' "${CRAWLER_DB[@]}") | grep -Fivf <(printf '%s\n' "${SAVED_BOTS[@]}") | grep -vi $MY_IP | grep -vi '127.0.0.1' | cut -d ' ' -f1 | sort -u))
2024-09-23 22:27:53 -06:00
2024-09-23 15:44:35 -06:00
for i in "${IP[@]}"; do
2024-09-24 21:52:37 -06:00
bash $MODULES/module-akkoma-instance.sh "$i" "$DATE"
bash $MODULES/module-akkoma-timeline-public.sh "$i" "$DATE"
bash $MODULES/module-akkoma-timeline-home.sh "$i" "$DATE"
bash $MODULES/module-akkoma-accounts.sh "$i" "$DATE"
bash $MODULES/module-akkoma-search.sh "$i" "$DATE"
bash $MODULES/module-lightning.sh "$i" "$DATE"
bash $MODULES/module-php.sh "$i" "$DATE"
bash $MODULES/module-go.sh "$i" "$DATE"
2024-09-24 21:40:35 -06:00
2024-09-24 09:51:37 -06:00
COUNT=$(grep $DATE $ACCESS | grep $i | grep -Fivf <(printf '%s\n' "${SAFE_TRAFFIC[@]}") | grep -Fivf <(printf '%s\n' "${SAVED_BOTS[@]}") | wc -l)
2024-09-23 15:44:35 -06:00
CHECK=$(cat $NFT_CACHE | sort -u | grep $i)
if [[ "$COUNT" -gt $ATTACK_THRESHOLD ]]; then
if [ "$CHECK" = "" ]; then
echo "Danger! Blocking IP: $i Count: $COUNT"
logger "Blocking IP: $i with a count of: $COUNT"
2024-09-23 22:08:38 -06:00
redis-cli SADD tmp_block $i
2024-09-23 15:44:35 -06:00
ipBlockParser $i
message "Blocking IP: $i with a count of: $COUNT"
else
echo
echo "Skipping Duplicate IP"
echo
fi
else
echo
echo "$i count: $COUNT below Threshhold: $ATTACK_THRESHOLD"
echo
fi
done
2024-09-24 17:44:34 -06:00
2024-09-24 17:51:03 -06:00
BLOCK_CHECK=$(redis-cli --raw SMEMBERS tmp_block)
if [[ "$BLOCK_CHECK" == *"empty"* || "$BLOCK_CHECK" == "" ]]; then
2024-09-24 22:43:29 -06:00
bash $MODULES/module-rate-limit.sh $HTTP_LIMIT
2024-09-24 17:51:03 -06:00
else
2024-09-24 22:43:29 -06:00
bash $MODULES/module-rate-limit.sh $RATE_LIMITED_HTTP
2024-09-24 17:51:03 -06:00
fi
}
2024-09-24 17:44:34 -06:00
message() {
2024-09-24 22:38:26 -06:00
#Message Alert Module. Configure modules/module-message.sh with actions.
bash $MODULES/module-message.sh "$1"
2024-09-24 17:44:34 -06:00
}
2024-09-23 15:44:35 -06:00
test-bots() {
2024-09-23 22:08:38 -06:00
for i in "${SAVED_BOTS[@]}"; do
2024-09-24 09:51:37 -06:00
DATA=$(grep $i $ACCESS | grep -Fivf <(printf '%s\n' "${CRAWLER_DB[@]}"))
2024-09-23 15:44:35 -06:00
if [ "$DATA" = "" ]; then
echo "No Data. Probably OK"
else
echo $DATA
echo
read -p 'Press Enter to Continue ' -e
fi
done
}
research-ip() {
echo "Enter an IP Address to search"
read -p 'IP Address: ' -e IP
2024-09-24 09:51:37 -06:00
cat $ACCESS | grep $IP
2024-09-23 15:44:35 -06:00
echo
read -p 'Press Enter to Continue ' -e
}
menu() {
clear
echo
echo $MENU_TOP
echo "1. Start"
echo "2. Stop"
echo "3. Reseearch"
echo "4. Forgive"
echo "5. Status"
echo "6. Live Traffic"
echo "7. Test Bot Search Rules"
echo "8. Research IP"
echo "9. View Current Rule Set"
echo "0. Quit"
echo $MENU_BOTTOM
echo
read -p 'Choice: ' CHOICE
echo
if [ "$CHOICE" = "1" ]; then
echo
echo "Starting Firewall"
start
read -p 'Press Enter to Continue ' -e-
elif [ "$CHOICE" = "2" ]; then
echo
echo "Stopping Firewall"
stop
read -p 'Press Enter to Continue ' -e
elif [ "$CHOICE" = "3" ]; then
research
read -p 'Press Enter to Continue ' -e
elif [ "$CHOICE" = "4" ]; then
forgive
elif [ "$CHOICE" = "55" ]; then
automaticStatus
elif [ "$CHOICE" = "5" ]; then
status
read -p 'Press Enter to Continue ' -e
elif [ "$CHOICE" = "6" ]; then
2024-09-24 09:51:37 -06:00
tail -f $ACCESS | grep -Fivf <(printf '%s\n' "${SAFE_TRAFFIC[@]}") | grep -Fivf <(printf '%s\n' "${CRAWLER_DB[@]}")
2024-09-23 15:44:35 -06:00
read -p 'Press Enter to Continue ' -e
elif [ "$CHOICE" = "7" ]; then
test-bots
read -p 'Press Enter to Continue ' -e
elif [ "$CHOICE" = "8" ]; then
research-ip
read -p 'Press Enter to Continue ' -e
elif [ "$CHOICE" = "9" ]; then
nft -s list ruleset | less
elif [ "$CHOICE" = "0" ]; then
exit
fi
echo
menu
}
2024-09-23 22:27:53 -06:00
importDB() {
DATA=($(cat safe.txt))
for i in "${DATA[@]}"; do redis-cli SADD safe_traffic $i; done
DATA=($(cat bots.txt))
for i in "${DATA[@]}"; do redis-cli SADD bots $i; done
DATA=($(cat crawlers.txt))
for i in "${DATA[@]}"; do redis-cli SADD crawlers $i; done
2024-09-23 22:44:50 -06:00
redis-cli SADD my_ip $(curl ifconfig.me)
2024-09-23 22:56:04 -06:00
redis-cli SADD country https://www.ipdeny.com/ipblocks/data/countries/il.zone \
https://www.ipdeny.com/ipblocks/data/countries/cn.zone
2024-09-24 17:51:03 -06:00
COUNTRY=($(redis-cli SMEMBERS country))
2024-09-23 22:56:04 -06:00
for i in "${COUNTRY[@]}"; do
echo
echo "Blocking $i"
DB=($(curl $i))
2024-09-24 17:51:03 -06:00
for j in "${DB[@]}"; do
redis-cli SADD country_ip $j
done
2024-09-23 22:56:04 -06:00
done
2024-09-23 22:17:27 -06:00
}
2024-09-23 22:27:53 -06:00
exportDB() {
2024-09-23 22:17:27 -06:00
rm -f crawlers.txt
rm -f bots.txt
rm -f safe.txt
2024-09-23 22:27:53 -06:00
for i in "${CRAWLER_DB[@]}"; do echo $i >>crawlers.txt; done
for i in "${SAVED_BOTS[@]}"; do echo $i >>bots.txt; done
for i in "${SAFE_TRAFFIC[@]}"; do echo $i >>safe.txt; done
2024-09-23 22:17:27 -06:00
}
2024-09-23 15:44:35 -06:00
if [ "$1" = "start" ]; then
start
2024-09-23 22:17:27 -06:00
elif [ "$1" = "import-db" ]; then
importDB
elif [ "$1" = "export-db" ]; then
exportDB
2024-09-23 15:44:35 -06:00
elif [ "$1" = "virt" ]; then
virtualization
elif [ "$1" = "bot-search" ]; then
bot-search
elif [ "$1" = "attacker-protection" ]; then
attacker-protection
elif [ "$1" = "status" ]; then
automaticStatus
elif [ "$1" = "forgive" ]; then
forgive
elif [ "$1" = "watch" ]; then
watch
elif [ "$1" = "research" ]; then
research
elif [ "$1" = "stop" ]; then
stop
elif [ "$1" = "test" ]; then
test-bots
2024-09-24 20:09:59 -06:00
elif [ "$1" = "message" ]; then
message "$2"
elif [ "$1" = "ipBlockParser" ]; then
ipBlockParser "$2"
2024-09-23 15:44:35 -06:00
elif [ "$1" = "import" ]; then
import-saved
else
menu
fi