How to Secure FreeBSD with PF Firewall


This tutorial will show you how to protect your FreeBSD server using OpenBSD PF firewall. We will assume that you have a clean FreeBSD installation deployed by Vultr with no users added. We will do some other things beside Firewall configuration which will also harden the security of our FreeBSD server. Before firewall configuration, we will install some packages since the default FreeBSD installation comes with a minimal set of tools and packages (which is correct), to make it easier for us to work.

The default shell in FreeBSD is /bin/sh. This is a basic shell with no auto-complete functions. We will use something better. We will install zsh.

First, install these packages:

# pkg install zsh gnulsThe package management tool is not yet installed on your system.Do you want to fetch and install it now? [y/N]: yBootstrapping pkg from pkg+http://pkg.FreeBSD.org/freebsd:10:x86:64/latest, please wait......

GNULS is the ls program from Linux. We just want to have the same ls command in Linux and
FreeBSD.

Add a normal user to the system:
(replace john with your username and don’t forget to add user to the wheel group)

# adduserUsername: johnFull name: John DoeUid (Leave empty for default): Login group [john]: Login group is john. Invite john into other groups? []: wheelLogin class [default]: Shell (sh csh tcsh zsh rzsh nologin) [sh]: zshHome directory [/home/john]: Home directory permissions (Leave empty for default): Use password-based authentication? [yes]: Use an empty password? (yes/no) [no]: Use a random password? (yes/no) [no]: Enter password: Enter password again: Lock out the account after creation? [no]: Username   : johnPassword   : *****Full Name  : John DoeUid        : 1001Class      : Groups     : john wheelHome       : /home/johnHome Mode  : Shell      : /usr/local/bin/zshLocked     : noOK? (yes/no): yesadduser: INFO: Successfully added (john) to the user database.Add another user? (yes/no): noGoodbye!

Create zsh config file:

# ee /home/your-username/.zshrc

Copy this to your .zshrc file:

PS1="<%U%m%u>$[%B%1~%b]%(#.#.$) "bindkey -ealias su='su -m'alias du='du -h -d0'alias df='df -h'alias l=lessalias ll='gnuls --color=always -l'alias ls='gnuls --color=always'alias pkg_ver='pkg version -v -l "<" | > upgrade'export EDITOR=eeautoload -U colors && colorsautoload -U promptinit && promptinitautoload -U compinit && compinit# History settingsSAVEHIST=1000HISTSIZE=1000HISTFILE=~/.historysetopt histignoredups appendhistory

Run this command:
(replace john with your username)

chown john:john /home/john/.zshrc

Now, login to the FreeBSD server with your username and change the default root password:

<vultr>[~]$ suPassword:<vultr>[~]# passwd Changing local password for rootNew Password:Retype New Password:<vultr>[~]# 

We don’t need sendmail. Stop and disable this service:

<vultr>[~]# /etc/rc.d/sendmail stopStopping sendmail.Waiting for PIDS: 7843.sendmail_submit not running? (check /var/run/sendmail.pid).Stopping sendmail_msp_queue.Waiting for PIDS: 7846.

Next, we will change our rc.conf file to look more natural:

# ee /etc/rc.conf

Change it to look like this:

#----------- NETWORKING ------------------------------------------------#hostname="ceph.domain1.com" # replace ceph.domain1.com with your domainifconfig_vtnet0="dhcp"static_routes=linklocalroute_linklocal="-net 169.254.0.0/16 -interface vtnet0"#--------- SERVICES BSD LOCAL ----------------------------------------#sshd_enable="YES"ntpd_enable="YES"#pf_enable="YES"#pf_rules="/etc/firewall"#pf_flags=""#pflog_enable="YES"              #pflog_logfile="/var/log/pflog"  #pflog_flags=""    sendmail_enable="NONE"sendmail_submit_enable="NO"sendmail_outbound_enable="NO"sendmail_msp_queue_enable="NO"

Edit /etc/hosts file:

# ee /etc/hosts

Add your IP address and hostname:

::1                     localhost localhost.ceph ceph127.0.0.1               localhost localhost.ceph ceph108.61.178.110          ceph.domain1.com       ceph

Set timezone:

# bsdconfig

Whenever you can, disable remote access for the root user. Most attacks on SSH will try to access through the root user account. Always connect with your username and then su to root. Only users from the wheel group can su to root. That’s why we added our user to the wheel group.

Disable root login:

# ee /etc/ssh/sshd_config

Uncomment this line:

