PF on OpenBSD: The fast track - Security & Cryptography
Users browsing this thread:
|
|||
Anyone in a rush to configure the firewall for a quick server? I know I was, so what follows is an incredibly ill-advised recommendation ;) Copy the config.
I know I'm not alone in feeling like this, but OpenBSD is, by and large, the simplest OS to setup if you want an all-in-one box for domain and web hosting for yourself. If you're going all out with a lot of scripting or programming tech, then it's probably not the best suited, but for someone creating a small personal server, it's basically ideal. The down side is securing it. Of course, OpenBSD has a reputation for security, but it must be emphasized that this is for the default install. Any new *thing* you add to your server is another *thing* that can potentially go wrong. I.E. The more services you have running, the more avenues to naughtiness from the Internet. What to do? Configure the firewall OpenBSD comes with PF, one of the most venerable pieces of software you'll find on a *nix system. It's been improved and modified since its introduction which effectively makes a lot of tutorials out there somewhat obsolete (a few language changes here and there may break your configurations). Of course, the best resource to setup your PF is the official manual, however it doesn't hurt to have a working config ready for quick deployment. I'll try to explain each bit as much as I can. This configuration assumes your server is a single box with one network card connected to a switch/router and that your system has already been installed The PF configuration will reside in /etc/pf.conf . If you don't like to use Vi to edit files, you can install nano, a more user-friendlish editor ;) Code: pkg_add nano Tables are your friends You rarely want to add an IP into pf.conf directly. Instead, you'll more than likely add it to a table list of IPs you can keep track of as necessary. Maybe you only want to block them for a bit and take them off later. Well, let's create a few lists you may need. Let's make a folder for these first Code: mkdir /etc/pflists Now let's make a few table files for your IPs Code: cd /etc/pflists "spammers" Of course are the unsavory types that may plague your application/site once you get it up and running. These can be manually added to and appended. "abuse" Is basically an automatically filled table. PF can be configured to send abusive clients (those who have way too many connections, download too fast etc...) to this table with no human intervention. To add an IP or IP range to any of these lists you can invoke the following: Code: pfctl -t spammers -T add 218.70.0.0/16 Code: pfctl -t spammers -T delete 218.70.0.0/16 Now then, before continuing, backup your configuration Code: cp /etc/pf.conf /etc/pf.conf.1 Now begin editing pf.conf Code: nano /etc/pf.conf Get rid of everything and include these lines... Code: # External interface Code: # All allowed protocols Macros are also your friend The nice thing about PF is the ability to set shortcuts for yourself that mean more. E.G. Let's say you're blocking from a specific list of IPs (like those table files we made). Instead of : Code: block in log quick from <blacklist> We can write ourselves a macro : Code: bquick = "block in log quick from " And then later : Code: # Table Rules Let's create some of those handy macros so your pf.conf file will look as follows so far : Code: # External interface The block/pass macros are shortcuts to specific types of TCP flags (or packet patterns). There are lots of resources online that explain these flags as they pertain to PF and internet security, but for now, I'll leave them as-is. Note the protocol block macro "pproto". The keyword *egress* refers to our single network interface card. PF will figure out that "egress inet proto" means outgoing traffic to the internet using protocols... and we'll include those protocols later. Connection throttling is a good idea if you're using this server for web use. You don't want too many connections to your machine from the same IP which is a good hint it may be a scraper. Of course, this does *not* mitigate DDoS (Distributed Denial of Service) attacks since... well... they're "distributed" ;) These are launched by many different clients, bots usually, which all have their own IP address. Mitigating DDoS is beyond the purview of this tutorial. The above throttling macro basically says: The maximum number of connections per IP is 100 with a connection rate of 15 per 5 seconds and if this is exceeded, it's sent to the *abuse* table. Now, you need to link those table files we created earlier Code: # Tables Now we need to make a few exceptions to the loopback (127.0.0.1) interface as well as prevent or reduce spoofing attacks Code: # Loopback skip and anti spoof If you need to collect statistics on everything (be careful with this), you can optionally add Code: set loginterface egress Now we can get to PFs greatest feature: It's pretty good at cleaning up. There are lots of odd forms of traffic out there; broken packets, odd TCP flag combinations, weird connections etc... PF can be asked nicely to deal with these so you don't have to : Code: # Scrub all incoming The fun begins It may come as a surprise to you, but we haven't actually set any rules yet ;) What we've done is make a few files for IPs, created a few helper macros and setup some basic configurations. Now we need some rules and let's set one to rule them all : Code: # Base Rules ( Do not remove! ) This is the "kill everything first" principle. If you have a party, it makes sense to have a guest list to make sure you only allow certain people to attend (unless you're a teenager throwing a house-party when your parents are out, in which case, you can imagine what a disaster that will end up in). Firewalls should be setup the same way; we can't account for every incoming *thing* so will disallow all *things* and only let in what we absolutely need. With the *block all* rule, we have effectively disconnected our server from everything. Let's also make sure that we block from those lists: Code: # Table Rules Now we need to allow two services to come into our server. Domain services (DNS) which uses UDP and web services (http(s)) which uses TCP. Remember the *pproto* macro we created earlier? That's what we'll use along with *mconn* macro to avoid getting flooded. Code: # Manual rules Now let's add some diagnostic protocols so we can test for PING and such and let necessary protocols leave the server. Code: # Diagnostics And that concludes a good starting point for a basic server. Here's the complete pf.conf file : Code: # Web server PF configuration Enjoy! p.s. Errors, omissions, improvements? Please reply! :) Edit: Some major corrections. Originally I had written, "connection rate of 15 per 5 minutes" (!) That should be "5 seconds". I guess I didn't have enough coffee :P Also fixed some spelling and grammar issues. |
|||
|
|||
Thanks! PF is lazy-people friendly so it's definitely up my alley ;) There are a few changes from different installations because they all use a slightly different syntax. As always, the best resource to start with is the PF man pages for the latest version syntax.
|
|||
|
|||
pf *taught* me that not all firewall systems are ugly. And that's why I love it. Great post!
@NeoTerra: I highly recommend "The Book of PF". *EDIT: Grammar. NeoTerra* |
|||
|
|||
Thanks guys! That's an excellent resource, shtols. The latest edition is a treasure trove of information on configuring (basically) a military grade firewall appliance with free software. Can't beat that! :D
|
|||
|
|||
And thanks for the grammar correction .. I have no idea what my brain was thinking.
|
|||
|
|||
Nice to see a PF post :) Good work eksith.
+1 for The Book of PF, it's a great read. I'll eventually get around to doing a post about my OpenBSD/PF ALIX firewall/router build :) |
|||
|
|||
Nice tutorial! I've been thinking of giving one of the BSDs a try on one of my old desktops, and I'll give this tutorial a go as well.
|
|||
|
|||
|
|||
one thing I've been looking for -- outside of Snort -- is an open-source application identification engine that could be integrated with any of the various firewall systems available across *NIX. Thoughts?
|
|||