Iptables: Difference between revisions

From Lolly's Wiki
Jump to navigationJump to search
(Created page with "==Block IPs dynamically from blocklists== I found a basic script https://www.lupovis.io/implementing-a-dynamic-blocklist-with-iptables/ here which I adapted to a set of lists and added logging. <SyntaxHighlight lang=bash> #!/bin/bash declare -A BLOCKLIST_URLS=( Emerging_Threats https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt TOR_exit_nodes https://opendbl.net/lists/tor-exit.list Bruteforce_Blocker https://opendbl.net/lists/bruteforce.list Block...")
 
Line 16: Line 16:


LIST_DIR="/etc/iptables_blocklist/lists"
LIST_DIR="/etc/iptables_blocklist/lists"
MAX_ELEMENTS=$[2**16]


[ ! -d ${LIST_DIR} ] && mkdir -p ${LIST_DIR}
[ ! -d ${LIST_DIR} ] && mkdir -p ${LIST_DIR}


for BLOCKLIST in ${!BLOCKLIST_URLS[@]}
case $1 in
do
stop)
  PREVIOUS_BLOCKLIST="${LIST_DIR}/previous_${BLOCKLIST}.txt"
for BLOCKLIST in ${!BLOCKLIST_URLS[@]}
  CURRENT_BLOCKLIST="${LIST_DIR}/current_${BLOCKLIST}.txt"
do
  LOG="DENY Dyn ${BLOCKLIST}"
PREVIOUS_BLOCKLIST="${LIST_DIR}/${BLOCKLIST}_previous.txt"
  [ -f ${CURRENT_BLOCKLIST} ] || touch ${CURRENT_BLOCKLIST}
LOG="DENY Dyn ${BLOCKLIST}"
  [ -f ${PREVIOUS_BLOCKLIST} ] || touch ${PREVIOUS_BLOCKLIST}
${IPTABLES} -D INPUT -m set --match-set ${BLOCKLIST} src -j DROP
  # Download the current blocklist
${IPTABLES} -D INPUT -m set --match-set ${BLOCKLIST} src -j LOG --log-prefix "${LOG} " --log-tcp-options --log-ip-options
  curl -s ${BLOCKLIST_URLS[${BLOCKLIST}]} -o ${CURRENT_BLOCKLIST}
${IPSET} destroy ${BLOCKLIST} -exist
  # Create the ipset set if it does not exist
>${PREVIOUS_BLOCKLIST}
  ${IPSET}  list -n ${BLOCKLIST} 2>/dev/null || ${IPSET} create ${BLOCKLIST} hash:ip maxelem 256000 timeout 0
done
  # Add new IPs to the blocklist
;;
  comm -13 <(sort -u <(grep -Ev "(^#|^$)" ${PREVIOUS_BLOCKLIST})) <(sort -u <(grep -Ev "(^#|^$)" ${CURRENT_BLOCKLIST})) | while read -r IP
restart)
  do
$0 stop
    ${IPSET} add ${BLOCKLIST} ${IP}
$0 start
  done
;;
  # Remove outdated IPs from the blocklist
start|update|*)
  comm -23 <(sort -u <(grep -Ev "(^#|^$)" ${PREVIOUS_BLOCKLIST})) <(sort -u <(grep -Ev "(^#|^$)" ${CURRENT_BLOCKLIST})) | while read -r IP
for BLOCKLIST in ${!BLOCKLIST_URLS[@]}
  do
do
    ${IPSET} del ${BLOCKLIST} ${IP}
PREVIOUS_BLOCKLIST="${LIST_DIR}/${BLOCKLIST}_previous.txt"
  done
CURRENT_BLOCKLIST="${LIST_DIR}/${BLOCKLIST}_current.txt"
  # Ensure the IPtables rule is in place
LOG="DENY Dyn ${BLOCKLIST}"
  ${IPTABLES} -C INPUT -m set --match-set ${BLOCKLIST} src -j DROP 2>/dev/null || ${IPTABLES} -I INPUT -m set --match-set ${BLOCKLIST} src -j DROP
[ -f ${CURRENT_BLOCKLIST} ] || touch ${CURRENT_BLOCKLIST}
  ${IPTABLES} -C INPUT -m set --match-set ${BLOCKLIST} src -j LOG --log-prefix "${LOG} " --log-tcp-options --log-ip-options 2>/dev/null || ${IPTABLES} -I INPUT -m set --match-set ${BLOCKLIST} src -j LOG --log-prefix "${LOG} " --log-tcp-options --log-ip-options
[ -f ${PREVIOUS_BLOCKLIST} ] || touch ${PREVIOUS_BLOCKLIST}
  # Save the current blocklist as the previous one for the next run
# Download the current blocklist
  cp ${CURRENT_BLOCKLIST} ${PREVIOUS_BLOCKLIST}
curl -s ${BLOCKLIST_URLS[${BLOCKLIST}]} -o ${CURRENT_BLOCKLIST}
done
# Create the ipset set if it does not exist
${IPSET} create ${BLOCKLIST} hash:net maxelem ${MAX_ELEMENTS} timeout 0 -exist
# Add new IPs to the blocklist
comm -13 <(sort -u <(grep -Ev "(^#|^$)" ${PREVIOUS_BLOCKLIST})) <(sort -u <(grep -Ev "(^#|^$)" ${CURRENT_BLOCKLIST})) | while read -r IP
do
  ${IPSET} add -exist ${BLOCKLIST} ${IP}
done
# Remove outdated IPs from the blocklist
comm -23 <(sort -u <(grep -Ev "(^#|^$)" ${PREVIOUS_BLOCKLIST})) <(sort -u <(grep -Ev "(^#|^$)" ${CURRENT_BLOCKLIST})) | while read -r IP
do
  ${IPSET} del -exist ${BLOCKLIST} ${IP}
