Firewall rules are in the wrong order?

Hi,

I’m trying to get some some “DROP” rules at the top of the firewall. I have this in rules.conf:

RULE='1' ACTION='DROP' PROTOCOL='TCP' PORT='0' IP='ipset:abuseipdb30d' COMMENT='abuseipdb' SUSPENDED='no' TIME='09:38:06' DATE='2025-02-18'

RULE='2' ACTION='DROP' PROTOCOL='TCP' PORT='0' IP='ipset:singapore' COMMENT='singaporespammers' SUSPENDED='no' TIME='09:49:38' DATE='2025-02-18'

RULE='3' ACTION='DROP' PROTOCOL='TCP' PORT='0' IP='ipset:china' COMMENT='china' SUSPENDED='no' TIME='09:52:06' DATE='2025-02-18'

RULE='4' ACTION='DROP' PROTOCOL='TCP' PORT='0' IP='ipset:alibabamain' COMMENT='alibabacloud' SUSPENDED='no' TIME='10:19:05' DATE='2025-02-18'

RULE='5' ACTION='DROP' PROTOCOL='TCP' PORT='0' IP='ipset:blacklist' COMMENT='blacklist' SUSPENDED='no' TIME='10:55:22' DATE='2023-09-08'

RULE='6' ACTION='ACCEPT' PROTOCOL='ICMP' PORT='0' IP='0.0.0.0/0' COMMENT='PING' SUSPENDED='no' TIME='17:13:48' DATE='2014-09-16'

RULE='7' ACTION='ACCEPT' PROTOCOL='TCP' PORT='9183' IP='0.0.0.0/0' COMMENT='HESTIA' SUSPENDED='no' TIME='07:40:16' DATE='2014-05-25'

RULE='8' ACTION='ACCEPT' PROTOCOL='TCP' PORT='143,993' IP='0.0.0.0/0' COMMENT='IMAP' SUSPENDED='no' TIME='07:40:16' DATE='2014-05-25'

RULE='9' ACTION='ACCEPT' PROTOCOL='TCP' PORT='110,995' IP='0.0.0.0/0' COMMENT='POP3' SUSPENDED='no' TIME='07:40:16' DATE='2014-05-25'

RULE='10' ACTION='ACCEPT' PROTOCOL='TCP' PORT='25,465,587' IP='0.0.0.0/0' COMMENT='SMTP' SUSPENDED='no' TIME='21:47:04' DATE='2018-11-07'

RULE='11' ACTION='ACCEPT' PROTOCOL='TCP' PORT='53' IP='0.0.0.0/0' COMMENT='DNS' SUSPENDED='no' TIME='07:40:16' DATE='2014-05-25'

RULE='12' ACTION='ACCEPT' PROTOCOL='UDP' PORT='53' IP='0.0.0.0/0' COMMENT='DNS' SUSPENDED='no' TIME='07:40:16' DATE='2014-05-25'

RULE='13' ACTION='ACCEPT' PROTOCOL='TCP' PORT='21,12000-12100' IP='0.0.0.0/0' COMMENT='FTP' SUSPENDED='no' TIME='07:40:16' DATE='2014-05-25'

RULE='14' ACTION='ACCEPT' PROTOCOL='TCP' PORT='80,443' IP='0.0.0.0/0' COMMENT='WEB' SUSPENDED='no' TIME='17:04:27' DATE='2014-09-24'

RULE='15' ACTION='ACCEPT' PROTOCOL='TCP' PORT='35621,35622,35623,55415' IP='0.0.0.0/0' COMMENT='urbackup' SUSPENDED='no' TIME='08:31:53' DATE='2023-06-15'

RULE='16' ACTION='ACCEPT' PROTOCOL='UDP' PORT='35622' IP='0.0.0.0/0' COMMENT='urbackup-listener' SUSPENDED='no' TIME='08:31:53' DATE='2023-06-15'

RULE='17' ACTION='ACCEPT' PROTOCOL='TCP' PORT='2812' IP='81.174.134.33' COMMENT='monit' SUSPENDED='no' TIME='08:31:53' DATE='2023-06-15'

RULE='18' ACTION='ACCEPT' PROTOCOL='TCP' PORT='22122' IP='0.0.0.0/0' COMMENT='SSH-new-port' SUSPENDED='no' TIME='08:57:32' DATE='2023-06-15'

RULE='19' ACTION='ACCEPT' PROTOCOL='TCP' PORT='8338' IP='0.0.0.0/0' COMMENT='maltrail' SUSPENDED='no' TIME='06:21:35' DATE='2023-06-16'

RULE='20' ACTION='DROP' PROTOCOL='TCP' PORT='3306' IP='0.0.0.0/0' COMMENT='drop-mysql' SUSPENDED='no' TIME='05:50:22' DATE='2023-07-27'

RULE='20' ACTION='ACCEPT' PROTOCOL='TCP' PORT='3306' IP='81.174.134.33' COMMENT='andy-mysql' SUSPENDED='no' TIME='05:51:49' DATE='2023-07-27'

RULE='21' ACTION='ACCEPT' PROTOCOL='TCP' PORT='3306' IP='92.70.93.185' COMMENT='MySQL-Office' SUSPENDED='no' TIME='17:30:18' DATE='2023-08-23'

RULE='22' ACTION='ACCEPT' PROTOCOL='TCP' PORT='3306' IP='178.22.63.50' COMMENT='MySQL-wbs.crio.nl' SUSPENDED='no' TIME='17:31:20' DATE='2023-08-23'

