rfxn / advanced-policy-firewall

Advanced Policy Firewall (APF)
GNU General Public License v2.0
93 stars 46 forks source link

Suggestion use systemd, as init.d has no status #27

Closed tomdoyle87 closed 5 years ago

tomdoyle87 commented 5 years ago

Hi,

init.d does not report any issues with apf:

/etc/init.d/apf start Starting apf (via systemctl): [ OK ]

Will report OK even if iptables is not running for example:

https://www.eukhost.com/blog/webhosting/apf-unable-to-load-iptables-module-ip_tables/

Currently only starting apf manually or iptables -S would show if there is an issue. If started with systemd unit:

[Unit]
Description=apf firewall with iptables
After=syslog.target network.target

[Service]
RemainAfterExit=yes
ExecStart=/usr/local/sbin/apf --start
ExecStop=/usr/local/sbin/apf --stop
Restart=on-failure
RestartSec=5

[Install]
WantedBy=basic.target

status will advise if iptables is running or not:

systemctl status apf

● apf.service - apf firewall with iptables
   Loaded: loaded (/usr/lib/systemd/system/apf.service; enabled; vendor preset: disabled)
   Active: active (exited) since Tue 2018-11-20 14:33:21 GMT; 3min 44s ago
  Process: 5443 ExecStop=/usr/local/sbin/apf --stop (code=exited, status=0/SUCCESS)
  Process: 5531 ExecStart=/usr/local/sbin/apf --start (code=exited, status=0/SUCCESS)
 Main PID: 5531 (code=exited, status=0/SUCCESS)

Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5638): {glob} opening inbound icmp type 30 on 0/0
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5638): {glob} opening inbound icmp type 8 on 0/0
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5638): {glob} resolv dns discovery for 192.168.1.20
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5638): {glob} resolv dns discovery for 192.168.1.22
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5638): {glob} resolv dns discovery for 192.168.1.1
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5638): {glob} loading postroute.rules
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5638): {glob} default (egress) output accept
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5638): {glob} default (ingress) input drop
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5531): {glob} firewall initalized
Nov 20 14:33:23 localhost.localdomain apf[5531]: apf(5531): {glob} fast load snapshot saved

Systemd unit file can probably be improved to actaul fail if iptables, this more of a start/suggestion.

Thanks

tomdoyle87 commented 5 years ago

Hi, I think I have a solution for apf not stopping when iptables fails to start. The main issue I had that the iptables processes exits after processing the rules and passes the work on to the kernel modules. So its pointless monitoring the process, instead monitoring the logs seems like a possible solution. This is far from perfect, again more of a start/suggestion.

/usr/local/sbin/start-apf.sh

#!/bin/bash
/usr/local/sbin/apf --start
if grep --quiet "unable to load iptables" /var/log/messages; then
/usr/local/sbin/apf --stop
else
echo not found
fi

The script checks the system log for any occurrences of iptables not loading; if found apf is stops. I realise in its current form this only works on redhat/redhat based GNU/Linux. Replacing /var/log/messages with /var/log/syslog for debian based. This could done on install with cat /etc/proc ?

chmod + /usr/local/sbin/start-apf.sh

/usr/lib/systemd/system/apf.service

[Unit]
Description=apf firewall with iptables
After=syslog.target network.target

[Service]
RemainAfterExit=yes
ExecStart=/usr/local/sbin/start-apf.sh
ExecStop=/usr/local/sbin/apf --stop
Restart=on-failure
RestartSec=5

[Install]
WantedBy=basic.target

systemctl daemon-reload

systemctl restart apf

This needs testing, as I am unable to produce or anything similar:

https://platonic.techfiz.info/2009/06/apf-fix-systemctl%20daemon-reloadunable-to-load-iptables-module-ip_tables/

Thanks Tom.

tomdoyle87 commented 5 years ago

Hi,

I believe I have a working solution for the apf service to fail, if apf doesn't start correctly:

/etc/systemd/system/apf.service:

[Unit]
Description=apf firewall with iptables
After=syslog.target network.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/local/sbin/apf-start.sh
ExecStop=/usr/local/sbin/apf --stop

[Install]
WantedBy=basic.target

/usr/local/sbin/apf-start.sh:

#!/bin/bash
/usr/local/sbin/apf --start &> /tmp/check-apf
if egrep 'unable to load iptables module|timed out while attempting to gain lock|could not process allow_hosts|could not process deny_hosts|apf does not appear to have rules loaded|could not verify that interface|trust rules unchanged since last refresh' /tmp/check-apf; then
    /usr/local/sbin/apf --stop
    echo "APF Aborted"
    exit 1
else
    echo "All ok"
fi
exit 0

From looking at /etc/apf/internals/functions.apf, the egrep should cover all possible errors; please let me know if that is not the case.

I have confirmed results in systemd failure by changing un-trusted interface to a interface which doesn't exist on my system.

Thanks Tom.