使用Docker时,简单防火墙(UFW)不会阻止任何内容


44

这是我第一次设置Ubuntu Server(14.04 LTS),但在配置防火墙(UFW)时遇到问题。

我只需要sshhttp,所以我正在这样做:

sudo ufw disable

sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp

sudo ufw enable
sudo reboot

但是我仍然可以连接到本机其他端口上的数据库。关于我在做什么错的任何想法吗?

编辑:这些数据库在Docker容器上。这可能有关吗?它会覆盖我的ufw配置吗?

EDIT2:输出sudo ufw status verbose

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)

什么数据库?哪个港口?您确定这是同一台机器吗?ufw status
solsTiCe 2015年

@solsTiCe是的,我确定它是同一台机器。该数据库是具有端口8083和的InfluxDB(在docker容器上)8086。我ufw status verbose在问题中添加了输出。谢谢。
ESala 2015年

Answers:


64

问题是-p在容器上使用标志。

事实证明Docker直接在您身上进行更改iptables,而这些更改未显示ufw status

可能的解决方案是:

  1. 停止使用该-p标志。改用docker链接或docker网络

  2. 在本地绑定容器,这样它们就不会暴露在机器外部:

    docker run -p 127.0.0.1:8080:8080 ...

  3. 如果您坚持使用该-p标志,请iptables通过禁用它们/etc/docker/daemon.json并重新启动来告诉docker不要触摸您的标志:

    { "iptables" : false }

我建议使用选项1或2。请注意,选项3 具有副作用,例如容器无法连接到Internet。


8
这是如此有用-我为能够访问ufw中不允许的端口而发疯。但是,使用iptables = false会造成很多麻烦,例如容器可以在localhost上访问,例如用于反向代理。最好确保容器正确侦听,不要使用-p 80:80,而要使用-p 127.0.0.1:80:80或其他端口(例如127.0.0.1:3000:80)使用nginx或apache进行反向代理,并且不使用端口冲突。
Andreas Reiff

2
@AndreasReiff,您是对的,但最近我发现最好避免-p使用。例如,在使用反向代理的情况下,我不为工作容器映射任何端口,然后将nginx -p 80:80与a --link一起放置在其自己的容器中。这样,就不会有任何端口冲突,并且唯一的访问点是通过nginx。
ESala 2016年

1
另外,请检查此帖子以获取您必须采取的第三项预防措施!svenv.nl/unixandlinux/dockerufw
Henk

1
要点/etc/default/docker是upstart config使用的配置文件。如果您已从新贵迁移到systemd,则不会使用此文件。
orshachar

@ESala您应该考虑取消对此答案的标记,因为它已经过时了。
ctbrown

8

16.04提出了新的挑战。我做了所有步骤,如图所示,在ufw防火墙后面运行Docker, 但是我无法使docker plus UFW在16.04上正常工作。换句话说,无论我做什么,所有docker端口都在全球范围内暴露于Internet。直到我发现:如何设置Docker 1.12+不干扰IPTABLES / FirewallD

我必须创建文件/etc/docker/daemon.json,并将以下内容放入:

{
    "iptables": false
}

然后我发出sudo service docker stop然后sudo service docker startFINALLY泊坞窗就是跟随在UFW相应的规则。

附加数据:Docker否决了UFW!


在Ubuntu 16.04和Docker 17.09版本中,此解决方案断开了容器的出站连接。请参阅回复askubuntu.com/a/833363/262702askubuntu.com/a/954041/262702
ctbrown

5

如果您使用的是systemd的初始化系统(Ubuntu 15.10及更高版本),请编辑/etc/docker/daemon.json(如果不存在,则可能需要创建它),请确保已iptables配置了密钥:

{   "iptables" : false }

编辑:这可能会导致您从容器内部失去与Internet的连接

如果启用了UFW,请确认您可以从容器内部访问Internet。如果不是,则必须将其定义DEFAULT_FORWARD_POLICYACCEPTon /etc/default/ufw并应用此处描述的技巧:https : //stackoverflow.com/a/17498195/507564


2

一种快速的解决方法是在运行Docker并进行端口映射时。你总是可以做

docker run ...-p 127.0.0.1:<ext pot>:<internal port> ...

防止从外部访问您的Docker。


2

/etc/docker/daemon.json与内容一起使用

{
  "iptables": false
}

听起来像是个解决方案,但是它只能在下次重新启动之前起作用。之后,您可能会注意到您的容器都没有访问Internet的权限,因此您无法例如ping任何网站。这可能是不希望的行为。

将容器绑定到特定IP的情况相同。您可能不想这样做。最终的选择是创建一个容器,并将其放置在UFW后面,无论发生什么情况以及如何创建此容器,都有一个解决方案:

创建/etc/docker/daemon.json文件后,调用:

sed -i -e 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/g' /etc/default/ufw
ufw reload

因此您可以在UFW中设置默认转发策略以接受并使用:

iptables -t nat -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE

如果您要使用docker-compose,则在使用运行时,应将上述命令中的IP替换为网络docker-compose create的IP docker-compose up

在本文中更全面地描述了问题和解决方案

希望能帮助到你!


1

就我而言,我最终修改了iptables,以仅允许从特定IP访问Docker。

根据ESala的回答

如果-p在容器上使用标志,则Docker会直接更改iptables,而忽略ufw。

Docker添加到iptables的记录示例

路由到“ DOCKER”链:

-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER

将数据包从“ DOCKER”链转发到容器:

-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 6379 -j DNAT --to-destination 172.17.0.3:6379

您可以修改iptables,以仅允许从指定的源IP(例如1.1.1.1)访问DOCKER链:

-A PREROUTING -s 1.1.1.1 -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -s 1.1.1.1 ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER

您可能要使用iptables-save > /tmp/iptables.confiptables-restore < /tmp/iptables.conf转储,编辑和还原iptables规则。


0

启动容器时使用--network = host,以便docker将端口映射到隔离的仅主机的网络,而不是默认的网桥网络。我看不到任何阻止桥接网络的合法方法。另外,您可以隔离使用自定义的用户定义网络。


0
  1. 登录到您的Docker控制台:

    须藤docker exec -i -t docker_image_name / bin / bash

  2. 然后在您的Docker控制台中:

    sudo apt-get update
    sudo apt-get install ufw
    sudo ufw allow 22
    
  3. 添加您的ufw规则并启用ufw

    sudo ufw启用

    • 您的Docker映像需要以--cap-add = NET_ADMIN开头

要启用“ NET_ADMIN” Docker选项:

1.停止容器:

码头工人停止你的容器; 2,获取容器ID:

码头工人检查您的容器; 3,修改hostconfig.json(默认docker路径:/ var / lib / docker,可以更改)

vim /var/lib/docker/containers/containerid/hostconfig.json

4.搜索“ CapAdd”,并将空值修改为[“ NET_ADMIN”];

....,“ VolumesFrom”:null,“ CapAdd”:[“ NET_ADMIN”],“ CapDrop”:null,.... 5.在主机中重新启动docker;

服务泊坞窗重启; 6,启动您的化妆师;

码头工人启动你的容器;


0

我曾经docker-compose启动过多个容器,还遇到一个问题,一个端口暴露在世界各地,而忽略了ufw规则。

仅使端口可用于我的Docker容器的解决方法是docker-compose.yml文件中的以下更改:

ports:
- "1234:1234"

对此:

ports:
- "1234"

现在其他docker-container仍然可以使用该端口,但是我无法从外部访问它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.