How to handle 5k entries in iptables? Ipset to the rescue

Recently taken a look at OPNSense and saw that they do block Bogons. I’m aware that Team Cymru maintains a list of bogons so that people can block them – Feeding them into iptables takes a while (tried it) and I believe iptables will slow down network traffic if one does so. That’s a job for ipset.

Update

Seems the fullbogons list by team cymru I do use here is gone. It’s a pity. In case you’re aware of a similar actively maintained list, please drop me a note. Obviously the wget calls below will fail (in case those text files won’t appear again)

Ipset is able to create maps or lists of networks and/or ip addresses (and more) and allows to be accessed by iptables. Let’s start by creating a hash map for the fullbogons-ipv4 list:

ipset create fullbogons-ipv4 hash:net

You can add all networks to it by just typing:

ipset add fullbogons-ipv4 cidr

e.g.

ipset add fullbogons-ipv4 0.0.0.0/8

Or you might use the following bash script (which is most likely not perfect, though it does what I want it to do).

#!/bin/bash
 
#
# Before using this script, take a look at 
# http://www.team-cymru.org/bogon-reference.html
# and do not run it more often than all 4 hours.
#
 
IPS="/sbin/ipset"
 
if [ -f /tmp/fullbogons-ipv4.txt ]; then
  mv /tmp/fullbogons-ipv4.txt /tmp/fullbogons-ipv4.txt.old
fi
 
wget -q -O /tmp/fullbogons-ipv4.txt \
        http://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt
 
if [ -f /tmp/fullbogons-ipv4.txt.old ]; then
  diff /tmp/fullbogons-ipv4.txt /tmp/fullbogons-ipv4.txt.old &>/dev/null
  if [ "$?" == 0 ]; then
    exit 0
  fi
fi
 
$IPS flush
$IPS destroy
$IPS create fullbogons-ipv4 hash:net
 
while read -r line; do
  if [ "$line" != "0.0.0.0/8" ]; then
    $IPS add fullbogons-ipv4 ${line}
  fi
done< <(cat /tmp/fullbogons-ipv4.txt | tail -n+2)

This fetches the fullbogons list, checks if it is different to your previously fetched fullbogons list (if not it exists, if it is different it’ll flush the bogons and adds the new bogons list)

Ah, by the way: You might wonder, why I did exclude 0.0.0.0/8 – I try to avoid blocking anything which starts with 0.0.0.0 because I managed to block myself in the past :^) Once I know it does work, I do remove that if-block.

Your iptables rule to access that list is simple:

 -m set --match-set fullbogons-ipv4 src -j ACTION

In my case:

iptables -A FORWARD -m physdev --physdev-is-bridged --physdev-in ens19 --physdev-out ens21 -m set --match-set fullbogons-ipv4 src -j DROP
iptables -A FORWARD -m physdev --physdev-is-bridged --physdev-in ens19 --physdev-out ens21 -m set --match-set fullbogons-ipv4 dst -j DROP

That is, because I am doing that on a bridge. In your case you’ll most likely apply that to your INPUT chain and you won’t need -m physdev –physdev-is-bridged –physdev-in ens19 –physdev-out ens21.

The interesting part about blocking bogons is that I wouldn’t have assumed that iptables would block anything (there’s really no internal network on that machine) though it did:

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   25  1236 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-in ens19 --physdev-out ens21 --physdev-is-bridged match-set fullbogons-ipv4 src
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-in ens19 --physdev-out ens21 --physdev-is-bridged match-set fullbogons-ipv4 dst

Sadly, I had no logging enabled so I really have no clue what IP/Network had been blocked with 25 packets.

By the way, want to check the contents of your ipset-map? ipset list

Name: fullbogons-ipv4
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 76960
References: 2
Members:

No Comments

Post a Comment