Get CSF to work with Docker iptables

If you’re using CSF with Docker containers, you’ve more than likely come across a conflict between the iptables generated by CSF and those generated by Docker, and the one will overwrite the other.

This can be solved by some great scripts written by Julien Kassar. There are a couple of tweaks necessary though. Firstly, install CSF and configure as necessary. Next, run the following:

cd /usr/local/src
git clone https://github.com/juliengk/csf-pre_post_sh.git
cd csf-pre_post_sh
bash install.sh

You’ll most likely receive an error similar to the following:

** Critical! **
/bin/sh is not linked to /bin/bash. Yours is dash.
Only /bin/bash is supported

This can be solved by running the following:

ln -sf bash /bin/sh

Not to worry, we’ll revert this change later.

Now run the following again, this time with no errors received:

bash install.sh

Next, clone Julien’s other repo and follow:

cd /usr/local/src
git clone https://github.com/juliengk/csf-post-docker.git
cd csf-post-docker
bash install.sh

Restart csf with:

csf -r

You could receive the following errors:

/usr/local/include/csf/post.d/docker.sh: line 106: [: !=: unary operator expected
iptables v1.8.4 (legacy): invalid port/service -j' specified Tryiptables -h’ or ‘iptables –help’ for more information.
/usr/local/include/csf/post.d/docker.sh: line 106: [: !=: unary operator expected
iptables v1.8.4 (legacy): invalid port/service -j' specified Tryiptables -h’ or ‘iptables –help’ for more information.

To solve these errors, edit the /usr/local/include/csf/post.d/docker.sh file with the following:

nano -c /usr/local/include/csf/post.d/docker.sh

Change the following line:

if [ ${src_ip} != "0.0.0.0" ]; then

To the following:

if [ "${src_ip}" != "0.0.0.0" ]; then

Notice the “” around “${src_ip}”

Also, change the following line:

iptables -t nat -A DOCKER ${iptables_opt_src}! -i ${DOCKER_NET_INT} -p ${dst_proto} -m ${dst_proto} --dport ${src_port} -j DNAT --to-destination ${ipaddr}:${dst_port}

To the following:

if [ ! -z ${src_ip} ]; then
	iptables -t nat -A DOCKER ${iptables_opt_src}! -i ${DOCKER_NET_INT} -p ${dst_proto} -m ${dst_proto} --dport ${src_port} -j DNAT --to-destination ${ipaddr}:${dst_port}
fi;

Notice the if statement around the iptables command.

Revert the symlink change made for bash by running the following:

ln -sf dash /bin/sh

Finally, in order for the above change to work, you’ll need to edit /usr/local/csf/bin/csfpost.sh and change !/bin/sh to the following:

#!/bin/bash

Restart CSF:

csf -r

You’ll now notice that CSF and Docker play nicely together by running:

csf -l

You’ll see the Docker iptables rules at the bottom, but this time managed by CSF.