mmx
Verified User
[HOWTO] FreeBSD 7.x 8.x 9.x + IPFW + Brute Force Monitor + block_ip.sh
Hello hello, here's a little guide to setup IPFW and DirectAdmin's BFM to play along nicely. I believe my method below is the cleanest out there, especially since I am using ipfw's tables for the best in organization and management. Using tables will allow you to maintain a separate block list, where your existing system firewall rules will not be modified.
Please make sure you have access to your server (locally, VM console or telnet) if you accidentally block yourself due to firewall configuration errors.
Here are the ingredients for this HOWTO:
You will have the following at the end of this HOWTO:
Updates (Y-M-D)
Hello hello, here's a little guide to setup IPFW and DirectAdmin's BFM to play along nicely. I believe my method below is the cleanest out there, especially since I am using ipfw's tables for the best in organization and management. Using tables will allow you to maintain a separate block list, where your existing system firewall rules will not be modified.
Please make sure you have access to your server (locally, VM console or telnet) if you accidentally block yourself due to firewall configuration errors.
Here are the ingredients for this HOWTO:
- FreeBSD 7.x, 8.x or 9.x; x86 or x64
- ipfw + tables support
- DirectAdmin's Brute Force Monitor (version 1.40 required)
You will have the following at the end of this HOWTO:
- Automated IP blocking by DirectAdmin's BFM.
- Automated IP unblocking by DirectAdmin's BFM after a specified interval of your choice (Admin Level -> Administrator Settings).
- A powerful stateless firewall.
- Clean and organized firewall table management to keep things tidy.
- Minimal modification to your system.
- Enable IPFW on FreeBSD (More information)
- Let's modify rc.conf and enable IPFW.
Code:# ee /etc/rc.conf
- Add this to rc.conf:
Code:firewall_enable="YES"
- Reboot your system to enable the firewall.
- Once the system is online, modify the rc.conf again and add the following lines after firewall_enable="YES":
Code:firewall_type="simple" firewall_script="/etc/ipfw.rules" firewall_logging="YES"
Additional changes may be required with sysctl (in regards to maximum firewall rules allowed). If you have a very busy server, you will get the following error message:
Code:ipfw: install_state: Too many dynamic rules
Update (2015-03-06): The follow lines in /etc/sysctl.conf are highly recommended (notably the finwait2 lines) to help reduce long keep-alive/persistent connections (and thus decrease server load). Adjust these values as necessary. If you want to prevent future possible headaches, also change the value of net.inet.ip.fw.dyn_max (default being 4096, which is way too low). This will allow FreeBSD to create and handle more dynamic rules in IPFW. I am using a value of 65536 (the maximum) because I have a very busy shared server.
Code:# IPFW enhancements: net.inet.ip.fw.verbose=1 net.inet.ip.fw.verbose_limit=5 net.inet.ip.fw.dyn_max=65536 net.inet.ip.fw.dyn_keepalive=1 # *NEW* Recycle finwait2 connections faster: net.inet.tcp.fast_finwait2_recycle=1 # *NEW* Faster finwait2 timeouts: net.inet.tcp.finwait2_timeout=15000
- Let's modify rc.conf and enable IPFW.
- Add some basic rules to your firewall.
You can customize the following to your liking. You might have to change the 'pif' to your network card's name (verify with ifconfig).
I have added all the standard services: FTP, SSH, POP, SMTP/EXIM, DNS, HTTP, SSL ports (exim) and DirectAdmin's 2222. You might have to change them if your setup is different.
The "setup limit src-addr <X>" is how I handle connections to my server. I find this is the safest way to do so, and I limit the amount of connections an IP can make to a service (the <X> value). I find the values in this ruleset are enough. They have been tested on production servers for over 3 years (and more).
- Time to modify /etc/ipfw.rules:
Code:# ee /etc/ipfw.rules
- Paste the following in /etc/ipfw.rules:
Code:#!/bin/sh ################################################# # ipfw Firewall Commands ################################################# cmd="ipfw -q add" ipfw -q -f flush pif="em0" ################################################# # Allow Loopback and Deny Loopback Spoofing ################################################# $cmd allow all from any to any via lo0 $cmd deny all from any to 127.0.0.0/8 $cmd deny all from 127.0.0.0/8 to any $cmd deny tcp from any to any frag ################################################# # Stateful rules ################################################# $cmd check-state $cmd deny tcp from any to any established $cmd allow all from any to any out keep-state $cmd allow icmp from any to any ################################################# # Table 10 for IP blocks ################################################# ipfw -q table 10 add 127.0.0.2 ipfw -q add 900 deny ip from 'table(10)' to any ################################################# # Incoming/Outgoing Services ################################################# $cmd 60001 allow tcp from any to any 21 setup limit src-addr 10 $cmd 60002 allow tcp from any to any 22 setup limit src-addr 8 $cmd 60003 allow tcp from any to any 25 setup limit src-addr 10 $cmd 60004 allow tcp from any to any 587 setup limit src-addr 20 $cmd 60005 allow tcp from any to any 53 setup limit src-addr 3 $cmd 60006 allow udp from any to any 53 limit src-addr 3 $cmd 60007 allow tcp from any to any 80 setup limit src-addr 20 $cmd 60008 allow tcp from any to any 110 setup limit src-addr 20 $cmd 60009 allow tcp from any to any 143 setup limit src-addr 10 $cmd 60010 allow tcp from any to any 443 setup limit src-addr 10 $cmd 60011 allow tcp from any to any 2222 setup limit src-addr 12 $cmd 60012 allow tcp from any to any 35000-35999 in setup limit src-addr 10 $cmd 60013 allow tcp from any to any 993 setup limit src-addr 10 $cmd 60014 allow tcp from any to any 995 setup limit src-addr 10 $cmd 60015 allow tcp from any to any 465 setup limit src-addr 10 $cmd 60016 allow tcp from any to any 585 setup limit src-addr 10 ################################################# # Deny Port scanning (Nmap) ################################################# $cmd 00600 deny log logamount 50 ip from any to any ipoptions rr $cmd 00610 deny log logamount 50 ip from any to any ipoptions ts $cmd 00620 deny log logamount 50 ip from any to any ipoptions lsrr $cmd 00630 deny log logamount 50 ip from any to any ipoptions ssrr $cmd 00640 deny log logamount 50 tcp from any to any tcpflags syn,fin $cmd 00650 deny log logamount 50 tcp from any to any tcpflags syn,rst ################################################# # Deny and Log ################################################# $cmd deny log all from any to any
- Time to modify /etc/ipfw.rules:
- Create the necessary DirectAdmin Block/Unblock scripts and make them executable:
Code:# cd /usr/local/directadmin/scripts/custom # touch block_ip.sh unblock_ip.sh brute_force_notice_ip.sh show_blocked_ips.sh # chmod 755 block_ip.sh unblock_ip.sh brute_force_notice_ip.sh show_blocked_ips.sh
- Get your copy and paste(s) ready!
- block_ip.sh:
Code:#!/bin/sh echo "Blocking IP: $ip<br>"; /sbin/ipfw -q table 10 add $ip echo "<br><br>Result:"; echo "<br><br><textarea cols=160 rows=60>"; /sbin/ipfw table 10 list echo "</textarea>"; exit 0;
- unblock_ip.sh:
Code:#!/bin/sh echo "Unblocking IP: $ip<br>"; /sbin/ipfw -q table 10 delete $ip/32 exit 0;
- brute_force_notice_ip.sh:
Code:#!/bin/sh SCRIPT=/usr/local/directadmin/scripts/custom/block_ip.sh ip=$value $SCRIPT exit $?;
- show_blocked_ips.sh (the sed removes the bits at the end so DA can pass the IPs):
Code:#!/bin/sh /sbin/ipfw table 10 list | sed 's/\/32 0//g' exit 0;
- block_ip.sh:
- Verify if DirectAdmin is showing you the Block and Unblock buttons in BFM.
- Restart your server one more time to make sure everything is ok once it's online again. Double-check all services: mail, FTP, web, SSL connections, etc.
If you have any questions or come across some problems, please reply to this thread so everyone can make use of the information.
Updates (Y-M-D)
- 2012-11-08: Thanks to bdj for pointing out a wrong command when adding the dyn_max value to sysctl.conf. An unnecessary "sysctl" was being pre-appended in front of the line.
- 2015-03-06: Added net.inet.tcp.fast_finwait2_recycle=1 and net.inet.tcp.finwait2_timeout=15000 to help reduce long keep-alive/persistent connections. Added /32 at the end of unblock_ips.sh's $ip variable (ipfw needs this).
Last edited: