Short story made longer: your rules setup is a total mess, you really need to pay better attention to the documentation.
For starters: rules get processed in sequence. And by default the firewall checks a rule and then continues to check if something else would match too. That's what's causing your problems:
Code:
table <blockedips> persist file "/etc/pfblocked.conf"
block on vtnet0 from <blockedips> to any
antispoof log for vtnet0 inet
antispoof log for vtnet0 inet6
pass in on vtnet0 all
pass out on vtnet0 all
pass in on lo0 all
pass out on lo0 all
table <fail2ban> persist
block in quick from <fail2ban>
First you tell the firewall that it should block all IP's within the
blockedips table. But then, a few rules later, you tell the system:
pas in on vtnet0 all
. So yeah, obviously it doesn't block anything from the table because you told the firewall to pass everything a few rules later. That should honestly be basic knowledge... From
pf.conf(5):
Code:
For each packet processed by the packet filter, the filter rules are
evaluated in sequential order, from first to last. The last matching
rule decides what action is taken. If no rule matches the packet, the
default action is to pass the packet.
Anyway, this might work:
Code:
ext_if = "vtnet0"
me = "127.12.13.14" # replace with your real IP address
table <blockedips> persist file "/etc/pfblocked.conf"
table <fail2ban> persist
set block-policy drop
set skip on lo0
pass in quick on $ext_if from $me to any port ssh
block in quick from <blockedips>
block in quick from <fail2ban>
If you don't know your own IP address then that still wouldn't matter too much, unless you suddenly find yourself listed on one of those tables. After all: all data gets accepted except when it originates from an IP within those tables.
Note: this is an optimized version of what you're using above, it's most definitely not something I'd use or even recommend using because it doesn't keep you safe.
Far from it. You're basically providing every service you run on that box to the Internet and only if you happen to catch someone performing foul play will you add him to your blocking tables. Here's hoping you didn't miss someone, which is very likely.
The real danger doesn't come from people trying to log in. It comes from people who are aware of exploitable bugs in the services you run and then exploit those bugs. Trust me: that's the stuff you
won't find in your logfiles.
So, what I would suggest is this:
Code:
ext_if = "vtnet0"
me = "127.12.13.14" # replace with your real IP address
table <blockedips> persist file "/etc/pfblocked.conf"
table <fail2ban> persist
set block-policy drop
set skip on lo0
# Personal failsave
pass in quick on $ext_if from $me to any port ssh
block in quick from <blockedips>
block in quick from <fail2ban>
block in on $ext_if
pass out quick on $ext_if keep state
# SSH failsave
pass in quick on $ext_if proto {tcp, udp} from any to port 5327
But before you enable this ruleset be sure to reconfigure
/etc/ssh/sshd_config and tune it to also use port
5327, as mentioned in the rules above. Of course: better yet is to use another random port.
If you value your security I'd also combine this with key based authentication for SSH. Disable PAM and passwords entirely, this will prevent people from being able to guess.
I would also advice you to look into
blacklistd(8) and maybe replace Fail2Ban with this critter. Nothing negative about Fail2Ban but it only works after the facts. It goes over your logs and stuff and only runs every once in a while when the cron tells it to.
blacklistd on the other hand constantly runs. Even better: it will respond to signals sent to it by the several services. SSH in the base system for example is perfectly capable of telling
blacklistd that someone tried to log in but failed. As a result they would get blocked immediately. Not when the next Fail2Ban cycle runs, after 15 or so minutes (dramatic assumption on my end

). Also: blacklistd is part of the FreeBSD base system, so you probably already have it, maybe without you knowing.
Anyway... about the ruleset:
It blocks everything but allows for other rules to be parsed. So unless you add a 'pass' rule then stuff gets blocked. It quickly passes outgoing data and enables stateful filtering. In short: make sure returning data passes through the firewall.
And one rule... is to allow incoming traffic on that weird port, which is meant for SSHd to listen on. You can continue building onto that with other services if you need.