mirror of
https://github.com/chaifeng/ufw-docker.git
synced 2025-07-03 17:26:12 +02:00
Add IPv6 network support and --docker-subnets
option for install/check
- Add support for IPv6 networks in firewall rule generation and validation. - Add --docker-subnets [SUBNET1 SUBNET2 ...] option to `ufw-docker install` and `ufw-docker check`. - When used without arguments, automatically detects and applies all Docker network subnets. - When given subnet arguments, applies firewall rules only to specified subnets (supports multiple subnets, including non-Docker-managed networks). - If not specified, falls back to default RFC1918 IPv4 and fd00::/8 IPv6 subnets. - Improve help output with detailed examples and usage guidance.
This commit is contained in:
parent
e9a9f13095
commit
168fc59905
5 changed files with 512 additions and 152 deletions
60
README.md
60
README.md
|
@ -236,6 +236,36 @@ This command does the following things:
|
||||||
- Back up the file `/etc/ufw/after.rules`
|
- Back up the file `/etc/ufw/after.rules`
|
||||||
- Append the rules of UFW and Docker at the end of the file
|
- Append the rules of UFW and Docker at the end of the file
|
||||||
|
|
||||||
|
#### IPv6 support
|
||||||
|
|
||||||
|
`ufw-docker` also supports IPv6 networks and will update `/etc/ufw/after6.rules` when necessary.
|
||||||
|
|
||||||
|
### Using the `--docker-subnets` option
|
||||||
|
|
||||||
|
You can use the `--docker-subnets` option to customize which subnets will be allowed to communicate with Docker containers.
|
||||||
|
This option applies to both IPv4 and IPv6 networks.
|
||||||
|
|
||||||
|
* If the option is **not provided**, only standard private LAN subnets will be used
|
||||||
|
(IPv4: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`; IPv6: `fd00::/8`)
|
||||||
|
* If `--docker-subnets` is given **without any arguments**, all Docker network subnets will be detected and used automatically.
|
||||||
|
**Note:** If you add or remove Docker networks, you need to run `ufw-docker install --docker-subnets` again to update the firewall rules according to the latest network configuration.
|
||||||
|
* If one or more subnets are specified, only these subnets will be used (you can list multiple subnets, separated by spaces; each should be in CIDR format).
|
||||||
|
The subnets can include networks not managed by Docker itself.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
# Use default private LAN subnets (IPv4: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16; IPv6: fd00::/8)
|
||||||
|
ufw-docker install
|
||||||
|
|
||||||
|
# Auto-detect and use all Docker network subnets (both IPv4 and IPv6)
|
||||||
|
ufw-docker install --docker-subnets
|
||||||
|
|
||||||
|
# Only allow these specified subnets to communicate with Docker containers
|
||||||
|
ufw-docker install --docker-subnets 192.168.207.0/24 10.207.0.0/16 fd00:cf::/64
|
||||||
|
|
||||||
|
|
||||||
|
You can use the same options with `ufw-docker check` to preview the changes before applying them.
|
||||||
|
|
||||||
#### Install for Docker Swarm mode
|
#### Install for Docker Swarm mode
|
||||||
|
|
||||||
We can only use this script on manager nodes to manage firewall rules when using in Swarm mode.
|
We can only use this script on manager nodes to manage firewall rules when using in Swarm mode.
|
||||||
|
@ -520,7 +550,8 @@ UFW 是 Ubuntu 上很流行的一个 iptables 前端,可以非常方便的管
|
||||||
|
|
||||||
### 支持 IPv6
|
### 支持 IPv6
|
||||||
|
|
||||||
[Enable IPv6 support](https://forums.docker.com/t/docker-user-chain-for-ip6tables/133961/3) in Docker by specifying ULA range (RFC 4193) in `/etc/docker/daemon.json`
|
要让 Docker Engine [启用 IPv6 的支持](https://forums.docker.com/t/docker-user-chain-for-ip6tables/133961/3). 你需要在 `/etc/docker/daemon.json` 文件中启用相关设置,并分配一个 ULA(唯一本地地址,RFC 4193)地址段作为 IPv6 网络范围。
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"experimental": true,
|
"experimental": true,
|
||||||
|
@ -556,6 +587,33 @@ UFW 是 Ubuntu 上很流行的一个 iptables 前端,可以非常方便的管
|
||||||
- 备份文件 `/etc/ufw/after.rules`
|
- 备份文件 `/etc/ufw/after.rules`
|
||||||
- 把 UFW 和 Docker 的相关规则添加到文件 `after.rules` 的末尾
|
- 把 UFW 和 Docker 的相关规则添加到文件 `after.rules` 的末尾
|
||||||
|
|
||||||
|
#### IPv6 支持
|
||||||
|
|
||||||
|
`ufw-docker` 也支持 IPv6 网络,并会在需要时自动更新 `/etc/ufw/after6.rules` 文件。
|
||||||
|
|
||||||
|
### 使用 `--docker-subnets` 选项
|
||||||
|
|
||||||
|
你可以使用 `--docker-subnets` 选项,自定义允许与 Docker 容器通信的子网。
|
||||||
|
该选项同时适用于 IPv4 和 IPv6 网络。
|
||||||
|
|
||||||
|
* 如果**未指定**该选项,只会使用标准的私有局域网子网
|
||||||
|
(IPv4:`10.0.0.0/8`、`172.16.0.0/12`、`192.168.0.0/16`;IPv6:`fd00::/8`)
|
||||||
|
* 如果指定了 `--docker-subnets` 但**未带参数**,会自动检测并使用所有 Docker 网络的子网。
|
||||||
|
**注意:** 如果你对 Docker 网络进行了新增或删除操作,需要重新运行 `ufw-docker install --docker-subnets`,以便根据最新的网络配置更新防火墙规则。
|
||||||
|
* 如果指定了一个或多个子网,则只会使用这些子网(你可以用空格分隔多个子网,每个子网应为 CIDR 格式)。
|
||||||
|
这些子网可以包括非 Docker 管理的网络。
|
||||||
|
|
||||||
|
#### 示例
|
||||||
|
|
||||||
|
# 使用默认的私有局域网子网(IPv4:10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16;IPv6:fd00::/8)
|
||||||
|
ufw-docker install
|
||||||
|
|
||||||
|
# 自动检测并使用所有 Docker 网络的子网(同时支持 IPv4 和 IPv6)
|
||||||
|
ufw-docker install --docker-subnets
|
||||||
|
|
||||||
|
# 仅允许这些指定的子网与 Docker 容器通信
|
||||||
|
ufw-docker install --docker-subnets 192.168.207.0/24 10.207.0.0/16 fd00:cf::/64
|
||||||
|
|
||||||
#### 为 Docker Swarm 环境安装
|
#### 为 Docker Swarm 环境安装
|
||||||
|
|
||||||
仅仅可以在管理节点上使用 `ufw-docker` 这个脚本来管理防火墙规则。
|
仅仅可以在管理节点上使用 `ufw-docker` 这个脚本来管理防火墙规则。
|
||||||
|
|
170
Vagrantfile
vendored
170
Vagrantfile
vendored
|
@ -27,14 +27,35 @@ Vagrant.configure('2') do |config|
|
||||||
end
|
end
|
||||||
|
|
||||||
ip_prefix="192.168.56"
|
ip_prefix="192.168.56"
|
||||||
|
ip6_prefix="fd00:a:b"
|
||||||
|
worker_count=1
|
||||||
|
|
||||||
|
def env_true?(env_name)
|
||||||
|
value = ENV[env_name] || 'false'
|
||||||
|
true_values = %w[true yes on 1]
|
||||||
|
down = value.strip.downcase
|
||||||
|
return 'true' if true_values.include?(down)
|
||||||
|
'false'
|
||||||
|
end
|
||||||
|
|
||||||
|
def env_true_str?(env_name)
|
||||||
|
env_true?(env_name).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
config.vm.provision 'setup', preserve_order: true, type: 'shell', privileged: false, inline: <<-SHELL
|
||||||
|
byobu-ctrl-a screen
|
||||||
|
SHELL
|
||||||
|
|
||||||
config.vm.provision 'docker-daemon-config', type: 'shell', inline: <<-SHELL
|
config.vm.provision 'docker-daemon-config', type: 'shell', inline: <<-SHELL
|
||||||
set -eu
|
set -eu
|
||||||
if [[ ! -f /etc/docker/daemon.json ]]; then
|
[[ -f /etc/profile.d/editor.sh ]] || echo 'export EDITOR=vim' > /etc/profile.d/editor.sh
|
||||||
|
if [[ "$(hostname)" = @(master|node?) && ! -f /etc/docker/daemon.json ]]; then
|
||||||
echo '{' >> /etc/docker/daemon.json
|
echo '{' >> /etc/docker/daemon.json
|
||||||
echo ' "insecure-registries": ["localhost:5000", "#{ip_prefix}.130:5000"]' >> /etc/docker/daemon.json
|
echo ' "insecure-registries": ["localhost:5000", "#{ip_prefix}.130:5000"]' >> /etc/docker/daemon.json
|
||||||
[[ -n "#{ENV['DOCKER_REGISTRY_MIRROR']}" ]] &&
|
[[ -n "#{ENV['DOCKER_REGISTRY_MIRROR']}" ]] &&
|
||||||
echo ' , "registry-mirrors": ["#{ENV['DOCKER_REGISTRY_MIRROR']}"]' >> /etc/docker/daemon.json
|
echo ' , "registry-mirrors": ["#{ENV['DOCKER_REGISTRY_MIRROR']}"]' >> /etc/docker/daemon.json
|
||||||
|
#{env_true_str?('ENABLE_DOCKER_IPV6')} &&
|
||||||
|
echo ' ,"ip6tables": true, "ipv6": true, "fixed-cidr-v6": "#{ip6_prefix}:deaf::/64"' >> /etc/docker/daemon.json
|
||||||
echo '}' >> /etc/docker/daemon.json
|
echo '}' >> /etc/docker/daemon.json
|
||||||
if type systemctl &>/dev/null; then
|
if type systemctl &>/dev/null; then
|
||||||
systemctl restart docker
|
systemctl restart docker
|
||||||
|
@ -44,27 +65,30 @@ Vagrant.configure('2') do |config|
|
||||||
fi
|
fi
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
config.vm.provision 'ufw-docker', type: 'shell', inline: <<-SHELL
|
config.vm.provision 'ufw-docker', preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -xeuo pipefail
|
||||||
export DEBUG=true
|
export DEBUG=true
|
||||||
lsb_release -is | grep -Fi ubuntu
|
lsb_release -is | grep -Fi ubuntu
|
||||||
/vagrant/ufw-docker check || {
|
|
||||||
|
declare -a subnets=(--docker-subnets 192.168.56.128/28 10.0.0.0/8 172.16.0.0/12)
|
||||||
|
#{env_true_str?('ENABLE_DOCKER_IPV6')} &&
|
||||||
|
subnets+=(fd00:a:b:deaf::/64 fd05:8f23:c937:1::/64 fd05:8f23:c937:2::/64 fd05:8f23:c937::/64)
|
||||||
|
if [[ "$(hostname)" = @(master|node?) ]]; then
|
||||||
|
/vagrant/ufw-docker check "${subnets[@]-}" >/dev/null 2>&1 || {
|
||||||
ufw allow OpenSSH
|
ufw allow OpenSSH
|
||||||
ufw allow from #{ip_prefix}.128/28 to any
|
ufw allow from #{ip_prefix}.128/28 to any
|
||||||
|
#{env_true_str?('ENABLE_DOCKER_IPV6')} &&
|
||||||
|
ufw allow from #{ip6_prefix}:0:cafe::/80 to any
|
||||||
|
|
||||||
yes | ufw enable || true
|
yes | ufw enable || true
|
||||||
ufw status | grep '^Status: active'
|
ufw status | grep '^Status: active'
|
||||||
|
|
||||||
/vagrant/ufw-docker install
|
/vagrant/ufw-docker install "${subnets[@]-}"
|
||||||
|
|
||||||
sed -i -e 's,192\.168\.0\.0/16,#{ip_prefix}.128/28,' /etc/ufw/after.rules
|
|
||||||
|
|
||||||
systemctl restart ufw
|
systemctl restart ufw
|
||||||
|
|
||||||
[[ -L /usr/local/bin/ufw-docker ]] || ln -s /vagrant/ufw-docker /usr/local/bin/
|
|
||||||
|
|
||||||
iptables -I DOCKER-USER 4 -p udp -j LOG --log-prefix '[UFW DOCKER] '
|
|
||||||
}
|
}
|
||||||
|
[[ -L /usr/local/bin/ufw-docker ]] || ln -s /vagrant/ufw-docker /usr/local/bin/
|
||||||
|
fi
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
private_registry="#{ip_prefix}.130:5000"
|
private_registry="#{ip_prefix}.130:5000"
|
||||||
|
@ -73,9 +97,13 @@ Vagrant.configure('2') do |config|
|
||||||
master_ip_address = "#{ip_prefix}.130"
|
master_ip_address = "#{ip_prefix}.130"
|
||||||
master.vm.hostname = "master"
|
master.vm.hostname = "master"
|
||||||
master.vm.network "private_network", ip: "#{master_ip_address}"
|
master.vm.network "private_network", ip: "#{master_ip_address}"
|
||||||
|
if env_true?('ENABLE_DOCKER_IPV6')
|
||||||
|
master.vm.network "private_network", ip: "#{ip6_prefix}:0:cafe::130", type: "static", netmast: 64, auto_config: true
|
||||||
|
end
|
||||||
|
|
||||||
master.vm.provision "unit-testing", preserve_order: true, type: 'shell', inline: <<-SHELL
|
master.vm.provision "unit-testing", preserve_order: true, type: 'shell', privileged: false, inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
[[ -n "#{ENV['DISABLE_UNIT_TESTING']}" ]] ||
|
||||||
/vagrant/test.sh
|
/vagrant/test.sh
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
|
@ -103,7 +131,7 @@ Vagrant.configure('2') do |config|
|
||||||
echo "Defaults env_keep += DEBUG" >> /etc/sudoers.d/98_ufw-docker
|
echo "Defaults env_keep += DEBUG" >> /etc/sudoers.d/98_ufw-docker
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
master.vm.provision "swarm-init", preserve_order: true, type: 'shell', inline: <<-SHELL
|
master.vm.provision "swarm-init", preserve_order: true, type: 'shell', privileged: false, inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
docker info | fgrep 'Swarm: active' && exit 0
|
docker info | fgrep 'Swarm: active' && exit 0
|
||||||
|
|
||||||
|
@ -111,8 +139,8 @@ Vagrant.configure('2') do |config|
|
||||||
docker swarm join-token worker --quiet > /vagrant/.vagrant/docker-join-token
|
docker swarm join-token worker --quiet > /vagrant/.vagrant/docker-join-token
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
master.vm.provision "build-webapp", preserve_order: true, type: 'shell', inline: <<-SHELL
|
master.vm.provision "build-webapp", preserve_order: true, type: 'shell', privileged: false, inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -xeuo pipefail
|
||||||
docker build -t #{private_registry}/chaifeng/hostname-webapp - <<\\DOCKERFILE
|
docker build -t #{private_registry}/chaifeng/hostname-webapp - <<\\DOCKERFILE
|
||||||
FROM httpd:alpine
|
FROM httpd:alpine
|
||||||
|
|
||||||
|
@ -130,7 +158,7 @@ DOCKERFILE
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
master.vm.provision "local-webapp", preserve_order: true, type: 'shell', inline: <<-SHELL
|
master.vm.provision "local-webapp", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -xeuo pipefail
|
||||||
for name in public:18080 local:8000; do
|
for name in public:18080 local:8000; do
|
||||||
webapp="${name%:*}_webapp"
|
webapp="${name%:*}_webapp"
|
||||||
port="${name#*:}"
|
port="${name#*:}"
|
||||||
|
@ -144,12 +172,16 @@ DOCKERFILE
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
master.vm.provision "multiple-network", preserve_order: true, type: 'shell', inline: <<-SHELL
|
master.vm.provision "multiple-network", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -xeuo pipefail
|
||||||
|
declare -a docker_opts=()
|
||||||
|
|
||||||
if ! docker network ls | grep -F foo-internal; then
|
if ! docker network ls | grep -F foo-internal; then
|
||||||
docker network create --internal foo-internal
|
! #{env_true_str?('ENABLE_DOCKER_IPV6')} || docker_opts=(--ipv6 --subnet fd05:8f23:c937:1::/64)
|
||||||
|
docker network create --internal "${docker_opts[@]}" foo-internal
|
||||||
fi
|
fi
|
||||||
if ! docker network ls | grep -F bar-external; then
|
if ! docker network ls | grep -F bar-external; then
|
||||||
docker network create bar-external
|
! #{env_true_str?('ENABLE_DOCKER_IPV6')} || docker_opts=(--ipv6 --subnet fd05:8f23:c937:2::/64)
|
||||||
|
docker network create "${docker_opts[@]}" bar-external
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for app in internal-multinet-app:7000 public-multinet-app:17070; do
|
for app in internal-multinet-app:7000 public-multinet-app:17070; do
|
||||||
|
@ -167,33 +199,42 @@ DOCKERFILE
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
master.vm.provision "swarm-webapp", preserve_order: true, type: 'shell', inline: <<-SHELL
|
master.vm.provision "swarm-webapp", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -xeuo pipefail
|
||||||
|
declare -a docker_opts=()
|
||||||
|
if #{env_true_str?('ENABLE_DOCKER_IPV6')}; then
|
||||||
|
docker inspect ip6net >/dev/null ||
|
||||||
|
docker network create --driver overlay --ipv6 ip6net
|
||||||
|
docker_opts+=(--network ip6net)
|
||||||
|
fi
|
||||||
for name in public:29090 local:9000; do
|
for name in public:29090 local:9000; do
|
||||||
webapp="${name%:*}_service"
|
webapp="${name%:*}_service"
|
||||||
port="${name#*:}"
|
port="${name#*:}"
|
||||||
if docker service inspect "$webapp" &>/dev/null; then docker service rm "$webapp"; fi
|
if docker service inspect "$webapp" &>/dev/null; then docker service rm "$webapp"; fi
|
||||||
docker service create --name "$webapp" \
|
docker service create --name "$webapp" "${docker_opts[@]}" \
|
||||||
--publish "${port}:80" --env name="$webapp" --replicas 3 #{private_registry}/chaifeng/hostname-webapp
|
--publish "${port}:80" --env name="$webapp" --replicas #{worker_count} #{private_registry}/chaifeng/hostname-webapp
|
||||||
done
|
done
|
||||||
|
|
||||||
ufw-docker service allow public_service 80/tcp
|
ufw-docker service allow public_service 80/tcp
|
||||||
|
|
||||||
docker service inspect "public_multiport" ||
|
docker service inspect "public_multiport" ||
|
||||||
docker service create --name "public_multiport" \
|
docker service create --name "public_multiport" "${docker_opts[@]}" \
|
||||||
--publish "40080:80" --publish "47000:7000" --publish "48080:8080" \
|
--publish "40080:80" --publish "47000:7000" --publish "48080:8080" \
|
||||||
--env name="public_multiport" --replicas 3 #{private_registry}/chaifeng/hostname-webapp
|
--env name="public_multiport" --replicas #{worker_count + 1} #{private_registry}/chaifeng/hostname-webapp
|
||||||
|
|
||||||
ufw-docker service allow public_multiport 80/tcp
|
ufw-docker service allow public_multiport 80/tcp
|
||||||
ufw-docker service allow public_multiport 8080/tcp
|
ufw-docker service allow public_multiport 8080/tcp
|
||||||
SHELL
|
SHELL
|
||||||
end
|
end
|
||||||
|
|
||||||
1.upto 1 do |ip|
|
1.upto worker_count do |ip|
|
||||||
config.vm.define "node#{ip}" do | node |
|
config.vm.define "node#{ip}" do | node |
|
||||||
node.vm.hostname = "node#{ip}"
|
node.vm.hostname = "node#{ip}"
|
||||||
node.vm.network "private_network", ip: "#{ip_prefix}.#{ 130 + ip }"
|
node.vm.network "private_network", ip: "#{ip_prefix}.#{ 130 + ip }"
|
||||||
|
if env_true?('ENABLE_DOCKER_IPV6')
|
||||||
|
node.vm.network "private_network", ip: "#{ip6_prefix}:0:cafe::#{ 130 + ip }", type: "static", netmast: 64, auto_config: true
|
||||||
|
end
|
||||||
|
|
||||||
node.vm.provision "swarm-join", preserve_order: true, type: 'shell', inline: <<-SHELL
|
node.vm.provision "node#{ip}-swarm-join", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
docker info | fgrep 'Swarm: active' && exit 0
|
docker info | fgrep 'Swarm: active' && exit 0
|
||||||
|
|
||||||
|
@ -206,38 +247,89 @@ DOCKERFILE
|
||||||
config.vm.define "node-internal" do |node|
|
config.vm.define "node-internal" do |node|
|
||||||
node.vm.hostname = "node-internal"
|
node.vm.hostname = "node-internal"
|
||||||
node.vm.network "private_network", ip: "#{ip_prefix}.142"
|
node.vm.network "private_network", ip: "#{ip_prefix}.142"
|
||||||
|
if env_true?('ENABLE_DOCKER_IPV6')
|
||||||
|
node.vm.network "private_network", ip: "#{ip6_prefix}:0:cafe::142", type: "static", netmast: 64, auto_config: true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
config.vm.define "external" do |external|
|
config.vm.define "external" do |external|
|
||||||
external.vm.hostname = "external"
|
external.vm.hostname = "external"
|
||||||
external.vm.network "private_network", ip: "#{ip_prefix}.127"
|
external.vm.network "private_network", ip: "#{ip_prefix}.127"
|
||||||
|
if env_true?('ENABLE_DOCKER_IPV6')
|
||||||
|
external.vm.network "private_network", ip: "#{ip6_prefix}:0:eeee::127", type: "static", netmast: 64, auto_config: true
|
||||||
|
end
|
||||||
|
|
||||||
external.vm.provision "testing", preserve_order: true, type: 'shell', inline: <<-SHELL
|
external.vm.provision "testing", preserve_order: true, type: 'shell', privileged: false, inline: <<-SHELL
|
||||||
set -euo pipefail
|
set -xuo pipefail
|
||||||
set -x
|
error_count=0
|
||||||
server="http://#{ip_prefix}.130"
|
|
||||||
function test-webapp() {
|
function test-webapp() {
|
||||||
if timeout 3 curl --silent "$@"
|
local actual=""
|
||||||
then echo "Success: $*"
|
|
||||||
else echo "Cannot visit: $*"; return 1
|
if [[ "$#" -eq 2 ]]; then
|
||||||
|
local expect_fail='!'
|
||||||
|
url="$2"
|
||||||
|
else
|
||||||
|
url="$1"
|
||||||
fi
|
fi
|
||||||
}
|
|
||||||
|
timeout 3 curl --silent "$url" || actual='!'
|
||||||
|
|
||||||
|
if [[ "${expect_fail:-}" = "${actual}" ]]; then
|
||||||
|
echo "OK: '$url' is ${expect_fail:+NOT }accessible${expect_fail:+ (should NOT be)}."
|
||||||
|
else
|
||||||
|
echo "FAIL: '$url' is ${expect_fail:+}${expect_fail:-NOT }accessible${expect_fail:-}."
|
||||||
|
(( ++ error_count ))
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
} 2>/dev/null
|
||||||
|
|
||||||
|
function run_tests() {
|
||||||
|
local server="$1"
|
||||||
test-webapp "$server:18080"
|
test-webapp "$server:18080"
|
||||||
! test-webapp "$server:8000"
|
test-webapp ! "$server:8000"
|
||||||
|
|
||||||
test-webapp "$server:17070" # multiple networks app
|
test-webapp "$server:17070" # multiple networks app
|
||||||
! test-webapp "$server:7000" # internal multiple networks app
|
test-webapp ! "$server:7000" # internal multiple networks app
|
||||||
|
|
||||||
|
# Docker Swarm
|
||||||
|
test-webapp ! "$server:9000"
|
||||||
|
test-webapp ! "$server:47000"
|
||||||
|
}
|
||||||
|
function run_tests_ipv4() {
|
||||||
|
local server="$1"
|
||||||
|
# Docker Swarm
|
||||||
test-webapp "$server:29090"
|
test-webapp "$server:29090"
|
||||||
! test-webapp "$server:9000"
|
|
||||||
|
|
||||||
test-webapp "$server:40080"
|
test-webapp "$server:40080"
|
||||||
test-webapp "$server:48080"
|
test-webapp "$server:48080"
|
||||||
! test-webapp "$server:47000"
|
|
||||||
|
|
||||||
|
}
|
||||||
|
function run_tests_ipv6() {
|
||||||
|
local server="$1"
|
||||||
|
|
||||||
|
echo TODO: It seems that Docker Swarm does not support IPv6 well >&2
|
||||||
|
|
||||||
|
test-webapp ! "$server:29090" # it is accessible via IPv4
|
||||||
|
test-webapp ! "$server:40080" # it is accessible via IPv4
|
||||||
|
test-webapp ! "$server:48080" # it is accessible via IPv4
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
run_tests "http://#{ip_prefix}.130"
|
||||||
|
run_tests_ipv4 "http://#{ip_prefix}.130"
|
||||||
|
|
||||||
|
if #{env_true_str?('ENABLE_DOCKER_IPV6')}; then
|
||||||
|
run_tests "http://[#{ip6_prefix}:0:cafe::130]"
|
||||||
|
run_tests_ipv6 "http://[#{ip6_prefix}:0:cafe::130]"
|
||||||
|
fi
|
||||||
|
{
|
||||||
echo "====================="
|
echo "====================="
|
||||||
echo " TEST DONE "
|
if [[ "$error_count" -eq 0 ]]; then echo " TEST DONE "
|
||||||
|
else echo " TESTS FAIL: ${error_count}"
|
||||||
|
fi
|
||||||
echo "====================="
|
echo "====================="
|
||||||
|
exit "${error_count}"
|
||||||
|
} 2>/dev/null
|
||||||
SHELL
|
SHELL
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -284,6 +284,7 @@ test-ufw-docker--service-delete-matches-assert() {
|
||||||
docker service update --update-parallelism=0 \
|
docker service update --update-parallelism=0 \
|
||||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||||
--env-add "ufw_public_abcd1234=webapp/deny" \
|
--env-add "ufw_public_abcd1234=webapp/deny" \
|
||||||
|
--env-add "DEBUG=false" \
|
||||||
--image "${ufw_docker_agent_image}" \
|
--image "${ufw_docker_agent_image}" \
|
||||||
"${ufw_docker_agent}"
|
"${ufw_docker_agent}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,14 @@ test-ufw-docker-install-assert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
test-ufw-docker-install--docker-subnets() {
|
||||||
|
ufw-docker install --docker-subnets
|
||||||
|
}
|
||||||
|
test-ufw-docker-install--docker-subnets-assert() {
|
||||||
|
ufw-docker--install --docker-subnets
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
test-ufw-docker-check() {
|
test-ufw-docker-check() {
|
||||||
ufw-docker check
|
ufw-docker check
|
||||||
}
|
}
|
||||||
|
@ -136,6 +144,14 @@ test-ufw-docker-check-assert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
test-ufw-docker-check--docker-subnets() {
|
||||||
|
ufw-docker check --docker-subnets
|
||||||
|
}
|
||||||
|
test-ufw-docker-check--docker-subnets-assert() {
|
||||||
|
ufw-docker--check --docker-subnets
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
test-ufw-docker-service() {
|
test-ufw-docker-service() {
|
||||||
ufw-docker service allow httpd
|
ufw-docker service allow httpd
|
||||||
}
|
}
|
||||||
|
@ -198,7 +214,7 @@ test-ufw-docker-list-httpd() {
|
||||||
ufw-docker list httpd
|
ufw-docker list httpd
|
||||||
}
|
}
|
||||||
test-ufw-docker-list-httpd-assert() {
|
test-ufw-docker-list-httpd-assert() {
|
||||||
ufw-docker--list httpd-container-name "" tcp ""
|
ufw-docker--list 'httpd-container-name\(/v6\)\?' "" tcp ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -246,21 +262,12 @@ test-ASSERT-FAIL-ufw-docker-allow-httpd-INVALID-port() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
test-ufw-docker-list-httpd() {
|
|
||||||
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
|
|
||||||
ufw-docker list httpd
|
|
||||||
}
|
|
||||||
test-ufw-docker-list-httpd-assert() {
|
|
||||||
ufw-docker--list httpd-container-name "" tcp ""
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
test-ufw-docker-delete-allow-httpd() {
|
test-ufw-docker-delete-allow-httpd() {
|
||||||
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
|
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
|
||||||
ufw-docker delete allow httpd
|
ufw-docker delete allow httpd
|
||||||
}
|
}
|
||||||
test-ufw-docker-delete-allow-httpd-assert() {
|
test-ufw-docker-delete-allow-httpd-assert() {
|
||||||
ufw-docker--delete httpd-container-name "" tcp ""
|
ufw-docker--delete 'httpd-container-name\(/v6\)\?' "" tcp ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -277,8 +284,15 @@ function setup-ufw-docker--allow() {
|
||||||
load-ufw-docker-function ufw-docker--allow
|
load-ufw-docker-function ufw-docker--allow
|
||||||
|
|
||||||
@mocktrue docker inspect instance-name
|
@mocktrue docker inspect instance-name
|
||||||
@mock docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{"\n"}}{{end}}' instance-name === @stdout 172.18.0.3
|
@mock docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout "default 172.18.0.3"
|
||||||
@mock docker inspect --format='{{range $k, $v := .NetworkSettings.Networks}}{{printf "%s\n" $k}}{{end}}' instance-name === @stdout default
|
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup-IPv6-ufw-docker--allow() {
|
||||||
|
load-ufw-docker-function ufw-docker--allow
|
||||||
|
|
||||||
|
@mocktrue docker inspect instance-name
|
||||||
|
@mock docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout "default 172.18.0.3" "default fd00:cf::42"
|
||||||
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
|
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,8 +300,15 @@ function setup-ufw-docker--allow--multinetwork() {
|
||||||
load-ufw-docker-function ufw-docker--allow
|
load-ufw-docker-function ufw-docker--allow
|
||||||
|
|
||||||
@mocktrue docker inspect instance-name
|
@mocktrue docker inspect instance-name
|
||||||
@mock docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{"\n"}}{{end}}' instance-name === @stdout 172.18.0.3 172.19.0.7
|
@mock docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout "default 172.18.0.3" "awesomenet 172.19.0.7"
|
||||||
@mock docker inspect --format='{{range $k, $v := .NetworkSettings.Networks}}{{printf "%s\n" $k}}{{end}}' instance-name === @stdout default awesomenet
|
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup-IPv6-ufw-docker--allow--multinetwork() {
|
||||||
|
load-ufw-docker-function ufw-docker--allow
|
||||||
|
|
||||||
|
@mocktrue docker inspect instance-name
|
||||||
|
@mock docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout "default 172.18.0.3" "default fd00:cf::42" "awesomenet 172.19.0.7" "awesomenet fd00:cf::207"
|
||||||
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
|
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,6 +408,83 @@ test-ufw-docker--allow-instance-all-published-port-multinetwork-select-network-a
|
||||||
ufw-docker--add-rule instance-name 172.19.0.7 5353 udp awesomenet
|
ufw-docker--add-rule instance-name 172.19.0.7 5353 udp awesomenet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
test-IPv6-ufw-docker--allow-instance-and-match-the-port() {
|
||||||
|
setup-IPv6-ufw-docker--allow
|
||||||
|
|
||||||
|
ufw-docker--allow instance-name 5000 tcp
|
||||||
|
}
|
||||||
|
test-IPv6-ufw-docker--allow-instance-and-match-the-port-assert() {
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5000 tcp default
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
test-IPv6-ufw-docker--allow-instance-all-published-port() {
|
||||||
|
setup-IPv6-ufw-docker--allow
|
||||||
|
|
||||||
|
ufw-docker--allow instance-name "" ""
|
||||||
|
}
|
||||||
|
test-IPv6-ufw-docker--allow-instance-all-published-port-assert() {
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5000 tcp default
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 8080 tcp default
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5353 udp default
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
test-IPv6-ufw-docker--allow-instance-all-published-tcp-port() {
|
||||||
|
setup-IPv6-ufw-docker--allow
|
||||||
|
|
||||||
|
ufw-docker--allow instance-name "" tcp
|
||||||
|
}
|
||||||
|
test-IPv6-ufw-docker--allow-instance-all-published-tcp-port-assert() {
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5000 tcp default
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 8080 tcp default
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default # FIXME
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5353 udp default # FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork() {
|
||||||
|
setup-IPv6-ufw-docker--allow--multinetwork
|
||||||
|
|
||||||
|
ufw-docker--allow instance-name "" ""
|
||||||
|
}
|
||||||
|
test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork-assert() {
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5000 tcp default
|
||||||
|
ufw-docker--add-rule instance-name 172.19.0.7 5000 tcp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::207 5000 tcp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 8080 tcp default
|
||||||
|
ufw-docker--add-rule instance-name 172.19.0.7 8080 tcp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::207 8080 tcp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5353 udp default
|
||||||
|
ufw-docker--add-rule instance-name 172.19.0.7 5353 udp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::207 5353 udp awesomenet
|
||||||
|
}
|
||||||
|
|
||||||
|
test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork-select-network() {
|
||||||
|
setup-IPv6-ufw-docker--allow--multinetwork
|
||||||
|
|
||||||
|
ufw-docker--allow instance-name "" "" awesomenet
|
||||||
|
}
|
||||||
|
test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork-select-network-assert() {
|
||||||
|
ufw-docker--add-rule instance-name 172.19.0.7 5000 tcp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::207 5000 tcp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name 172.19.0.7 8080 tcp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::207 8080 tcp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name 172.19.0.7 5353 udp awesomenet
|
||||||
|
ufw-docker--add-rule instance-name/v6 fd00:cf::207 5353 udp awesomenet
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
test-ufw-docker--add-rule-a-non-existing-rule() {
|
test-ufw-docker--add-rule-a-non-existing-rule() {
|
||||||
@mockfalse ufw-docker--list webapp 5000 tcp ""
|
@mockfalse ufw-docker--list webapp 5000 tcp ""
|
||||||
|
|
||||||
|
@ -410,7 +508,7 @@ test-ufw-docker--add-rule-a-non-existing-rule-with-network-assert() {
|
||||||
|
|
||||||
test-ufw-docker--add-rule-modify-an-existing-rule() {
|
test-ufw-docker--add-rule-modify-an-existing-rule() {
|
||||||
@mocktrue ufw-docker--list webapp 5000 tcp default
|
@mocktrue ufw-docker--list webapp 5000 tcp default
|
||||||
@mocktrue ufw --dry-run route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp default"
|
@mock ufw --dry-run route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp default" === @echo
|
||||||
@mockfalse grep "^Skipping"
|
@mockfalse grep "^Skipping"
|
||||||
|
|
||||||
load-ufw-docker-function ufw-docker--add-rule
|
load-ufw-docker-function ufw-docker--add-rule
|
||||||
|
@ -423,6 +521,21 @@ test-ufw-docker--add-rule-modify-an-existing-rule-assert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
test-IPv6-ufw-docker--add-rule-modify-an-existing-rule() {
|
||||||
|
@mocktrue ufw-docker--list webapp/v6 5000 tcp default
|
||||||
|
@mock ufw --dry-run route allow proto tcp from any to fd00:cf::42 port 5000 comment "allow webapp/v6 5000/tcp default" === @echo
|
||||||
|
@mockfalse grep "^Skipping"
|
||||||
|
|
||||||
|
load-ufw-docker-function ufw-docker--add-rule
|
||||||
|
ufw-docker--add-rule webapp/v6 fd00:cf::42 5000 tcp default
|
||||||
|
}
|
||||||
|
test-IPv6-ufw-docker--add-rule-modify-an-existing-rule-assert() {
|
||||||
|
ufw-docker--delete webapp/v6 5000 tcp default
|
||||||
|
|
||||||
|
ufw route allow proto tcp from any to fd00:cf::42 port 5000 comment "allow webapp/v6 5000/tcp default"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
test-ufw-docker--add-rule-skip-an-existing-rule() {
|
test-ufw-docker--add-rule-skip-an-existing-rule() {
|
||||||
@mocktrue ufw-docker--list webapp 5000 tcp ""
|
@mocktrue ufw-docker--list webapp 5000 tcp ""
|
||||||
@mocktrue ufw --dry-run route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp"
|
@mocktrue ufw --dry-run route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp"
|
||||||
|
@ -438,8 +551,7 @@ test-ufw-docker--add-rule-skip-an-existing-rule-assert() {
|
||||||
|
|
||||||
test-ufw-docker--add-rule-modify-an-existing-rule-without-port() {
|
test-ufw-docker--add-rule-modify-an-existing-rule-without-port() {
|
||||||
@mocktrue ufw-docker--list webapp "" tcp ""
|
@mocktrue ufw-docker--list webapp "" tcp ""
|
||||||
|
@mock ufw --dry-run route allow proto tcp from any to 172.18.0.4 comment "allow webapp" === @echo
|
||||||
@mocktrue ufw --dry-run route allow proto tcp from any to 172.18.0.4 comment "allow webapp"
|
|
||||||
@mockfalse grep "^Skipping"
|
@mockfalse grep "^Skipping"
|
||||||
|
|
||||||
load-ufw-docker-function ufw-docker--add-rule
|
load-ufw-docker-function ufw-docker--add-rule
|
||||||
|
@ -484,11 +596,14 @@ test-ufw-docker--instance-name-found-an-id-assert() {
|
||||||
|
|
||||||
test-ufw-docker--list-name() {
|
test-ufw-docker--list-name() {
|
||||||
@mocktrue ufw status numbered
|
@mocktrue ufw status numbered
|
||||||
|
@mockfalse grep "# allow foo\\( [[:digit:]]\\+\\/\\(tcp\\|udp\\)\\)\\( [[:graph:]]*\\)\$"
|
||||||
|
@mockfalse grep "# allow foo\\( [[:digit:]]\\+\\/\\(tcp\\|udp\\)\\)\$"
|
||||||
|
|
||||||
load-ufw-docker-function ufw-docker--list
|
load-ufw-docker-function ufw-docker--list
|
||||||
ufw-docker--list foo
|
ufw-docker--list foo
|
||||||
}
|
}
|
||||||
test-ufw-docker--list-name-assert() {
|
test-ufw-docker--list-name-assert() {
|
||||||
grep "# allow foo\\( [[:digit:]]\\+\\/\\(tcp\\|udp\\)\\)\\( [[:graph:]]*\\)\$"
|
grep "# allow foo\$"
|
||||||
}
|
}
|
||||||
|
|
||||||
test-ufw-docker--list-name-udp() {
|
test-ufw-docker--list-name-udp() {
|
||||||
|
@ -523,24 +638,23 @@ test-ufw-docker--list-name-80-udp-assert() {
|
||||||
|
|
||||||
test-ufw-docker--list-grep-without-network() {
|
test-ufw-docker--list-grep-without-network() {
|
||||||
@mocktrue ufw status numbered
|
@mocktrue ufw status numbered
|
||||||
@mockfalse grep "# allow foo\\( 80\\/udp\\)\\( [[:graph:]]*\\)\$"
|
|
||||||
load-ufw-docker-function ufw-docker--list
|
load-ufw-docker-function ufw-docker--list
|
||||||
ufw-docker--list foo 80 udp
|
ufw-docker--list foo 80 udp
|
||||||
}
|
}
|
||||||
test-ufw-docker--list-grep-without-network-assert() {
|
test-ufw-docker--list-grep-without-network-assert() {
|
||||||
grep "# allow foo\\( 80\\/udp\\)\$"
|
grep "# allow foo\\( 80\\/udp\\)\\( [[:graph:]]*\\)\$"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
test-ufw-docker--list-grep-without-network-and-port() {
|
test-ufw-docker--list-grep-without-network-and-port() {
|
||||||
@mocktrue ufw status numbered
|
@mocktrue ufw status numbered
|
||||||
@mockfalse grep "# allow foo\\( 80\\/udp\\)\\( [[:graph:]]*\\)\$"
|
@mockfalse grep "# allow foo\\( 80\\/tcp\\)\\( [[:graph:]]*\\)\$"
|
||||||
@mockfalse grep "# allow foo\\( 80\\/udp\\)\$"
|
|
||||||
load-ufw-docker-function ufw-docker--list
|
load-ufw-docker-function ufw-docker--list
|
||||||
ufw-docker--list foo 80 udp
|
ufw-docker--list foo 80
|
||||||
}
|
}
|
||||||
test-ufw-docker--list-grep-without-network-and-port-assert() {
|
test-ufw-docker--list-grep-without-network-and-port-assert() {
|
||||||
grep "# allow foo\$"
|
grep "# allow foo\\( 80\\/tcp\\)\$"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
229
ufw-docker
229
ufw-docker
|
@ -24,7 +24,7 @@ fi
|
||||||
test -n "$ufw_docker_agent_image"
|
test -n "$ufw_docker_agent_image"
|
||||||
|
|
||||||
function ufw-docker--status() {
|
function ufw-docker--status() {
|
||||||
ufw-docker--list "$GREP_REGEXP_INSTANCE_NAME" | uniq
|
ufw-docker--list "$GREP_REGEXP_INSTANCE_NAME\(/v6\)\?"
|
||||||
}
|
}
|
||||||
|
|
||||||
function ufw-docker--list() {
|
function ufw-docker--list() {
|
||||||
|
@ -32,6 +32,7 @@ function ufw-docker--list() {
|
||||||
local INSTANCE_PORT="${2:-}"
|
local INSTANCE_PORT="${2:-}"
|
||||||
local PROTO="${3:-${DEFAULT_PROTO}}"
|
local PROTO="${3:-${DEFAULT_PROTO}}"
|
||||||
local NETWORK="${4:-}"
|
local NETWORK="${4:-}"
|
||||||
|
local params_count="$#"
|
||||||
|
|
||||||
if [[ -z "$INSTANCE_PORT" ]]; then
|
if [[ -z "$INSTANCE_PORT" ]]; then
|
||||||
INSTANCE_PORT="[[:digit:]]\\+"
|
INSTANCE_PORT="[[:digit:]]\\+"
|
||||||
|
@ -42,19 +43,16 @@ function ufw-docker--list() {
|
||||||
NETWORK="[[:graph:]]*"
|
NETWORK="[[:graph:]]*"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# IPv4
|
local ufw_output
|
||||||
ufw status numbered | grep "# allow ${INSTANCE_NAME}\\( ${INSTANCE_PORT}\\/${PROTO}\\)\\( ${NETWORK}\\)\$" || \
|
ufw_output="$(ufw status numbered)"
|
||||||
ufw status numbered | grep "# allow ${INSTANCE_NAME}\\( ${INSTANCE_PORT}\\/${PROTO}\\)\$" || \
|
|
||||||
ufw status numbered | grep "# allow ${INSTANCE_NAME}\$"
|
|
||||||
|
|
||||||
# IPv6
|
grep "# allow ${INSTANCE_NAME}\\( ${INSTANCE_PORT}\\/${PROTO}\\)\\( ${NETWORK}\\)\$" <<< "$ufw_output" ||
|
||||||
ufw status numbered | grep "# allow ${INSTANCE_NAME}_IPv6\\( ${INSTANCE_PORT}\\/${PROTO}\\)\\( ${NETWORK}\\)\$" || \
|
grep "# allow ${INSTANCE_NAME}\\( ${INSTANCE_PORT}\\/${PROTO}\\)\$" <<< "$ufw_output" ||
|
||||||
ufw status numbered | grep "# allow ${INSTANCE_NAME}_IPv6\\( ${INSTANCE_PORT}\\/${PROTO}\\)\$" || \
|
grep "# allow ${INSTANCE_NAME}\$" <<< "$ufw_output"
|
||||||
ufw status numbered | grep "# allow ${INSTANCE_NAME}_IPv6\$"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ufw-docker--list-number() {
|
function ufw-docker--list-number() {
|
||||||
ufw-docker--list "$@" | sed -e 's/^\[[[:blank:]]*\([[:digit:]]\+\)\].*/\1/' | uniq
|
ufw-docker--list "$@" | sed -e 's/^\[[[:blank:]]*\([[:digit:]]\+\)\].*/\1/'
|
||||||
}
|
}
|
||||||
|
|
||||||
function ufw-docker--delete() {
|
function ufw-docker--delete() {
|
||||||
|
@ -69,16 +67,15 @@ function ufw-docker--allow() {
|
||||||
local INSTANCE_PORT="$2"
|
local INSTANCE_PORT="$2"
|
||||||
local PROTO="$3"
|
local PROTO="$3"
|
||||||
local NETWORK="${4:-}"
|
local NETWORK="${4:-}"
|
||||||
|
local NETWORK_ADDRESSES PORT_PROTO_LIST PROT_PROTO IP SUFFIX
|
||||||
|
|
||||||
docker inspect "$INSTANCE_NAME" &>/dev/null ||
|
docker inspect "$INSTANCE_NAME" &>/dev/null ||
|
||||||
die "Docker instance \"$INSTANCE_NAME\" doesn't exist."
|
die "Docker instance \"$INSTANCE_NAME\" doesn't exist."
|
||||||
|
|
||||||
mapfile -t INSTANCE_IP_ADDRESSES < <(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{"\n"}}{{end}}' "$INSTANCE_NAME" 2>/dev/null | remove_blank_lines)
|
mapfile -t NETWORK_ADDRESSES < <(docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' "$INSTANCE_NAME" 2>/dev/null | remove_blank_lines)
|
||||||
mapfile -t INSTANCE_IP_V6_ADDRESSES < <(docker inspect --format='{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{"\n"}}{{end}}' "$INSTANCE_NAME" 2>/dev/null | remove_blank_lines)
|
|
||||||
|
|
||||||
[[ -z "${INSTANCE_IP_ADDRESSES:-}" ]] && die "Could not find a running instance \"$INSTANCE_NAME\"."
|
[[ -z "${NETWORK_ADDRESSES:-}" ]] && die "Could not find a running instance \"$INSTANCE_NAME\"."
|
||||||
|
|
||||||
mapfile -t INSTANCE_NETWORK_NAMES < <(docker inspect --format='{{range $k, $v := .NetworkSettings.Networks}}{{printf "%s\n" $k}}{{end}}' "$INSTANCE_NAME" 2>/dev/null | remove_blank_lines)
|
|
||||||
mapfile -t PORT_PROTO_LIST < <(docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' "$INSTANCE_NAME" | remove_blank_lines)
|
mapfile -t PORT_PROTO_LIST < <(docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' "$INSTANCE_NAME" | remove_blank_lines)
|
||||||
|
|
||||||
if [[ -z "${PORT_PROTO_LIST:-}" ]]; then
|
if [[ -z "${PORT_PROTO_LIST:-}" ]]; then
|
||||||
|
@ -86,36 +83,26 @@ function ufw-docker--allow() {
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RETVAL=1
|
local count=0
|
||||||
for PORT_PROTO in "${PORT_PROTO_LIST[@]}"; do
|
for PORT_PROTO in "${PORT_PROTO_LIST[@]}"; do
|
||||||
if [[ -z "$INSTANCE_PORT" || "$PORT_PROTO" = "${INSTANCE_PORT}/${PROTO}" ]]; then
|
if [[ -z "$INSTANCE_PORT" || "$PORT_PROTO" = "${INSTANCE_PORT}/${PROTO}" ]]; then
|
||||||
ITER=0
|
for item in "${NETWORK_ADDRESSES[@]}"; do
|
||||||
for IP in "${INSTANCE_IP_ADDRESSES[@]}"; do
|
INSTANCE_NETWORK="${item% *}"
|
||||||
INSTANCE_NETWORK="${INSTANCE_NETWORK_NAMES[$ITER]}"
|
IP="${item#* }"
|
||||||
ITER=$((ITER+1))
|
|
||||||
if [[ -n "$NETWORK" ]] && [[ "$NETWORK" != "$INSTANCE_NETWORK" ]]; then
|
if [[ -n "$NETWORK" ]] && [[ "$NETWORK" != "$INSTANCE_NETWORK" ]]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
ufw-docker--add-rule "$INSTANCE_NAME" "$IP" "${PORT_PROTO%/*}" "${PORT_PROTO#*/}" "${INSTANCE_NETWORK}"
|
if [[ "$IP" = *:* ]]; then SUFFIX="/v6"; else SUFFIX=""; fi
|
||||||
RETVAL="$?"
|
ufw-docker--add-rule "${INSTANCE_NAME}${SUFFIX}" "$IP" "${PORT_PROTO%/*}" "${PORT_PROTO#*/}" "${INSTANCE_NETWORK}"
|
||||||
done
|
(( ++count ))
|
||||||
|
|
||||||
ITER_V6=0
|
|
||||||
for IP in "${INSTANCE_IP_V6_ADDRESSES[@]}"; do
|
|
||||||
INSTANCE_NETWORK="${INSTANCE_NETWORK_NAMES[$ITER_V6]}"
|
|
||||||
ITER_V6=$((ITER_V6+1))
|
|
||||||
if [[ -n "$NETWORK" ]] && [[ "$NETWORK" != "$INSTANCE_NETWORK" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
ufw-docker--add-rule "${INSTANCE_NAME}_IPv6" "$IP" "${PORT_PROTO%/*}" "${PORT_PROTO#*/}" "${INSTANCE_NETWORK}"
|
|
||||||
RETVAL="$?"
|
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [[ "$RETVAL" -ne 0 ]]; then
|
if [[ "$count" -eq 0 ]]; then
|
||||||
err "Fail to add rule(s), cannot find the published port ${INSTANCE_PORT}/${PROTO} of instance \"${INSTANCE_NAME}\" or cannot update outdated rule(s)."
|
err "Fail to add rule(s), cannot find the published port ${INSTANCE_PORT}/${PROTO} of instance \"${INSTANCE_NAME}\" or cannot update outdated rule(s)."
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
return "$RETVAL"
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function ufw-docker--add-service-rule() {
|
function ufw-docker--add-service-rule() {
|
||||||
|
@ -299,6 +286,7 @@ function ufw-docker--service-delete() {
|
||||||
docker service update --update-parallelism=0 \
|
docker service update --update-parallelism=0 \
|
||||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||||
--env-add "${service_env}" \
|
--env-add "${service_env}" \
|
||||||
|
--env-add DEBUG="${DEBUG-}" \
|
||||||
--image "${ufw_docker_agent_image}" \
|
--image "${ufw_docker_agent_image}" \
|
||||||
"${ufw_docker_agent}"
|
"${ufw_docker_agent}"
|
||||||
}
|
}
|
||||||
|
@ -315,13 +303,15 @@ function ufw-docker--check() {
|
||||||
iptables -n -L DOCKER-USER
|
iptables -n -L DOCKER-USER
|
||||||
|
|
||||||
err "\\n\\n########## diff $after_rules ##########"
|
err "\\n\\n########## diff $after_rules ##########"
|
||||||
ufw-docker--check-install && err "\\nCheck done."
|
ufw-docker--check-install "$@" && err "\\nCheck IPv4 firewall rules done."
|
||||||
|
|
||||||
|
if command -v ip6tables >/dev/null 2>&1; then
|
||||||
err "\\n########## ip6tables -n -L DOCKER-USER ##########"
|
err "\\n########## ip6tables -n -L DOCKER-USER ##########"
|
||||||
ip6tables -n -L DOCKER-USER
|
ip6tables -n -L DOCKER-USER
|
||||||
|
|
||||||
err "\\n\\n########## diff $after6_rules ##########"
|
err "\\n\\n########## diff $after6_rules ##########"
|
||||||
ufw-docker--check-install_ipv6 && err "\\nCheck IPv6 done."
|
ufw-docker--check-install_ipv6 "$@" && err "\\nCheck IPv6 firewall rules done."
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
declare -a files_to_be_deleted
|
declare -a files_to_be_deleted
|
||||||
|
@ -339,12 +329,45 @@ function on-exit() {
|
||||||
|
|
||||||
trap on-exit EXIT INT TERM QUIT ABRT ERR
|
trap on-exit EXIT INT TERM QUIT ABRT ERR
|
||||||
|
|
||||||
|
function ufw-docker--list-docker-subnets() {
|
||||||
|
local ipversion="$1"
|
||||||
|
shift || true
|
||||||
|
if [[ -z "${1-}" ]]; then
|
||||||
|
docker network ls --format '{{.ID}}' |
|
||||||
|
while read -r net; do
|
||||||
|
docker network inspect "$net" --format '{{range .IPAM.Config}}{{.Subnet}}{{"\n"}}{{end}}'
|
||||||
|
done
|
||||||
|
else
|
||||||
|
printf "%s\n" "$@"
|
||||||
|
fi |
|
||||||
|
while read -r cidr; do
|
||||||
|
if [[ "${ipversion}" = "IPv4" && "$cidr" = *.* ]] || [[ "${ipversion}" = "IPv6" && "$cidr" = *:* ]]
|
||||||
|
then echo "$cidr"
|
||||||
|
fi
|
||||||
|
done |
|
||||||
|
sort
|
||||||
|
}
|
||||||
|
|
||||||
function ufw-docker--check-install() {
|
function ufw-docker--check-install() {
|
||||||
|
declare -a cidr_list
|
||||||
|
declare cidr
|
||||||
|
if [[ -z "${1-}" ]]; then
|
||||||
|
cidr_list=(10.0.0.0/8 172.16.0.0/12 192.168.0.0/16)
|
||||||
|
elif [[ "${1-}" = '--docker-subnets' ]]; then
|
||||||
|
shift || true
|
||||||
|
mapfile -t cidr_list < <(ufw-docker--list-docker-subnets IPv4 "$@")
|
||||||
|
fi
|
||||||
|
if [[ -z "${cidr_list:-}" ]]; then
|
||||||
|
err "ERROR: Could not find any IPv4 subnets used by docker engine\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
after_rules_tmp="${after_rules_tmp:-$(mktemp)}"
|
after_rules_tmp="${after_rules_tmp:-$(mktemp)}"
|
||||||
rm-on-exit "$after_rules_tmp"
|
rm-on-exit "$after_rules_tmp"
|
||||||
|
|
||||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after_rules" > "$after_rules_tmp"
|
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after_rules" > "$after_rules_tmp"
|
||||||
>> "${after_rules_tmp}" cat <<-\EOF
|
{
|
||||||
|
cat <<-\EOF
|
||||||
# BEGIN UFW AND DOCKER
|
# BEGIN UFW AND DOCKER
|
||||||
*filter
|
*filter
|
||||||
:ufw-user-forward - [0:0]
|
:ufw-user-forward - [0:0]
|
||||||
|
@ -352,18 +375,26 @@ function ufw-docker--check-install() {
|
||||||
:DOCKER-USER - [0:0]
|
:DOCKER-USER - [0:0]
|
||||||
-A DOCKER-USER -j ufw-user-forward
|
-A DOCKER-USER -j ufw-user-forward
|
||||||
|
|
||||||
-A DOCKER-USER -j RETURN -s 10.0.0.0/8
|
EOF
|
||||||
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
|
|
||||||
-A DOCKER-USER -j RETURN -s 192.168.0.0/16
|
for cidr in "${cidr_list[@]}"; do
|
||||||
|
echo "-A DOCKER-USER -j RETURN -s ${cidr}"
|
||||||
|
done
|
||||||
|
|
||||||
|
cat <<-\EOF
|
||||||
|
|
||||||
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
|
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
|
||||||
|
|
||||||
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
|
EOF
|
||||||
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
|
|
||||||
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
|
for cidr in "${cidr_list[@]}"; do
|
||||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
|
echo "-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d ${cidr}"
|
||||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
|
done
|
||||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
|
for cidr in "${cidr_list[@]}"; do
|
||||||
|
echo "-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d ${cidr}"
|
||||||
|
done
|
||||||
|
|
||||||
|
cat <<-\EOF
|
||||||
|
|
||||||
-A DOCKER-USER -j RETURN
|
-A DOCKER-USER -j RETURN
|
||||||
|
|
||||||
|
@ -373,19 +404,30 @@ function ufw-docker--check-install() {
|
||||||
COMMIT
|
COMMIT
|
||||||
# END UFW AND DOCKER
|
# END UFW AND DOCKER
|
||||||
EOF
|
EOF
|
||||||
|
} >> "${after_rules_tmp}"
|
||||||
diff -u --color=auto "$after_rules" "$after_rules_tmp"
|
diff -u --color=auto "$after_rules" "$after_rules_tmp"
|
||||||
}
|
}
|
||||||
|
|
||||||
function ufw-docker--check-install_ipv6() {
|
function ufw-docker--check-install_ipv6() {
|
||||||
DOCKER_IPV6_NETWORK=$(sed -En 's/.*"fixed-cidr-v6":.?"([^"]*).*/\1/p' /etc/docker/daemon.json)
|
declare -a cidr6_list
|
||||||
[[ -z "${DOCKER_IPV6_NETWORK:-}" ]] && die "Could not find \"fixed-cidr-v6\" in \"/etc/docker/daemon.json\"."
|
declare cidr
|
||||||
|
if [[ -z "${1-}" ]]; then
|
||||||
|
cidr6_list=(fd00::/8)
|
||||||
|
elif [[ "${1-}" = '--docker-subnets' ]]; then
|
||||||
|
shift || true
|
||||||
|
mapfile -t cidr6_list < <(ufw-docker--list-docker-subnets IPv6 "$@")
|
||||||
|
fi
|
||||||
|
if [[ -z "${cidr6_list:-}" ]]; then
|
||||||
|
err "INFO: Could not find any IPv6 subnets used by docker engine, will disable IPv6 support.\n"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
after6_rules_tmp="${after6_rules_tmp:-$(mktemp)}"
|
after6_rules_tmp="${after6_rules_tmp:-$(mktemp)}"
|
||||||
rm-on-exit "$after6_rules_tmp"
|
rm-on-exit "$after6_rules_tmp"
|
||||||
|
|
||||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after6_rules" > "$after6_rules_tmp"
|
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after6_rules" > "$after6_rules_tmp"
|
||||||
>> "${after6_rules_tmp}" cat <<-\EOF
|
{
|
||||||
|
cat <<-\EOF
|
||||||
# BEGIN UFW AND DOCKER
|
# BEGIN UFW AND DOCKER
|
||||||
*filter
|
*filter
|
||||||
:ufw6-user-forward - [0:0]
|
:ufw6-user-forward - [0:0]
|
||||||
|
@ -393,12 +435,22 @@ function ufw-docker--check-install_ipv6() {
|
||||||
:DOCKER-USER - [0:0]
|
:DOCKER-USER - [0:0]
|
||||||
-A DOCKER-USER -j ufw6-user-forward
|
-A DOCKER-USER -j ufw6-user-forward
|
||||||
|
|
||||||
-A DOCKER-USER -j RETURN -s {DOCKER_IPV6_NETWORK}
|
EOF
|
||||||
|
|
||||||
|
for cidr in "${cidr6_list[@]}"; do
|
||||||
|
echo "-A DOCKER-USER -j RETURN -s ${cidr}"
|
||||||
|
done
|
||||||
|
|
||||||
|
cat <<-\EOF
|
||||||
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
|
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
|
||||||
|
EOF
|
||||||
|
|
||||||
-A DOCKER-USER -j ufw6-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d {DOCKER_IPV6_NETWORK}
|
for cidr in "${cidr6_list[@]}"; do
|
||||||
-A DOCKER-USER -j ufw6-docker-logging-deny -p udp -m udp --dport 0:32767 -d {DOCKER_IPV6_NETWORK}
|
echo "-A DOCKER-USER -j ufw6-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d ${cidr}"
|
||||||
|
echo "-A DOCKER-USER -j ufw6-docker-logging-deny -p udp -m udp --dport 0:32767 -d ${cidr}"
|
||||||
|
done
|
||||||
|
|
||||||
|
cat <<-\EOF
|
||||||
|
|
||||||
-A DOCKER-USER -j RETURN
|
-A DOCKER-USER -j RETURN
|
||||||
|
|
||||||
|
@ -408,33 +460,31 @@ function ufw-docker--check-install_ipv6() {
|
||||||
COMMIT
|
COMMIT
|
||||||
# END UFW AND DOCKER
|
# END UFW AND DOCKER
|
||||||
EOF
|
EOF
|
||||||
|
} >> "${after6_rules_tmp}"
|
||||||
sed -i "s/{DOCKER_IPV6_NETWORK}/${DOCKER_IPV6_NETWORK/\//\\/}/g" "$after6_rules_tmp"
|
|
||||||
|
|
||||||
diff -u --color=auto "$after6_rules" "$after6_rules_tmp"
|
diff -u --color=auto "$after6_rules" "$after6_rules_tmp"
|
||||||
}
|
}
|
||||||
|
|
||||||
function ufw-docker--install() {
|
function ufw-docker--install() {
|
||||||
if ! ufw-docker--check-install; then
|
local changed=false
|
||||||
|
if ! ufw-docker--check-install "$@"; then
|
||||||
|
changed=true
|
||||||
local after_rules_bak
|
local after_rules_bak
|
||||||
after_rules_bak="${after_rules}-ufw-docker~$(date '+%Y-%m-%d-%H%M%S')~"
|
after_rules_bak="${after_rules}-ufw-docker~$(date '+%Y-%m-%d-%H%M%S')~"
|
||||||
err "\\nBacking up $after_rules to $after_rules_bak"
|
err "\\nBacking up $after_rules to $after_rules_bak"
|
||||||
cp "$after_rules" "$after_rules_bak"
|
cp "$after_rules" "$after_rules_bak"
|
||||||
cat "$after_rules_tmp" > "$after_rules"
|
cat "$after_rules_tmp" > "$after_rules"
|
||||||
err "Please restart UFW service manually by using the following command:"
|
|
||||||
if type systemctl &>/dev/null; then
|
|
||||||
err " sudo systemctl restart ufw"
|
|
||||||
else
|
|
||||||
err " sudo service ufw restart"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! ufw-docker--check-install_ipv6; then
|
if ! ufw-docker--check-install_ipv6 "$@"; then
|
||||||
|
changed=true
|
||||||
local after6_rules_bak
|
local after6_rules_bak
|
||||||
after6_rules_bak="${after6_rules}-ufw-docker~$(date '+%Y-%m-%d-%H%M%S')~"
|
after6_rules_bak="${after6_rules}-ufw-docker~$(date '+%Y-%m-%d-%H%M%S')~"
|
||||||
err "\\nBacking up $after6_rules to $after6_rules_bak"
|
err "\\nBacking up $after6_rules to $after6_rules_bak"
|
||||||
cp "$after6_rules" "$after6_rules_bak"
|
cp "$after6_rules" "$after6_rules_bak"
|
||||||
cat "$after6_rules_tmp" > "$after6_rules"
|
cat "$after6_rules_tmp" > "$after6_rules"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if "$changed"; then
|
||||||
err "Please restart UFW service manually by using the following command:"
|
err "Please restart UFW service manually by using the following command:"
|
||||||
if type systemctl &>/dev/null; then
|
if type systemctl &>/dev/null; then
|
||||||
err " sudo systemctl restart ufw"
|
err " sudo systemctl restart ufw"
|
||||||
|
@ -444,6 +494,31 @@ function ufw-docker--install() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ufw-docker--install--help() {
|
||||||
|
cat <<HELP
|
||||||
|
ufw-docker $1 --docker-subnets [SUBNET1 SUBNET2 …]
|
||||||
|
|
||||||
|
Specify which subnets should be used when configuring firewall rules for Docker containers and any allowed networks that communicate with containers.
|
||||||
|
|
||||||
|
- If this option is not provided, only standard private LAN subnets are used (RFC1918 for IPv4 and fd00::/8 for IPv6).
|
||||||
|
- If --docker-subnets is given without any arguments, all Docker network subnets will be automatically detected and used.
|
||||||
|
- If one or more subnets are specified, these subnets will be used for firewall rules, and they can include any networks that need to communicate with containers—not just the subnets configured by the Docker engine.
|
||||||
|
You can specify multiple subnets separated by spaces (each in CIDR format).
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- ufw-docker $1
|
||||||
|
Use only standard private subnets (default behavior).
|
||||||
|
- IPv4 subnets: 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
|
||||||
|
- IPv6 subnet: fd00::/8
|
||||||
|
|
||||||
|
- ufw-docker $1 --docker-subnets
|
||||||
|
Auto-detect and use all Docker network subnets.
|
||||||
|
|
||||||
|
- ufw-docker $1 --docker-subnets 10.207.0.0/16 192.168.207.0/24 fd00:cf::/64
|
||||||
|
Use only the specified subnets, including those outside of Docker’s own configuration, for all networks that should be allowed to communicate with containers.
|
||||||
|
HELP
|
||||||
|
}
|
||||||
|
|
||||||
function ufw-docker--help() {
|
function ufw-docker--help() {
|
||||||
cat <<-EOF >&2
|
cat <<-EOF >&2
|
||||||
Usage:
|
Usage:
|
||||||
|
@ -453,19 +528,27 @@ function ufw-docker--help() {
|
||||||
ufw-docker service allow <swarm-service-id-or-name <port</tcp|/udp>>>
|
ufw-docker service allow <swarm-service-id-or-name <port</tcp|/udp>>>
|
||||||
ufw-docker service delete allow <swarm-service-id-or-name>
|
ufw-docker service delete allow <swarm-service-id-or-name>
|
||||||
|
|
||||||
|
ufw-docker <install|check> [--docker-subnets [SUBNET0 SUBNET1 ...]]
|
||||||
|
|
||||||
ufw-docker <status|install|check|help>
|
ufw-docker <status|install|check|help>
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
ufw-docker help
|
ufw-docker help
|
||||||
|
ufw-docker check --help
|
||||||
|
ufw-docker install --help
|
||||||
|
|
||||||
ufw-docker check # Check the installation of firewall rules
|
ufw-docker check # Check the installation of firewall rules
|
||||||
|
ufw-docker check --docker-subnets # Auto-detect and use all Docker network subnets
|
||||||
|
ufw-docker check --docker-subnets 192.168.207.0/24 10.207.0.0/16 fd00:cf::/64
|
||||||
|
|
||||||
ufw-docker install # Install firewall rules
|
ufw-docker install # Install firewall rules
|
||||||
|
ufw-docker install --docker-subnets # Auto-detect and use all Docker network subnets
|
||||||
|
ufw-docker install --docker-subnets 192.168.207.0/24 10.207.0.0/16 fd00:cf::/64
|
||||||
|
|
||||||
ufw-docker status
|
ufw-docker status
|
||||||
|
|
||||||
ufw-docker list httpd
|
ufw-docker list httpd
|
||||||
|
|
||||||
|
|
||||||
ufw-docker allow httpd
|
ufw-docker allow httpd
|
||||||
ufw-docker allow httpd 80
|
ufw-docker allow httpd 80
|
||||||
ufw-docker allow httpd 80/tcp
|
ufw-docker allow httpd 80/tcp
|
||||||
|
@ -534,14 +617,26 @@ case "$ufw_action" in
|
||||||
NETWORK="${1:-}"
|
NETWORK="${1:-}"
|
||||||
|
|
||||||
INSTANCE_PORT="${INSTANCE_PORT%/*}"
|
INSTANCE_PORT="${INSTANCE_PORT%/*}"
|
||||||
|
;;&
|
||||||
|
delete|list)
|
||||||
|
"ufw-docker--$ufw_action" "$INSTANCE_NAME\\(/v6\\)\\?" "$INSTANCE_PORT" "$PROTO" "$NETWORK"
|
||||||
|
;;
|
||||||
|
allow)
|
||||||
"ufw-docker--$ufw_action" "$INSTANCE_NAME" "$INSTANCE_PORT" "$PROTO" "$NETWORK"
|
"ufw-docker--$ufw_action" "$INSTANCE_NAME" "$INSTANCE_PORT" "$PROTO" "$NETWORK"
|
||||||
;;
|
;;
|
||||||
service|raw-command|add-service-rule)
|
service|raw-command|add-service-rule)
|
||||||
shift || true
|
shift || true
|
||||||
"ufw-docker--$ufw_action" "$@"
|
"ufw-docker--$ufw_action" "$@"
|
||||||
;;
|
;;
|
||||||
status|install|check)
|
install|check)
|
||||||
|
shift || true
|
||||||
|
if [[ "${1-}" = @(help|-h|--help) ]]; then
|
||||||
|
ufw-docker--install--help "$ufw_action"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
"ufw-docker--$ufw_action" "$@"
|
||||||
|
;;
|
||||||
|
status)
|
||||||
ufw-docker--"$ufw_action"
|
ufw-docker--"$ufw_action"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue