mirror of
https://github.com/chaifeng/ufw-docker.git
synced 2025-07-09 19:16:12 +02:00
Compare commits
No commits in common. "master" and "220920-legacy" have entirely different histories.
master
...
220920-leg
10 changed files with 216 additions and 1321 deletions
54
.github/workflows/build.yml
vendored
54
.github/workflows/build.yml
vendored
|
@ -1,54 +0,0 @@
|
|||
name: Build and Push Images
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
variant:
|
||||
- name: nf_tables
|
||||
use_iptables_legacy: "false"
|
||||
- name: legacy
|
||||
use_iptables_legacy: "true"
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log into DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ github.actor }}/ufw-docker-agent
|
||||
tags: |
|
||||
type=ref,event=tag,suffix=-${{ matrix.variant.name }}
|
||||
type=ref,event=branch,suffix=-${{ matrix.variant.name }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build-args: |
|
||||
use_iptables_legacy=${{ matrix.variant.use_iptables_legacy }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1 @@
|
|||
.vagrant
|
||||
.env
|
||||
|
|
17
Dockerfile
17
Dockerfile
|
@ -1,7 +1,6 @@
|
|||
FROM ubuntu:24.04
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ARG docker_version="28.3.1"
|
||||
ARG use_iptables_legacy=false
|
||||
ARG docker_version="20.10.17"
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update \
|
||||
|
@ -13,17 +12,9 @@ RUN apt-get update \
|
|||
| tee /etc/apt/sources.list.d/docker.list > /dev/null \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends locales ufw \
|
||||
&& apt-get install -y --no-install-recommends "docker-ce=$(apt-cache madison docker-ce | grep -m1 -F "${docker_version}" | cut -d'|' -f2 | tr -d '[[:blank:]]')" \
|
||||
&& ( apt-get install -y --no-install-recommends "docker-ce=5:${docker_version}~*" || \
|
||||
apt-get install -y --no-install-recommends "docker-ce=${docker_version}~*" ) \
|
||||
&& locale-gen en_US.UTF-8 \
|
||||
&& if "$use_iptables_legacy"; then \
|
||||
apt-get -y install arptables ebtables \
|
||||
&& update-alternatives --install /usr/sbin/arptables arptables /usr/sbin/arptables-legacy 100 \
|
||||
&& update-alternatives --install /usr/sbin/ebtables ebtables /usr/sbin/ebtables-legacy 100 \
|
||||
&& update-alternatives --set iptables /usr/sbin/iptables-legacy \
|
||||
&& update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy \
|
||||
&& update-alternatives --set arptables /usr/sbin/arptables-legacy \
|
||||
&& update-alternatives --set ebtables /usr/sbin/ebtables-legacy; \
|
||||
fi \
|
||||
&& apt-get clean autoclean \
|
||||
&& apt-get autoremove --yes \
|
||||
&& rm -rf /var/lib/{apt,dpkg,cache,log}/
|
||||
|
|
96
README.md
96
README.md
|
@ -18,7 +18,7 @@ UFW is a popular iptables front end on Ubuntu that makes it easy to manage firew
|
|||
The issue is:
|
||||
|
||||
1. UFW is enabled on a server that provides external services, and all incoming connections that are not allowed are blocked by default.
|
||||
2. Run a Docker container on the server and use the `-p` option to publish ports for that container on all IP addresses.
|
||||
2. Run a Docker container on the server and use the `-p` option to publish ports for that container on all IP addresses.
|
||||
For example: `docker run -d --name httpd -p 0.0.0.0:8080:80 httpd:alpine`, this command will run an httpd service and publish port 80 of the container to port 8080 of the server.
|
||||
3. UFW will not block all external requests to visit port 8080. Even the command `ufw deny 8080` will not prevent external access to this port.
|
||||
4. This problem is actually quite serious, which means that a port that was originally intended to provide services internally is exposed to the public network.
|
||||
|
@ -43,7 +43,7 @@ Almost all of these solutions are similar. It requires to disable docker's iptab
|
|||
|
||||
The solutions that we can find on internet are very similar and not elegant, I hope a new solution can:
|
||||
|
||||
- Don't need to disable Docker's iptables and let Docker to manage it's network.
|
||||
- Don't need to disable Docker's iptables and let Docker to manage it's network.
|
||||
We don't need to manually maintain iptables rules for any new Docker networks, and avoid potential side effects after disabling iptables in Docker.
|
||||
- The public network cannot access ports that published by Docker. Even if the port is published on all IP addresses using an option like `-p 8080:80`. Containers and internal networks can visit each other normally.
|
||||
Although it is possible to have Docker publish a container's port to the server's private IP address, the port will not be accessed on the public network. But, this server may have multiple private IP addresses, and these private IP addresses may also change.
|
||||
|
@ -193,22 +193,6 @@ Con:
|
|||
|
||||
Doesn't support older versions of Ubuntu, and the command is a bit more complicated. But you can use my script.
|
||||
|
||||
### 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`
|
||||
```json
|
||||
{
|
||||
"experimental": true,
|
||||
"ipv6": true,
|
||||
"ip6tables": true,
|
||||
"fixed-cidr-v6": "fd00:dead:beef::/48"
|
||||
}
|
||||
```
|
||||
|
||||
Restart Docker
|
||||
```shell
|
||||
systemctl restart docker
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
|
@ -236,36 +220,6 @@ This command does the following things:
|
|||
- Back up the file `/etc/ufw/after.rules`
|
||||
- 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
|
||||
|
||||
We can only use this script on manager nodes to manage firewall rules when using in Swarm mode.
|
||||
|
@ -335,7 +289,7 @@ Remove rules from all nodes related to the service `web`
|
|||
|
||||
### Try it out
|
||||
|
||||
We use [Vagrant](https://www.vagrantup.com/) to set up a local testing environment.
|
||||
We use [Vagrant](https://www.vagrantup.com/) to set up a local testing environment.
|
||||
|
||||
Run the following command to create 1 master node and 2 worker nodes
|
||||
|
||||
|
@ -452,7 +406,7 @@ UFW 是 Ubuntu 上很流行的一个 iptables 前端,可以非常方便的管
|
|||
|
||||
COMMIT
|
||||
# END UFW AND DOCKER
|
||||
|
||||
|
||||
然后重启 UFW,`sudo systemctl restart ufw`。现在外部就已经无法访问 Docker 发布出来的任何端口了,但是容器内部以及私有网络地址上可以正常互相访问,而且容器也可以正常访问外部的网络。**可能由于某些未知原因,重启 UFW 之后规则也无法生效,请重启服务器。**
|
||||
|
||||
如果希望允许外部网络访问 Docker 容器提供的服务,比如有一个容器的服务端口是 `80`。那就可以用以下命令来允许外部网络访问这个服务:
|
||||
|
@ -548,19 +502,6 @@ UFW 是 Ubuntu 上很流行的一个 iptables 前端,可以非常方便的管
|
|||
|
||||
不支持老版本的 Ubuntu,而且命令的使用上可能也会比较复杂。
|
||||
|
||||
### 支持 IPv6
|
||||
|
||||
要让 Docker Engine [启用 IPv6 的支持](https://forums.docker.com/t/docker-user-chain-for-ip6tables/133961/3). 你需要在 `/etc/docker/daemon.json` 文件中启用相关设置,并分配一个 ULA(唯一本地地址,RFC 4193)地址段作为 IPv6 网络范围。
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": true,
|
||||
"ipv6": true,
|
||||
"ip6tables": true,
|
||||
"fixed-cidr-v6": "fd00:dead:beef::/48"
|
||||
}
|
||||
```
|
||||
|
||||
#### 结论
|
||||
|
||||
如果我们正在使用老版本的 Ubuntu,我们可以使用 `ufw-user-input`。但是要小心避免把不该暴露的服务暴露出去。
|
||||
|
@ -587,33 +528,6 @@ UFW 是 Ubuntu 上很流行的一个 iptables 前端,可以非常方便的管
|
|||
- 备份文件 `/etc/ufw/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 环境安装
|
||||
|
||||
仅仅可以在管理节点上使用 `ufw-docker` 这个脚本来管理防火墙规则。
|
||||
|
@ -681,8 +595,6 @@ UFW 是 Ubuntu 上很流行的一个 iptables 前端,可以非常方便的管
|
|||
|
||||
ufw-docker service delete allow web
|
||||
|
||||
ufw-docker service delete allow web 80/tcp
|
||||
|
||||
### 试试
|
||||
|
||||
我们使用 [Vagrant](https://www.vagrantup.com/) 来创建一个本地的测试环境。
|
||||
|
|
220
Vagrantfile
vendored
220
Vagrantfile
vendored
|
@ -6,15 +6,9 @@
|
|||
ENV['VAGRANT_NO_PARALLEL']="true"
|
||||
|
||||
Vagrant.configure('2') do |config|
|
||||
ubuntu_version = File.readlines("Dockerfile").filter { |line|
|
||||
line.start_with?("FROM ")
|
||||
}.first.match(/\d\d\.\d\d/)[0]
|
||||
|
||||
docker_version = File.readlines("Dockerfile").filter { |line|
|
||||
line.start_with?("ARG docker_version=")
|
||||
}.first.match(/"([\d\.]+)"/)[1]
|
||||
|
||||
config.vm.box = "chaifeng/ubuntu-#{ubuntu_version}-docker-#{docker_version}"
|
||||
#config.vm.box = "chaifeng/ubuntu-22.04-docker-#{(`uname -m`.strip == "arm64")?"20.10.17-arm64":"19.03.13"}"
|
||||
config.vm.box = "chaifeng/ubuntu-20.04-docker-#{(`uname -m`.strip == "arm64")?"19.03.13-arm64":"19.03.13"}"
|
||||
|
||||
config.vm.provider 'virtualbox' do |vb|
|
||||
vb.memory = '1024'
|
||||
|
@ -27,35 +21,14 @@ Vagrant.configure('2') do |config|
|
|||
end
|
||||
|
||||
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
|
||||
[[ -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
|
||||
if [[ ! -f /etc/docker/daemon.json ]]; then
|
||||
echo '{' >> /etc/docker/daemon.json
|
||||
echo ' "insecure-registries": ["localhost:5000", "#{ip_prefix}.130:5000"]' >> /etc/docker/daemon.json
|
||||
[[ -n "#{ENV['DOCKER_REGISTRY_MIRROR']}" ]] &&
|
||||
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
|
||||
if type systemctl &>/dev/null; then
|
||||
systemctl restart docker
|
||||
|
@ -65,30 +38,27 @@ Vagrant.configure('2') do |config|
|
|||
fi
|
||||
SHELL
|
||||
|
||||
config.vm.provision 'ufw-docker', preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -xeuo pipefail
|
||||
config.vm.provision 'ufw-docker', type: 'shell', inline: <<-SHELL
|
||||
set -euo pipefail
|
||||
export DEBUG=true
|
||||
lsb_release -is | grep -Fi ubuntu
|
||||
/vagrant/ufw-docker check || {
|
||||
ufw allow OpenSSH
|
||||
ufw allow from #{ip_prefix}.128/28 to any
|
||||
|
||||
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 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
|
||||
ufw status | grep '^Status: active'
|
||||
|
||||
yes | ufw enable || true
|
||||
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/
|
||||
fi
|
||||
|
||||
iptables -I DOCKER-USER 4 -p udp -j LOG --log-prefix '[UFW DOCKER] '
|
||||
}
|
||||
SHELL
|
||||
|
||||
private_registry="#{ip_prefix}.130:5000"
|
||||
|
@ -97,14 +67,10 @@ Vagrant.configure('2') do |config|
|
|||
master_ip_address = "#{ip_prefix}.130"
|
||||
master.vm.hostname = "master"
|
||||
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', privileged: false, inline: <<-SHELL
|
||||
master.vm.provision "unit-testing", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -euo pipefail
|
||||
[[ -n "#{ENV['DISABLE_UNIT_TESTING']}" ]] ||
|
||||
/vagrant/test.sh
|
||||
/vagrant/test.sh
|
||||
SHELL
|
||||
|
||||
master.vm.provision "docker-registry", preserve_order: true, type: 'docker' do |d|
|
||||
|
@ -118,20 +84,18 @@ Vagrant.configure('2') do |config|
|
|||
ufw_docker_agent_image = "#{private_registry}/chaifeng/ufw-docker-agent:test"
|
||||
|
||||
master.vm.provision "docker-build-ufw-docker-agent", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -xeuo pipefail
|
||||
suffix="$(iptables --version | grep -o '\\(nf_tables\\|legacy\\)')"
|
||||
if [[ "$suffix" = legacy ]]; then use_iptables_legacy=true; else use_iptables_legacy=false; fi
|
||||
docker build --build-arg use_iptables_legacy="${use_iptables_legacy:-false}" -t "#{ufw_docker_agent_image}-${suffix}" /vagrant
|
||||
docker push "#{ufw_docker_agent_image}-${suffix}"
|
||||
set -euo pipefail
|
||||
docker build -t #{ufw_docker_agent_image}-legacy /vagrant
|
||||
docker push #{ufw_docker_agent_image}-legacy
|
||||
|
||||
echo "export UFW_DOCKER_AGENT_IMAGE=#{ufw_docker_agent_image}-${suffix}" > /etc/profile.d/ufw-docker.sh
|
||||
echo "export UFW_DOCKER_AGENT_IMAGE=#{ufw_docker_agent_image}-nf_tables" > /etc/profile.d/ufw-docker.sh
|
||||
echo "export DEBUG=true" >> /etc/profile.d/ufw-docker.sh
|
||||
|
||||
echo "Defaults env_keep += UFW_DOCKER_AGENT_IMAGE" > /etc/sudoers.d/98_ufw-docker
|
||||
echo "Defaults env_keep += DEBUG" >> /etc/sudoers.d/98_ufw-docker
|
||||
SHELL
|
||||
|
||||
master.vm.provision "swarm-init", preserve_order: true, type: 'shell', privileged: false, inline: <<-SHELL
|
||||
master.vm.provision "swarm-init", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -euo pipefail
|
||||
docker info | fgrep 'Swarm: active' && exit 0
|
||||
|
||||
|
@ -139,13 +103,11 @@ Vagrant.configure('2') do |config|
|
|||
docker swarm join-token worker --quiet > /vagrant/.vagrant/docker-join-token
|
||||
SHELL
|
||||
|
||||
master.vm.provision "build-webapp", preserve_order: true, type: 'shell', privileged: false, inline: <<-SHELL
|
||||
set -xeuo pipefail
|
||||
master.vm.provision "build-webapp", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -euo pipefail
|
||||
docker build -t #{private_registry}/chaifeng/hostname-webapp - <<\\DOCKERFILE
|
||||
FROM httpd:alpine
|
||||
|
||||
RUN printf "Listen %s\\n" 7000 8080 >> /usr/local/apache2/conf/httpd.conf
|
||||
|
||||
RUN { echo '#!/bin/sh'; \\
|
||||
echo 'set -e; (echo -n "${name:-Hi} "; hostname;) > /usr/local/apache2/htdocs/index.html'; \\
|
||||
echo 'exec "$@"'; \\
|
||||
|
@ -158,7 +120,7 @@ DOCKERFILE
|
|||
SHELL
|
||||
|
||||
master.vm.provision "local-webapp", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -xeuo pipefail
|
||||
set -euo pipefail
|
||||
for name in public:18080 local:8000; do
|
||||
webapp="${name%:*}_webapp"
|
||||
port="${name#*:}"
|
||||
|
@ -172,16 +134,12 @@ DOCKERFILE
|
|||
SHELL
|
||||
|
||||
master.vm.provision "multiple-network", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -xeuo pipefail
|
||||
declare -a docker_opts=()
|
||||
|
||||
set -euo pipefail
|
||||
if ! docker network ls | grep -F foo-internal; then
|
||||
! #{env_true_str?('ENABLE_DOCKER_IPV6')} || docker_opts=(--ipv6 --subnet fd05:8f23:c937:1::/64)
|
||||
docker network create --internal "${docker_opts[@]}" foo-internal
|
||||
docker network create --internal foo-internal
|
||||
fi
|
||||
if ! docker network ls | grep -F bar-external; then
|
||||
! #{env_true_str?('ENABLE_DOCKER_IPV6')} || docker_opts=(--ipv6 --subnet fd05:8f23:c937:2::/64)
|
||||
docker network create "${docker_opts[@]}" bar-external
|
||||
docker network create bar-external
|
||||
fi
|
||||
|
||||
for app in internal-multinet-app:7000 public-multinet-app:17070; do
|
||||
|
@ -199,42 +157,25 @@ DOCKERFILE
|
|||
SHELL
|
||||
|
||||
master.vm.provision "swarm-webapp", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
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
|
||||
set -euo pipefail
|
||||
for name in public:29090 local:9000; do
|
||||
webapp="${name%:*}_service"
|
||||
port="${name#*:}"
|
||||
if docker service inspect "$webapp" &>/dev/null; then docker service rm "$webapp"; fi
|
||||
docker service create --name "$webapp" "${docker_opts[@]}" \
|
||||
--publish "${port}:80" --env name="$webapp" --replicas #{worker_count} #{private_registry}/chaifeng/hostname-webapp
|
||||
docker service create --name "$webapp" \
|
||||
--publish "${port}:80" --env name="$webapp" --replicas 3 #{private_registry}/chaifeng/hostname-webapp
|
||||
done
|
||||
|
||||
ufw-docker service allow public_service 80/tcp
|
||||
|
||||
docker service inspect "public_multiport" ||
|
||||
docker service create --name "public_multiport" "${docker_opts[@]}" \
|
||||
--publish "40080:80" --publish "47000:7000" --publish "48080:8080" \
|
||||
--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 8080/tcp
|
||||
SHELL
|
||||
end
|
||||
|
||||
1.upto worker_count do |ip|
|
||||
1.upto 2 do |ip|
|
||||
config.vm.define "node#{ip}" do | node |
|
||||
node.vm.hostname = "node#{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 "node#{ip}-swarm-join", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
node.vm.provision "swarm-join", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -euo pipefail
|
||||
docker info | fgrep 'Swarm: active' && exit 0
|
||||
|
||||
|
@ -244,92 +185,27 @@ DOCKERFILE
|
|||
end
|
||||
end
|
||||
|
||||
config.vm.define "node-internal" do |node|
|
||||
node.vm.hostname = "node-internal"
|
||||
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
|
||||
|
||||
config.vm.define "external" do |external|
|
||||
external.vm.hostname = "external"
|
||||
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', privileged: false, inline: <<-SHELL
|
||||
set -xuo pipefail
|
||||
error_count=0
|
||||
function test-webapp() {
|
||||
local actual=""
|
||||
external.vm.provision "testing", preserve_order: true, type: 'shell', inline: <<-SHELL
|
||||
set -euo pipefail
|
||||
set -x
|
||||
server="http://#{ip_prefix}.130"
|
||||
function test-webapp() { timeout 3 curl --silent "$@"; }
|
||||
test-webapp "$server:18080"
|
||||
! test-webapp "$server:8000"
|
||||
|
||||
if [[ "$#" -eq 2 ]]; then
|
||||
local expect_fail='!'
|
||||
url="$2"
|
||||
else
|
||||
url="$1"
|
||||
fi
|
||||
test-webapp "$server:17070" # multiple networks app
|
||||
! test-webapp "$server:7000" # internal multiple networks app
|
||||
|
||||
timeout 3 curl --silent "$url" || actual='!'
|
||||
test-webapp "$server:29090"
|
||||
! test-webapp "$server:9000"
|
||||
|
||||
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:8000"
|
||||
|
||||
test-webapp "$server:17070" # 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:40080"
|
||||
test-webapp "$server:48080"
|
||||
|
||||
}
|
||||
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 "====================="
|
||||
if [[ "$error_count" -eq 0 ]]; then echo " TEST DONE "
|
||||
else echo " TESTS FAIL: ${error_count}"
|
||||
fi
|
||||
echo " TEST DONE "
|
||||
echo "====================="
|
||||
exit "${error_count}"
|
||||
} 2>/dev/null
|
||||
SHELL
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
[[ "${DEBUG:-}" = true ]] && set -x
|
||||
[[ -n "${DEBUG:-}" ]] && set -x
|
||||
[[ 0 -eq "$#" ]] && set -- start
|
||||
|
||||
ufw_docker_agent=ufw-docker-agent
|
||||
|
@ -10,12 +10,8 @@ function ufw-allow-or-deny-service() {
|
|||
declare id="$1"
|
||||
declare port="$2"
|
||||
|
||||
if [[ "$port" = deny || "$port" = */deny ]]; then
|
||||
port="${port%deny}"
|
||||
port="${port%/}"
|
||||
declare -a opts=("$id")
|
||||
[[ -z "$port" ]] || opts+=("$port")
|
||||
run-ufw-docker delete allow "${opts[@]}"
|
||||
if [[ "$port" = deny ]]; then
|
||||
run-ufw-docker delete allow "$id"
|
||||
else
|
||||
run-ufw-docker add-service-rule "$id" "$port"
|
||||
fi
|
||||
|
@ -26,14 +22,8 @@ function update-ufw-rules() {
|
|||
-e 's/^declare -x ufw_public_//' \
|
||||
-e 's/="/ /' \
|
||||
-e 's/"$//' |
|
||||
while read -r id ruleset; do
|
||||
declare -a rules=( $(tr ',' '\n' <<< "$ruleset") )
|
||||
for rule in "${rules[@]}"; do
|
||||
[[ "$rule" = */deny ]] && ufw-allow-or-deny-service "${id}" "${rule#*/}"
|
||||
done
|
||||
for rule in "${rules[@]}"; do
|
||||
[[ "$rule" = */deny ]] || ufw-allow-or-deny-service "${id}" "${rule#*/}"
|
||||
done
|
||||
while read -r id port; do
|
||||
ufw-allow-or-deny-service "${id}" "${port#*/}"
|
||||
done
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 871528a805b21e3c4432e4c23cacc3c4f4ddfc39
|
||||
Subproject commit 447edb60db232d3dbc2267f37c49bd7a070cc83d
|
|
@ -6,8 +6,9 @@ source "$working_dir"/bach/bach.sh
|
|||
|
||||
@setup {
|
||||
set -euo pipefail
|
||||
|
||||
ufw_docker_agent=ufw-docker-agent
|
||||
ufw_docker_agent_image=chaifeng/ufw-docker-agent:090502
|
||||
ufw_docker_agent_image=chaifeng/ufw-docker-agent:181005
|
||||
}
|
||||
|
||||
@setup-test {
|
||||
|
@ -18,17 +19,9 @@ source "$working_dir"/bach/bach.sh
|
|||
@ignore echo
|
||||
@ignore err
|
||||
|
||||
UFW_DOCKER_AGENT_IMAGE=chaifeng/ufw-docker-agent:090502
|
||||
builtin source <(@sed -n -e '/^# UFW-DOCKER GLOBAL VARIABLES START #$/,/^# UFW-DOCKER GLOBAL VARIABLES END #$/{' -e '/^PATH=/d' -e 'p' -e '}' "$working_dir/../ufw-docker")
|
||||
|
||||
DEFAULT_PROTO=tcp
|
||||
GREP_REGEXP_INSTANCE_NAME="[-_.[:alnum:]]\\+"
|
||||
DEBUG=false
|
||||
|
||||
unset RANDOM
|
||||
RANDOM=42
|
||||
|
||||
@allow-real sed -e '/^ufw_public_/!d' -e 's/^ufw_public_//' -e 's/=/ /'
|
||||
@allow-real tr ',' '\n'
|
||||
@allow-real grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
}
|
||||
|
||||
function die() {
|
||||
|
@ -117,26 +110,6 @@ test-ufw-docker--service-delete-allow-webapp-assert() {
|
|||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-allow-webapp-8080-tcp() {
|
||||
load-ufw-docker-function ufw-docker--service
|
||||
|
||||
ufw-docker--service delete allow webapp 8080/tcp
|
||||
}
|
||||
test-ufw-docker--service-delete-allow-webapp-8080-tcp-assert() {
|
||||
ufw-docker--service-delete webapp 8080/tcp
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-allow-webapp-8080() {
|
||||
load-ufw-docker-function ufw-docker--service
|
||||
|
||||
ufw-docker--service delete allow webapp 8080
|
||||
}
|
||||
test-ufw-docker--service-delete-allow-webapp-8080-assert() {
|
||||
ufw-docker--service-delete webapp 8080
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--get-service-id() {
|
||||
load-ufw-docker-function ufw-docker--get-service-id
|
||||
ufw-docker--get-service-id database
|
||||
|
@ -156,6 +129,8 @@ test-ufw-docker--get-service-name-assert() {
|
|||
|
||||
|
||||
test-ufw-docker--service-allow-invalid-port-syntax() {
|
||||
@mockfalse grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
ufw-docker--service-allow webapp invalid-port
|
||||
}
|
||||
|
@ -166,6 +141,7 @@ test-ufw-docker--service-allow-invalid-port-syntax-assert() {
|
|||
|
||||
|
||||
test-ufw-docker--service-allow-an-non-existed-service() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id web404 === @stdout ""
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
|
@ -178,9 +154,11 @@ test-ufw-docker--service-allow-an-non-existed-service-assert() {
|
|||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-without-ports-published() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id private-web === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name private-web === @stdout private-web
|
||||
@mock ufw-docker--list-service-ports private-web === @stdout ""
|
||||
@mock docker service inspect private-web \
|
||||
--format '{{range .Endpoint.Spec.Ports}}{{.PublishedPort}} {{.TargetPort}}/{{.Protocol}}{{"\n"}}{{end}}' === @stdout ""
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
ufw-docker--service-allow private-web 80/tcp
|
||||
|
@ -192,9 +170,12 @@ test-ufw-docker--service-allow-a-service-without-ports-published-assert() {
|
|||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-while-agent-not-running() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
@mock docker service inspect webapp \
|
||||
--format '{{range .Endpoint.Spec.Ports}}{{.PublishedPort}} {{.TargetPort}}/{{.Protocol}}{{"\n"}}{{end}}' \
|
||||
=== @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
@mockfalse docker service inspect ufw-docker-agent
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
|
@ -204,17 +185,20 @@ test-ufw-docker--service-allow-a-service-while-agent-not-running-assert() {
|
|||
docker service create --name ufw-docker-agent --mode global \
|
||||
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
|
||||
--mount type=bind,source=/etc/ufw,target=/etc/ufw,readonly=true \
|
||||
--env ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env ufw_docker_agent_image="chaifeng/ufw-docker-agent:181005" \
|
||||
--env DEBUG="false" \
|
||||
--env "ufw_public_abcd1234=webapp/80/tcp" \
|
||||
"chaifeng/ufw-docker-agent:090502"
|
||||
"chaifeng/ufw-docker-agent:181005"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-add-new-env() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
@mock docker service inspect webapp \
|
||||
--format '{{range .Endpoint.Spec.Ports}}{{.PublishedPort}} {{.TargetPort}}/{{.Protocol}}{{"\n"}}{{end}}' \
|
||||
=== @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
@mocktrue docker service inspect ufw-docker-agent
|
||||
@mock ufw-docker--get-env-list === @stdout "abcd1234 webapp/80/tcp"
|
||||
|
||||
|
@ -223,18 +207,21 @@ test-ufw-docker--service-allow-a-service-add-new-env() {
|
|||
}
|
||||
test-ufw-docker--service-allow-a-service-add-new-env-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:181005" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
--image "chaifeng/ufw-docker-agent:181005" \
|
||||
ufw-docker-agent
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-update-a-env() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
@mock docker service inspect webapp \
|
||||
--format '{{range .Endpoint.Spec.Ports}}{{.PublishedPort}} {{.TargetPort}}/{{.Protocol}}{{"\n"}}{{end}}' \
|
||||
=== @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
@mocktrue docker service inspect ufw-docker-agent
|
||||
@mock ufw-docker--get-env-list === @stdout "a_different_id webapp/80/tcp"
|
||||
|
||||
|
@ -243,60 +230,11 @@ test-ufw-docker--service-allow-a-service-update-a-env() {
|
|||
}
|
||||
test-ufw-docker--service-allow-a-service-update-a-env-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:181005" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-rm "ufw_public_a_different_id" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
ufw-docker-agent
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-add-value-to-an-env() {
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "5353 53/udp" "8080 80/tcp" "18080 8080/tcp"
|
||||
@mocktrue docker service inspect ufw-docker-agent
|
||||
@mock ufw-docker--get-env-list === @stdout "a_different_id webapp/8080/tcp" "abcd1234 webapp/5353/udp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
ufw-docker--service-allow webapp 80/tcp
|
||||
ufw-docker--service-allow webapp 8080/tcp
|
||||
}
|
||||
test-ufw-docker--service-allow-a-service-add-value-to-an-env-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-rm "ufw_public_a_different_id" \
|
||||
--env-add "ufw_public_abcd1234=webapp/8080/tcp,webapp/5353/udp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
ufw-docker-agent
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-rm "ufw_public_a_different_id" \
|
||||
--env-add "ufw_public_abcd1234=webapp/18080/tcp,webapp/5353/udp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
ufw-docker-agent
|
||||
}
|
||||
|
||||
test-ufw-docker--service-allow-a-service-denied-port() {
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "5353 53/udp" "8080 80/tcp" "18080 8080/tcp"
|
||||
@mocktrue docker service inspect ufw-docker-agent
|
||||
@mock ufw-docker--get-env-list === @stdout "a_different_id webapp/8080/tcp" "abcd1234 webapp/8080/tcp/deny" "abcd1234 webapp/5353/udp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
ufw-docker--service-allow webapp 80/tcp
|
||||
}
|
||||
test-ufw-docker--service-allow-a-service-denied-port-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-rm "ufw_public_a_different_id" \
|
||||
--env-add "ufw_public_abcd1234=webapp/8080/tcp,webapp/5353/udp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
--image "chaifeng/ufw-docker-agent:181005" \
|
||||
ufw-docker-agent
|
||||
}
|
||||
|
||||
|
@ -305,50 +243,27 @@ test-ufw-docker--get-env-list() {
|
|||
@mock docker service inspect ufw-docker-agent \
|
||||
--format '{{range $k,$v := .Spec.TaskTemplate.ContainerSpec.Env}}{{ $v }}{{"\n"}}{{end}}' \
|
||||
=== @stdout \
|
||||
"ufw_docker_agent_image=192.168.56.130:5000/chaifeng/ufw-docker-agent:test" \
|
||||
"DEBUG=true" \
|
||||
"ufw_public_id111111=webapp/9090/tcp" \
|
||||
"ufw_public_id222222=foo/2222/udp" \
|
||||
"OTHER_ENV=blabla"
|
||||
"ufw_docker_agent_image=192.168.56.130:5000/chaifeng/ufw-docker-agent:test" \
|
||||
"DEBUG=true" \
|
||||
"ufw_public_zv6esvmwnmmgnlauqn7m77jo4=webapp/9090/tcp" \
|
||||
"OTHER_ENV=blabla"
|
||||
|
||||
@allow-real sed "s/^/id111111 /g"
|
||||
@allow-real sed "s/^/id222222 /g"
|
||||
@mock sed -e '/^ufw_public_/!d' \
|
||||
-e 's/^ufw_public_//' \
|
||||
-e 's/=/ /' === @real sed -e '/^ufw_public_/!d' \
|
||||
-e 's/^ufw_public_//' \
|
||||
-e 's/=/ /'
|
||||
|
||||
load-ufw-docker-function ufw-docker--get-env-list
|
||||
ufw-docker--get-env-list
|
||||
}
|
||||
test-ufw-docker--get-env-list-assert() {
|
||||
@stdout "id111111 webapp/9090/tcp"
|
||||
@stdout "id222222 foo/2222/udp"
|
||||
}
|
||||
|
||||
test-ufw-docker--get-env-list-multiple() {
|
||||
@mock docker service inspect ufw-docker-agent \
|
||||
--format '{{range $k,$v := .Spec.TaskTemplate.ContainerSpec.Env}}{{ $v }}{{"\n"}}{{end}}' \
|
||||
=== @stdout \
|
||||
"ufw_docker_agent_image=192.168.56.130:5000/chaifeng/ufw-docker-agent:test" \
|
||||
"DEBUG=true" \
|
||||
"ufw_public_id111111=webapp/9090/tcp,webapp/8888/tcp,webapp/5555/udp" \
|
||||
"ufw_public_id222222=foo/2222/udp,foo/3333/tcp" \
|
||||
"OTHER_ENV=blabla"
|
||||
|
||||
@allow-real sed "s/^/id111111 /g"
|
||||
@allow-real sed "s/^/id222222 /g"
|
||||
|
||||
load-ufw-docker-function ufw-docker--get-env-list
|
||||
ufw-docker--get-env-list
|
||||
}
|
||||
test-ufw-docker--get-env-list-multiple-assert() {
|
||||
@stdout "id111111 webapp/9090/tcp"
|
||||
@stdout "id111111 webapp/8888/tcp"
|
||||
@stdout "id111111 webapp/5555/udp"
|
||||
@stdout "id222222 foo/2222/udp"
|
||||
@stdout "id222222 foo/3333/tcp"
|
||||
@stdout "zv6esvmwnmmgnlauqn7m77jo4 webapp/9090/tcp"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-no-matches() {
|
||||
@mockfalse ufw-docker--get-service-id webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "ffff111 foo/80/tcp" "eeee2222 bar/53/udp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp
|
||||
|
@ -358,15 +273,9 @@ test-ufw-docker--service-delete-no-matches-assert() {
|
|||
@fail
|
||||
}
|
||||
|
||||
function mock-abcd1234-webapp() {
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--get-service-id webapp === @stdout "abcd1234"
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "22 2222/tcp" "80 8080/tcp" "53 5353/udp"
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/22/tcp"
|
||||
@mock ufw-docker--get-env-list === @stdout "ffff111 foo/80/tcp" "eeee2222 bar/53/udp" "abcd1234 webapp/5000/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp
|
||||
|
@ -375,188 +284,6 @@ test-ufw-docker--service-delete-matches-assert() {
|
|||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/deny" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches2() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/22/tcp" "abcd1234 webapp/53/udp" "abcd1234 webapp/80/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp
|
||||
}
|
||||
test-ufw-docker--service-delete-matches2-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/deny" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/80/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 8080
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp/deny" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port2() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/80/tcp" "abcd1234 webapp/53/udp" "abcd1234 webapp/53/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 8080
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port2-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp/deny,webapp/53/udp,webapp/53/tcp" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port-but-no-previous-rule() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/53/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 2222
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port-but-no-previous-rule-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/22/tcp/deny,webapp/53/tcp" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port-proto-pair() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/80/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 8080/tcp
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port-proto-pair-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp/deny" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port-proto-pair2() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/80/tcp" "abcd1234 webapp/53/udp" "abcd1234 webapp/53/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 5353/udp
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port-proto-pair2-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/53/udp/deny,webapp/80/tcp,webapp/53/tcp" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-not-matched-port() {
|
||||
mock-abcd1234-webapp
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 3333
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-not-matched-port-assert() {
|
||||
@do-nothing
|
||||
@fail
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-not-matched-protocal() {
|
||||
@mock ufw-docker--get-service-id webapp === @stdout "abcd1234"
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "22 2222/tcp" "80 8080/tcp" "53 5353/udp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 8080/udp
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-not-matched-protocal-assert() {
|
||||
@do-nothing
|
||||
@fail
|
||||
}
|
||||
|
||||
test-ufw-docker--list-service-ports() {
|
||||
load-ufw-docker-function ufw-docker--list-service-ports
|
||||
ufw-docker--list-service-ports foo
|
||||
}
|
||||
test-ufw-docker--list-service-ports-assert() {
|
||||
docker service inspect foo --format '{{range .Endpoint.Spec.Ports}}{{.PublishedPort}} {{.TargetPort}}/{{.Protocol}}{{"\n"}}{{end}}'
|
||||
}
|
||||
|
||||
function setup-mock-for-testing-docker-entrypoint() {
|
||||
@mock date '+%Y%m%d%H%M%S' === @stdout 200902140731
|
||||
|
||||
declare -gx ufw_public_id111111=alpha/80/tcp
|
||||
declare -gx ufw_public_id222222=beta/deny
|
||||
declare -gx ufw_public_id333333=gamma/8080/tcp/deny,gamma/5353/udp
|
||||
|
||||
@allow-real sed -e '/^declare -x ufw_public_/!d' -e 's/^declare -x ufw_public_//' -e 's/="/ /' -e 's/"$//'
|
||||
@allow-real tr ',' '\n'
|
||||
}
|
||||
|
||||
test-dockerentrypoint() {
|
||||
setup-mock-for-testing-docker-entrypoint
|
||||
declare -x ufw_public_id333333=gamma/8080/tcp/deny,gamma/5353/udp
|
||||
|
||||
@run "$working_dir"/../docker-entrypoint.sh update-ufw-rules
|
||||
}
|
||||
test-dockerentrypoint-assert() {
|
||||
declare -a docker_opts=(run --rm -t --name ufw-docker-agent-42-200902140731
|
||||
--cap-add NET_ADMIN --network host --env DEBUG=false
|
||||
-v /var/run/docker.sock:/var/run/docker.sock
|
||||
-v /etc/ufw:/etc/ufw
|
||||
chaifeng/ufw-docker-agent:090502
|
||||
)
|
||||
docker "${docker_opts[@]}" add-service-rule id111111 80/tcp
|
||||
docker "${docker_opts[@]}" delete allow id222222
|
||||
docker "${docker_opts[@]}" delete allow id333333 8080/tcp
|
||||
docker "${docker_opts[@]}" add-service-rule id333333 5353/udp
|
||||
}
|
||||
|
||||
test-dockerentrypoint-deny-first() {
|
||||
setup-mock-for-testing-docker-entrypoint
|
||||
declare -x ufw_public_id333333=gamma/5353/udp,gamma/8080/tcp/deny
|
||||
|
||||
@run "$working_dir"/../docker-entrypoint.sh update-ufw-rules
|
||||
}
|
||||
test-dockerentrypoint-deny-first-assert() {
|
||||
declare -a docker_opts=(run --rm -t --name ufw-docker-agent-42-200902140731
|
||||
--cap-add NET_ADMIN --network host --env DEBUG=false
|
||||
-v /var/run/docker.sock:/var/run/docker.sock
|
||||
-v /etc/ufw:/etc/ufw
|
||||
chaifeng/ufw-docker-agent:090502
|
||||
)
|
||||
docker "${docker_opts[@]}" add-service-rule id111111 80/tcp
|
||||
docker "${docker_opts[@]}" delete allow id222222
|
||||
docker "${docker_opts[@]}" delete allow id333333 8080/tcp
|
||||
docker "${docker_opts[@]}" add-service-rule id333333 5353/udp
|
||||
}
|
||||
|
|
|
@ -15,14 +15,13 @@ source "$working_dir"/bach/bach.sh
|
|||
@mock iptables --version
|
||||
@mocktrue grep -F '(legacy)'
|
||||
|
||||
@mocktrue docker -v
|
||||
@mock docker -v === @stdout Docker version 0.0.0, build dummy
|
||||
|
||||
@mockpipe remove_blank_lines
|
||||
#@ignore echo
|
||||
@ignore remove_blank_lines
|
||||
@ignore echo
|
||||
@ignore err
|
||||
|
||||
builtin source <(@sed -n -e '/^# UFW-DOCKER GLOBAL VARIABLES START #$/,/^# UFW-DOCKER GLOBAL VARIABLES END #$/{' -e '/^PATH=/d' -e 'p' -e '}' "$working_dir/../ufw-docker")
|
||||
DEFAULT_PROTO=tcp
|
||||
GREP_REGEXP_INSTANCE_NAME="[-_.[:alnum:]]\\+"
|
||||
|
||||
UFW_DOCKER_AGENT_IMAGE=chaifeng/ufw-docker-agent:090502-legacy
|
||||
}
|
||||
|
||||
|
@ -32,6 +31,7 @@ function ufw-docker() {
|
|||
|
||||
function load-ufw-docker-function() {
|
||||
set -euo pipefail
|
||||
|
||||
@load_function "$working_dir/../ufw-docker" "$1"
|
||||
}
|
||||
|
||||
|
@ -98,17 +98,6 @@ test-ufw-is-disabled-assert() {
|
|||
}
|
||||
|
||||
|
||||
test-docker-is-installed() {
|
||||
@mockfalse docker -v
|
||||
|
||||
ufw-docker
|
||||
}
|
||||
test-docker-is-installed-assert() {
|
||||
die "Docker executable not found."
|
||||
ufw-docker--help
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker-status() {
|
||||
ufw-docker status
|
||||
}
|
||||
|
@ -125,14 +114,6 @@ 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() {
|
||||
ufw-docker check
|
||||
}
|
||||
|
@ -141,14 +122,6 @@ 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() {
|
||||
ufw-docker service allow httpd
|
||||
}
|
||||
|
@ -259,6 +232,15 @@ 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() {
|
||||
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
|
||||
ufw-docker delete allow httpd
|
||||
|
@ -281,15 +263,8 @@ function setup-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"
|
||||
@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 .NetworkSettings.Networks}}{{.IPAddress}}{{"\n"}}{{end}}' instance-name === @stdout 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
|
||||
}
|
||||
|
||||
|
@ -297,15 +272,8 @@ function setup-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" "awesomenet 172.19.0.7"
|
||||
@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 .NetworkSettings.Networks}}{{.IPAddress}}{{"\n"}}{{end}}' instance-name === @stdout 172.18.0.3 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
|
||||
}
|
||||
|
||||
|
@ -405,86 +373,8 @@ 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
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
@mockfalse ufw-docker--list webapp 5000 tcp ""
|
||||
@ignore echo
|
||||
|
||||
load-ufw-docker-function ufw-docker--add-rule
|
||||
ufw-docker--add-rule webapp 172.18.0.4 5000 tcp
|
||||
|
@ -495,7 +385,6 @@ test-ufw-docker--add-rule-a-non-existing-rule-assert() {
|
|||
|
||||
test-ufw-docker--add-rule-a-non-existing-rule-with-network() {
|
||||
@mockfalse ufw-docker--list webapp 5000 tcp default
|
||||
@ignore echo
|
||||
|
||||
load-ufw-docker-function ufw-docker--add-rule
|
||||
ufw-docker--add-rule webapp 172.18.0.4 5000 tcp default
|
||||
|
@ -507,9 +396,8 @@ test-ufw-docker--add-rule-a-non-existing-rule-with-network-assert() {
|
|||
|
||||
test-ufw-docker--add-rule-modify-an-existing-rule() {
|
||||
@mocktrue ufw-docker--list 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
|
||||
@mocktrue ufw --dry-run route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp default"
|
||||
@mockfalse grep "^Skipping"
|
||||
@ignore echo
|
||||
|
||||
load-ufw-docker-function ufw-docker--add-rule
|
||||
ufw-docker--add-rule webapp 172.18.0.4 5000 tcp default
|
||||
|
@ -521,27 +409,10 @@ 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"
|
||||
@ignore echo
|
||||
|
||||
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() {
|
||||
@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 grep "^Skipping"
|
||||
@ignore echo
|
||||
|
||||
load-ufw-docker-function ufw-docker--add-rule
|
||||
ufw-docker--add-rule webapp 172.18.0.4 5000 tcp ""
|
||||
|
@ -553,9 +424,9 @@ test-ufw-docker--add-rule-skip-an-existing-rule-assert() {
|
|||
|
||||
test-ufw-docker--add-rule-modify-an-existing-rule-without-port() {
|
||||
@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"
|
||||
@ignore echo
|
||||
|
||||
load-ufw-docker-function ufw-docker--add-rule
|
||||
|
||||
|
@ -571,7 +442,7 @@ test-ufw-docker--add-rule-modify-an-existing-rule-without-port-assert() {
|
|||
test-ufw-docker--instance-name-found-a-name() {
|
||||
@mock docker inspect --format="{{.Name}}" foo
|
||||
@mock sed -e 's,^/,,'
|
||||
@mockfalse grep "^$GREP_REGEXP_NAME\$"
|
||||
@mockfalse grep "^$GREP_REGEXP_INSTANCE_NAME\$"
|
||||
|
||||
@mock echo -n foo
|
||||
|
||||
|
@ -580,158 +451,59 @@ test-ufw-docker--instance-name-found-a-name() {
|
|||
}
|
||||
test-ufw-docker--instance-name-found-a-name-assert() {
|
||||
docker inspect --format="{{.Name}}" foo
|
||||
@dryrun echo -n foo
|
||||
echo -n foo
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--instance-name-found-an-id() {
|
||||
@mock docker inspect --format="{{.Name}}" fooid
|
||||
@mock sed -e 's,^/,,'
|
||||
@mockfalse grep "^$GREP_REGEXP_NAME\$"
|
||||
@mock echo -n fooid
|
||||
@mockfalse grep "^$GREP_REGEXP_INSTANCE_NAME\$"
|
||||
|
||||
load-ufw-docker-function ufw-docker--instance-name
|
||||
ufw-docker--instance-name fooid
|
||||
}
|
||||
test-ufw-docker--instance-name-found-an-id-assert() {
|
||||
docker inspect --format="{{.Name}}" fooid
|
||||
@dryrun echo -n fooid
|
||||
}
|
||||
|
||||
function mock-ufw-status-numbered-foo() {
|
||||
@mock ufw status numbered === @echo "Status: active
|
||||
|
||||
To Action From
|
||||
-- ------ ----
|
||||
[ 1] OpenSSH ALLOW IN Anywhere
|
||||
[ 2] Anywhere ALLOW IN 192.168.56.128/28
|
||||
[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge
|
||||
[ 4] 172.20.0.3 80/tcp ALLOW FWD Anywhere # allow bar 80/tcp bar-external
|
||||
[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal
|
||||
[ 6] 172.17.0.3 53/tcp ALLOW FWD Anywhere # allow foo 53/tcp
|
||||
[ 7] 172.18.0.2 29090/tcp ALLOW FWD Anywhere # allow id111111 29090/tcp
|
||||
[ 8] 172.18.0.2 48080/tcp ALLOW FWD Anywhere # allow id222222 48080/tcp
|
||||
[ 9] 172.18.0.2 40080/tcp ALLOW FWD Anywhere # allow id333333 40080/tcp
|
||||
[10] OpenSSH (v6) ALLOW IN Anywhere (v6)
|
||||
[11] Anywhere (v6) ALLOW IN fd00:a:b:0:cafe::/80
|
||||
[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge
|
||||
[13] fd05:8f23:c937:2::3 80/tcp ALLOW FWD Anywhere (v6) # allow bar/v6 80/tcp bar-external
|
||||
[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal
|
||||
[15] fd00:a:b:deaf::3 53/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 53/tcp
|
||||
"
|
||||
|
||||
}
|
||||
|
||||
test-ufw-docker--status() {
|
||||
mock-ufw-status-numbered-foo
|
||||
@allow-real grep '# allow [-_.[:alnum:]]\+\(/v6\)\?\( [[:digit:]]\+/\(tcp\|udp\)\( [-_.[:alnum:]]\+\)\?\)\?$'
|
||||
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
load-ufw-docker-function ufw-docker--status
|
||||
ufw-docker--status
|
||||
}
|
||||
test-ufw-docker--status-assert() {
|
||||
test-ufw-docker--list-all-assert
|
||||
}
|
||||
|
||||
test-ufw-docker--list-all() {
|
||||
mock-ufw-status-numbered-foo
|
||||
@allow-real grep '# allow [-_.[:alnum:]]\+\(/v6\)\?\( [[:digit:]]\+/\(tcp\|udp\)\( [-_.[:alnum:]]\+\)\?\)\?$'
|
||||
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
ufw-docker--list
|
||||
}
|
||||
test-ufw-docker--list-all-assert() {
|
||||
@stdout "[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge"
|
||||
@stdout "[ 4] 172.20.0.3 80/tcp ALLOW FWD Anywhere # allow bar 80/tcp bar-external"
|
||||
@stdout "[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal"
|
||||
@stdout "[ 6] 172.17.0.3 53/tcp ALLOW FWD Anywhere # allow foo 53/tcp"
|
||||
@stdout "[ 7] 172.18.0.2 29090/tcp ALLOW FWD Anywhere # allow id111111 29090/tcp"
|
||||
@stdout "[ 8] 172.18.0.2 48080/tcp ALLOW FWD Anywhere # allow id222222 48080/tcp"
|
||||
@stdout "[ 9] 172.18.0.2 40080/tcp ALLOW FWD Anywhere # allow id333333 40080/tcp"
|
||||
@stdout "[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge"
|
||||
@stdout "[13] fd05:8f23:c937:2::3 80/tcp ALLOW FWD Anywhere (v6) # allow bar/v6 80/tcp bar-external"
|
||||
@stdout "[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal"
|
||||
@stdout "[15] fd00:a:b:deaf::3 53/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 53/tcp"
|
||||
}
|
||||
|
||||
test-ufw-docker--list-name() {
|
||||
mock-ufw-status-numbered-foo
|
||||
@allow-real grep '# allow foo\(/v6\)\?\( [[:digit:]]\+/\(tcp\|udp\)\( [-_.[:alnum:]]\+\)\?\)\?$'
|
||||
|
||||
@mocktrue ufw status numbered
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
ufw-docker--list foo
|
||||
}
|
||||
test-ufw-docker--list-name-assert() {
|
||||
@stdout "[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge"
|
||||
@stdout "[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal"
|
||||
@stdout "[ 6] 172.17.0.3 53/tcp ALLOW FWD Anywhere # allow foo 53/tcp"
|
||||
@stdout "[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge"
|
||||
@stdout "[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal"
|
||||
@stdout "[15] fd00:a:b:deaf::3 53/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 53/tcp"
|
||||
grep "# allow foo\\( [[:digit:]]\\+\\/\\(tcp\\|udp\\)\\)\\?\\( [[:graph:]]*\\)\\?\$"
|
||||
}
|
||||
|
||||
test-ufw-docker--list-name-udp() {
|
||||
mock-ufw-status-numbered-foo
|
||||
@allow-real grep '# allow foo\(/v6\)\? [[:digit:]]\+/udp\( [-_.[:alnum:]]\+\)\?$'
|
||||
|
||||
@mocktrue ufw status numbered
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
ufw-docker--list foo "" udp
|
||||
}
|
||||
test-ufw-docker--list-name-udp-assert() {
|
||||
@stdout "[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal"
|
||||
@stdout "[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal"
|
||||
grep "# allow foo\\( [[:digit:]]\\+\\/\\(tcp\\|udp\\)\\)\\?\\( [[:graph:]]*\\)\\?\$"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--list-name-80-_-bridge() {
|
||||
mock-ufw-status-numbered-foo
|
||||
@allow-real grep '# allow foo\(/v6\)\? 80/tcp bridge$'
|
||||
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
ufw-docker--list foo 80 "" bridge
|
||||
}
|
||||
test-ufw-docker--list-name-80-_-bridge-assert() {
|
||||
@stdout "[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge"
|
||||
@stdout "[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--list-name-53-udp() {
|
||||
mock-ufw-status-numbered-foo
|
||||
@allow-real grep '# allow foo\(/v6\)\? 53/udp\( [-_.[:alnum:]]\+\)\?$'
|
||||
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
ufw-docker--list foo 53 udp
|
||||
}
|
||||
test-ufw-docker--list-name-53-udp-assert() {
|
||||
@stdout "[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal"
|
||||
@stdout "[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--list-grep-with-incorrect-network() {
|
||||
mock-ufw-status-numbered-foo
|
||||
@allow-real grep '# allow foo\(/v6\)\? 53/udp incorrect-network$'
|
||||
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
ufw-docker--list foo 53 udp incorrect-network
|
||||
}
|
||||
test-ufw-docker--list-grep-with-incorrect-network-assert() {
|
||||
@fail
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--list-foo-80-_-_() {
|
||||
mock-ufw-status-numbered-foo
|
||||
@allow-real grep '# allow foo\(/v6\)\? 80/tcp\( [-_.[:alnum:]]\+\)\?$'
|
||||
|
||||
test-ufw-docker--list-name-80() {
|
||||
@mocktrue ufw status numbered
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
ufw-docker--list foo 80
|
||||
}
|
||||
test-ufw-docker--list-foo-80-_-_-assert() {
|
||||
@stdout "[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge"
|
||||
@stdout "[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge"
|
||||
test-ufw-docker--list-name-80-assert() {
|
||||
grep "# allow foo\\( 80\\/tcp\\)\\?\\( [[:graph:]]*\\)\\?\$"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--list-name-80-udp() {
|
||||
@mocktrue ufw status numbered
|
||||
load-ufw-docker-function ufw-docker--list
|
||||
ufw-docker--list foo 80 udp
|
||||
}
|
||||
test-ufw-docker--list-name-80-udp-assert() {
|
||||
grep "# allow foo\\( 80\\/udp\\)\\?\\( [[:graph:]]*\\)\\?\$"
|
||||
}
|
||||
|
||||
|
||||
|
@ -748,7 +520,7 @@ test-ufw-docker--list-number-assert() {
|
|||
|
||||
test-ufw-docker--delete-empty-result() {
|
||||
@mock ufw-docker--list-number webapp 80 tcp === @stdout ""
|
||||
@mockpipe sort -rn
|
||||
@mock sort -rn
|
||||
|
||||
load-ufw-docker-function ufw-docker--delete
|
||||
ufw-docker--delete webapp 80 tcp
|
||||
|
@ -760,8 +532,7 @@ test-ufw-docker--delete-empty-result-assert() {
|
|||
|
||||
test-ufw-docker--delete-all() {
|
||||
@mock ufw-docker--list-number webapp 80 tcp === @stdout 5 8 9
|
||||
@mockpipe sort -rn
|
||||
@ignore echo
|
||||
@mock sort -rn
|
||||
|
||||
load-ufw-docker-function ufw-docker--delete
|
||||
ufw-docker--delete webapp 80 tcp
|
||||
|
@ -771,91 +542,3 @@ test-ufw-docker--delete-all-assert() {
|
|||
ufw delete 8
|
||||
ufw delete 9
|
||||
}
|
||||
|
||||
test-ufw-docker--check-install_ipv4() {
|
||||
@mock mktemp === @stdout /tmp/after_rules_tmp
|
||||
@mock sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" /etc/ufw/after.rules
|
||||
@mock tee "/tmp/after_rules_tmp"
|
||||
@capture tee -a /tmp/after_rules_tmp
|
||||
@allow-real cat
|
||||
|
||||
load-ufw-docker-function ufw-docker--check-install
|
||||
ufw-docker--check-install
|
||||
}
|
||||
test-ufw-docker--check-install_ipv4-assert() {
|
||||
rm-on-exit /tmp/after_rules_tmp
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" /etc/ufw/after.rules
|
||||
@assert-capture tee -a /tmp/after_rules_tmp <<\EOF
|
||||
# BEGIN UFW AND DOCKER
|
||||
*filter
|
||||
:ufw-user-forward - [0:0]
|
||||
:ufw-docker-logging-deny - [0:0]
|
||||
:DOCKER-USER - [0:0]
|
||||
-A DOCKER-USER -j ufw-user-forward
|
||||
|
||||
-A DOCKER-USER -j RETURN -s 10.0.0.0/8
|
||||
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
|
||||
-A DOCKER-USER -j RETURN -s 192.168.0.0/16
|
||||
|
||||
-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 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
|
||||
-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
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
|
||||
|
||||
-A DOCKER-USER -j RETURN
|
||||
|
||||
-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
|
||||
-A ufw-docker-logging-deny -j DROP
|
||||
|
||||
COMMIT
|
||||
# END UFW AND DOCKER
|
||||
EOF
|
||||
diff -u --color=auto /etc/ufw/after.rules /tmp/after_rules_tmp
|
||||
}
|
||||
|
||||
test-ufw-docker--check-install_ipv4-subnets() {
|
||||
@mock ufw-docker--list-docker-subnets IPv4 192.168.56.128/28 172.16.0.0/12 === @stdout "172.16.0.0/12" "192.168.56.128/28"
|
||||
@mock mktemp === @stdout /tmp/after_rules_tmp
|
||||
@mock sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" /etc/ufw/after.rules
|
||||
@mock tee "/tmp/after_rules_tmp"
|
||||
@capture tee -a /tmp/after_rules_tmp
|
||||
@allow-real cat
|
||||
|
||||
load-ufw-docker-function ufw-docker--check-install
|
||||
ufw-docker--check-install --docker-subnets 192.168.56.128/28 172.16.0.0/12
|
||||
}
|
||||
test-ufw-docker--check-install_ipv4-subnets-assert() {
|
||||
rm-on-exit /tmp/after_rules_tmp
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" /etc/ufw/after.rules
|
||||
@assert-capture tee -a /tmp/after_rules_tmp <<\EOF
|
||||
# BEGIN UFW AND DOCKER
|
||||
*filter
|
||||
:ufw-user-forward - [0:0]
|
||||
:ufw-docker-logging-deny - [0:0]
|
||||
:DOCKER-USER - [0:0]
|
||||
-A DOCKER-USER -j ufw-user-forward
|
||||
|
||||
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
|
||||
-A DOCKER-USER -j RETURN -s 192.168.56.128/28
|
||||
|
||||
-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 172.16.0.0/12
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.56.128/28
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.56.128/28
|
||||
|
||||
-A DOCKER-USER -j RETURN
|
||||
|
||||
-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
|
||||
-A ufw-docker-logging-deny -j DROP
|
||||
|
||||
COMMIT
|
||||
# END UFW AND DOCKER
|
||||
EOF
|
||||
diff -u --color=auto /etc/ufw/after.rules /tmp/after_rules_tmp
|
||||
}
|
||||
|
|
367
ufw-docker
367
ufw-docker
|
@ -2,20 +2,16 @@
|
|||
set -euo pipefail
|
||||
[[ -n "${DEBUG:-}" ]] && set -x
|
||||
|
||||
# UFW-DOCKER GLOBAL VARIABLES START #
|
||||
LC_ALL=C
|
||||
PATH="/bin:/usr/bin:/sbin:/usr/sbin:/snap/bin/"
|
||||
LANG=en_US.UTF-8
|
||||
LANGUAGE=en_US:
|
||||
LC_ALL=en_US.UTF-8
|
||||
PATH="/bin:/usr/bin:/sbin:/usr/sbin"
|
||||
|
||||
GREP_REGEXP_NAME="[-_.[:alnum:]]\\+"
|
||||
GREP_REGEXP_INSTANCE_NAME="[-_.[:alnum:]]\\+"
|
||||
DEFAULT_PROTO=tcp
|
||||
ENV_VALUE_SPLITTER=','
|
||||
|
||||
ufw_docker_agent=ufw-docker-agent
|
||||
ufw_docker_agent_image="${UFW_DOCKER_AGENT_IMAGE:-chaifeng/${ufw_docker_agent}:250708-nf_tables}"
|
||||
|
||||
after_rules="/etc/ufw/after.rules"
|
||||
after6_rules="/etc/ufw/after6.rules"
|
||||
# UFW-DOCKER GLOBAL VARIABLES END #
|
||||
ufw_docker_agent_image="${UFW_DOCKER_AGENT_IMAGE:-chaifeng/${ufw_docker_agent}:220920-legacy}"
|
||||
|
||||
if [[ "${ufw_docker_agent_image}" = *-@(legacy|nf_tables) ]]; then
|
||||
if iptables --version | grep -F '(legacy)' &>/dev/null; then
|
||||
|
@ -28,37 +24,25 @@ fi
|
|||
test -n "$ufw_docker_agent_image"
|
||||
|
||||
function ufw-docker--status() {
|
||||
ufw-docker--list
|
||||
ufw-docker--list "$GREP_REGEXP_INSTANCE_NAME"
|
||||
}
|
||||
|
||||
function ufw-docker--list() {
|
||||
local INSTANCE_NAME="${1:-}"
|
||||
local INSTANCE_NAME="$1"
|
||||
local INSTANCE_PORT="${2:-}"
|
||||
local PROTO="${3:-}"
|
||||
local PROTO="${3:-${DEFAULT_PROTO}}"
|
||||
local NETWORK="${4:-}"
|
||||
local params_count="$#"
|
||||
local _grep_regexp
|
||||
|
||||
[[ -n "${INSTANCE_NAME:-}" ]] || INSTANCE_NAME="$GREP_REGEXP_NAME"
|
||||
if [[ -z "${INSTANCE_PORT:-}" && -z "${PROTO:-}" && -z "${NETWORK-}" ]]; then
|
||||
if [[ -z "$INSTANCE_PORT" ]]; then
|
||||
INSTANCE_PORT="[[:digit:]]\\+"
|
||||
[[ -n "${PROTO:-}" ]] || PROTO="\\(tcp\\|udp\\)"
|
||||
_grep_regexp="\\( ${INSTANCE_PORT}/${PROTO}\\( ${GREP_REGEXP_NAME}\\)\\?\\)\\?"
|
||||
else
|
||||
[[ -n "${INSTANCE_PORT:-}" ]] || INSTANCE_PORT="[[:digit:]]\\+"
|
||||
[[ -n "${PROTO:-}" ]] || PROTO="${DEFAULT_PROTO}"
|
||||
if [[ -n "${NETWORK:-}" ]]; then
|
||||
NETWORK=" ${NETWORK}"
|
||||
else
|
||||
NETWORK="\\( ${GREP_REGEXP_NAME}\\)\\?"
|
||||
fi
|
||||
_grep_regexp=" ${INSTANCE_PORT}/${PROTO}${NETWORK}"
|
||||
PROTO="\\(tcp\\|udp\\)"
|
||||
fi
|
||||
|
||||
local ufw_output
|
||||
ufw_output="$(ufw status numbered)"
|
||||
if [[ -z "$NETWORK" ]]; then
|
||||
NETWORK="[[:graph:]]*"
|
||||
fi
|
||||
|
||||
grep "# allow ${INSTANCE_NAME}\\(/v6\\)\\?${_grep_regexp}\$" <<< "$ufw_output"
|
||||
ufw status numbered | grep "# allow ${INSTANCE_NAME}\\( ${INSTANCE_PORT}\\/${PROTO}\\)\\?\\( ${NETWORK}\\)\\?\$"
|
||||
}
|
||||
|
||||
function ufw-docker--list-number() {
|
||||
|
@ -77,15 +61,15 @@ function ufw-docker--allow() {
|
|||
local INSTANCE_PORT="$2"
|
||||
local PROTO="$3"
|
||||
local NETWORK="${4:-}"
|
||||
local NETWORK_ADDRESSES PORT_PROTO_LIST PROT_PROTO IP SUFFIX
|
||||
|
||||
docker inspect "$INSTANCE_NAME" &>/dev/null ||
|
||||
die "Docker instance \"$INSTANCE_NAME\" doesn't exist."
|
||||
|
||||
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_ADDRESSES < <(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{"\n"}}{{end}}' "$INSTANCE_NAME" 2>/dev/null | remove_blank_lines)
|
||||
|
||||
[[ -z "${NETWORK_ADDRESSES:-}" ]] && die "Could not find a running instance \"$INSTANCE_NAME\"."
|
||||
[[ -z "${INSTANCE_IP_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)
|
||||
|
||||
if [[ -z "${PORT_PROTO_LIST:-}" ]]; then
|
||||
|
@ -93,26 +77,25 @@ function ufw-docker--allow() {
|
|||
return 1
|
||||
fi
|
||||
|
||||
local count=0
|
||||
RETVAL=1
|
||||
for PORT_PROTO in "${PORT_PROTO_LIST[@]}"; do
|
||||
if [[ -z "$INSTANCE_PORT" || "$PORT_PROTO" = "${INSTANCE_PORT}/${PROTO}" ]]; then
|
||||
for item in "${NETWORK_ADDRESSES[@]}"; do
|
||||
INSTANCE_NETWORK="${item% *}"
|
||||
IP="${item#* }"
|
||||
ITER=0
|
||||
for IP in "${INSTANCE_IP_ADDRESSES[@]}"; do
|
||||
INSTANCE_NETWORK="${INSTANCE_NETWORK_NAMES[$ITER]}"
|
||||
ITER=$((ITER+1))
|
||||
if [[ -n "$NETWORK" ]] && [[ "$NETWORK" != "$INSTANCE_NETWORK" ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ "$IP" = *:* ]]; then SUFFIX="/v6"; else SUFFIX=""; fi
|
||||
ufw-docker--add-rule "${INSTANCE_NAME}${SUFFIX}" "$IP" "${PORT_PROTO%/*}" "${PORT_PROTO#*/}" "${INSTANCE_NETWORK}"
|
||||
(( ++count ))
|
||||
ufw-docker--add-rule "$INSTANCE_NAME" "$IP" "${PORT_PROTO%/*}" "${PORT_PROTO#*/}" "${INSTANCE_NETWORK}"
|
||||
RETVAL="$?"
|
||||
done
|
||||
fi
|
||||
done
|
||||
if [[ "$count" -eq 0 ]]; then
|
||||
if [[ "$RETVAL" -ne 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)."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
function ufw-docker--add-service-rule() {
|
||||
|
@ -165,7 +148,7 @@ function ufw-docker--instance-name() {
|
|||
{
|
||||
{
|
||||
docker inspect --format='{{.Name}}' "$INSTANCE_ID" 2>/dev/null | sed -e 's,^/,,' |
|
||||
grep "^${GREP_REGEXP_NAME}\$" 2>/dev/null
|
||||
grep "^${GREP_REGEXP_INSTANCE_NAME}\$" 2>/dev/null
|
||||
} || echo -n "$INSTANCE_ID";
|
||||
} | remove_blank_lines
|
||||
}
|
||||
|
@ -181,7 +164,7 @@ function ufw-docker--service() {
|
|||
shift || true
|
||||
declare service_id_or_name="${1:?Missing swarm service name or service ID}"
|
||||
|
||||
"ufw-docker--service-${service_action}" "$@"
|
||||
"ufw-docker--service-${service_action}" "${service_id_or_name}"
|
||||
;;
|
||||
allow)
|
||||
shift || true
|
||||
|
@ -206,12 +189,6 @@ function ufw-docker--get-service-name() {
|
|||
docker service inspect "${service_name}" --format "{{.Spec.Name}}"
|
||||
}
|
||||
|
||||
function ufw-docker--list-service-ports() {
|
||||
declare service_name="$1"
|
||||
docker service inspect "$service_name" \
|
||||
--format '{{range .Endpoint.Spec.Ports}}{{.PublishedPort}} {{.TargetPort}}/{{.Protocol}}{{"\n"}}{{end}}'
|
||||
}
|
||||
|
||||
function ufw-docker--service-allow() {
|
||||
declare service_name="$1"
|
||||
declare service_port="$2"
|
||||
|
@ -231,24 +208,23 @@ function ufw-docker--service-allow() {
|
|||
declare service_id
|
||||
service_id="$(ufw-docker--get-service-id "${service_name}")"
|
||||
[[ -z "${service_id:-}" ]] && die "Could not find service \"$service_name\""
|
||||
|
||||
service_name="$(ufw-docker--get-service-name "${service_name}")"
|
||||
|
||||
declare env_value= published_port= target_port=
|
||||
exec 9< <(ufw-docker--list-service-ports "$service_name")
|
||||
while read -u 9 -r published_port target_port; do
|
||||
exec 9< <(docker service inspect "$service_name" \
|
||||
--format '{{range .Endpoint.Spec.Ports}}{{.PublishedPort}} {{.TargetPort}}/{{.Protocol}}{{"\n"}}{{end}}')
|
||||
while read -u 9 -r port target_port; do
|
||||
if [[ "$target_port" = "${service_port}/${service_proto}" ]]; then
|
||||
env_value="${service_name}/${published_port}/${service_proto}"
|
||||
declare service_env="ufw_public_${service_id}=${service_name}/${port}/${service_proto}"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
exec 9<&-
|
||||
|
||||
[[ -z "${env_value:-}" ]] && die "Service $service_name does not publish port $service_port."
|
||||
[[ -z "${service_env:-}" ]] && die "Service $service_name does not publish port $service_port."
|
||||
|
||||
declare service_env
|
||||
if ! docker service inspect "$ufw_docker_agent" &>/dev/null; then
|
||||
err "Not found ufw-docker-agent service, creating ..."
|
||||
service_env="ufw_public_${service_id}=${env_value}"
|
||||
docker service create --name "$ufw_docker_agent" --mode global \
|
||||
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
|
||||
--mount type=bind,source=/etc/ufw,target=/etc/ufw,readonly=true \
|
||||
|
@ -257,20 +233,15 @@ function ufw-docker--service-allow() {
|
|||
--env "${service_env}" \
|
||||
"${ufw_docker_agent_image}"
|
||||
else
|
||||
declare -a value_list=() service_env_list=()
|
||||
declare -a service_env_list
|
||||
service_env_list+=(--env-add "${service_env}")
|
||||
|
||||
exec 8< <(ufw-docker--get-env-list)
|
||||
while read -u 8 -r id value; do
|
||||
[[ "$id" != "$service_id" && "$value" = "${service_name}"/* ]] && service_env_list+=(--env-rm "ufw_public_${id}")
|
||||
[[ "$id" = "$service_id" ]] || continue
|
||||
[[ "${value}" = "${env_value}" || "${value}" = "${env_value}"/* ]] ||
|
||||
value_list+=("${value}")
|
||||
[[ "$id" = "$service_id" ]] && continue
|
||||
[[ "$value" = "${service_name}"/* ]] && service_env_list+=(--env-rm "ufw_public_${id}")
|
||||
done
|
||||
exec 8<&-
|
||||
value_list=("${env_value}" "${value_list[@]}")
|
||||
|
||||
service_env="ufw_public_${service_id}=$(IFS="${ENV_VALUE_SPLITTER}"; printf '%s' "${value_list[*]}")"
|
||||
|
||||
service_env_list+=(--env-add "${service_env}")
|
||||
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
|
@ -286,62 +257,28 @@ function ufw-docker--get-env-list() {
|
|||
--format '{{range $k,$v := .Spec.TaskTemplate.ContainerSpec.Env}}{{ $v }}{{"\n"}}{{end}}' |
|
||||
sed -e '/^ufw_public_/!d' \
|
||||
-e 's/^ufw_public_//' \
|
||||
-e 's/=/ /' |
|
||||
while read -r id value; do
|
||||
tr ',' '\n' <<< "$value" | sed "s/^/${id} /g"
|
||||
done
|
||||
-e 's/=/ /'
|
||||
}
|
||||
|
||||
function ufw-docker--service-delete() {
|
||||
declare service_name="$1"
|
||||
declare service_port="${2:-}"
|
||||
declare port proto
|
||||
if [[ "${service_port:-}" = */* ]]; then
|
||||
port="${service_port%/*}"
|
||||
proto="${service_port#*/}"
|
||||
elif [[ -n "${service_port:-}" ]]; then
|
||||
port="$service_port"
|
||||
proto="$DEFAULT_PROTO"
|
||||
fi
|
||||
|
||||
declare service_id
|
||||
service_id="$(ufw-docker--get-service-id "${service_name}")"
|
||||
[[ -z "${service_id:-}" ]] && die "Could not find service \"$service_name\""
|
||||
service_name="$(ufw-docker--get-service-name "${service_name}")"
|
||||
|
||||
declare env_value= published_port= target_port=
|
||||
if [[ -n "${port:-}" ]]; then
|
||||
exec 9< <(ufw-docker--list-service-ports "$service_name")
|
||||
while read -u 9 -r published_port target_port; do
|
||||
if [[ "$target_port" = "${port}/${proto}" ]]; then
|
||||
env_value="${service_name}/${published_port}/${proto}"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
exec 9<&-
|
||||
[[ -n "${env_value:-}" ]] || die "Service $service_name does not publish port $service_port."
|
||||
else
|
||||
declare env_value="${service_name}"
|
||||
fi
|
||||
|
||||
declare id value
|
||||
declare -a value_list=()
|
||||
exec 8< <(ufw-docker--get-env-list)
|
||||
while read -u 8 -r id value; do
|
||||
[[ "$id" = "$service_id" ]] || continue
|
||||
[[ "${value}" = "${env_value}" || "${value}" = "${env_value}"/* ]] ||
|
||||
value_list+=("${value}")
|
||||
if [[ "$id" = "$service_name" ]] || [[ "$value" = "${service_name}"/* ]]; then
|
||||
declare service_id="$id"
|
||||
service_name="${value%%/*}"
|
||||
declare service_env="ufw_public_${service_id}=${service_name}/deny"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
exec 8<&-
|
||||
value_list=("${env_value}/deny" "${value_list[@]}")
|
||||
|
||||
declare service_env
|
||||
service_env="ufw_public_${service_id}=$(IFS="${ENV_VALUE_SPLITTER}"; printf '%s' "${value_list[*]}")"
|
||||
[[ -z "${service_env:-}" ]] && die "Could not find service \"$service_name\""
|
||||
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "${service_env}" \
|
||||
--env-add DEBUG="${DEBUG-}" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
@ -350,20 +287,14 @@ function ufw-docker--raw-command() {
|
|||
ufw "$@"
|
||||
}
|
||||
|
||||
after_rules="/etc/ufw/after.rules"
|
||||
|
||||
function ufw-docker--check() {
|
||||
err "\\n########## iptables -n -L DOCKER-USER ##########"
|
||||
iptables -n -L DOCKER-USER
|
||||
|
||||
err "\\n\\n########## diff $after_rules ##########"
|
||||
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 ##########"
|
||||
ip6tables -n -L DOCKER-USER
|
||||
|
||||
err "\\n\\n########## diff $after6_rules ##########"
|
||||
ufw-docker--check-install_ipv6 "$@" && err "\\nCheck IPv6 firewall rules done."
|
||||
fi
|
||||
ufw-docker--check-install && err "\\nCheck done."
|
||||
}
|
||||
|
||||
declare -a files_to_be_deleted
|
||||
|
@ -381,45 +312,12 @@ function on-exit() {
|
|||
|
||||
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() {
|
||||
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)}"
|
||||
rm-on-exit "$after_rules_tmp"
|
||||
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after_rules" | tee "$after_rules_tmp" >/dev/null
|
||||
{
|
||||
cat <<-\EOF
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after_rules" > "$after_rules_tmp"
|
||||
>> "${after_rules_tmp}" cat <<-\EOF
|
||||
# BEGIN UFW AND DOCKER
|
||||
*filter
|
||||
:ufw-user-forward - [0:0]
|
||||
|
@ -427,26 +325,18 @@ function ufw-docker--check-install() {
|
|||
:DOCKER-USER - [0:0]
|
||||
-A DOCKER-USER -j ufw-user-forward
|
||||
|
||||
EOF
|
||||
|
||||
for cidr in "${cidr_list[@]}"; do
|
||||
echo "-A DOCKER-USER -j RETURN -s ${cidr}"
|
||||
done
|
||||
|
||||
cat <<-\EOF
|
||||
-A DOCKER-USER -j RETURN -s 10.0.0.0/8
|
||||
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
|
||||
-A DOCKER-USER -j RETURN -s 192.168.0.0/16
|
||||
|
||||
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
|
||||
|
||||
EOF
|
||||
|
||||
for cidr in "${cidr_list[@]}"; do
|
||||
echo "-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d ${cidr}"
|
||||
done
|
||||
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 ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
|
||||
-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
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
|
||||
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
|
||||
|
||||
-A DOCKER-USER -j RETURN
|
||||
|
||||
|
@ -456,87 +346,17 @@ function ufw-docker--check-install() {
|
|||
COMMIT
|
||||
# END UFW AND DOCKER
|
||||
EOF
|
||||
} | tee -a "${after_rules_tmp}" >/dev/null
|
||||
|
||||
diff -u --color=auto "$after_rules" "$after_rules_tmp"
|
||||
}
|
||||
|
||||
function ufw-docker--check-install_ipv6() {
|
||||
declare -a cidr6_list
|
||||
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)}"
|
||||
rm-on-exit "$after6_rules_tmp"
|
||||
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after6_rules" | tee "$after6_rules_tmp" >/dev/null
|
||||
{
|
||||
cat <<-\EOF
|
||||
# BEGIN UFW AND DOCKER
|
||||
*filter
|
||||
:ufw6-user-forward - [0:0]
|
||||
:ufw6-docker-logging-deny - [0:0]
|
||||
:DOCKER-USER - [0:0]
|
||||
-A DOCKER-USER -j ufw6-user-forward
|
||||
|
||||
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
|
||||
EOF
|
||||
|
||||
for cidr in "${cidr6_list[@]}"; do
|
||||
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 ufw6-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
|
||||
-A ufw6-docker-logging-deny -j DROP
|
||||
|
||||
COMMIT
|
||||
# END UFW AND DOCKER
|
||||
EOF
|
||||
} | tee -a "${after6_rules_tmp}"
|
||||
diff -u --color=auto "$after6_rules" "$after6_rules_tmp"
|
||||
}
|
||||
|
||||
function ufw-docker--install() {
|
||||
local changed=false
|
||||
if ! ufw-docker--check-install "$@"; then
|
||||
changed=true
|
||||
if ! ufw-docker--check-install; then
|
||||
local after_rules_bak
|
||||
after_rules_bak="${after_rules}-ufw-docker~$(date '+%Y-%m-%d-%H%M%S')~"
|
||||
err "\\nBacking up $after_rules to $after_rules_bak"
|
||||
cp "$after_rules" "$after_rules_bak"
|
||||
cat "$after_rules_tmp" > "$after_rules"
|
||||
fi
|
||||
|
||||
if ! ufw-docker--check-install_ipv6 "$@"; then
|
||||
changed=true
|
||||
local after6_rules_bak
|
||||
after6_rules_bak="${after6_rules}-ufw-docker~$(date '+%Y-%m-%d-%H%M%S')~"
|
||||
err "\\nBacking up $after6_rules to $after6_rules_bak"
|
||||
cp "$after6_rules" "$after6_rules_bak"
|
||||
cat "$after6_rules_tmp" > "$after6_rules"
|
||||
fi
|
||||
|
||||
if "$changed"; then
|
||||
err "Please restart UFW service manually by using the following command:"
|
||||
if type systemctl &>/dev/null; then
|
||||
err " sudo systemctl restart ufw"
|
||||
|
@ -546,31 +366,6 @@ function ufw-docker--install() {
|
|||
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() {
|
||||
cat <<-EOF >&2
|
||||
Usage:
|
||||
|
@ -580,27 +375,19 @@ function ufw-docker--help() {
|
|||
ufw-docker service allow <swarm-service-id-or-name <port</tcp|/udp>>>
|
||||
ufw-docker service delete allow <swarm-service-id-or-name>
|
||||
|
||||
ufw-docker <install|check> [--docker-subnets [SUBNET0 SUBNET1 ...]]
|
||||
|
||||
ufw-docker <status|install|check|help>
|
||||
|
||||
Examples:
|
||||
ufw-docker help
|
||||
ufw-docker check --help
|
||||
ufw-docker install --help
|
||||
|
||||
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 --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 check # Check the installation of firewall rules
|
||||
ufw-docker install # Install firewall rules
|
||||
|
||||
ufw-docker status
|
||||
|
||||
ufw-docker list httpd
|
||||
|
||||
|
||||
ufw-docker allow httpd
|
||||
ufw-docker allow httpd 80
|
||||
ufw-docker allow httpd 80/tcp
|
||||
|
@ -635,10 +422,6 @@ if ! ufw status 2>/dev/null | grep -Fq "Status: active" ; then
|
|||
die "UFW is disabled or you are not root user, or mismatched iptables legacy/nf_tables, current $(iptables --version)"
|
||||
fi
|
||||
|
||||
if ! docker -v &> /dev/null; then
|
||||
die "Docker executable not found."
|
||||
fi
|
||||
|
||||
ufw_action="${1:-help}"
|
||||
|
||||
case "$ufw_action" in
|
||||
|
@ -669,26 +452,14 @@ case "$ufw_action" in
|
|||
NETWORK="${1:-}"
|
||||
|
||||
INSTANCE_PORT="${INSTANCE_PORT%/*}"
|
||||
;;&
|
||||
delete|list)
|
||||
"ufw-docker--$ufw_action" "$INSTANCE_NAME" "$INSTANCE_PORT" "$PROTO" "$NETWORK"
|
||||
;;
|
||||
allow)
|
||||
|
||||
"ufw-docker--$ufw_action" "$INSTANCE_NAME" "$INSTANCE_PORT" "$PROTO" "$NETWORK"
|
||||
;;
|
||||
service|raw-command|add-service-rule)
|
||||
shift || true
|
||||
"ufw-docker--$ufw_action" "$@"
|
||||
;;
|
||||
install|check)
|
||||
shift || true
|
||||
if [[ "${1-}" = @(help|-h|--help) ]]; then
|
||||
ufw-docker--install--help "$ufw_action"
|
||||
exit
|
||||
fi
|
||||
"ufw-docker--$ufw_action" "$@"
|
||||
;;
|
||||
status)
|
||||
status|install|check)
|
||||
ufw-docker--"$ufw_action"
|
||||
;;
|
||||
*)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue