A modular approach to iptables-based firewall rulesets.
fwkit is primarily designed around the concept of roles and services. Roles maintain a collection of enabled services. A ruleset is compiled based on the services enabled for the active role. Roles can be customized to suit any need, and a number of roles are configured by default.
You can view a list of available roles, and set one of them to be the active role.
# fwkit role list
file-server
fog
nextcloud
open
samba-ad-dc
web-server
# fwkit role set file-server
role changed: samba-ad-dc -> file-server
# fwkit role list
* file-server
fog
nextcloud
open
samba-ad-dc
web-server
Now the active role has been set to file-server
, and the role listing indicated this.
You can view the services enabled for the role.
# fwkit service list
LOCAL SERVICES
Active Name Description
* cups CUPS (IPP); 631/tcp, 631/udp
* dhcp Dynamic Host Configuration Protocol; 67/udp, 68/udp
dns Domain Name Service; 53/tcp, 53/udp
ftp File Transfer Protocol; 20/tcp, 21/tcp, 1024-65535/tcp
http Hypertext Transfer Protocol; 80/tcp
https Hypertext Transfer Protocol over TLS; 443/tcp
kerberos Kerberos v5; 88/tcp. 88/udp
kpasswd Kerberos v5 kpasswd; 464/tcp, 464/udp
ldap Lightweight Directory Access Protocol; 389/tcp, 389/udp
ldaps Lightweight Directory Access Protocol over TLS; 636/tcp
msgc Microsoft Global Catalog (Active Directory); 3268/tcp
msgc-ssl Microsoft Global Catalog over TLS (Active Directory); 3269/tcp
msrpc Microsoft RPC Dynamic Ports; 1024-1300/tcp, 49152-65535/tcp
* ntp Network Time Protocol; 123/udp
radacct RADIUS Accounting; 1813/tcp, 1813/udp
* radius RADIUS Authentication; 1812/tcp, 1812/udp
* rpcls Microsoft End Point Mapper (DCE/RPC Locator Service); 135/tcp
* smb Server Message Block (SMB); 445/tcp
* smtp Simple Message Transfer Protocol; 25/tcp
* ssh Secure Shell Server; 22/tcp
* tftp Trivial File Transfer Protocol; 69/udp
REMOTE SERVICES
Active Name Description
* dns Domain Name Service; 53/tcp, 53/udp
* http Hypertext Transfer Protocol; 80/tcp
https Hypertext Transfer Protocol over TLS; 443/tcp
* kerberos Kerberos v5; 88/tcp, 88/udp
* kpasswd Kerberos v5 kpasswd; 464/tcp, 464/udp
ldap Lightweight Directory Access Protocol; 389/tcp, 389/udp
ldaps Lightweight Directory Access Protocol over TLS; 636/tcp
msgc Microsoft Global Catalog (Active Directory); 3268/tcp
msgc-ssl Microsoft Global Catalog over TLS (Active Directory); 3269/tcp
msrpc Microsoft RPC Dynamic Ports; 1024-1300/tcp, 49152-65535/tcp
* ntp Network Time Protocol; 123/udp
rpcls Microsoft End Point Mapper (DCE/RPC Locator Service); 135/tcp
smb Server Message Block (SMB); 445/tcp
* smtp Simple Message Transfer Protocol; 25/tcp
* ssh Secure Shell Server; 22/tcp
A listing of all available local and remote services is display, with a description and port listing.
Enabling and disabling services is easy.
# fwkit service enable local ldap ldaps
enabled local service(s) ldap ldaps
Once you've configured the appropriate services, you can load the ruleset.
# fwkit rules load
compiled rules into /var/lib/fwkit/compiled.rules
loading compiled rules...done
Unloading the ruleset is simple, and fwkit caches the ruleset for later.
# fwkit rules unload
rules unloaded
Subsequent calls to fwkit rules load
will load the cached ruleset. If you makes changes to the enabled services, you'll need to clean the cache before loading the ruleset to see your changes.
# fwkit rules unload && fwkit rules clean && fwkit rules load
There is a handy shortcut for all three actions.
# fwkit reload
Beyond simply enabling or disabling services, there are a few options for customizing rulesets further. There are a number of files that are included during compilation. To get an understanding of how these files interact, here's an overview of fwkit's config structure.
/etc/fwkit/
role.active -> roles/file-server
roles/
file-server/
description
policy.rules
zones/
default/
default_action
description
services/
local/
services/
remote/
...
rules.d/
pre/
0default.rules
post/
services/
local/
...
remote/
...
This file is included before all others during the compilation process and is intented to configure chain policies. For example, you may want to set the INPUT
and OUTPUT
chain policies to DROP
.
# policy.rules - set default policy to drop
iptables -P INPUT DROP
iptables -P OUTPUT DROP
This file specifies the default action of traffic for the zone. Values are allow
or deny
.
This directory contains two sub-directories: pre
and post
. Files in the pre
sub-directory are included before service rules, while files in the post
sub-directory are included after the service rules. Files in either of these sub-directories must be suffixed with .rules
in order to be included.
# rules.d/pre/0default.rules
# stateful traffic
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# loopback traffic
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# icmp traffic
iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT
Service definitions - those that appear when running fwkit service list
- are defined in services/local
and services/remote
respectively. services/local
contains rules for locally available services, while services/remote
contains rules for remotely available services. Service definitions should contain a comment at the top of the file with information regarding the server. This information is used when listing the services.
# fwkit - local/dns.service - Domain Name Service; 53/tcp, 53/udp
iptables -A INPUT -p tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT
When a service is enabled, it is symlinked into the active role's zones/<zone>/services/local
or zones/<zone>/services/remote
sub-directory.
# ls /etc/fwkit/role.active/zones/default/services/local
lrwxrwxrwx 1 root root 35 Jul 20 18:01 dns.service -> /etc/fwkit/role.active/zones/default/services/local/dns.service
lrwxrwxrwx 1 root root 35 Jul 20 18:01 ntp.service -> /etc/fwkit/role.active/zones/default/services/local/ntp.service
lrwxrwxrwx 1 root root 36 Jul 20 18:01 smtp.service -> /etc/fwkit/role.active/zones/default/services/local/smtp.service
lrwxrwxrwx 1 root root 35 Jul 20 18:37 ssh.service -> /etc/fwkit/role.active/zones/default/services/local/ssh.service
If service definition files have the execute bit set, then fwkit attempts to run the definition as a script. The script is passed two arguments: the zone the service is being enabled for, and the location of the service (local or remote). The script's output is captured and is included in the compiled rule data. fwkit includes an utility that called fwksrv
which is used to allow for YAML service definitions. A service definition using a YAML format looks like:
#!/usr/sbin/fwksrv
# fwkit - local/dns.service - Domain Name Service; 53/tcp, 53/udp
services:
dns:
description: Domain Name Service
connections:
-
protocol: tcp
listen_port: 53
-
protocol: udp
listen_port: 53
Configuration values are set/unset/viewed using the fwkit config
command and come in two flavours: core configuration options, and ruleset variables. You can view the full list of configured values like so:
# fwkit config get
core.interpreter = /bin/sh
vars.opt_log_dropped = no
The above values are defined by default. core.interpreter
controls the command used to parse the compiled ruleset. vars.opt_log_dropped
defines the variable opt_log_dropped
for use within the ruleset and is ultimately used to determine if logging rules should be added for dropped packets.
# fwkit - rules.d/post/99log-dropped.rules
if [ "$opt_log_dropped" = "yes" ]; then
iptables -A INPUT -j LOG
iptables -A OUTPUT -j LOG
fi
To set a configuration value, use fwkit config set
.
# fwkit config set vars.foo bar
# fwkit config get
core.interpreter = /bin/sh
vars.opt_log_dropped = no
vars.foo = bar
To remove a configuration value, use fwkit config unset
# fwkit config unset vars.foo
# fwkit config get
core.interpreter = /bin/sh
vars.opt_log_dropped = no
fwkit provides some runtime variables for use within your ruleset. These variables provide easy access to each network interface's address and network address. These variables take the format if_<ifname>_addr
and if_<ifname>_net
and can be used within a ruleset to provide some more dynamic rules.
iptables -A INPUT -p icmp -s $if_eth0_net -j ACCEPT
iptables -A OUTPUT -p icmp -d $if_eth0_net -j ACCEPT
Runtime variables can also be referenced in config values for further abstracton.
# fwkit config set vars.lan_net \$if_eth0_net
The above ICMP rules can now be written in an interface agnostic way, making them more portable across hosts.
iptables -A INPUT -p icmp -s $lan_net -j ACCEPT
iptables -A OUTPUT -p icmp -d $lan_net -j ACCEPT
The rules file rules.d/pre/10dnat.rules
helps to make simple port forwarding easy to setup. Variables starting with dnat_
are assumed to be port forwarding specifications, and the appropriate iptables command are generated to fulfill the specification. Port forward specifications have the format:
proto/src_addr:src_port/dst_addr:dst_port
src_addr
and dst_port
are optional. In cases where src_addr
isn't defined, src_port
must still be prefixed with a colon. Here are some examples.
tcp/:2022/10.10.5.17:22
- redirect incoming SSH connections on port 2202 to port 22 on host 10.10.5.17udp/172.16.42.3:53/172.16.42.13
- redirect incoming DNS requests to local address 172.16.42.3 to host 172.16.42.13 (port 53 is implied as not destination port was specified)
To setup the port forward, run fwkit config set
.
# fwkit config set vars.dnat_ssh tcp/:2202/10.10.5.17:22
# fwkit config set vars.dnat_dns udp/172.16.42.3:53/172.16.42.13
# fwkit config get
...
vars.dnat_ssh = tcp/:2202/10.10.5.17:22
vars.dnat_dns = udp/172.16.42.3:53/172.16.42.13
Rules automatically generated by this simple port forwarding setup are commented to make troubleshooting easier.