Skip to content
Matt Simerson edited this page Nov 10, 2024 · 6 revisions

Mail Toaster runs all the micro-services (both jails and VMs) on private addresses. Jails are isolated from public networks so redirection, network address translation (NAT) and firewall rules are used to pass only the necessary traffic.

Host

The pf.conf file on the host is similar to this:

## Macros

ext_if="em0"
table <ext_ip4> { 10.0.1.209 }
table <ext_ip6> { 2602:61:7e0a:8400:20c:29ff:fedb:44d8 }

table <bruteforce> persist
table <sshguard> persist

## Translation rules

# default route to the internet for jails
nat on $ext_if inet  from 172.16.15.0/12 to any -> ($ext_if)
nat on $ext_if inet6 from (lo1) to any -> <ext_ip6>

nat-anchor "nat/*"

## Redirection

rdr-anchor "rdr/*"

## Filtering rules

# block everything by default. Test before enabling!
#block in log on $ext_if

block in quick from <bruteforce>

block in quick inet  proto tcp from <sshguard> to any port { 22 }
block in quick inet6 proto tcp from <sshguard> to any port { 22 }

anchor "allow/*"

Jails

Each jail inserts PF rules when it starts and removes them when it stops. This happens using jail.conf hooks to call a shell script that loads named config files. From data/etc/jail.conf.d/dovecot.conf:

    exec.created = "/data/dovecot/etc/pf.conf.d/pfrule.sh load";
    exec.poststop = "/data/dovecot/etc/pf.conf.d/pfrule.sh unload";

pfrule.sh

pfrule.sh lists all .conf files in its working directory and attempts to [un]load them based on the file's name. Therefore, the base name of each config file must match an anchor in /etc/pf.conf. Example:

ls /data/dovecot/etc/pf.conf.d/
pfrule.sh*    rdr.conf allow.conf table

rdr.conf

rdr inet  proto tcp from any to <dovecot> port { 993 995 } -> 172.16.15.15
rdr inet6 proto tcp from any to <dovecot> port { 993 995 } -> fd7a:e5cd:1fc1:186f:dead:beef:cafe:000f

# to permit legacy users to access insecure POP3 & IMAP, add their IPs/masks to ./table/insecure_mua
rdr inet  proto tcp from <insecure_mua> to <dovecot> port { 110 143 } -> 172.16.15.15
rdr inet6 proto tcp from <insecure_mua> to <dovecot> port { 110 143 } -> fd7a:e5cd:1fc1:186f:dead:beef:cafe:000f

allow.conf

ext_if = "ix2"

mua_ports = "{ 993 995 }"
insecure_ports = "{ 110 143 }"

block in log on $ext_if from any to <dovecot>

pass in quick proto tcp from any to <dovecot> port $mua_ports
pass in quick proto tcp from <insecure_mua> to <dovecot> port $insecure_ports

# allow pings
pass in quick inet proto icmp from any to <dovecot> icmp-type 8 code 0
pass in quick proto icmp6 from any to <dovecot>

table/dovecot

Clone this wiki locally