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.
Structure¶
When CSF is installed for the first time, it automatically creates two files:
- 📄
/usr/local/csf/bin/csfpre.sh - 📄
/usr/local/csf/bin/csfpost.sh
These files act as loader scripts. They allow you to run your own custom Bash scripts before and after CSF executes. To use them, create the following directories:
- 📁
/usr/local/include/csf/pre.d/— scripts run before CSF - 📁
/usr/local/include/csf/post.d/— scripts run after CSF
Existing Files
If you already have pre-loader and post-loader files in placve on your server, CSF will not overwrite them. Your existing configuration will be left exactly as-is.
After creating the directories above, you can now place your own custom bash scripts inside these folders. Restart CSF to load them.
Loader Files¶
As mentioned above, when installing CSF, two files will be loaded to your system. Those files are outlined below:
-
/usr/local/csf/bin/csfpre.sh -
- The
csfpre.shloader executes every custom Bash script located in the
/usr/local/include/csf/pre.d/directory. - If you create your own
csfpre.sh, CSF will accept it from either of the following locations:-
/usr/local/csf/bin/csfpre.sh(default location) -
/etc/csf/csfpre.sh(alternative location)
-
- Scripts run before any default iptables rules are applied, making this the ideal place to add custom firewall rules that should exist alongside CSF’s defaults.
- The
-
/usr/local/csf/bin/csfpost.sh -
- The
csfpost.shloader executes every custom Bash script located in the
/usr/local/include/csf/post.d/directory. - If you create your own
csfpost.sh, CSF will accept it from either of the following locations:-
/usr/local/csf/bin/csfpost.sh(default location) -
/etc/csf/csfpost.sh(alternative location)
-
- Scripts run after all default iptables rules have been applied, allowing you to safely append custom rules that persist without interfering with CSF’s core configuration.
- The
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 files /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.