-
Notifications
You must be signed in to change notification settings - Fork 5
Configuration
Foomuuri reads configuration files from /etc/foomuuri/*.conf
in alphabetical
order, including all sub directories. Foomuuri also reads static configuration
from /usr/share/foomuuri/*.conf
which can be overwritten in /etc/foomuuri
.
Raw nftables
rules can be written to /etc/foomuuri/*.nft
and they will be
included to generated ruleset.
See best practices for recommendations how to split different sections to multiple configuration files.
This section can be usually omitted as default values should be fine.
This section defines common options for Foomuuri. If really needed, it is usually better to override single value, not full section. Example:
foomuuri {
# Change rpfilter's value, keep everything else as default
rpfilter no
}
Full list of default values are:
foomuuri {
log_rate "1/second burst 3"
log_input yes
log_output yes
log_forward yes
log_rpfilter yes
log_invalid no
log_smurfs no
log_level "level info flags skuid"
localhost_zone localhost
dbus_zone public
rpfilter yes
counter no
set_size 65535
recursion_limit 65535
priority_offset 5
dbus_firewalld no
nft_bin nft
}
log_rate
is the default logging rate per source IP. Default value is to
log first three entries per source IP and then one additional entry per second.
Rate specification is the same as in rate limit rule.
log_input
... log_smurfs
defines default value for specific logging.
Value can be:
-
yes
to log it withlog_rate
-
no
to not log -
"3/second burst 10"
to log it with specific rate
log_level
is the syslog level of logging. For possible values see
rule specific version.
localhost_zone
is the name of zone used for the computer running Foomuuri,
similar to "localhost" in hostnames. See zone and
zone-zone sections for more information.
dbus_zone
is the name of your outgoing internet zone. This is used in
D-Bus support.
rpfilter
is to enable or disable reverse path filtering. Value can be:
-
yes
to enable it to all interfaces -
no
to disable it -
eth0 eth1 eth2
to enable it to specified interfaceseth0 eth1 eth2
-
-eth1 -eth2
to enable it to all other interfaces thaneth1 eth2
counter
is to add anonymous byte and packet counter to
all rules. Value can be:
-
yes
to add it to all rules -
no
to not add it -
localhost-public public-localhost
to add it to all rules inlocalhost-public
andpublic-localhost
sections
set_size
is the size for rate limit sets. Value 65535 is fine for normal
hosts. For company firewall larger value is required, like 262143 (=2^18 - 1).
This is the maximum amount of rate limit entries in kernel. If set is full,
new entry can't be added and the traffic is accepted without rate limit. See
foomuuri list
for content of your active sets.
recursion_limit
is the internal limit to avoid template expansion loop.
Increase this value if you get false "Possible template loop" error.
priority_offset
is the chain priority offset for rules generated by Foomuuri.
Tune this value if you have multiple software adding chains and want to
process them in some particular order. For example, iptables uses offset 0
and FirewallD uses 10. Lowest priority is processed first. So to process
Foomuuri rules first, use value -5
. To process them last, use 20
.
dbus_firewalld
is to enable or disable FirewallD D-Bus emulation inside
Foomuuri. NetworkManager can tell FirewallD to attach and detach interfaces
to zones via D-Bus call. This option enables Foomuuri to listen to FirewallD
D-Bus and do the same thing.
nft_bin
is the name for nft
binary. Full path can be specified if required.
This section is required on all configurations. It lists all known zones.
zone {
localhost
public
}
Above example defines two zones, localhost
and public
. All configurations
must have zone localhost
, which is the computer running Foomuuri,
similar to "localhost" in hostnames. See
best practices for recommended zone names.
Above example assumes that you are using FirewallD D-Bus (dbus_firewalld
config option) emulation where interfaces are attached and detached to zones
by NetworkManager. It is the recommended way for laptops and personal servers.
This config option will be turned on by default when installing
foomuuri-firewalld
package.
You can also define default interface to zone mapping by specifying interface name(s) after zone name. This is useful for corporate servers with static network configuration. This method can be used with or without FirewallD D-Bus emulation. This mapping is only default, not static. Interfaces can still be moved to other zones with D-Bus calls.
zone {
localhost # Localhost must be left empty
public eth0 # eth0 is attached to public
dmz eth1 eth2 # eth1 and eth2 are in dmz
}
It is also possible to use wildcard interface names. If you define wg*
then make sure that NetworkManager doesn't try to assing wg0
to any zone.
It would create "interval overlap" error as wg*
and wg0
conflicts.
zone {
localhost
public eth0
wireguard wg* # Matches wg0, wg1, wgfoo, and so on
}
Instead of writing rule tcp 443
it is easier and more readable to use rule
https
. These alias names are called macros. Macro can be used in any part
of rule you want to, defining rule fully or partially.
macro {
# Define service as macro
smtp tcp 25
https tcp 443; udp 443
googlemeet udp 3478 19302-19309; https
# Define rate limit as macro
ssh_rate saddr_rate "5/minute burst 5"
# Macro can be split to two lines with + (append) or \ (continue in next line)
good_hosts 10.0.0.1 fd00:f00::1
good_hosts + 10.0.0.2 fd00:f00::2
}
You can use above macros in zone-zone section:
localhost-public {
https daddr good_hosts # Allow https to specific IP addresses
tcp 23 daddr good_hosts # Allow TCP 23 to specific IP addresses
https reject # Reject all other https traffic
googlemeet # Allow Google Meet to everywhere
}
public-localhost {
ssh ssh_rate # Allow incoming ssh with rate limit
}
All
known macros
can be listed with foomuuri list macro
command.
FromZone-ToZone section defines rules for traffic coming from FromZone and going to ToZone. Normally you first accept some traffic and then reject or drop everything else as final rule. Rules inside zone-zone section are (mostly, see below) processed in listed order. Example:
public-localhost {
# Allow some incoming traffic
dhcp-client
ping
ssh
# Drop everything else
drop log
}
localhost-public {
# Allow some outgoing traffic
dhcp-server
domain
https
ping
ssh
# Reject everything else
reject log
}
Foomuuri will automatically add final drop log
(or reject log
for
localhost-something
) rule to zone-zone section if not specified. It is
always better to add explicit final rule to configuration.
Zone-zone section localhost-localhost
[new in version 0.22] (aka loopback
traffic, aka 127.0.0.1
and ::1
) is special case. It's final rule is
accept
. Usually there is no need to add localhost-localhost
section.
Normal use case for localhost-localhost
is to deny some traffic and then
accept everything else.
localhost-localhost {
# Don't allow user "untrusted" to connect local services
uid untrusted drop log
# Don't allow local http traffic
http reject log
# Accept everything else
accept
}
Please note that loopback traffic from your public IP to your public IP
belongs to localhost-localhost
, not public-public
.
If you have a lot of zones there will be a lot of zone-zone pairs. See best practices for recommendations how to split them to multiple files.
"Mostly": Rules inside zone-zone section are automatically sorted and processed in following block order:
- ICMP rules in listed order
- Previously accepted established and related traffic is accepted again by conntrack
- Incoming multicast and broadcast rules in listed order
- Everything else in listed order
Instead of using static IP addresses Foomuuri can perform periodical DNS
lookups for hostnames and store their IPv4 and IPv6 addresses to set. Set
name must begin with @
character. Static IPv4 or IPv6 address with or
without mask can also be used [new in version 0.25].
resolve {
# Resolve foobar.fi and store its IP addresses to @foobar_fi set
@foobar_fi foobar.fi
# Resolve multiple hostnames to set @fooweb
@fooweb foo-web.foobar.fi bar-web.foobar.fi
@fooweb + baz-web.foobar.fi
# Mixing hostnames and IP addresses
@one_ip 10.0.0.1
@mixed foobar.fi 192.0.2.0/24
}
localhost-public {
https daddr @fooweb # Allow https to above hostnames
https reject # Reject all other https
}
Lookups are refreshed every 15 minutes. This interval can be changed using
systemctl edit foomuuri-resolve.timer
. Single lookup failure does not
matter, Foomuuri will cache results for 24 hours. These results are also
saved for reloads and reboots.
This is similar to resolve
but set content can be specified as:
- Filename containing one IP address per line, with or without mask
- URL for file, as above
- IPv4 or IPv6 address, with or without mask [new in version 0.25]
iplist
can be used to blacklist or whitelist IP addresses, or to
download IP address country databases (aka geolocation). Set name must
begin with @
character.
Set name without filename or URL configures an empty set. Its entries can be
manipulated with foomuuri iplist add
and foomuuri iplist del
commands.
iplist {
# Download Finnish IPv4 and IPv6 addresses from https://github.com/ipverse/rir-ip
@fi https://raw.githubusercontent.com/ipverse/rir-ip/master/country/fi/ipv4-aggregated.txt
@fi + https://raw.githubusercontent.com/ipverse/rir-ip/master/country/fi/ipv6-aggregated.txt
# Download Finnish Elisa operator IP addresses from https://github.com/ipverse/asn-ip
@elisa https://raw.githubusercontent.com/ipverse/asn-ip/master/as/719/ipv4-aggregated.txt
@elisa + https://raw.githubusercontent.com/ipverse/asn-ip/master/as/719/ipv6-aggregated.txt
# Read blacklist from text files
@blacklist /etc/foomuuri/blacklist*.txt
# Read content from file and add some extra IPs to it
@whitelist /etc/foomuuri/whitelist*.txt 10.0.0.0/8 192.0.2.32
# Manipulate this list with "foomuuri iplist add mylist 10.0.0.1" command.
@mylist
}
public-localhost {
# Don't allow blacklisted addresses to IMAP
imap saddr @blacklist drop log "public-localhost DROP-blacklist"
# Allow mylist entries to IMAP without rate
imap saddr @mylist
# Allow Finnish users to IMAP with fast 1 per second rate
imap saddr @fi saddr_rate "1/second burst 10"
# Allow everybody to IMAP with slow 1 per minute rate. This includes
# over rate limit Finnish users.
imap saddr_rate "1/minute burst 1"
# ...rest of the rules...
}
Another example how to create a macro to allow access to Valve Steam:
iplist {
# Create iplist from Valve's IP addresses
@valve_as https://raw.githubusercontent.com/ipverse/asn-ip/master/as/32590/ipv4-aggregated.txt
@valve_as + https://raw.githubusercontent.com/ipverse/asn-ip/master/as/32590/ipv6-aggregated.txt
}
macro {
# Create macro to allow outgoing traffic to Valve iplist
valve-steam udp 3478 4379-4380 27000-27100 daddr @valve_as;
valve-steam + tcp 27015-27050 daddr @valve_as
}
localhost-public {
# Allow outgoing traffic to Valve Steam
valve-steam
}
Lookups are refreshed every 24 hours. Like in resolve
, lookups are
cached for 10 days for lookup failures, reloads and reboots.
Refresh interval can be configured [new in version 0.22] globally or
per-iplist with refresh
option:
iplist {
# Set global refresh interval
refresh 4h15m
# Use global refresh interval
@blacklist /etc/foomuuri/blacklist*.txt
# Use per-iplist refresh interval
@whitelist /etc/foomuuri/whitelist*.txt refresh=1h15m
}
Interval is rounded to 15 minutes. This can be configured with
systemctl edit foomuuri-iplist.timer
command.
These sections are similar to zone-zone section, except that they match any destination (zone-any), any source (any-zone) or all (any-any) traffic. These rules are processed first and then normal zone-zone rules. Example:
localhost-any {
# Allow ping and SSH for all traffic from localhost, no matter where
# it is going. Normally reject/drop statement is added to specific
# localhost-zone section, not to localhost-any.
ping
ssh
}
localhost-public {
# Accept HTTPS to public, in addition to localhost-any rules.
https
reject log
}
localhost-internal {
# Accept DNS queries to internal, in addition to localhost-any rules.
domain
reject log
}
Matcher szone -public
can be used in rule to skip adding it to
public-localhost
[new in version 0.24]. Example:
any-localhost {
ssh # allow ssh from anywhere
https szone -public # allow https from anywhere except from public
}
localhost-any {
ssh # allow ssh to anywhere
vnc dzone -public # allow vnc to anywhere except to public
}
Template is similar to macro but it is used to define list of rules, while macro defines single rule. Example:
template outgoing_services {
# Define template called "outgoing_services"
dhcp-server
domain
https
ntp
ping
ssh
}
localhost-public {
# Include template's content here
template outgoing_services
# Continue with other rules
http
reject log
}
dmz-public {
# Use same template for traffic coming from dmz zone
template outgoing_services
# Continue with other rules
reject log
}
Normally Foomuuri will map incoming and outgoing traffic to zones by source and destination network interface. These interfaces are assigned to zones dynamically by NetworkManager, or configured in zone section.
Zonemap section can be used to map traffic to different zone by using standard rules. Example:
zonemap {
# Map outgoing IPsec traffic that is going to zone "public" to use zone
# "vpn" instead.
dipsec dzone public new_dzone vpn
# Same for incoming.
sipsec szone public new_szone vpn
}
localhost-public {
# Rules for non-IPsec traffic
ipsec # You must allow IPsec traffic here and in public-localhost
...accept some traffic...
reject log
}
localhost-vpn {
# Rules for IPsec traffic
...accept some traffic...
reject log
}
Above example, splitting traffic to IPsec and non-IPsec zones is the most
common use case. You can use any matcher, for example daddr
or saddr
to
map some IP addresses to own zones, or uid
or gid
to map outgoing
traffic from some local user to own zone:
zonemap {
# Map IP address 10.2.3.0/24 from internal to dmz
saddr 10.2.3.0/24 szone internal new_szone dmz
daddr 10.2.3.0/24 dzone internal new_dzone dmz
# Map outgoing traffic from user myservice to myzone
uid myservice szone localhost new_szone myzone
# Map all outgoing IPsec traffic to xxx-vpn, no matter what the original
# dzone was
dipsec new_dzone vpn
}
Source NAT is used to mangle traffic by using standard rules. Example:
snat {
# Masquerade all traffic from 10.0.0.0/8 going to eth0 interface.
# New outgoing IP is eth0's IP address.
saddr 10.0.0.0/8 oifname eth0 masquerade
# Use outgoing IP 192.0.2.32 to all non-IPsec traffic coming from
# 10.0.0.0/8 and going to eth1 interface.
saddr 10.0.0.0/8 oifname eth1 -dipsec snat to 192.0.2.32
}
Remember to accept SNAT'ed traffic in zone-zone section. See dnat below for more examples.
Destination NAT is used to mangle traffic by using standard rules. Example:
dnat {
# http traffic to 10.0.0.1 is DNAT'ed to 10.0.0.2 port 8080
daddr 10.0.0.1 http dnat to 10.0.0.2:8080
# http traffic to fd00:f00::1 is DNAT'ed to fd00:f00::2 port 8080
# [new in version 0.22]
daddr fd00:f00::1 http dnat to [fd00:f00::2]:8080
# http traffic to 10.0.0.6 is DNAT'ed to 10.0.0.7, port doesn't change
daddr 10.0.0.6 http dnat to 10.0.0.7
# All smtp traffic from eth2 is DNAT'ed to 10.0.0.8 or fd00:f00::8,
# port doesn't change
iifname eth2 smtp dnat to 10.0.0.8 fd00:f00::8
# All traffic from eth1 inteface is DNAT'ed to 10.0.0.3
iifname eth1 dnat to 10.0.0.3
# http traffic to 10.0.0.4 coming from interface eth2 is DNAT'ed to 10.0.0.5
iifname eth2 daddr 10.0.0.4 http dnat to 10.0.0.5
}
Remember to accept DNAT'ed traffic in zone-zone section. This can be done
with specific rule or with ct_status
matcher. Example:
public-internal {
# Specific rule to accept https
https daddr 10.0.0.9
# Generic rule to accept all DNAT'ed traffic
ct_status dnat
}
These sections are used to specify packet mangle rules. prerouting
is for
all incoming packets, postrouting
is for all outgoing packets,
output
is for all locally generated packets and forward
is for all
forwarded packets. Mangle rules are processed before normal zone-zone
filtering rules.
Normally these sections are used to set packet mark value. Example:
prerouting {
# Do nothing if mark is already set
mark_match -0x0000/0xff00 accept
# Set default mark 0x100 to packet
mark_set 0x100/0xff00
# Change mark to 0x200 if it is coming from eth2
iifname eth2 mark_set 0x200/0xff00
# Use mark 0x300 for SSH traffic from eth2
iifname eth2 ssh mark_set 0x300/0xff00
}
Packets entering invalid
, rpfilter
or smurfs
chains will be dropped.
These sections can be used to specify more rules to them [new in version 0.23].
For example load balanced IPVS traffic might enter to invalid
chain and must
be accepted:
invalid {
# Accept HTTPS IPVS traffic
https
}
Foomuuri can run external command before/after starting and stopping. This section configures those commands. Example:
hook {
pre_start command-to-run with arguments before loading ruleset
post_start echo firewall started
pre_stop /etc/foomuuri/pre_stop.sh
post_stop /etc/foomuuri/post_stop.sh with arguments
}
Foomuuri includes simple network connectivity monitor. It can monitor your internet connection by pinging some external server. Command can be run if network link goes up or down. Example script to send an email to root is included in doc directory. Another example is multi-ISP configuration and script.
Minimal configuration is:
target google {
command fping 8.8.4.4
}
This creates monitor called google
and runs fping
command pinging
IP 8.8.4.4 every second. Foomuuri parses its output and logs up and down
events. Multiple targets can be defined.
Better real life example is:
target my-isp-router {
command fping --interval 2000 172.25.31.149
command_up /etc/foomuuri/monitor.event
command_down /etc/foomuuri/monitor.event
}
This pings IP 172.25.31.149 every two seconds and runs monitor.event
script when link goes up or down. That script sends an email to root.
See man fping
or their website for description
of fping
parameters.
"Up" and "down" are defined with parameters:
target my-isp-router {
history_size 100 # how many results are saved
history_up 80 # count of UPs => n => UP
history_down 30 # count of DOWNs >= n => DOWN
consecutive_up 20 # last n were UP => UP
consecutive_down 10 # last n were DOWN => DOWN
...
}
Target is considered up if 80 of the last 100 pings were successful (allowing failures in between) and last 20 pings were successful (no failures allowed).
Target is considered down if 30 of the last 100 pings were failures or last 10 pings were failures.
curl
and other programs can also be used instead of fping
. See example
shell script
how to use them.
Multiple network connectivity monitor targets can be grouped to single monitor. Example:
group my-isp-group {
target my-isp-router google
command_up /etc/foomuuri/monitor.event
command_down /etc/foomuuri/monitor.event
}
This creates monitor called my-isp-group
which includes two targets.
Group is considered up if any of the targets is up. It is considered down
if all of the targets are down.
Comments can be written as # comment
.
Long line can be split to multiple lines by adding \
to end of line.
Multiple words can be combined to single word by writing them in quotes.
For example ssh accept log "accept ssh for testing"
will accept SSH
traffic with log message accept ssh for testing
.
Macro expansion can be skipped by writing word in
quotes. For example "ssh"
is kept as ssh
and not expanded to tcp 22
.
Output from external command can be used to generate rules. It can return
single line, multiple lines or part of line. Syntax is
$(shell command to run)
. Command is run with shell so pipes and ;
will
work. Be careful to run only trusted commands.
Example:
# This is a comment
macro {
# Define local_port_range macro by reading correct value from /proc file
local_port_range $(shell sed s/\\t/-/ < /proc/sys/net/ipv4/ip_local_port_range)
}
localhost-public {
ssh # This is a comment
smtp \
daddr 192.0.2.32 # Allow SMTP to single IP
}
public-localhost {
tcp local_port_range # Allow TCP to ports 32768-60999 (default range)
}