侧边栏壁纸
博主头像
BvBeJ的小站 博主等级

行动起来,活在当下

  • 累计撰写 37 篇文章
  • 累计创建 1 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Docker 绕过 UFW

BvBeJ
2025-12-06 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

解决方案:以MySQL为例

方案 1:修改 Docker 容器的端口绑定(最简单)

将 MySQL 容器只绑定到本地地址,而不是 0.0.0.0:

# 1. 停止并删除当前 MySQL 容器(先备份数据!)
docker stop mysql
docker rm mysql

# 2. 重新运行 MySQL 容器,只绑定到 127.0.0.1
docker run -d \
  --name mysql \
  -p 127.0.0.1:3306:3306 \  # 关键:只绑定到本地回环地址
  -e MYSQL_ROOT_PASSWORD=您的密码 \
  mysql:latest

# 或者如果使用 Docker Compose,在 ports 部分修改:
# ports:
#   - "127.0.0.1:3306:3306"

这样外部就无法通过 IP 访问 MySQL,但本地应用仍可连接。

方案 2:限制 Docker 容器的网络访问

创建自定义 Docker 网络并限制访问:

# 1. 创建一个自定义网络
docker network create --subnet=172.20.0.0/16 internal_network

# 2. 停止并重新运行容器,使用此网络
docker stop mysql
docker rm mysql

docker run -d \
  --name mysql \
  --network internal_network \
  -p 127.0.0.1:3306:3306 \
  -e MYSQL_ROOT_PASSWORD=您的密码 \
  mysql:latest

方案 3:在 UFW 中阻止 Docker 的 3306 端口

# 1. 查看当前的 UFW 规则编号
sudo ufw status numbered

# 2. 在 DOCKER-USER 链中添加规则(这是 Docker 推荐的方法)
sudo iptables -I DOCKER-USER 1 -p tcp --dport 3306 -j DROP

# 3. 保存规则(如果需要持久化)
# 对于 Debian 12,使用 netfilter-persistent
sudo apt install iptables-persistent -y
sudo netfilter-persistent save

# 或者保存到特定文件
sudo sh -c "iptables-save > /etc/iptables/rules.v4"

方案 4:配置 Docker 不操作 iptables

警告:这会影响所有 Docker 容器的网络功能!

# 1. 创建或编辑 Docker 配置文件
sudo nano /etc/docker/daemon.json

# 2. 添加以下内容
{
  "iptables": false
}

# 3. 重启 Docker
sudo systemctl restart docker

# 4. 重新创建 MySQL 容器
docker stop mysql
docker rm mysql
docker run -d --name mysql -p 127.0.0.1:3306:3306 -e MYSQL_ROOT_PASSWORD=您的密码 mysql:latest

方案 5:使用 docker-ufw-wrapper(推荐)

这是一个专门解决 Docker 与 UFW 冲突的工具:

# 安装
wget https://raw.githubusercontent.com/chaifeng/ufw-docker/master/ufw-docker
sudo mv ufw-docker /usr/local/bin/
sudo chmod +x /usr/local/bin/ufw-docker

# 安装到系统
sudo ufw-docker install

# 修复 UFW 规则
sudo ufw-docker fix

# 然后重新创建容器

方案 6:通过 CloudCone 控制面板限制

登录 CloudCone 控制面板,在防火墙/安全组中拒绝 3306 端口。

推荐的解决步骤:

  1. 首先尝试方案 1(修改端口绑定):

    # 备份 MySQL 数据
    docker exec mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > backup.sql
    
    # 停止并删除容器
    docker stop mysql && docker rm mysql
    
    # 重新运行,只绑定到 127.0.0.1
    docker run -d \
      --name mysql \
      -p 127.0.0.1:3306:3306 \
      -e MYSQL_ROOT_PASSWORD=您的密码 \
      -v mysql_data:/var/lib/mysql \
      mysql:latest
    
  2. 验证是否生效

    # 查看容器端口绑定
    docker ps --format "table {{.Names}}\t{{.Ports}}"
    # 应该显示:127.0.0.1:3306->3306/tcp
    
    # 检查是否仍能从外部访问
    nc -zv 您的服务器IP 3306
    # 应该显示 Connection refused
    
    # 本地应该可以连接
    mysql -h 127.0.0.1 -u root -p
    
  3. 如果还需要其他解决方案

    • 如果多个容器需要此配置,使用方案 5(docker-ufw-wrapper)
    • 如果只需要简单解决,方案 1 足够了

长期维护建议:

  1. 使用 Docker Compose 管理容器,配置更清晰:

    version: '3.8'
    services:
      mysql:
        image: mysql:latest
        container_name: mysql
        ports:
          - "127.0.0.1:3306:3306"  # 关键:只绑定本地
        environment:
          MYSQL_ROOT_PASSWORD: 您的密码
        volumes:
          - mysql_data:/var/lib/mysql
    volumes:
      mysql_data:
    
  2. 定期检查暴露的端口

    # 查看所有暴露的端口
    docker ps --format "table {{.Names}}\t{{.Ports}}"
    
    # 查看 iptables 中 Docker 相关的规则
    sudo iptables -L DOCKER-USER -n -v
    
  3. 使用网络策略限制

    # 创建仅内部访问的网络
    docker network create --internal internal-only
    
0

评论区