MikeL's FreeBSD howto - Firewall

Yay, this works! Be sure to add a huge glaring obvious comment into your .mc file reminding you to manually hack in after any change/rebuild.
It didn't work - port 25 was still not showing up in ipfw list. I've now manually hacked it into sendmail.cf (see below), we'll see if that works. sendmail does restart, so that's more encouraging than before.
I managed to get sendmail to build successfully from ports by doing a portsnap fetch update and waiting for a while (I think it was about 2 hrs).

I had to make config and uncheck items that would blow chunks when building but I got down to blacklistd and the usual others, so hopefully it's gonna work now?

FYI: All previous comments about getting sendmail to interface to blacklistd are out right now. I tried hacking the option into the sendmail.cf file, and actually got a startup error of no such option. I tried including it as an rc.conf flags option, and again got a startup error of no such option.

Lastly, I tried building sendmail from the ports tree. Doing a make config I am offered the blacklistd option, yay! But when I try to build it, I get asked for a patch file, and when I can't provide one, it blows chucks. (I tried a portmaster -a but it shows everything as up-to-date.)

For some reason, last night's backups (using ftp) from external worked, but in-house network did not. I've messed around, and determined that suddenly I have to use ACTIVE mode -- PASSIVE mode used to work, but now I'm having to explicilty call out ACTIVE. If I don't, I get a connection, then a timeout trying to get the dir listing - classic PASSIVE mode symptom. Note that this is only on the in-house 192.168 network, all is still well external.

My understanding, is that the only difference is that in PASSIVE, the connection will be re-routed to an upper port in the range 49152-65534 instead of the default of 20.

My firewall is in OPEN mode.
ipfw list
00100 allow ip from any to any via lo0
00200 deny ip from any to
00300 deny ip from to any
00400 deny ip from any to ::1
00500 deny ip from ::1 to any
03022 deny tcp from table(port22) to any 22
65000 allow ip from any to any
65535 deny ip from any to any
This list will not block those upper ports. (Oh BTW - I did an ipfw table port(22) flush, it's empty, but even when populated it's a list of hardcode IP addresses from blacklistd with no port specific limitations.) Just to be sure, I deleted rule 3022 and there was no change.

I have no explanation - to fix it, I've simply added the ACTIVE flag to my in-house backup scripts and to my in-house filezilla settings. This really bugs me, I'm sure it's gonna nip me in the butt again in the future. I just deleted all the deny rules, there's nothing left but line 100, 65000 and 65535 - still need active mode. Weird. Ok, so I've proven it's not the freebsd firewall, what's left?

For fuck's sake! I just tried changing my DSL modem settings, and that fixes it. Interesting enough, the internal firewall is already disabled, but changing the "all public" firewall settings to default to open - now it works. I've added allow that port range to the "all public" and I no longer seem to need to specify PASSIVE. Again, this still bugs me. Why does it need to be added to the external when that already works? And I haven't changed any modem settings in months - why do I have to do this now? It cannot be a coincidence that I just changed the FreeBSD config. Anyways, it's working now so I'll go work on other stuff - if it nips me again, I'll deal with it then.

blacklistctl dump -a will show all blacklisted entries.

Confirm that they're making it to ipfw, by ipfw table all list
If blacklistd is doing it's job, you'll see tables "port22" for ssh, "port21" for ftp, and "port25" for smtp.

Note that there may initially be no activity as it takes time for the script kiddies to bang on your machine enough times to get blocked. Although it is amazing how quickly they'll find you and get started...

I'd like to reiterate once again - it really is reasonable to simply operate a firewall under "OPEN" mode for this purpose. Bear in mind that if you were not operating a firewall at all, you'd be wide open. This way, you're mostly wide open, but you are blocking the obvious baddies. This is better than no firewall at all. (What this shows you is that I spent a lot of time trying to get a firewall running that would just allow my important services through, and did not succeed.)

Note that the sample /etc/blacklistd.conf file as the first entry in the "remote stanza", has a typoed IP address. You are likely to want" not etc.

Getting errors in /var/log/console.log like:
/etc/ipfw-blacklist.rc: [local]: not found
for every line in my /etc/blacklistd.conf file. Depending on which pages I read, it may be supposed to be named .rc? Tried:
ln -s blacklistd.conf blacklistd.rc
Service restart didn't show a new error in log, so maybe this fixed it? -- Nope.
Ok, think I got it figured out. This file should have only one directive, namely ipfw_offset=xxxx. Anything else will generate a spurious "not found" error.

See FreeBSD Handbook 30.6.
You'll need to add the following to /etc/rc.conf:
While you're in there, add:

Then create and edit:
In this, create whitelist rules to prevent yourself from blocking yourself out.
[your main access ip] * * * * * *

You'll also need to install 'ipfw' (see below).

Edit /etc/ssh/sshd_conf:
  UseBlacklist yes
service sshd restart - note - does NOT drop your ssh connection.

After using setup as implemented by docs above, ssh protection is working, yay! (ipfw list shows 'table22'). However, smtp is not (no 'table25'). Lots of googling, I find that you have to hack your sendmail.cf file and add:
  O UseBlacklist=True