done
# Ensure the IPtables rule is in place
${IPTABLES} -C INPUT -m set --match-set ${BLOCKLIST} src -j DROP 2>/dev/null || ${IPTABLES} -I INPUT -m set --match-set ${BLOCKLIST} src -j DROP
${IPTABLES} -C INPUT -m set --match-set ${BLOCKLIST} src -j LOG --log-prefix "${LOG} " --log-tcp-options --log-ip-options 2>/dev/null || ${IPTABLES} -I INPUT -m set --match-set ${BLOCKLIST} src -j LOG --log-prefix "${LOG} " --log-tcp-options --log-ip-options
# Save the current blocklist as the previous one for the next run
cp ${CURRENT_BLOCKLIST} ${PREVIOUS_BLOCKLIST}
done
;;
esac
</SyntaxHighlight>
</SyntaxHighlight>
To find the blocked IPs of the last 24hours you can try:
To find the blocked IPs of the last 24hours you can try:

Revision as of 05:21, 8 May 2025

Block IPs dynamically from blocklists

I found a basic script [here] which I adapted to a set of lists and added logging.

#!/bin/bash
declare -A BLOCKLIST_URLS=(
Emerging_Threats   https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt
TOR_exit_nodes     https://opendbl.net/lists/tor-exit.list
Bruteforce_Blocker https://opendbl.net/lists/bruteforce.list
Blocklist_de       https://opendbl.net/lists/blocklistde-all.list
Dshield            https://opendbl.net/lists/dshield.list
SSL_Abuse_IP_list  https://opendbl.net/lists/sslblock.list
IPSum_Level_3      https://opendbl.net/lists/ipsum.list
)
IPTABLES="/sbin/iptables"
IPSET="/sbin/ipset"

LIST_DIR="/etc/iptables_blocklist/lists"
MAX_ELEMENTS=$[2**16]

[ ! -d ${LIST_DIR} ] && mkdir -p ${LIST_DIR}

case $1 in
stop)
	for BLOCKLIST in ${!BLOCKLIST_URLS[@]}
	do
	 PREVIOUS_BLOCKLIST="${LIST_DIR}/${BLOCKLIST}_previous.txt"
 	 LOG="DENY Dyn ${BLOCKLIST}"
	 ${IPTABLES} -D INPUT -m set --match-set ${BLOCKLIST} src -j DROP
	 ${IPTABLES} -D INPUT -m set --match-set ${BLOCKLIST} src -j LOG --log-prefix "${LOG} " --log-tcp-options --log-ip-options
	 ${IPSET} destroy ${BLOCKLIST} -exist
	 >${PREVIOUS_BLOCKLIST}
	done
	;;
restart)
	$0 stop
	$0 start
	;;
start|update|*)
	for BLOCKLIST in ${!BLOCKLIST_URLS[@]}
	do
	 PREVIOUS_BLOCKLIST="${LIST_DIR}/${BLOCKLIST}_previous.txt"
	 CURRENT_BLOCKLIST="${LIST_DIR}/${BLOCKLIST}_current.txt"
	 LOG="DENY Dyn ${BLOCKLIST}"
	 [ -f ${CURRENT_BLOCKLIST} ] || touch ${CURRENT_BLOCKLIST}
	 [ -f ${PREVIOUS_BLOCKLIST} ] || touch ${PREVIOUS_BLOCKLIST}
	 # Download the current blocklist
	 curl -s ${BLOCKLIST_URLS[${BLOCKLIST}]} -o ${CURRENT_BLOCKLIST}
	 # Create the ipset set if it does not exist
	 ${IPSET} create ${BLOCKLIST} hash:net maxelem ${MAX_ELEMENTS} timeout 0 -exist
	 # Add new IPs to the blocklist
	 comm -13 <(sort -u <(grep -Ev "(^#|^$)" ${PREVIOUS_BLOCKLIST})) <(sort -u <(grep -Ev "(^#|^$)" ${CURRENT_BLOCKLIST})) | while read -r IP
	 do
	   ${IPSET} add -exist ${BLOCKLIST} ${IP}
	 done
	 # Remove outdated IPs from the blocklist
	 comm -23 <(sort -u <(grep -Ev "(^#|^$)" ${PREVIOUS_BLOCKLIST})) <(sort -u <(grep -Ev "(^#|^$)" ${CURRENT_BLOCKLIST})) | while read -r IP
	 do
	   ${IPSET} del -exist ${BLOCKLIST} ${IP}
	 done
	 # Ensure the IPtables rule is in place
	 ${IPTABLES} -C INPUT -m set --match-set ${BLOCKLIST} src -j DROP 2>/dev/null || ${IPTABLES} -I INPUT -m set --match-set ${BLOCKLIST} src -j DROP
	 ${IPTABLES} -C INPUT -m set --match-set ${BLOCKLIST} src -j LOG --log-prefix "${LOG} " --log-tcp-options --log-ip-options 2>/dev/null || ${IPTABLES} -I INPUT -m set --match-set ${BLOCKLIST} src -j LOG --log-prefix "${LOG} " --log-tcp-options --log-ip-options
	 # Save the current blocklist as the previous one for the next run
	 cp ${CURRENT_BLOCKLIST} ${PREVIOUS_BLOCKLIST}
	done
	;;
esac

To find the blocked IPs of the last 24hours you can try:

# journalctl --full --dmesg --no-pager --grep "DENY Dyn \w+ " --since -24hours

or what is going on now:

# journalctl --full --dmesg --no-pager --follow --grep "DENY Dyn \w+ "