OpenBGPD + RTBH = dynamic PF rules
What if you could dynamically update PF tables across all your hosts? Here is one way you can...
If you have been networking for a while you will come across the need to route
traffic to Null0 (black hole). For the uninitiated, this means that traffic will just be
dropped by the router. What if there was a way to automate adding these routes to firewall rules. Good news! There is.
OpenBGPD is capable BGP daemon in it's own right. It has a hidden capability. It can add routes to a PF table.
Why would you want to use this if you do not run a large routing network? Glad you asked. Let's say you have several servers on a hostile network doing server stuff (email, web, blog, etc). And being a good admin the have things pretty locked down. The servers keep getting harassed by ne'er-do-wells, filling logs with noise, etc. By using RTBH and OpenBGPD, harassment of one server is a block on all servers.
Headend Setup
First thing is to configure the BGP Headend router. This router, and in fact
all of the routing daemons, will not update the routing tables on the systems. They
are just setup to exchange routes between each other.
Now enable BGP on the headend and start it.
rcctl enable bgpd
rcctl start bgpd
Spoke Setup
Next each spoke will need 3 parts: PF config update; BGP config; and a helper program. The first part is an update to the PF rules running on the device. The
following updates will add PF table(s) and a drop rule.
###### partial PF configuration
# store the routes learned from BGP
table <rtbh> persist
# locally banned hosts added manually
table <banned> persist
# aggressive hosts added automatically by PF
table <aggressive> persist
block quick from <rtbh> label "rtbh host"
block quick from <banned> label "banned host"
block quick from <aggressive> label "aggressive host"
Validate and restart PF.
pfctl -nf /etc/pf.conf && pfctl -f /etc/pf.conf
The second part is the BGP config. This config will be exactly the same on all
the spoke servers.
Now enable and start bgpd.
rcctl enable bgpd
rcctl start bgpd
Now for the last part... the watcher daemon. OpenBGPD has the ability to add
and remove addresses/networks using a PF table. However, it does not monitor
PF tables for additions/subtractions that are made outside the BGP daemon.
This is where the watcher daemon comes in. It watches one or more tables for
additions/subtractions and utilizes bgpctl commands to add/remove routes as
they are added and removed from the table(s).
The script can be downloaded from github. Word of warning, this is a
minimal viable script. There are probably better programs out there. (If you
know of any feel free to drop me an email.) However, it is lightweight and
should run on any flavor of *nix out there.
Assuming you are configuring OpenBSD, there is a rc.d script. Enable the
daemon, set the tables to watch, and then start.
rcctl enable watchtabled
rcctl set watchtabled flag -t banned:65535:102 -t aggressive:65535:103
rcctl start watchtabled
Now with everything running lets take a look at the tables.
pfctl -T show -t table1 | wc -l
Typing this can get tedious quickly. I created a this script to help.
One thing we should notice is there are no records. While we have setup the
environment to watch and replicate records, we need to add records. There are
several ways this can happen. The most straight forward is to add them
manually to the table.
pfctl -T add -t banned 1.2.3.4
To see if the address is in the BGP daemon, use the bgpctl command. NOTE:
that the community filter will need to match the community that references the
specific PF table.
bgpctl show ip bgp community 65535:102
Another option for adding records more automatically is to utilize the PF
'overload' option.
#### partial PF config
pass in inet proto tcp from any to ($ext) port ssh keep state \
(source-track rule, max-src-conn-rate 20/10, \
overload <aggressive> flush global)
Here aggressive hosts will trigger an addition to the aggressive PF
table. NOTE: the max connection rate rule will need to be tailored to the
service. SSH on a console server is much different that SSH on an Email
server.
Last, but not least, is the use of some other application like sshguard or
fail2ban. The setup of these services is outside the scope of this post, but
once setup to add 'bad hosts' to PF tables, these tables can be watched and
trigger RTBH bans.
Conclusion
Hopefully this article has help explain remote triggered blackholes and how they can be used to protect multiple systems from outside attacks.