RULE='23' ACTION='ACCEPT' PROTOCOL='TCP' PORT='3306' IP='185.31.247.103' COMMENT='MySQL-VPN' SUSPENDED='no' TIME='17:31:31' DATE='2023-08-23'

RULE='24' ACTION='ACCEPT' PROTOCOL='TCP' PORT='3306' IP='24.132.219.5' COMMENT='MySQL-Frans' SUSPENDED='no' TIME='08:42:41' DATE='2023-09-02'

RULE='25' ACTION='ACCEPT' PROTOCOL='TCP' PORT='3306' IP='178.79.177.65' COMMENT='syk-testmysql' SUSPENDED='no' TIME='14:12:22' DATE='2023-09-07'

RULE='26' ACTION='ACCEPT' PROTOCOL='TCP' PORT='3306' IP='192.168.165.50' COMMENT='MySQL-wbs.crio.nl' SUSPENDED='no' TIME='17:26:54' DATE='2023-09-07'

RULE='28' ACTION='ACCEPT' PROTOCOL='TCP' PORT='3306' IP='172.105.244.200' COMMENT='bbserver' SUSPENDED='no' TIME='13:09:05' DATE='2024-04-04'

Yet after running v-update-firewall, they don’t appear at the start:

iptables -L -n --line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination
1    fail2ban-WEB  tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 80,443
2    fail2ban-HESTIA  tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:9183
3    fail2ban-MAIL  tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587,110,995,143,993
4    fail2ban-FTP  tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:21
5    fail2ban-SSH  tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22122
6    fail2ban-RECIDIVE  tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 1:65535
7    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
8    ACCEPT     all  --  170.187.188.92       0.0.0.0/0
9    ACCEPT     all  --  127.0.0.1            0.0.0.0/0
10   ACCEPT     tcp  --  172.105.244.200      0.0.0.0/0            tcp dpt:3306
11   ACCEPT     tcp  --  192.168.165.50       0.0.0.0/0            tcp dpt:3306
12   ACCEPT     tcp  --  178.79.177.65        0.0.0.0/0            tcp dpt:3306
13   ACCEPT     tcp  --  24.132.219.5         0.0.0.0/0            tcp dpt:3306
14   ACCEPT     tcp  --  185.31.247.103       0.0.0.0/0            tcp dpt:3306
15   ACCEPT     tcp  --  178.22.63.50         0.0.0.0/0            tcp dpt:3306
16   ACCEPT     tcp  --  92.70.93.185         0.0.0.0/0            tcp dpt:3306
17   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:3306
18   ACCEPT     tcp  --  81.174.134.33        0.0.0.0/0            tcp dpt:3306
19   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8338
20   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22122
21   ACCEPT     tcp  --  81.174.134.33        0.0.0.0/0            tcp dpt:2812
22   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:35622
23   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 35621,35622,35623,55415
24   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 80,443
25   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 21,12000:12100
26   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:53
27   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:53
28   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587
29   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 110,995
30   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 143,993
31   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:9183
32   ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0
33   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            match-set blacklist src
34   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            match-set alibabamain src
35   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            match-set china src
36   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            match-set singapore src
37   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            match-set abuseipdb30d src

How can I get it to put them up the top? I need to block the bad IPs right from the start, otherwise they seem to be getting through :frowning:

Thanks

Andy

Hi Andy,

You’re right to want those DROP rules at the very top of the firewall to stop bad IPs before anything else is accepted. However, HestiaCP’s v-update-firewall script does not support a pre.sh hook (confirmed by reviewing the source /usr/local/hestia/bin/v-update-firewall), and it always appends rules from rules.conf using -A, not -I.

-A (append): Adds the rule to the end of the chain. It’s evaluated after all existing rules.
-I (insert): Inserts the rule at a specific position (e.g., -I INPUT 1 puts it at the very top). It’s evaluated before lower rules.

So:

  • Use -A to add rules last.
  • Use -I to add rules first (or at a specific point).

Working Manual Solution (Immediate + Persistent via Cron)

To ensure your DROP rules always stay at the top, you need to insert them manually using iptables -I, and re-apply them after every v-update-firewall call or reboot.

Here’s how to do it:


1. Create a script to prepend the rules

Create a file:

sudo nano /usr/local/sbin/hestia-firewall-prepend.sh

With this content:

#!/bin/bash
iptables -I INPUT 1 -p tcp -m set --match-set abuseipdb30d src -j DROP
iptables -I INPUT 2 -p tcp -m set --match-set singapore src -j DROP
iptables -I INPUT 3 -p tcp -m set --match-set china src -j DROP
iptables -I INPUT 4 -p tcp -m set --match-set alibabamain src -j DROP
iptables -I INPUT 5 -p tcp -m set --match-set blacklist src -j DROP

Make it executable:

sudo chmod +x /usr/local/sbin/hestia-firewall-prepend.sh

2. Auto-apply it after boot and firewall updates

Option A: Add to crontab (for root):

sudo crontab -e

Add:

@reboot /usr/local/sbin/hestia-firewall-prepend.sh

Option B: Run manually after any v-update-firewall call:

sudo v-update-firewall
sudo /usr/local/sbin/hestia-firewall-prepend.sh

Result

Your DROP rules will always be at the top of the INPUT chain, enforced before any ACCEPT or fail2ban logic.

Let me know if you’d like a fully automated systemd service instead of cron.

Best regards

Thank you - that looks great :slight_smile:

There is a PR to allow to change the order

3 Likes