├── README.md ├── install.sh └── docker.sh /README.md: -------------------------------------------------------------------------------- 1 | # ConfigServer Security & Firewall (CSF) - Docker 2 | 3 | ## Installation 4 | ### Requirement 5 | Make sure to use the scripts from https://github.com/juliengk/csf-pre_post_sh 6 | 7 | ### Install 8 | Installation is quite straightforward: 9 | 10 | ``` 11 | # cd /usr/local/src 12 | # git clone https://github.com/juliengk/csf-post-docker.git 13 | # cd csf-post-docker 14 | # sh install.sh 15 | ``` 16 | 17 | ## User Feedback 18 | ### Issues 19 | 20 | If you have any problems with or questions about this image, please contact us through a [GitHub](https://github.com/juliengk/csf-post-docker/issues) issue. 21 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SCRIPT_NAME="docker.sh" 4 | 5 | CSF_CUSTOM_PATH="/usr/local/include/csf" 6 | CSFPOSTD_PATH="${CSF_CUSTOM_PATH}/post.d" 7 | 8 | 9 | if [ ! -d ${CSF_CUSTOM_PATH} ]; then 10 | echo "** CSF-PRE_POST_SH is not installed **" 11 | echo "Get it from https://github.com/juliengk/csf-pre_post_sh" 12 | 13 | exit 1 14 | fi 15 | 16 | PREFIX="None" 17 | if [ "$1" == "-p" ] || [ "$1" == "--prefix" ]; then 18 | PREFIX=$2 19 | 20 | shift 2 21 | fi 22 | 23 | SCRIPT_NAME_FINAL="${SCRIPT_NAME}" 24 | if [ ${PREFIX} != "None" ]; then 25 | SCRIPT_NAME_FINAL="${PREFIX}_${SCRIPT_NAME}" 26 | fi 27 | 28 | if [ -f ${CSFPOSTD_PATH}/${SCRIPT_NAME_FINAL} ]; then 29 | md5_0=`md5sum docker.sh | awk '{ print $1 }'` 30 | md5_1=`md5sum ${CSFPOSTD_PATH}/${SCRIPT_NAME_FINAL} | awk '{ print $1 }'` 31 | 32 | if [ ${md5_0} == ${md5_1} ]; then 33 | exit 0 34 | else 35 | ok=0 36 | while [ ${ok} -eq 0 ]; do 37 | clear 38 | 39 | echo "** Warning! **" 40 | echo "A different version of the script is already present" 41 | echo "Do you want to replace it (y/n)?" 42 | 43 | read answer 44 | 45 | if [ ${answer} == "y" -o ${answer} == "n" ]; then 46 | ok=1 47 | fi 48 | done 49 | 50 | if [ ${answer} == "n" ]; then 51 | exit 1 52 | fi 53 | fi 54 | fi 55 | 56 | cp -f ${SCRIPT_NAME} ${CSFPOSTD_PATH}/${SCRIPT_NAME_FINAL} 57 | chown root:root ${CSFPOSTD_PATH}/${SCRIPT_NAME_FINAL} 58 | chmod 700 ${CSFPOSTD_PATH}/${SCRIPT_NAME_FINAL} 59 | 60 | exit 0 61 | -------------------------------------------------------------------------------- /docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 4 | 5 | chain_exists() { 6 | [ $# -lt 1 -o $# -gt 2 ] && { 7 | echo "Usage: chain_exists [table]" >&2 8 | return 1 9 | } 10 | local chain_name="$1" ; shift 11 | [ $# -eq 1 ] && local table="--table $1" 12 | iptables $table -n --list "$chain_name" >/dev/null 2>&1 13 | } 14 | 15 | add_to_forward() { 16 | local docker_int=$1 17 | 18 | if [ `iptables -nvL FORWARD | grep ${docker_int} | wc -l` -eq 0 ]; then 19 | iptables -A FORWARD -o ${docker_int} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 20 | iptables -A FORWARD -o ${docker_int} -j DOCKER 21 | iptables -A FORWARD -i ${docker_int} ! -o ${docker_int} -j ACCEPT 22 | iptables -A FORWARD -i ${docker_int} -o ${docker_int} -j ACCEPT 23 | fi 24 | } 25 | 26 | add_to_nat() { 27 | local docker_int=$1 28 | local subnet=$2 29 | 30 | iptables -t nat -A POSTROUTING -s ${subnet} ! -o ${docker_int} -j MASQUERADE 31 | iptables -t nat -A DOCKER -i ${docker_int} -j RETURN 32 | } 33 | 34 | add_to_docker_isolation() { 35 | local docker_int=$1 36 | 37 | iptables -A DOCKER-ISOLATION-STAGE-1 -i ${docker_int} ! -o ${docker_int} -j DOCKER-ISOLATION-STAGE-2 38 | iptables -A DOCKER-ISOLATION-STAGE-2 -o ${docker_int} -j DROP 39 | } 40 | 41 | DOCKER_INT="docker0" 42 | DOCKER_NETWORK="172.17.0.0/16" 43 | 44 | iptables-save | grep -v -- '-j DOCKER' | iptables-restore 45 | chain_exists DOCKER && iptables -X DOCKER 46 | chain_exists DOCKER nat && iptables -t nat -X DOCKER 47 | 48 | iptables -N DOCKER 49 | iptables -N DOCKER-ISOLATION-STAGE-1 50 | iptables -N DOCKER-ISOLATION-STAGE-2 51 | iptables -N DOCKER-USER 52 | 53 | iptables -t nat -N DOCKER 54 | 55 | iptables -A FORWARD -j DOCKER-USER 56 | iptables -A FORWARD -j DOCKER-ISOLATION-STAGE-1 57 | add_to_forward ${DOCKER_INT} 58 | 59 | iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER 60 | iptables -t nat -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER 61 | iptables -t nat -A POSTROUTING -s ${DOCKER_NETWORK} ! -o ${DOCKER_INT} -j MASQUERADE 62 | 63 | bridges=`docker network ls -q --filter='Driver=bridge'` 64 | 65 | for bridge in $bridges; do 66 | DOCKER_NET_INT=`docker network inspect -f '{{"'br-$bridge'" | or (index .Options "com.docker.network.bridge.name")}}' $bridge` 67 | subnet=`docker network inspect -f '{{(index .IPAM.Config 0).Subnet}}' $bridge` 68 | 69 | add_to_nat ${DOCKER_NET_INT} ${subnet} 70 | add_to_forward ${DOCKER_NET_INT} 71 | add_to_docker_isolation ${DOCKER_NET_INT} 72 | done 73 | 74 | containers=`docker ps -q` 75 | 76 | if [ `echo ${containers} | wc -c` -gt "1" ]; then 77 | for container in ${containers}; do 78 | netmode=`docker inspect -f "{{.HostConfig.NetworkMode}}" ${container}` 79 | if [ $netmode == "default" ]; then 80 | DOCKER_NET_INT=${DOCKER_INT} 81 | ipaddr=`docker inspect -f "{{.NetworkSettings.IPAddress}}" ${container}` 82 | else 83 | bridge=$(docker inspect -f "{{with index .NetworkSettings.Networks \"${netmode}\"}}{{.NetworkID}}{{end}}" ${container} | cut -c -12) 84 | DOCKER_NET_INT=`docker network inspect -f '{{"'br-$bridge'" | or (index .Options "com.docker.network.bridge.name")}}' $bridge` 85 | ipaddr=`docker inspect -f "{{with index .NetworkSettings.Networks \"${netmode}\"}}{{.IPAddress}}{{end}}" ${container}` 86 | fi 87 | 88 | rules=`docker port ${container} | sed 's/ //g'` 89 | 90 | if [ `echo ${rules} | wc -c` -gt "1" ]; then 91 | for rule in ${rules}; do 92 | src=`echo ${rule} | awk -F'->' '{ print $2 }'` 93 | dst=`echo ${rule} | awk -F'->' '{ print $1 }'` 94 | 95 | src_ip=`echo ${src} | awk -F':' '{ print $1 }'` 96 | src_port=`echo ${src} | awk -F':' '{ print $2 }'` 97 | 98 | dst_port=`echo ${dst} | awk -F'/' '{ print $1 }'` 99 | dst_proto=`echo ${dst} | awk -F'/' '{ print $2 }'` 100 | 101 | iptables -A DOCKER -d ${ipaddr}/32 ! -i ${DOCKER_NET_INT} -o ${DOCKER_NET_INT} -p ${dst_proto} -m ${dst_proto} --dport ${dst_port} -j ACCEPT 102 | 103 | iptables -t nat -A POSTROUTING -s ${ipaddr}/32 -d ${ipaddr}/32 -p ${dst_proto} -m ${dst_proto} --dport ${dst_port} -j MASQUERADE 104 | 105 | iptables_opt_src="" 106 | if [ ${src_ip} != "0.0.0.0" ]; then 107 | iptables_opt_src="-d ${src_ip}/32 " 108 | fi 109 | 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} 110 | done 111 | fi 112 | done 113 | fi 114 | 115 | iptables -A DOCKER-ISOLATION-STAGE-1 -j RETURN 116 | iptables -A DOCKER-ISOLATION-STAGE-2 -j RETURN 117 | iptables -A DOCKER-USER -j RETURN 118 | 119 | if [ `iptables -t nat -nvL DOCKER | grep ${DOCKER_INT} | wc -l` -eq 0 ]; then 120 | iptables -t nat -I DOCKER -i ${DOCKER_INT} -j RETURN 121 | fi 122 | --------------------------------------------------------------------------------