Rich Kulawiec on 20 Jul 2017 17:28:38 -0700

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [PLUG] Firewall choices for a small software development business

On Tue, Jul 04, 2017 at 12:58:10PM -0400, Steve Litt wrote:
> The preceding is true, but OpenBSD/pf is very terse and not
> recognizeably a match for what you're trying to pass or stop.
> Do you know of any online documentation that outlines which commands do
> what and in what order, without drowning the whole thing in a
> mind-numbing sea of detail?

Try this one on for size -- maybe it'll help:

	Firewalling with OpenBSD's PF packet filter

I strongly recommend the approach in the section entitled "Slightly stricter",
to wit:

	block all

or actually, because you're going to need logging turned on in order
to debug the mistakes you're about to make ;) :

	block log all

This bidirectionally blocks EVERYTHING.  This forces you to think about
what you need to let in *and* what you need to let out.  If you're doing
this for a single host, it's not that hard.  If you're doing this for a new
deployment of a small network, it's not much harder.  If you're doing this
for an existing medium-to-large network that has, to this point, been
default-permit in either direction, then you're going to spend a lot of
quality time with tcpdump, ntop, wireshark, etc.  But the highly useful
outcome of that is you will know, in excruciating detail, exactly what's
supposed to be traversing your firewall and what's not.  The value of
this is enormous.  It's worth every bit of tedium and pain.

I'll pause while you read that. ;)  Let me augment the advice it gives
with some tips.

1. Use the Spamhaus "DROP" and "EDROP" lists in your firewall(s).

These enumerate network blocks that have been hijacked by spammers --
and worse.  You don't want any network traffic from these, nor do
you want to send them any: so block bidirectionally.

To do that, put the CIDR ranges from both lists in files that live
in /etc/pf; then load them into pf with this:

	table <droplist> persist file "/etc/pf/pf.droplist"
	table <edroplist> persist file "/etc/pf/pf.edroplist"

(Note: the drop.txt and edrop.txt files contain the CIDR ranges
*and* other stuff.  But it's one line of sed to create pf.droplist
from drop.txt.)

Then -- and you'll need to salt this to taste with $myboard as
the external network interface -- use this:

	block quick log on $myboard from <droplist>
	block quick log on $myboard from <edroplist>

Put this before the "pass" rules.  Note that it uses the "quick"
directive.  Here's the reasoning: pf evaluates rules in order.  Last
match wins.  "quick" tells it to stop right there.  So even if a
subsequent rule would, let's say, allow a connection originating
from a DROP-listed host to reach port 80 on a web server, the fact
that this one matches first means that the later rule won't matter.

Exercise for the reader: how do you block outbound traffic to these?

Update your copies of the DROP/EDROP lists once a month.

2. Use geoblocking to restrict access to anything that you can.  For example,
you can find an aggregated list of US networks here:

(You can find a lot more, by the way.  Worth bookmarking the site
and investigating.)  Armed with that list, you can do this:

	table <us> persist file "/etc/pf/"

which loads the entire table into "us", so that you can reference it:

	block log on $myboard proto tcp to $myself port $pservices
	pass log on $myboard proto tcp from <us> to $myself port ssh

This blocks all incoming ssh attempts (to the host pf is running on)
that originate anywhere outside the US.  Unless you have an operational
need for connections from Peru, Pakistan, Portugal, and other places,
you should be doing this, because they're always going to be attacks.
Every possible thing that could happen to you as a result of letting
them through is bad for you and good for attackers: so don't do that.

(Sure, you could use fail2ban and similar.  But why?  Just drop the
packets on the floor, and move on.  Do you really, really, really
care if some random IP address in Greece attacks you 5432 or 2345
times?  If so: why?)

Obviously this isn't going to work if you need to accept ssh connections
from all over the world.  But if it's just -- let's say -- the US, Canada,
and Spain, you can do that by using two additional rules along with the
aggregated networks for the latter two countries...also from

Do remember, if you're going to be traveling, to add a rule for the
country(ies) you're visiting before you leave, and to remove it when
you get back.  (I've done this with sizable networks, by the way:
personnel are told that they need to give a week's notice of international
travel, both departure and return.  Yes, some of them forget to do that.
But they only forget once.)

This takes some getting used to when you first deploy it.  But it's
worth it.  If you can pre-emptively block ssh attacks (or other attacks)
from 90% of the Internet at almost zero cost, then why not?

I use rules like this for many services: ssh, pops, imaps, etc.

There's more, but this is long enough already, so I'll shaddup for now.

Philadelphia Linux Users Group         --
Announcements -
General Discussion  --