I'm sure there's a way to do this via the .mc, but I'm not a wizard with mc files, so not sure. I've hacked it in for now, if this seems to have fixed it, I'll do some digging to see if I can find how to do it in sendmail.mc.


First thing to note -- Be very careful when doing this stuff on a remote machine! You will undoubtedly at least have your ssh/x11 session dropped, and you CAN lock yourself out. Practice on a local (with console access) twin system first.

All the stuff below on recompiling the kernel is no longer necessary, it's now built-in (this is true in FreeBSD12, may have been that way for a while). Follow FreeBSD Handbook Ch 30.4.

Simply add to your /etc/rc.conf:
Now be prepared to have your connection dropped, and do:
  service ipfw start

Restart your ssh session - you should be able to get in.

Note - as you advance, and if you transition up to the SIMPLE firewall rule:
in /etc/rc.conf:
  firewall_simple_oif="[your main network IF]"
  firewall_simple_onet="[your main ip slash netmask]"
  firewall_simple_iif="[your internal network IF]"
  firewall_simple_inet="[your internal ip slash netmask]"
Use ifconfig -a to determine IP addresses and interfaces.
In the old days, these values were hard-coded into the rc.firewall script, I prefer to have them in rc.conf so I'm reminded to change them in the event I were to change basic IP settings. The tradeoff though, is that you cannot simply run the /etc/rc.firewall as a script that way - your choice. Lastly, be sure to make a copy of the default file before you go mucking with it - having it right there allows you to do diffs when you lose track. You can also find it in /usr/share/examples/etc/rc.firewall.

What I'm trying to do is to simply block a handful of script kiddies out there that are pounding on my server, doing brain-dead dictionary attacks to get into imap and ssh. I'm getting about 20,000 imap attempts, and about 2,500 ssh attempts daily. The logspam this generates makes it difficult to find real problems.

I'm not really worried about the security of the system in general, I just want to block these few jerks - so at this point I'm not going into a more detailed firewall. I'm hosting multiple domains, websites, email, email lists, FTP, DNS, etc. so it's not an easy task to do a good job on the firewall. It's simply a standalone server, it's not a gateway.

So the next step will be fail2ban. (When I get to that, I'll add the install info here.) In the meantime, adding the handful of worst offenders by hand to the rc.firewall file as follows should suffice:
  ${fwcmd} add 5000 deny all from 46.38.144/24 to any
This can be added in the OPEN rule, be sure it is BEFORE the 65000 rule. Increment the number 5000, perhaps by 10, for each additional blocking rule you add here.

It's up to you to figure out what it takes to make a good firewall, there's entire textbooks written on it. An extremely detailed reference book is Building Internet Firewalls, Chapman & Zwicky, O'Reilly.

[20200514] - Trying out 'blacklistd'. Will report back here. See FreeBSD11 install for those instructions.

19-Sep-2005 Wait!
Everything below on this page is out of date. Go directly to the FreeBSD handbook page. Copy their sample "ipf.rules" file there.
The only changes I made to it are to correct to use my interface, and in the FTP OUT rule, I had to drop the trailing "flags S keep state" in order for command-line ftp from the box to the outside world to work. (P.S. Although my description below is for a gateway machine, this was not -- strictly a standalone server.)

This is basically a checklist of how to setup a new system to be a firewall. The intent is not to cover everything in detail, merely to point you to each of the tasks that must be performed.

Obviously you must already have your hardware set up with two Network Interface Cards (NICs). One connected to the external network that you're protecting yourself from, the other connected to the internal network.

The manual for this process is: FreeBSD.org, Handbook ch. 6.

Getting a Microsoft VPN (MS PPTP) client working through ipfw
I can state that the following does work -- I cannot say it is the optimal (ie. most limiting you can get away with).
	# The following (47, 1723) are for Microsoft PPTP.
	${fwcmd} add pass tcp from any 1723 to ${inet}:${imask}
	${fwcmd} add pass tcp from ${inet}:${imask} to any 1723
	${fwcmd} add pass tcp from ${oip} to any 1723

	${fwcmd} add pass gre from any to ${inet}:${imask}
	${fwcmd} add pass gre from ${inet}:${imask} to any
	${fwcmd} add pass gre from ${oip} to any
Getting a Cisco Systems VPN client working through ipfw
I can state that the following does work -- I cannot say it is the optimal (ie. most limiting you can get away with).
	# The following (500, 10000) are for Cisco VPN.
	${fwcmd} add pass udp from any 500 to ${inet}:${imask}
	${fwcmd} add pass udp from ${inet}:${imask} to any 500
	${fwcmd} add pass udp from ${oip} to any 500 keep-state

	${fwcmd} add pass udp from any 10000 to ${inet}:${imask}
	${fwcmd} add pass udp from ${inet}:${imask} to any 10000
	${fwcmd} add pass udp from ${oip} to any 10000 keep-state

Copyright © 1995-2023 Mike Lempriere (running on host pedicel)