|
|
#!/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 </dev/null
## ## Configuration ##
cat <<EOF > /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 <<EOF > /etc/shorewall/zones fw firewall net ipv4 lan ipv4 EOF
cat <<EOF > /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 <<EOF > /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 <<EOF > /etc/shorewall/policy #SOURCE DEST RULE LOG
fw all ACCEPT lan all ACCEPT net all DROP info all all DROP info EOF
cat <<EOF > /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 <<EOF > /etc/shorewall/masq $HOST_EXTERNAL_DEVICE lxcbr0 EOF
cat <<EOF > /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 <<EOF > /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 <<EOF > /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 <<EOF > /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
|