Skip to content


Folders and files

Last commit message
Last commit date

Latest commit



34 Commits

Repository files navigation


sf-ip-fw extension provides several building blocks to build your own firewall solution, based on raw iptables. You can build your firewall profiles for each machine as simple shell scripts, portable across all major Linux distributions:

  • Debian since 5.0 (Lenny)
  • Ubuntu since 8.04 LTS
  • Raspbian all versions
  • most Debian/Ubuntu clones
  • RHEL since 6.0 (or even earlier versions except LXC support)
  • all RHEL clones (CentOS, Oracle Linux, Scientific Linux etc.)

FreeBSD (ipfw) support is planned for further future. Want it faster? See this page.

Building your own firewall extension on top of Server Farmer


First, you need a fresh, Github private repository named firewall (under your own Github username).

It should contain:

  • ranges file - it extends allocs file with your own variables
  • script - it will be executed during extension setup, see below
  • script - the startup script for your firewall, it will:
    • execute initial firewall scripts
    • load per-host firewall profiles
    • enable ssh accesses that should be enabled everywhere (in case something is wrong with per-host profiles, to prevent locking access to the host)
    • enable any other accesses that you want to be enabled globally (see SNMP example below) script


/opt/farm/scripts/setup/ sf-ip-allocs
/opt/farm/scripts/setup/ sf-ip-fw
/opt/farm/scripts/setup/ sf-ip-noipv6
/opt/farm/scripts/setup/ sf-secure-kernel

echo "enforcing /opt/farm/ext/firewall file/directory permissions"
chown -R root:root /opt/farm/ext/firewall
chmod -R go-rwx /opt/farm/ext/firewall

/opt/farm/ext/ip-fw/service/ script

/etc/farmconfig file provides $HOST variable. It contains the hostname defined during Server Farmer setup - it doesn't need to match /etc/hostname.

/etc/local/.config directory contains several Server Farmer per-host settings files - mostly used to disable particular Server Farmer features on particular hosts, but also to configure monitoring-related details.

In the below example, $CACTI variable is defined in ranges file (see below).

. /opt/farm/ext/ip-allocs/allocs
. /opt/farm/ext/firewall/ranges
. /etc/farmconfig


# custom per-host rules first (to allow injecting DROP rules for ssh)
if [ -x /opt/farm/ext/firewall/hosts/$ ]; then


if [ -s /etc/local/.config/ ]; then
    $fw udp 161 $CACTI

# default ssh accesses on all servers - this is the real line from firewall script, used for customers in Poland

ranges file

It is recommended to provide at least $CACTI variable in this file - containing the list of IP addresses of your SNMP monitoring applications (not necessarily Cacti).


Example per-host firewall profile script

. /opt/farm/ext/ip-allocs/allocs
. /opt/farm/ext/firewall/ranges
. /etc/farmconfig


# expose ports 80/443 to the whole world
$fw tcp 80 any
$fw tcp 443 any

# enable ssh access from:
# - custom IP range(s) defined in file (additionally to these defined in last line of script)
# - custom IP(s) resolved from
$fw tcp 22 $SONERAFI

# enable ssh access from explicitly defined subnet
$fw tcp 22

Example per-host profile for server hosting LXC containers

$YOURLAN variable is often defined in ranges file as either your LAN subnet, or list of particular IP addresses.

. /opt/farm/ext/ip-allocs/allocs
. /opt/farm/ext/firewall/ranges
. /etc/farmconfig
. /etc/default/lxc-net


# dnsmasq - DHCP service for LXC containers

# masquerade for LXC outgoing traffic
/opt/farm/ext/ip-fw/utils/ $LOCALIF


# DNS for LXC containers ($LXC_NETWORK variable is taken from /etc/default/lxc-net file)
$fw udp 53 $LXC_NETWORK

# container port redirects
$nat $LOCALIF $LXC_BRIDGE tcp 9993   lxc-imap-server   993 $LXC_NETWORK $YOURLAN $UPTIMEROBOT  # IMAP service, additionally monitored by
$nat $LOCALIF $LXC_BRIDGE tcp 22001  lxc-imap-server    22 $LXC_NETWORK $YOURLAN  # ssh access
$nat $LOCALIF $LXC_BRIDGE tcp 45364  lxc-imap-server 45364 any  # certbot authentication (exposed as port 80 on edge router)

Example per-host profile with Docker support

This example assumes that server has public IP address.

$DOCKERONLY variable always refers to the default Docker subnet

$YOUROFFICE variable should be defined in ranges file, as your office external IP address.

. /opt/farm/ext/ip-allocs/allocs
. /opt/farm/ext/firewall/ranges
. /etc/farmconfig



# expose ports 80/443 to the whole world (from webserver installed on host, NOT exposed from Docker container)
$fw tcp 80 any
$fw tcp 443 any

# Postgres on host, available only for Docker containers
$fw tcp 5432 $DOCKERONLY

# Docker ports available for programmers/devops to use for exposing services
# these ports are accessible from:
# - Docker subnet (to allow particular containers to connect to themselves)
# - your office external IP address (eg. for debug purposes)
$fw  tcp 3000:4999 $DOCKERONLY $YOUROFFICE
$dck tcp 3000:4999 $DOCKERONLY $YOUROFFICE

Example per-host profile for internal LAN webserver, exposed via SSL-terminating proxy

This example assumes that proxy hostname properly resolves to the IP address of your LAN proxy server. This way, unencrypted web traffic is exchanged only between the application webserver, and proxy.

It can be easily combined with LXC services, where you have eg. 500 LXC containers with Apache or something else (separately for each customer), and additional LXC container with Nginx responsible for terminating SSL connections, and keeping SSL certificates away from direct customer access.

. /opt/farm/ext/ip-allocs/allocs
. /opt/farm/ext/firewall/ranges
. /etc/farmconfig

$fw tcp 80 proxy