Unofficial FreeBSD Security Checklist / Links / Resources

This is list of recommended security settings to protect FreeBSD server from both internal (done by your own users) and external attacks (done by crackers). Please discuss your recommendation below and I will update main post as and when required. The goal is to create a nice itemized and linked (to man files, handbook articles, etc.) article in the HOWTO section.

OpenSSH server
Unless the system needs to provide the remote login and file transfer capabilities of SSH, disable the OpenSSH server. However, it is required in 95% case.

Block ssh login attempts
Use any one of the following port:
  1. security/denyhosts Works with both jaild ssh and host sshd without firewall access. Blocks ssh access.
  2. security/sshguard-pf Protect hosts from brute force attacks against ssh and other services using pf
  3. security/sshguard-ipfw Protect hosts from brute force attacks against ssh and other services using ipfw
  4. security/sshguard-ipfilter Protect hosts from brute force attacks against ssh and other services using ipfilter
  5. security/sshblock Block abusive SSH login attempts
  6. security/sshit Checks for SSH/FTP bruteforce and blocks given IPs
Configure firewall such as pf to limit incomming port 22 traffic. Allow, ssh login from only. A typical pf rule:
pass in on $ext_if inet proto tcp from {, } to port ssh flags S/SA synproxy state

/etc/ssh/sshd_config Settings
Set Idle Timeout Interval for User Logins (600 seconds)

ClientAliveInterval 600
ClientAliveCountMax 0

Disable .rhosts Files
IgnoreRhosts yes

Disable Host-Based Authentication
HostbasedAuthentication no

Disable Empty Passwords
PermitEmptyPasswords no

Limit Users' SSH Access, allow only foo (add foo to wheel so that he can su - root) and bar to login via ssh:
AllowUsers foo bar

Configure public keybased login for ssh -

Use Keychain from Gntoo project, which is a shell script which acts as a user-friendly front-end to ssh-agent(1), allowing you to have one long-running ssh-agent process per system rather than per login session. This is must for all servers, if you are configuring password less login for backup or any other purposes.

Other suggestions - Disable root login, change ssh port, Bind ssh to specific IP address,Only use SSH protocol 2,Deny root user login,Setup login banner ,Disable SSHD password authentication See:

Recommend readings:

FreeBSD Jails
FreeBSD jail establish a clean cut separation between various services and users, mainly for security and ease of administration reasons. Run major services such as HTTPD, SMTPD, SQL Server and other public services in a jail. It offers the following features:
  • Virtualization: Each jail is a virtual environment running on the host machine with its own files, processes, user and superuser accounts. From within a jailed process, the environment is (almost) indistinguishable from a real system.
  • Security: Each jail is sealed from the others thus providing an additional level of security.
  • Ease of delegation: Thanks to the limited scope of a jail, it allows administrators to painlessly delegate several tasks which require superuser access without handing out complete control over the system.
  • Jail Setup Tutorial -
  • Multiple IPs in jail -
  • Man pages - jail() jls() jexec()

Host-based intrusion detection system
Use integrity checking software which can detect the intrusions. It monitors filesystem for unauthorized change such as find out if system binaries modified and new cracked versions installed or not.
  1. security/aide - AIDE is Advanced Intrusion Detection Environment. This piece of software was written as a replacement and extension for Tripwire.
  2. security/integrit - Integrit is an alternative to file integrity verification programs like tripwire and aide. It helps you determine whether an intruder has modified a computer system.
  3. security/tripwire is a tool that aids system administrators and users in monitoring a designated set of files for any changes.

Monitor log files
FreeBSD installs couple of scripts and email output to root account. Read those security emails. It contains lots of useful information and warnings. You can also use the following tools:
  1. sysutils/logcheck helps spot problems, anomalies and security violations in your logfiles automatically and will send the summaries to you via e-mail. Logcheck is run as a cron job.
    Logwatch is a customizable, pluggable log-monitoring system. It will go through your logs for a given period of time and make a report in the areas that you wish with the detail that you wish.
  2. Use shell tools such as tail, grep, awk and friends to monitor log files. A few quick examples:
tail -f /var/log/messages
tail -f /var/log/maillog
egrep -i 'wanr|error' /var/log/messages
awk '{ print $1}'  /var/log/httpd-access.log| sort  | uniq -c  | sort -n

