372 lines
9.5 KiB

  1. #!/bin/bash
  2. ## Depends lxc-scripts installed
  3. ##
  4. ## Install
  5. ##
  6. HOST_EXTERNAL_DEVICE=${HOST_EXTERNAL_DEVICE:-eth0}
  7. version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
  8. shorewall_candidate_version=$(echo $(apt-cache policy shorewall | grep "Candidate:" | cut -f 2 -d :))
  9. ## Support for docker introduced in 5.0.6
  10. if version_gt "$shorewall_candidate_version" 5.0.5; then
  11. apt-get install -y shorewall
  12. else
  13. (
  14. VERSION="5.0.7.2-1"
  15. cd /tmp &&
  16. wget http://ftp.fr.debian.org/debian/pool/main/s/shorewall-core/shorewall-core_${VERSION}_all.deb &&
  17. wget http://ftp.fr.debian.org/debian/pool/main/s/shorewall/shorewall_${VERSION}_all.deb &&
  18. dpkg -i shorewall-core_${VERSION}_all.deb shorewall_${VERSION}_all.deb &&
  19. rm shorewall-core_${VERSION}_all.deb shorewall_${VERSION}_all.deb
  20. ) || {
  21. echo "Failed to install shorewall."
  22. exit 1
  23. }
  24. fi
  25. case $(lsb_release -is) in
  26. Debian)
  27. case $(lsb_release -rs) in
  28. 10)
  29. ## we had trouble with ``nft`` shorewall
  30. update-alternatives --set iptables /usr/sbin/iptables-legacy
  31. ;;
  32. esac
  33. ;;
  34. esac
  35. apt-get install -y dnsutils </dev/null
  36. ##
  37. ## Configuration
  38. ##
  39. cat <<EOF > /etc/shorewall/README
  40. Important notes gathered through time:
  41. # Shorewall duties on our host
  42. - block any access from outside to local ports if not mentionned
  43. explicitely in shorewall.
  44. - connect external ports to LXC (dockers has its own means)
  45. - This uses ``/var/lib/lxc/*/shorewall`` files
  46. - let mosh connect correctly
  47. - ensure a correct access from Host/LXC/Docker to server's services.
  48. For instance, an Host/LXC/Docker should be able to as if it was
  49. external: ``curl https://myhostwebsite``. This is called routeback
  50. and requires some special rules.
  51. # Shorewall restarting and cache
  52. Some process in shorewall seems to be using cache in some ways in
  53. recent version that implies that it won't take actions if files are
  54. not changed. A simple 'touch FILE' seems to be enough. Notice the
  55. 'Compiling' lines appearing in ``shorewall restart``.
  56. It's always good to double-check in ``iptables -nL`` that some rules
  57. actually seem to match your intention.
  58. Don't forget that ``iptables-save`` is probably the best way to get
  59. the full rules printed on stdout.
  60. # Debian, ovh kernels and iptables-nft
  61. Starting from Debian10, iptables by default uses iptables-nft... which
  62. works well with default debian kernel. OVH kernels DO NOT provide
  63. necessary kernel and we must:
  64. update-alternatives --set iptables /usr/sbin/iptables-legacy
  65. Note that transition is a little tricky because BOTH ways can have
  66. their tables simultaneously. Use ``iptables-nft -nL`` and
  67. ``iptables-legacy -nL`` to check.
  68. For now, we had little success to properly have the ``nft`` version
  69. working properly on debian kernel. So even on debian kernel, we switch
  70. here to iptables-legacy if on debian system.
  71. # Interaction with docker's iptables rules
  72. This is configured in ``shorewall.conf``, thanks to a simple::
  73. DOCKER=Yes
  74. # Route back
  75. Be sure to check in /var/lib/lxc/*/shorewall definitions, they
  76. must include special stances (see in next section).
  77. On the side of shorewall, all network interface should be declared in
  78. ``/etc/shorewall/interfaces``.
  79. # lxc ``shorewall`` files
  80. Prefer the usage of ``ports`` files. If you insist on having a better
  81. control of rules per LXC, you can use ``shorewall`` files.
  82. They should be located in /var/lib/lxc/*/shorewall. This is a standard
  83. redirection from external host port 10022 to lxc's port 22, on port
  84. tcp::
  85. DNAT net lan:%%IP%%:22 tcp 10022
  86. #DNAT net lan:%%IP%%:22 udp 10022
  87. Routeback (access of the same service from Host/LXC/Docker on the external
  88. address) is given by these additional rules::
  89. DNAT lan lan:www:80 tcp 80 - %%HOST_INTERNET_IP%%
  90. DNAT lan lan:www:443 tcp 443 - %%HOST_INTERNET_IP%%
  91. DNAT fw lan:www:80 tcp 80 - %%HOST_INTERNET_IP%%
  92. DNAT fw lan:www:443 tcp 443 - %%HOST_INTERNET_IP%%
  93. # lxc ``ports`` files
  94. They should be located in /var/lib/lxc/*/ports. This is a standard
  95. redirection from external host port 10022 to lxc's port 22, on both
  96. tcp and udp::
  97. 10022:22 ## Normal port
  98. # 10023:23 ## This is commented !
  99. Note that comments are supported also.
  100. EOF
  101. cat <<EOF > /etc/shorewall/zones
  102. fw firewall
  103. net ipv4
  104. lan ipv4
  105. EOF
  106. cat <<EOF > /etc/shorewall/macro.Mosh
  107. #######################################################################################################
  108. # DO NOT REMOVE THE FOLLOWING LINE
  109. ##############################################################################################################################################################
  110. #ACTION SOURCE DEST PROTO DPORT SPORT ORIGDEST RATE USER MARK CONNLIMITTIME HEADERS SWITCH HELPER
  111. #
  112. PARAM - - udp 60000:61000
  113. EOF
  114. cat <<EOF > /etc/shorewall/interfaces
  115. #ZONE INTERFACE BROADCAST OPTIONS
  116. net $HOST_EXTERNAL_DEVICE
  117. ## Uncomment to enable vpn setup
  118. #vpn tun0 detect
  119. ## All interfaces that require route back should be listed
  120. ## here:
  121. lan lxcbr0 - routeback
  122. BEGIN SHELL
  123. ifconfig=\$(ifconfig)
  124. echo "BEGIN DOCKER adding networks rules:" >&2
  125. for docker_net in \$(docker network list -f driver=bridge -q); do
  126. gws=\$(docker network inspect "\$docker_net" --format "{{range .IPAM.Config}}{{.Gateway}}{{\"\n\"}}{{end}}") || continue
  127. for gw in \$gws; do
  128. if=\$(printf "%s" "\$ifconfig" | egrep "\$gw" -B 1 | head -n 1 | cut -f 1 -d " ")
  129. echo " lan \$if - routeback" >&2
  130. echo "lan \$if - routeback"
  131. done
  132. done
  133. echo "END DOCKER" >&2
  134. true
  135. END SHELL
  136. EOF
  137. cat <<EOF > /etc/shorewall/policy
  138. #SOURCE DEST RULE LOG
  139. fw all ACCEPT
  140. lan all ACCEPT
  141. net all DROP info
  142. all all DROP info
  143. EOF
  144. cat <<EOF > /etc/shorewall/rules
  145. SSH/ACCEPT net fw
  146. Ping/ACCEPT net fw
  147. Mosh(ACCEPT) net fw
  148. BEGIN SHELL
  149. host_ip="\$(/sbin/ifconfig $HOST_EXTERNAL_DEVICE 2> /dev/null | sed "s/^.*inet //g" | grep ^[0-9] | sed "s/ .*$//g")"
  150. for name in \$(lxc-ls-running); do
  151. ip=\$(dig +short A "\$name")
  152. [ -e "/var/lib/lxc/\$name/shorewall" ] &&
  153. cat /var/lib/lxc/\$name/shorewall |
  154. sed -r "s/%%HOST_INTERNET_IP%%/\$host_ip/g" |
  155. sed -r "s/%%IP%%/\$ip/g"
  156. if [ -e "/var/lib/lxc/\$name/ports" ]; then
  157. for ports in \$(cat /var/lib/lxc/\$name/ports | sed -r 's/#.*\$//g'); do
  158. lxc_port=\${ports#*:}
  159. ext_port=\${ports%:*}
  160. echo "LXC \$name: redirection from \$host_ip:\$ext_port -> \$ip:\$lxc_port" >&2
  161. for proto in tcp udp; do
  162. for zone in net lan fw; do
  163. echo "DNAT \$zone lan:\$ip:\$lxc_port \$proto \$ext_port - \$host_ip"
  164. done
  165. done
  166. done
  167. fi
  168. done
  169. true
  170. END SHELL
  171. EOF
  172. cat <<EOF > /etc/shorewall/masq
  173. $HOST_EXTERNAL_DEVICE lxcbr0
  174. EOF
  175. cat <<EOF > /etc/shorewall/start
  176. ## correct a bug that prevent DHCP packet to be correctly sent between
  177. ## LXC, preventing them to receive an IP.
  178. . /etc/default/lxc
  179. if [ -d "/sys/class/net/\$LXC_BRIDGE" ] && [ "\$(cat /sys/class/net/\$LXC_BRIDGE/operstate)" = "up" ]; then
  180. source_file=
  181. if [ -e /etc/init/lxc-net.conf ]; then
  182. source_file=/etc/init/lxc-net.conf
  183. elif [ -e /usr/lib/x86_64-linux-gnu/lxc/lxc-net ]; then
  184. source_file=/usr/lib/x86_64-linux-gnu/lxc/lxc-net
  185. fi
  186. if [ "\$source_file" ]; then
  187. code=\$(egrep '^\s+iptables.*\s+-j\s+' \$source_file | grep -v '\-D' | sed -r 's/^\s+[^-]+/run_iptables /g')
  188. echo "Adding LXC rules:"
  189. echo "\$code"
  190. eval "\$code"
  191. fi
  192. fi
  193. EOF
  194. ##
  195. ## lxc-scripts
  196. ##
  197. [ -d "/opt/apps/lxc-scripts" ] || {
  198. echo "Error: required 'lxc-scripts' not installed." >&2
  199. exit 1
  200. }
  201. apt-get install -y moreutils ## needed because ``ts`` is used in this script
  202. ln -sf /opt/apps/lxc-scripts/etc/cron.d/lxc-shorewall-repair /etc/cron.d/lxc-shorewall-repair
  203. cat <<EOF > /etc/logrotate.d/lxc-shorewall-repair
  204. /var/log/lxc-shorewall-repair.log {
  205. weekly
  206. missingok
  207. dateext
  208. dateyesterday
  209. dateformat _%Y-%m-%d
  210. extension .log
  211. rotate 52
  212. compress
  213. delaycompress
  214. notifempty
  215. create 640 root root
  216. sharedscripts
  217. }
  218. EOF
  219. ##
  220. ## LOGS
  221. ##
  222. mkdir -p /var/log/shorewall
  223. chgrp syslog /var/log/shorewall
  224. chmod g+w /var/log/shorewall
  225. cat <<EOF > /etc/rsyslog.d/shorewall.conf
  226. :msg, contains, "Shorewall:" /var/log/shorewall/main.log
  227. & ~
  228. if \$msg contains 'net-fw DROP IN=' then {
  229. action(type="omfile" file="/var/log/shorewall/net-fw.log")
  230. stop
  231. }
  232. EOF
  233. cat <<EOF > /etc/logrotate.d/shorewall
  234. /var/log/shorewall/init.log
  235. /var/log/shorewall/net-fw.log
  236. /var/log/shorewall/main.log
  237. {
  238. weekly
  239. missingok
  240. dateext
  241. dateyesterday
  242. dateformat _%Y-%m-%d
  243. extension .log
  244. rotate 52
  245. compress
  246. delaycompress
  247. notifempty
  248. create 640 root root
  249. sharedscripts
  250. postrotate
  251. reload rsyslog >/dev/null 2>&1 || true
  252. endscript
  253. }
  254. EOF
  255. ## Init logs
  256. sed -ri 's%^(STARTUP_LOG=).*$%\1/var/log/shorewall/init.log%g' /etc/shorewall/shorewall.conf
  257. service rsyslog restart
  258. ##
  259. ## Final settings
  260. ##
  261. ## Activate support for docker
  262. sed -ri 's/^DOCKER=No$/DOCKER=Yes/g' /etc/shorewall/shorewall.conf
  263. sed -ri 's/^IP_FORWARDING=Keep$/IP_FORWARDING=On/g' /etc/shorewall/shorewall.conf