Usage βΊ Pre and Post Loader ScriptsΒΆ
CSF includes dedicated directories where you can place custom Bash scripts to run at specific stages of the firewallβs startup process. This allows you to easily maintain persistent, custom firewall rules that are automatically applied each time the CSF service starts or restarts.
SummaryΒΆ
The following is a summary of what this page explains:
- When you install CSF, two files will be placed on your server. These are known as the
preandpostloader scripts:- Preloader:
/usr/local/csf/bin/csfpre.sh - Postloader:
/usr/local/csf/bin/csfpost.sh
- Preloader:
- These loader scripts scan two different folders on your server to see if you have added any custom bash scripts you want ran when CSF starts. You can place your custom bash scripts in two different folders:
/usr/local/include/csf/pre.d/- Place your bash scripts in this folder if you want your scripts to run BEFORE CSF imports the default rules into your server.
/usr/local/include/csf/post.d/- Place your bash scripts in this folder if you want your scripts to run AFTER CSF imports the default rules into your server.
- Once the scripts are added, restart CSF with
sudo csf -ra
Location and StructureΒΆ
This section outlines exactly how the pre and post scripts are initialized and loaded.
Loader ScriptsΒΆ
- When CSF is installed for the first time, two files
/usr/local/csf/bin/csfpre.shand/usr/local/csf/bin/csfpost.share automatically created on your system (they will not overwrite existing copies). These files are loader scripts, giving you the ability to add your own custom bash scripts.- You must create the pre-loader folder
/usr/local/include/csf/pre.d/and post-loader folder/usr/local/include/csf/post.d/
- You must create the pre-loader folder
- If you already have existing pre/post loader files in place, CSF will respect this and NOT overwrite your existing files. Your existing setup will not be touched.
-
/usr/local/csf/bin/csfpre.sh -
- The file
csfpre.shinstalled with CSF loads every custom bash script you drop in the/usr/local/include/csf/pre.d/folder. - If making your own
csfpre.shloader, there are two allowed locations to place this script β either one is valid:-
/usr/local/csf/bin/csfpre.sh(default) -
/etc/csf/csfpre.sh(alternative)
-
- Runs before all default iptables rules are applied; allows you to add custom rules which persist alongside CSF's defaults.
- The file
-
/usr/local/csf/bin/csfpost.sh -
- The file
csfpost.shinstalled with CSF loads every custom bash script you drop in the/usr/local/include/csf/post.d/folder. - If making your own
csfpost.shloader, there are two allowed locations to place this script β either one is valid:-
/usr/local/csf/bin/csfpost.sh(default) -
/etc/csf/csfpost.sh(alternative)
-
- Runs after all default iptables rules are applied, allowing you to add custom rules which persist alongside CSF's defaults.
- The file
pre.sh & post.sh: Multiple Locations Allowed
By default, installing CSF will create the loader files csfpre.sh and csfpost.sh, and place them in the folder /usr/local/csf/bin/.
However, this location is not strict; you can place these loader files in one of two allowed locations:
- csfpre.sh
/usr/local/csf/bin/csfpre.sh/etc/csf/csfpre.sh
- csfpost.sh
/usr/local/csf/bin/csfpost.sh/etc/csf/csfpost.sh
Loader FoldersΒΆ
When the loader scripts /usr/local/csf/bin/csfpre.sh and /usr/local/csf/bin/csfpost.sh run, they check specific folders to see if you have placed any custom bash scripts inside. By placing custom bash scripts in these folders, you can write bash scripts which assist with setting up custom firewall rules which are automatically applied every time CSF starts or restarts, ensuring your custom rules persist.
-
/usr/local/include/csf/pre.d/ -
- Your custom bash scripts will run before CSF applies any default iptables rules.
- Scripts placed here run automatically every time CSF starts or restarts.
-
/usr/local/include/csf/post.d/ -
- Your custom bash scripts will run after CSF applies any default iptables rules.
- Scripts placed here run automatically every time CSF starts or restarts.
Defining A New Loader Folder
The CSF loader files /usr/local/csf/bin/csfpre.sh and /usr/local/csf/bin/csfpost.sh will look inside a specific folder for any custom bash scripts you have added.
If you wish to change the folder name / path used for storing your custom bash scripts, open these loader files and change the assigned variable toward the top of each file:
Loader ExampleΒΆ
We have provided both example structures of how your scripts can be set up. Script names can be any name you want, no restrictions.
This example stores your loader files in:
/usr/local/csf/bin/csfpre.sh/usr/local/csf/bin/csfpost.sh
Writing Custom RulesΒΆ
As outlined earlier, the pre.d and post.d folders allow you to drop your own custom bash scripts inside the folders which will be responsible for any iptable rules you need to add to CSF every time CSF is started or restarted.
We will provide an example script below just to outline what can be done. In our example, we will create /usr/local/include/csf/post.d/ports-blacklist.sh. The script will do the following:
- Defines a list of blacklisted ports using a JSON array in
BLACKLIST_PORTS. Each port we want to block will include the port number and a comment describing what that port is used for. - Iterates over each port in the blacklist using
jqto parse the JSON. - For each port:
- Extract the port number
ENTRY_PORTand its description/commentENTRY_COMMENT. - Check if a UDP rule already exists in iptables for that port:
- Sets
DELETE_INPUT_UDP=1if the rule does not exist.
- Sets
- Check if a TCP rule already exists in iptables for that port:
- Sets
DELETE_INPUT_TCP=1if the rule does not exist.
- Sets
- Add a firewall rule if it isn't already present:
- Inserts a rule to drop UDP traffic to the port.
- Inserts a rule to drop TCP traffic to the port.
- Extract the port number
Add the code below to your new file /usr/local/include/csf/post.d/ports-blacklist.sh and save.
#!/bin/sh
# #
# Settings > Ports
# #
BLACKLIST_PORTS=$(cat <<EOF
[
{"port":"111", "comment":"used by sunrpc/rpcbind, has vulnerabilities"}
]
EOF
)
# #
# Define > Iptables
# #
path_iptables4=$(which iptables)
path_iptables6=$(which ip6tables)
# #
# Loop blacklists, create if missing
# #
printf "\n"
printf " + RESTRICT Blacklisting Ports\n"
echo "$BLACKLIST_PORTS" | jq -c '.[]' | while IFS= read -r row; do
ENTRY_PORT=$(echo "$row" | jq -r '.port')
ENTRY_COMMENT=$(echo "$row" | jq -r '.comment')
# #
# See if ports already exist in iptables
# #
DELETE_INPUT_UDP=0
DELETE_INPUT_TCP=0
$path_iptables4 -C INPUT -p udp --dport "$ENTRY_PORT" -j DROP >/dev/null 2>&1 || DELETE_INPUT_UDP=1
$path_iptables4 -C INPUT -p tcp --dport "$ENTRY_PORT" -j DROP >/dev/null 2>&1 || DELETE_INPUT_TCP=1
# #
# Drop Port > UDP
# #
if [ "$DELETE_INPUT_UDP" = "0" ]; then
printf " β Port already blacklisted\n"
else
sudo $path_iptables4 -I INPUT -p udp --dport "$ENTRY_PORT" -j DROP
printf '%-17s %-50s %-55s\n' " " "ββ Blacklisting $ENTRY_PORT (UDP)" "$ENTRY_COMMENT"
fi
# #
# Drop Port > TCP
# #
if [ "$DELETE_INPUT_TCP" = "0" ]; then
printf " β Port already blacklisted\n"
else
sudo $path_iptables4 -I INPUT -p tcp --dport "$ENTRY_PORT" -j DROP
printf '%-17s %-50s %-55s\n' " " "ββ Blacklisting $ENTRY_PORT (TCP)" "$ENTRY_COMMENT"
fi
done
The script itself is very easy to use. We make sure to edit the list BLACKLIST_PORTS and populate it with ports we do not want the outside world being able to access.
BLACKLIST_PORTS=$(cat <<EOF
[
{"port":"111", "comment":"used by sunrpc/rpcbind, has vulnerabilities"}
{"port":"21", "comment":"insecure ftp"}
]
EOF
)
After you edit the list of ports above, restart CSF and the script will be automatically re-loaded:
LOGDROPOUT all opt -- in * out !lo 0.0.0.0/0 -> 0.0.0.0/0
LOGDROPIN all opt -- in !lo out * 0.0.0.0/0 -> 0.0.0.0/0
csf: FASTSTART loading DNS (IPv4)
LOCALOUTPUT all opt -- in * out !lo 0.0.0.0/0 -> 0.0.0.0/0
LOCALINPUT all opt -- in !lo out * 0.0.0.0/0 -> 0.0.0.0/0
Running /usr/local/csf/bin/csfpost.sh
Loading post-script: /usr/local/include/csf/post.d/ports-blacklist.sh
+ RESTRICT Blacklisting Ports
ββ Blacklisting 111 (UDP) used by sunrpc/rpcbind, has vulnerabilities
ββ Blacklisting 111 (TCP) used by sunrpc/rpcbind, has vulnerabilities
ββ Blacklisting 21 (UDP) insecure ftp
ββ Blacklisting 21 (TCP) insecure ftp
We can now use the iptables command to confirm our rules were added. Iptables will resolve whatever service is associated with a port, which means port 111 will show as sunrpc. If you wish to show just the port number, append -n to your iptables command:
If you use the command sudo iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:sunrpc
DROP udp -- anywhere anywhere udp dpt:sunrpc
Chain LOGDROPIN (2 references)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:sunrpc
DROP udp -- anywhere anywhere udp dpt:sunrpc
If you use the command sudo iptables -L -n
ConclusionΒΆ
From this point forward, you can create any number of pre and post bash scripts for your firewall. Simply drop any bash scripts you wish to load with CSF inside the folders /usr/local/include/csf/pre.d/ and /usr/local/include/csf/post.d/.
For a quick reference to the file and folder names, you can view the section Location and Structure.
Next Steps ΒΆ
Select what documentation you would like to proceed with next ...
-
Blocklists provide the foundation for blocking unwanted and malicious traffic in CSF. They allow you to automatically deny access from IP addresses that have been identified as abusive or high risk.
This section introduces what blocklists are, how they work, and how to configure them using CSFβs official blocklist or trusted third-party sources.
Once you are comfortable using blocklists, you can advance to IPSETs to handle larger lists more efficiently and improve performance as your ruleset grows.
-
Blocklists and IPSETs are designed to work together. Blocklists provide a simple way to block unwanted traffic from reaching your server, but large blocklists can be inefficient and memory-intensive.
If you plan to import blocklists containing more than a few thousand IP addresses, it is strongly recommended to enable CSFβs IPSET integration.
IPSETs allow you to block significantly larger numbers of IP addresses in a far more efficient way, without the risk of excessive memory usage or performance degradation.