Root account security
You need to protect root account. A few tips:
  1. Never give out root password to anyone. Delegate root level access using sudo() (port security/sudo. Never give shell or vi or any command that can escape to shell access using sudo. Keep an eye on sudo log file and /var/log/auth.log.
  2. Automatically log users out after a period of inactivity by setting
    # csh  / tcsh - 5 minutes time out
    set -r autologout 5 
    # bash / sh 300 seconds time out
    readonly TMOUT
    export TMOUT
  3. Add above to system global shell startup files.
  4. Use sysutils/vlock a utility which locks a terminal so it can only be unlocked with the user's password (or the root password).
  5. See Openssh and scripts for more info -
  6. See FreeBSD handbook for protecting root user -

  • Set kern.securelevel level 3 once *everything is configured* properly. Any super-user process can raise the level, but no process can lower it. See security() man page and FreeBSD handbook security chapter -
  • Sample /etc/rc.conf settings:

Various limitations on users
  • Use limitations to avoid DoS attack from both internal and external threats.
  • Disk limitations via file system disk quota - See tutorial -
  • Configure user resource limits, accounting limits via login class. You can control cputime, memory, vm usage, umask, path, open FDs, file limits, max process and so on. See login.conf() man page for details.
  • ACL - Access Control Lists extend the standard UNIX® permission model in a highly compatible (POSIX®.1e) way. This feature permits an administrator to make use of and take advantage of a more sophisticated security model.

NOTE: I'm still working on a list...
Continued from post # 1...

Apache Security
Run minimal built-in modules. To see all compiled modules:
httpd -l
Only following 4 compiled in modules should be listed to reduce the risk:
  1. core.c
  2. prefork.c
  3. http_core.c
  4. mod_so.c
Rebuild Apache if compiled-in modules is significantly larger than the above list.

Hide Apache version (/usr/local/etc/apache22/extra/httpd-default.conf
ServerTokens Prod
ServerSignature Off

Remove and minimize loadable modules. Open httpd.conf and start removing unwanted modules. After each module run the following to make sure module is not breaking something:
/usr/local/etc/rc.d/apache22 configtest

Turn off directory browsing (default index).

Turn off server side includes and server side scripting such as php, python and so on. Only grant access to certian diretories to run perl, python, php. Use mod_fastcgi or mod_fcgi

Disable symbolic links.

Secure /tmp and /var/tmp directories and mount it with noexec, nosuid, nosymfollow.

Disable .htaccess if not required.

Make sure you use mod_ssl to encrypt content.

Make sure you install and use mod security, which provides an application level firewall for Apache. A sample pf.conf(5) rule:

http_servers = "{,,}"
https_servers = "{,}"
# ....
pass in on $ext_if inet proto tcp from any to $http_servers port http flags S/SA synproxy state
pass in on $ext_if inet proto tcp from any to $https_servers port https flags S/SA synproxy state

Make sure you use DoS service protection modules such as mod_throttle mod_bwshare www/mod_limitipconn mod_dosevasive.

Configure php securely use suexec or other wrappers. If possible use www/mod_fastcgi (see FreeBSD apache FastCGI PHP tutorial) to start php externally with other UID.

Restrict file and directory access, use chmod and chgrp command to set permission on documentroot.

Configure firewall to allow access to the web server.

Run Apache in a chroot jail if possible. Use chroot(8), FreeBSD jails, www/mod_chroot, www/mod_security (mod_security tutorial and project website) SecChrootDir directive. Some basic examples of mod_security:

# Prevent directory traversal
SecFilter "\.\./"

# Filter on specific system specific paths
SecFilter /etc/passwd
SecFilter /bin/

# Prevent cross-site scripting
SecFilter "<[[:space:]]* script"

# Prevent SQL injection
SecFilter "delete[[:space:]]+from"
SecFilter "insert[[:space:]]+into"
SecFilter "select.+from"

Run updated apache version:
portsnap fetch update
pkg_version -vl '<'
Use portmaster(8) or other tool to update Apache version.

Run lightweight web server. If you just run a wordpress blog or static html site, switch to www/lighttpd or www/nginx web server.

  1. Official Apache 2.2 Security Tips
  2. FreeBSD Apache HTTP Server tutorial
  3. 20 ways to Secure your Apache Configuration
  4. Recommended book - Apache Securitybook.

BIND9 is in base system.

Isolate DNS from Other Services. FreeBSD support chrooting bind server out of box. Add following to /etc/rc.conf

Configure firewalls to protect the DNS server. Sample pf rules:
dns_servers = "{ }"
# ...
pass in on $ext_if inet proto udp from any to $dns_servers  port domain
pass in on $ext_if inet proto tcp from any to $dns_servers  port domain flags S/SA synproxy state

Run separate DNS servers for External and Internal Queries (use jails).

Use Views to partition External and Internalinformation.

Authenticate Zone Transfers using TSIG. On primary ns:
cd /tmp
dnssec-keygen -a HMAC-MD5 -b 128 -n HOST
Note downl base64-key-string:
Edit /var/named/etc/namedb/named.conf on the primary nameserver. Add the following:
key zone-transfer-key {
       algorithm hmac-md5;
       secret "base64-key-string";
     zone " " IN {
       type master;
       allow-transfer { key zone-transfer-key; };
Edit /var/named/etc/namedb/named.conf on the secondary nameserver. Add the directives:
     key zone-transfer-key {
       algorithm hmac-md5;
       secret "base64-key-string ";

Disable dynamic updates
zone " " IN {
  allow-update { none; };

Configure the logging options for security and monitoring purpose:
logging {
    channel security_channel {
        # Send log messages to the specified file
        file            "/var/log/security.log" versions 3 size 50m;
        # Log all messages
        severity        debug;
        # Log the date and time of the message
        print-time      yes;
        # Log the category of the message
        print-category  yes;
        # Log the severity level of the message
        print-severity  yes;

    channel default {
        # Send logs to the syslog 'local0' facility
        syslog          local0;
        # Log messages of severity 'info' or higher
        severity        info;
        print-category  yes;
        print-severity  yes;

    # Logs about approval and denial of requests
    category security {

    # Ignore logs about misconfigured remote servers
    category lame-servers { null; };

    # Default logging options
    category default { default; };

   channel "querylog" { file "/var/log/query.log" versions 3 size 50m; print-time yes; };
   category queries { querylog; };
Note /var/log/query.log will be created in /var/named/ jail i.e. actual location will be /var/named/var/log/query.log.

FreeBSD Hardening System Via /etc/sysctl.conf
# Security networking
# Limit ICMP
# Drop synfin packets
# a single pass through the firewall
# net.inet.ip.fw.one_pass=1
# adds more queue buckets for ipfw dummynet
# net.inet.ip.dummynet.hash_size=2048
# increase the size of network mbufs to allocate
# kern.ipc.nmbclusters=65536
# If above used add the following to /boot/loader.conf - reboot needed
# kern.ipc.nmbclusers="65536"
# This is for dos protection 
# net.inet.tcp.msl=7500
# Turn off stealth IP networking 
# Try to protect against scans
# Try to stop some syn flood attacks, and route cache degregation
# Drop evil sourcerouted packets
# Turn it on when you have two interfaces on same switch
# IPCS - memory optimization 

# Hide UID and GID from other users
# Max open file?

See sysctl.conf(5) and sysctl(8) for more info,
Continued from post # 2...

General security tips
  1. Encrypt transmitted data whenever possible – Do not use rservices or insecure protocol such as telnet / ftp etc. Use scp, ssh and other secure alternative.
  2. Minimize software to minimize vulnerability - Only install required ports and applications. The simplest way to avoid vulnerabilities in software is to avoid installing that software. Run the following command to see open ports
    sockstat -4
    sockstat -6
    sockstat -4 | grep something
  3. Run different network services on separate systems - If possible, a server should be dedicated to serving exactly one network service. This limits the number of other services that can be compromised in the event that an attacker is able to successfully exploit a software flaw in one network service. Use FreeBSD jails to save hardware costs.
  4. Use and configure security tools to improve system robustness - Use firewall for host based firewalling and kernel protection, MAC etc for protection against vulnerable services. Configure log auditing for detecting problems. There are plenty of security tools for various purposes provides by FreeBSD security ports (located at/usr/ports/security)
  5. Updating Software - You need to update both base system + kernel (via buildworld or binary tool called freebsd-update) and applications (ports) via various tools. It is recommended that you use the following tools to keep systems up to date with the latest security patches.
    1. Updating and Upgrading FreeBSD
    2. FreeBSD Update Software and Apply Security Patches
    3. Install ports-mgmt/portaudit to monitor 3rd party apps and ports for security issues.
    4. Subscribe to freebsd-security-notifications mailing list or RSS feed.
  6. Avoid weak and default passwords - Do not leave network ports open. Always follow close all, open required port policy using firewall. Do not expose internal hosts such as sql servers, backup servers to the Internet. Use nating / proxy to hide internal server IPs.
  7. Do not run insecure and badly configured programs - For e.g. do not run apache, dns or mail server as a root user. Do not grant full system access to php or perl script. Restrict them to directories.
  8. Delete all unwanted account - For e.g. laid-off employee may seek revenge
  9. You need both host and firewall security.
  10. Never ever assumed that you are not target - you can be targeted by both humans and automated worms and virus. All you can do is set tight permissions and make sure you are always prepared for attacks.
  11. Always make a backup. Keep offsite backups on tape or dvd. RAID is not backup solution. Second hard disk on the same system is not a backup solution. Mirroring (to other server or disk) is not a backup. Backups are physically removed from the machine and stored where they can't be altered until they're needed for a restore. Always, check backup media and run dummy restore procedure. Use tools such as dump(8), restore(8), tar(1) etc. You can also use net/rsync, sysutils/rsnapshot and other 3rd party apps.
  12. Always read /usr/ports/UPDATING before updating ports.
  13. Always read /usr/src/UPDATING before starting buildworld procedure.

Tools for monitoring systems
  1. nmap() - scan your server for open ports.
  2. top(1) - display and update information about the top cpu processes.
  3. vmstat(8) - report virtual memory statistics.
  4. fstat(1) - identify active files
  5. lsof() - list open files, network connections and much more.
  6. systat(1) - display system statistics
  7. iostat(8) - report I/O statistics
  8. pstat(8) and swapinfo(8) - display system data structures
  9. netstat(1) - show network status
  10. sockstat(1) - list open sockets
  11. sysctl(8) - get or set kernel state. Many security settings and system information can be displayed using this tool. Use /etc/sysctl.conf to store configuration.
  12. ps(1) - list process status.
  13. w(1) / who(1) - display who is logged in and what they are doing
  14. uptime(1) - show how long system has been running
  15. last(1) - - indicate last logins of users and ttys
  16. lastcomm(1) - - show last commands executed
  17. ac(8) - connect time accounting
  18. sa(8) - print system accounting statistics

This is a just tiny list. Try the following resources / books:

I've tried to keep this small but useful list. Please add other information and comments below. Good luck!
vivek said:
OpenSSH server

Disable .rhosts Files
IgnoreRhosts yes

Disable Host-Based Authentication
HostbasedAuthentication no

Disable Empty Passwords
PermitEmptyPasswords no
I know it's not terribly important, but aren't these the default?
nice guide but be aware on mod security it is very easy to break mainstream apps eg. the mysql injection filter that you printed breaks phpmyadmin. The rules on break various mainstream apps as well, the core ruleset I have never tested tho.
This is a really nice guide, but I feel I have to correct one minor error.
vivek said:
OpenSSH server
Set Idle Timeout Interval for User Logins (600 seconds)
ClientAliveInterval 600
ClientAliveCountMax 0

I think you were looking for "LoginGraceTime", as the aforementioned directives have nothing to do with "Idle Timeout Interval for User Logins".
Or was the intention to kick off anyone who successfully logged in but didn't do anything actively in the console for 10 mins? I might be a bit slow as I'm rather tired at the moment. :)

Quoting sshd_config(5):
             Sets the number of client alive messages (see below) which may be
             sent without sshd(8) receiving any messages back from the client.
             If this threshold is reached while client alive messages are
             being sent, sshd will disconnect the client, terminating the ses-
             sion.  It is important to note that the use of client alive mes-
             sages is very different from TCPKeepAlive (below).  The client
             alive messages are sent through the encrypted channel and there-
             fore will not be spoofable.  The TCP keepalive option enabled by
             TCPKeepAlive is spoofable.  The client alive mechanism is valu-
             able when the client or server depend on knowing when a connec-
             tion has become inactive.

             The default value is 3.  If ClientAliveInterval (see below) is
             set to 15, and ClientAliveCountMax is left at the default, unre-
             sponsive SSH clients will be disconnected after approximately 45
             seconds.  This option applies to protocol version 2 only.

             Sets a timeout interval in seconds after which if no data has
             been received from the client, sshd(8) will send a message
             through the encrypted channel to request a response from the
             client.  The default is 0, indicating that these messages will
             not be sent to the client.  This option applies to protocol ver-
             sion 2 only.

             The server disconnects after this time if the user has not suc-
             cessfully logged in.  If the value is 0, there is no time limit.
             The default is 120 seconds.
Any tips on PHP security? For example how to configure Apache+PHP so when a user upload a php file manager he will be "see" only his home folder (and not the entire structure of / and other users ).
Jails are great and filesystem quotas are great, but as far as I can tell it is not possible to combine them? I've been working on a secure shell server for some users, which I've created inside a jail. I have not been able to figure out how to apply filesystem quotas for the jail users.

Is it possible to define filesystem quotas to users inside a jail? (I'm using ezjail-admin)
overmind said:
Any tips on PHP security? For example how to configure Apache+PHP so when a user upload a php file manager he will be "see" only his home folder (and not the entire structure of / and other users ).

Looks like you're looking for the FastCGI + Suexec combo in combo with PHP's open_basedir etc.

Related to IDS - you may add Yafic to the list - nice tool :)

To SSH - a simple SFTP only user may have nologin as login shell and in sshd:

Subsystem internal-sftp /usr/libexec/sftp-server

Match User example
 ChrootDirectory /home/example
 AllowTcpForwarding no
 ForceCommand internal-sftp
Google brought me here.

Are these modifications all still valid for FreeBSD 11.0 ?
If not, where are updated suggestions for hardening stored?
Other suggestions - Disable root login, change ssh port, Bind ssh to specific IP address,Only use SSH protocol 2,Deny root user login,Setup login banner ,Disable SSHD password authentication See:

root login via SSH is disabled on FreeBSD (but not all Linux distros).
[edited to reflect reality]

I used to run ssh on a non-default port. I got curious so I added a 2nd ssh to the default port and watched the logs for 3 months. In that time I had a few attempts to brute force passwords but nothing more interesting showed up in the logs. Since I only allow RSA authentication (I used to allow DSA until it got weakened) I stopped using the non-default port. I continue to watch logs and continue to see very little in the way of attempts to breach ssh.

I like what you are doing, in terms of putting together a solid list of suggestions.

A few years back I wrote a blog post on how to read the FreeBSD security reports. Some people might find it useful.
So, none of these proposed hardenings have made it (yet) into the default distro, to date...
I suggest you read security(7), which has been available since 3.1. Besides that, most of the suggestions here are referencing ports, ports are not part of the OS. Third party software needs to be correctly configured.
root login via SSH is the default on FreeBSD (but not all Linux distros).
That's nonsense. Root login over SSH is disabled out of the box, where even the commented out option has a sane default (from /etc/ssh/sshd_config):

#LoginGraceTime 2m
#PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
I don't know where you drew your conclusion from but trust me: it's horribly wrong. Just because the option has been commented out doesn't imply that it somehow got magically enabled. The sshd_config(5) manualpage will also tell you as much.

Please don't spread false information like that, at the very least confirm your opinion before just venting it, especially involving topics which somewhat matter.

So, none of these proposed hardenings have made it (yet) into the default distro, to date...
That... is worrying. Especially as many of them seem very sensible defaults in today's world.
It's not worrying at all. Apart from what SirDice already said I can also mention that you base your conclusion on the wrong information too.

For example: blocking SSH login. By default the daemon won't even get started after installation, so there's little to block there. Only after the user has explicitly enabled it. Another thing is that this task is usually done by a firewall. Not only does FreeBSD provide several, it also limits the amount of listening daemons. Just check # sockstat -l on a vanilla system.

Then the OP addresses IDS. FreeBSD ships with a basic one these days: /usr/sbin/mtree.

And I could go on for a while, but all of that doesn't even matter at all when it comes to security. Security isn't a product you install, it's a procedure which you comply to. Just installing a Unix-like operating system will by no means give you any guarantee that you'll be safer than if you'd be installing a Windows system (which is still a popular myth these days). For the simple reason that the whole art of security isn't guided by the OS but by its user(s).

So yeah, there's nothing worrying about this whole thing at all.
That's nonsense. Root login over SSH is disabled out of the box, where even the commented out option has a sane default (from /etc/ssh/sshd_config):

#LoginGraceTime 2m
#PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

Apologies. You are of course absolutely correct. I don't know how I got that so wrong. Must have been a brain fart. I have corrected my earlier post to remove the incorrect statement.
You should see some of my logs ;)

I still don't understand the lack of attacks on my system. I even turned up logging when I saw how infrequent it was. My firewall does filter out improperly configured IP packets and such but something else must be happening. Possibly my ISP has some sort of honeypot that catches and blocks things before it gets to me (and I am unaware of it).