#!/bin/bash ## Depends lxc-scripts installed ## ## Install ## HOST_EXTERNAL_DEVICE=${HOST_EXTERNAL_DEVICE:-eth0} version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; } shorewall_candidate_version=$(echo $(apt-cache policy shorewall | grep "Candidate:" | cut -f 2 -d :)) ## Support for docker introduced in 5.0.6 if version_gt "$shorewall_candidate_version" 5.0.5; then apt-get install -y shorewall else ( VERSION="5.0.7.2-1" cd /tmp && wget http://ftp.fr.debian.org/debian/pool/main/s/shorewall-core/shorewall-core_${VERSION}_all.deb && wget http://ftp.fr.debian.org/debian/pool/main/s/shorewall/shorewall_${VERSION}_all.deb && dpkg -i shorewall-core_${VERSION}_all.deb shorewall_${VERSION}_all.deb && rm shorewall-core_${VERSION}_all.deb shorewall_${VERSION}_all.deb ) || { echo "Failed to install shorewall." exit 1 } fi case $(lsb_release -is) in Debian) case $(lsb_release -rs) in 10) ## we had trouble with ``nft`` shorewall update-alternatives --set iptables /usr/sbin/iptables-legacy ;; esac ;; esac apt-get install -y dnsutils /etc/shorewall/README Important notes gathered through time: # Shorewall duties on our host - block any access from outside to local ports if not mentionned explicitely in shorewall. - connect external ports to LXC (dockers has its own means) - This uses ``/var/lib/lxc/*/shorewall`` files - let mosh connect correctly - ensure a correct access from Host/LXC/Docker to server's services. For instance, an Host/LXC/Docker should be able to as if it was external: ``curl https://myhostwebsite``. This is called routeback and requires some special rules. # Shorewall restarting and cache Some process in shorewall seems to be using cache in some ways in recent version that implies that it won't take actions if files are not changed. A simple 'touch FILE' seems to be enough. Notice the 'Compiling' lines appearing in ``shorewall restart``. It's always good to double-check in ``iptables -nL`` that some rules actually seem to match your intention. Don't forget that ``iptables-save`` is probably the best way to get the full rules printed on stdout. # Debian, ovh kernels and iptables-nft Starting from Debian10, iptables by default uses iptables-nft... which works well with default debian kernel. OVH kernels DO NOT provide necessary kernel and we must: update-alternatives --set iptables /usr/sbin/iptables-legacy Note that transition is a little tricky because BOTH ways can have their tables simultaneously. Use ``iptables-nft -nL`` and ``iptables-legacy -nL`` to check. For now, we had little success to properly have the ``nft`` version working properly on debian kernel. So even on debian kernel, we switch here to iptables-legacy if on debian system. # Interaction with docker's iptables rules This is configured in ``shorewall.conf``, thanks to a simple:: DOCKER=Yes # Route back Be sure to check in /var/lib/lxc/*/shorewall definitions, they must include special stances (see in next section). On the side of shorewall, all network interface should be declared in ``/etc/shorewall/interfaces``. # lxc ``shorewall`` files Prefer the usage of ``ports`` files. If you insist on having a better control of rules per LXC, you can use ``shorewall`` files. They should be located in /var/lib/lxc/*/shorewall. This is a standard redirection from external host port 10022 to lxc's port 22, on port tcp:: DNAT net lan:%%IP%%:22 tcp 10022 #DNAT net lan:%%IP%%:22 udp 10022 Routeback (access of the same service from Host/LXC/Docker on the external address) is given by these additional rules:: DNAT lan lan:www:80 tcp 80 - %%HOST_INTERNET_IP%% DNAT lan lan:www:443 tcp 443 - %%HOST_INTERNET_IP%% DNAT fw lan:www:80 tcp 80 - %%HOST_INTERNET_IP%% DNAT fw lan:www:443 tcp 443 - %%HOST_INTERNET_IP%% # lxc ``ports`` files They should be located in /var/lib/lxc/*/ports. This is a standard redirection from external host port 10022 to lxc's port 22, on both tcp and udp:: 10022:22 ## Normal port # 10023:23 ## This is commented ! Note that comments are supported also. EOF cat < /etc/shorewall/zones fw firewall net ipv4 lan ipv4 EOF cat < /etc/shorewall/macro.Mosh ####################################################################################################### # DO NOT REMOVE THE FOLLOWING LINE ############################################################################################################################################################## #ACTION SOURCE DEST PROTO DPORT SPORT ORIGDEST RATE USER MARK CONNLIMITTIME HEADERS SWITCH HELPER # PARAM - - udp 60000:61000 EOF cat < /etc/shorewall/interfaces #ZONE INTERFACE BROADCAST OPTIONS net $HOST_EXTERNAL_DEVICE ## Uncomment to enable vpn setup #vpn tun0 detect ## All interfaces that require route back should be listed ## here: lan lxcbr0 - routeback BEGIN SHELL ifconfig=\$(ifconfig) echo "BEGIN DOCKER adding networks rules:" >&2 for docker_net in \$(docker network list -f driver=bridge -q); do gws=\$(docker network inspect "\$docker_net" --format "{{range .IPAM.Config}}{{.Gateway}}{{\"\n\"}}{{end}}") || continue for gw in \$gws; do if=\$(printf "%s" "\$ifconfig" | egrep "\$gw" -B 1 | head -n 1 | cut -f 1 -d " ") echo " lan \$if - routeback" >&2 echo "lan \$if - routeback" done done echo "END DOCKER" >&2 true END SHELL EOF cat < /etc/shorewall/policy #SOURCE DEST RULE LOG fw all ACCEPT lan all ACCEPT net all DROP info all all DROP info EOF cat < /etc/shorewall/rules SSH/ACCEPT net fw Ping/ACCEPT net fw Mosh(ACCEPT) net fw BEGIN SHELL host_ip="\$(/sbin/ifconfig $HOST_EXTERNAL_DEVICE 2> /dev/null | sed "s/^.*inet //g" | grep ^[0-9] | sed "s/ .*$//g")" for name in \$(lxc-ls-running); do ip=\$(dig +short A "\$name") [ -e "/var/lib/lxc/\$name/shorewall" ] && cat /var/lib/lxc/\$name/shorewall | sed -r "s/%%HOST_INTERNET_IP%%/\$host_ip/g" | sed -r "s/%%IP%%/\$ip/g" if [ -e "/var/lib/lxc/\$name/ports" ]; then for ports in \$(cat /var/lib/lxc/\$name/ports | sed -r 's/#.*\$//g'); do lxc_port=\${ports#*:} ext_port=\${ports%:*} echo "LXC \$name: redirection from \$host_ip:\$ext_port -> \$ip:\$lxc_port" >&2 for proto in tcp udp; do for zone in net lan fw; do echo "DNAT \$zone lan:\$ip:\$lxc_port \$proto \$ext_port - \$host_ip" done done done fi done true END SHELL EOF cat < /etc/shorewall/masq $HOST_EXTERNAL_DEVICE lxcbr0 EOF cat < /etc/shorewall/start ## correct a bug that prevent DHCP packet to be correctly sent between ## LXC, preventing them to receive an IP. . /etc/default/lxc if [ -d "/sys/class/net/\$LXC_BRIDGE" ] && [ "\$(cat /sys/class/net/\$LXC_BRIDGE/operstate)" = "up" ]; then source_file= if [ -e /etc/init/lxc-net.conf ]; then source_file=/etc/init/lxc-net.conf elif [ -e /usr/lib/x86_64-linux-gnu/lxc/lxc-net ]; then source_file=/usr/lib/x86_64-linux-gnu/lxc/lxc-net fi if [ "\$source_file" ]; then code=\$(egrep '^\s+iptables.*\s+-j\s+' \$source_file | grep -v '\-D' | sed -r 's/^\s+[^-]+/run_iptables /g') echo "Adding LXC rules:" echo "\$code" eval "\$code" fi fi EOF ## ## lxc-scripts ## [ -d "/opt/apps/lxc-scripts" ] || { echo "Error: required 'lxc-scripts' not installed." >&2 exit 1 } apt-get install -y moreutils ## needed because ``ts`` is used in this script ln -sf /opt/apps/lxc-scripts/etc/cron.d/lxc-shorewall-repair /etc/cron.d/lxc-shorewall-repair cat < /etc/logrotate.d/lxc-shorewall-repair /var/log/lxc-shorewall-repair.log { weekly missingok dateext dateyesterday dateformat _%Y-%m-%d extension .log rotate 52 compress delaycompress notifempty create 640 root root sharedscripts } EOF ## ## LOGS ## mkdir -p /var/log/shorewall chgrp syslog /var/log/shorewall chmod g+w /var/log/shorewall cat < /etc/rsyslog.d/shorewall.conf :msg, contains, "Shorewall:" /var/log/shorewall/main.log & ~ if \$msg contains 'net-fw DROP IN=' then { action(type="omfile" file="/var/log/shorewall/net-fw.log") stop } EOF cat < /etc/logrotate.d/shorewall /var/log/shorewall/init.log /var/log/shorewall/net-fw.log /var/log/shorewall/main.log { weekly missingok dateext dateyesterday dateformat _%Y-%m-%d extension .log rotate 52 compress delaycompress notifempty create 640 root root sharedscripts postrotate reload rsyslog >/dev/null 2>&1 || true endscript } EOF ## Init logs sed -ri 's%^(STARTUP_LOG=).*$%\1/var/log/shorewall/init.log%g' /etc/shorewall/shorewall.conf service rsyslog restart ## ## Final settings ## ## Activate support for docker sed -ri 's/^DOCKER=No$/DOCKER=Yes/g' /etc/shorewall/shorewall.conf sed -ri 's/^IP_FORWARDING=Keep$/IP_FORWARDING=On/g' /etc/shorewall/shorewall.conf