PermitRootLogin no

Reboot:

# reboot

After the reboot finishes, you will see a message like this in the Vultr console:

time correction of 3600 seconds exceeds sanity limit (1000); set clock manually tocorrect UTC time.

That’s why we need to correct the clock manually. Follow these commands, first su to root:

$ suPassword:# ntpdate 0.europe.pool.ntp.org

Now, we are going to configure the firewall. OpenBSD PF is included in the FreeBSD kernel, so you don’t have to install any packages.

With ee editor, create file /etc/firewall:

# ee /etc/firewall

Insert this: (replace any IP addresses with yours)

#######################################################################me="vtnet0"                table <bruteforcers> persist    table <trusted> persist file "/etc/trusted"icmp_types = "echoreq"          junk_ports="{ 135,137,138,139,445,68,67,3222 }"junk_ip="224.0.0.0/4"           set loginterface vtnet0           scrub on vtnet0 reassemble tcp no-df random-id# ---- First rule obligatory "Pass all on loopback"pass quick on lo0 all           # ---- Block junk logsblock quick proto { tcp, udp } from any to $junk_ip block quick proto { tcp, udp } from any to any port $junk_ports# ---- Second rule "Block all in and pass all out"block in log all                pass out all keep state         ############### FIREWALL ################################################ ---- Allow all traffic from my Homepass quick proto {tcp, udp} from 1.2.3.4 to $me keep state# ---- block SMTP out block quick proto tcp from $me to any port 25# ---- Allow incoming Web trafficpass quick proto tcp from any to $me port { 80, 443 } flags S/SA keep state# ---- Allow my team member SSH access pass quick proto tcp from 1.2.3.5 to $me port ssh flags S/SA keep state# ---- Block bruteforcersblock log quick from <bruteforcers># ---- Allow SSH from trusted sources, but block bruteforcerspass quick proto tcp from <trusted> to $me port ssh /flags S/SA keep state /(max-src-conn 10, max-src-conn-rate 20/60, /overload <bruteforcers> flush global)# ---- Allow ICMP pass in inet proto icmp all icmp-type $icmp_types keep statepass out inet proto icmp all icmp-type $icmp_types keep state

Create /etc/trusted file. In this file, we will put IPs that we “trust”.

# ee /etc/trusted

Add some IP’s:

# Hosting1.2.0.0/16# My friends1.2.4.0/24

Now some explanation. Junk ports and junk IPs are just some ports/IPs that we don’t
want to see in logs. We have done this with this rule:

# ---- Block junk logsblock quick proto { tcp, udp } from any to $junk_ip block quick proto { tcp, udp } from any to any port $junk_ports

These are just defaults and you don’t have to worry about it:

icmp_types = "echoreq"                                            set loginterface vtnet0           scrub on vtnet0 reassemble tcp no-df random-idpass quick on lo0 allblock in log all                pass out all keep state

This rule blocks outgoing SMTP traffic from your server (which is the default on Vultr).

# ---- block SMTP out block quick proto tcp from $me to any port 25

Except bruteforcers the rest is pretty straight forward.

# ---- Allow SSH from trusted sources, but block bruteforcerspass quick proto tcp from <trusted> to $me port ssh /flags S/SA keep state /(max-src-conn 10, max-src-conn-rate 20/60, /overload <bruteforcers> flush global)

Bruteforcers just says: Allow from <trusted> IPs to port 22 but only 10 concurrent connections can be made from one source IP. If it’s more than 10, block this IP and put it in table bruteforcers. The same goes for 20/60 rule. It means a max of 20 connections in 60 seconds.

Enable firewall:

# ee /etc/rc.conf

Uncomment these lines:

pf_enable="YES"pf_rules="/etc/firewall"pf_flags=""pflog_enable="YES"pflog_logfile="/var/log/pflog"pflog_flags=""

Reboot:

# reboot 

If you have done everything right, then you will be able to login and the firewall will be enabled. You don’t have to reboot every time you change the /etc/firewall file. Just do:

# /etc/rc.d/pf reload

See who is trying to connect to your server in real-time:

# tcpdump -n -e -ttt -i pflog0

Show history:

# tcpdump -n -e -ttt -r /var/log/pflog

See if you have someone in bruteforcers table:

# pfctl -t bruteforcers -T show

And that’s it. You have successfully implemented PF firewall on FreeBSD server!

Want to contribute?

You could earn up to $300 by adding new articles

Submit your article
Suggest an update
Request an article

No comments

Powered by Blogger.