Docker容器服务不受防火墙限制?

2023-03-07 #docker, #linux 1648 words 4 min read

最近在绿云vps上跑docker服务的时候,发现了一个奇怪的现象。如我运行memos容器时,ufw并没有放行相应端口,

但是却可以通过ip地址:5230的形式,访问到memos容器服务。

memo时能访问

memos的docker-compose.yml文件如下所示。

version: '3'
services:
  memos:
    image: neosmemo/memos:latest
    container_name: memos
    ports:
      - "5230:5230"
    volumes:
      - ~/.memos:/var/opt/memos
    restart: always

其中我们重点关注ports字段。

    ports:
      - "5230:5230"

这段代码的意思是将容器的5230端口映射到宿主机的5230端口。这样做可以让宿主机和其他设备可以通过5230端口访问容器内的应用程序。

我能通过ip地址:5230的形式访问到memos应用程序,说明宿主机的5230端口处于开放状态。

采用nmap工具对目标主机的端口开放情况进行探测。

# 扫描指定ip地址的5230端口是否开放
nmap -p 5230 xx.xx.xx.xx

nmap 5230

绿云vps的5230端口处于开放状态。

# 使用nmap工具对目标IP地址为xx.xx.xx.xx的主机进行全端口扫描,
# 选项-T4表示使用较高的扫描速度(4表示4个线程),选项-p-表示扫描所有端口。
nmap -T4 -p- xx.xx.xx.xx

绿云vps端口开放情况

扫描全端口,发现除了ufw罗列出来的22、80、443端口外,还有3002和5230端口开放着。其中3002端口是chatgpt-web项目docker容器内和主机之间映射的端口。

# 显示当前防火墙状态
ufw status

ufw状态

查看了chatgpt-web的docker-compose.yml文件发现,也同样存在这样的ports字段。

    ports:
      - 3002:3002

stackoverflow上网友们对于此问题也进行了讨论。Uncomplicated Firewall (UFW) is not blocking anything when using Docker

ufw not block anything

高分回答中指明:docker会直接在iptables上做相关的调整,这些调整并不会显示在ufw的状态上。对于用反向代理服务器来代理相应端口的朋友来讲,最好的解决方案是将docker-compose.yml文件中的ports字段调整为如下形式:

    # 将主机的3002端口映射到Docker容器内的3002端口上,从而让主机上的应用程序可以通过
    # 127.0.0.1:3002访问Docker容器内的应用程序。
    ports:
      - 127.0.0.1:3002:3002

这样可以保证仅允许本主机上的进程访问本主机的3002端口,外界无法获取本主机3002端口上的服务。

借助反向代理服务器,如caddy,让其监听80、443端口,当外部有新的http(s)请求时,caddy接收到相关的请求,并将相关的请求转交给本主机上的相应端口,相应端口接收请求后返回响应,caddy再将代理目标返回的响应转发给用户。

caddy反向代理的流程

之所以ufw无法管控相应的docker与主机之间的映射端口,是因为docker会直接操作iptables来放行相应的端口。附new bing给出的树形图。

iptables和ufw

为了更好地管控docker与主机之间的映射端口,以后最好将ports字段前加上127.0.0.1,仅允许本主机访问映射端口,即让反向代理服务器去访问相应端口,取回相应内容,并返回给请求方。

修改docker-compose.yml中的ports字段。

修改ports字段

并重启由docker-compose.yml文件定义的相关服务。

重启服务

这时再次使用ip地址:5230,或使用nmap探测5230端口,会发现已经无法访问,因为这个端口仅允许主机内部访问(127.0.0.1,环回地址在起作用)。

nmap 5230端口被过滤

这时再搭配反向代理服务器,这里以caddy为例。

# 编辑caddy的默认配置文件
vi /etc/caddy/Caddyfile

# 添加以下内容
memos.gujiakai.top {
 	reverse_proxy localhost:3002
}
# 重新加载caddy
systemctl reload caddy

操作完成后,就能通过域名的形式访问到memos服务了。

成功访问memos

这样子操作,可以对于端口进行安全控制,减少非必要的端口在互联网上的暴露。

虽然有些大厂的服务器,如阿里云、aws等,会在服务器的外侧再包裹一层防火墙。要放行端口时,还需要到防火墙控制面板进行放行操作。 (这些大厂的vps上使用docker进行端口映射可以不加127.0.0.1的前缀,只要防火墙的控制面板不放行,就不会将服务的端口暴露到互联网上,所有服务的入口均为nginx占用的443端口。)但我建议平时就应该养成好习惯,这样子无论是大厂的vps,还是小众商家的vps,都有规范参照。


Emoji Reaction


© 2022-2024 Made with ❤️ By Jiakai