公网Docker的端口暴露风险

2025-01-02 18:46:13 4


场景

默认配置下docker启动的容器, 如果进行了端口映射

docker run --network bgnet --ip 172.18.0.3  --name http03 -p 9090:8080 http-docker

docker会修改iptables的规则, 以支持对应端口的流量转发.

如果机器使用firewalld关闭入方向的端口, 但由于docker添加的规则优先级最高, 此时会导致firewalld配置的策略失效.

以上面的命令为例, 即使firewalld屏蔽了所有端口, 外部也能通过9090访问到服务. 这样暴露是较危险的

github的讨论: https://github.com/moby/moby/issues/22054


解决方法


1. 修改docker启动参数

在docker启动时添加–iptables=false参数来禁止docker对iptables的操作



2. nginx转发

docker run --network rootnet --ip 172.18.0.4  --name http04 -p 127.0.0.1:9091:8080 http-docker

-p 127.0.0.1:19091:8080 将容器的8080端口只发布到127.0.0.1的19091

nginx监听9091, 再通过nginx转发到这个19091端口, 这样firewall就能通过控制nginx的9091端口, 间接决定这个容器是否对外网提供服务



3. 定义iptables规则限制

docker run --network rootnet --ip 172.18.0.3  --name http03 -p 9090:8080 -d http-docker

这个容器将端口9090发布到0.0.0.0上

3.1 修改iptables DOCKER链规则

# 删除docker为容器添加的默认规则(允许任意流量访问172.18.0.3:8080)
iptables -D DOCKER 1

# 仅允许源ip为192.168.143.1的流量访问服务
iptables -I DOCKER -s 192.168.143.1  -d 172.18.0.3 -p tcp --dport 8080 -j ACCEPT
systemctl restart docker

docker重启后, 手动设置的规则消失. 仍然是任意端口都能访问服务


3.1.1 iptables规则持久化

参照https://blog.csdn.net/qq_43665434/article/details/127069813iptables-services保存规则, 将#3.1设置的规则持久化


dnf install iptables-services -y
service iptables save
systemctl restart iptables

3.1.2 重启docker后, 规则变为默认, 手动设置的也被清空. 需要手动重启iptables使设置的规则生效

systemctl restart docker
systemctl restart iptables


3.1.3 重启http03服务, 手动设置的未被清空, 但docker重新添加了默认规则. 需要手动重启iptables使设置的规则生效

docker restart http03
systemctl restart iptables


3.2 修改iptables DOCKER-USER链规则

iptables -D DOCKER-USER 1

# 禁止所有流量访问8080
iptables -I DOCKER-USER -p tcp --dport 8080 -j DROP

# 仅允许192.168.143.1访问
iptables -I DOCKER-USER -s 192.168.143.1 -p tcp --dport 8080 -j ACCEPT


3.2.1 重启docker和http03容器, DOCKER-USER规则仍然在

systemctl restart docker
docker start http03 http04

3.2.2 重启机器, DOCKER-USER规则消失

reboot

service iptables save保存规则后, 需要手动重启iptables, 保存的规则才能重新加载

systemctl restart iptables
3.2.2.1 配置开机自动加载iptables规则

开机自动配置iptables规则

vim /etc/systemd/system/custom-iptables.service

service iptables save是默认保存到/etc/sysconfig/iptables

docker启动后再运行, 仅运行一次

[Unit]
Description=Run custom commands after docker
After=docker.service

[Service]
Type=oneshot
ExecStart=/bin/bash -c "iptables -D DOCKER-USER 1 && /usr/sbin/iptables-restore < /etc/sysconfig/iptables"

[Install]
WantedBy=multi-user.target


重载配置

systemctl daemon-reload

配置开机启动

systemctl enable custom-iptables.service

重启后规则未消失, 端口正常限制

总结

方案优点问题
修改docker启动参数1. 可以通过firewall进行统一管理 2. 启动新容器, 外网流量默认无法访问容器间无法进行内部通信
nginx转发1. 可以通过firewall进行统一管理 2. 启动新容器, 外网流量默认无法访问1. 已经创建的容器不方便修改 2. 需要多配置一个组件, 增加运维成本
iptables DOCKER能管理到正在运行的容器1. 增加运维成本, 重启机器或docker后, 必须手动重启iptables 2. 不能通过firewall进行统一管理
iptables DOCKER-UESR1. 能管理到正在运行的容器 2. 重启docker规则不会消失1. 增加运维成本 2. 不能通过firewall进行统一管理


公网Docker的端口暴露风险

场景默认配置下docker启动的容器, 如果进行了端口映射docker run --network bgnet --ip 172.18.0.3 --name http03 -p 9090:8080 http-docker则docker会修改iptables的规则, 以支持对应端口的流量转发. 如果
2025-01-02

Kubernetes Cloud Native 实践 ( 一 ) 安装

全文目录Kubernetes Cloud Native 实践 ( 一 ) 安装Kubernetes Cloud Native 实践 ( 二 ) 简单使用Kubernetes Cloud Native 实践 ( 三 ) NFS/PV/PVCKubernetes Cloud Native 实践 ( 四
2023-06-13
SkyWalking for Java

SkyWalking for Java

Skywalking的性能损耗接近3%一. Docker配置docker pull apache/skywalking-oap-server:9.4.0-java17docker pull apache/skywalking-ui:v9.4.0-java17docker pull elasticse
2023-05-19

Docker Graceful Shutdown

有几个前提操作系统层面: 提供了 kill -9 (SIGKILL)和 kill -15(SIGTERM) 两种停机策略. SIGKILL 信号是一个不能被阻塞、处理或忽略的信号,它会立即终止目标进程. SIGTERM 信号是一个可以被阻塞、处理或忽略的信号,它也可以通知目标进程终止,但是它相对于
2023-05-17

Docker启动容器出现No Such File Or Directory排查

dockerfile如下FROM alpine ADD test-backend /test-backend RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/time
2023-03-22

Ubuntu Golang 编译 + Docker部署

配置Golang编译环境下载go环境 https://studygolang.com/dl 选择go1.20.2.linux-amd64.tar.gztar -zxvf go1.20.2.linux-amd64.tar.gz 解压到 /usr/local/go创建 /usr/local/go-pat
2023-03-22
Ubuntu编译调试OpenJDK8

Ubuntu编译调试OpenJDK8

Centos编译调试OpenJDK11下载源码非官方 切换到jdk8u分支https://github.com/unofficial-openjdk/openjdk.git编译编译jdk需要一个引导jdk, 引导jdk版本需要比编译版本小一个版本或等于当前版本命令行运行sh configure -
2022-08-05

Java服务高CPU占用代码排查方法

1.查找进程通过top -c命令可以确定出现问题的进程2.查找线程 接下来就要找到这个进程中是哪个线程出现问题这个确定也是比较简单的,只需要输入命令:top -Hp PID例top -Hp 9828 3.定位代码jstack 进程PID | grep 线程id的16进制 -c 显示行数jstack
2022-03-31

Nginx+Frp+Docker实现HTTPS内网穿透

内网穿透实用性非常强, 例如支付回调/访问内网数据库域名dns需要解析到服务器地址frp下载地址https://github.com/fatedier/frp/releases下载这两个文件frp_0.38.0_linux_amd64.tar.gzfrp_0.38.0_windows_amd64.z
2021-10-29

Docker 安装 MongoDB

docker pull mongo docker run -itd --name mongo -p 27017:27017 mongo --auth -p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mo
2021-01-13

SpringBoot连接Redis服务出现Command timed out

docker 部署的redis一直出现超时docker pull redis 网上的都说要设置这个值spring.redis.timeout=50000 然而实际使用过程中仍然超时查看redis 服务端配置-bash# cat redis.conf | grep tcp-k tcp-keepali
2020-12-14

Jenkins + Gitee 持续集成

接上文/article/537098261463302145 Jenkins安装JDK安装将jdk-8u171-linux-x64.rpm(oracle官网下载)上传至服务器执行安装命令rpm -ivh jdk-8u171-linux‐x64.rpm RPM方式安装JDK,其根目录为:/usr/ja
2020-12-04

Maven插件自动构建项目镜像

搭建docker私有仓库docker pull registry 启动容器docker run ‐di --name=registry -p 5000:5000 registry 打开浏览器 输入地址http://localhost:5000/v2/_catalog看到{"repositories"
2020-11-22

Docker 部署 详细全过程 附代码

Docker 部署本站 全过程环境:CentOS7.61. 安装Docker其他版本CentOS可以参考这个https://help.aliyun.com/document_detail/187598.html查看本机内核版本,内核版本需高于 3.10uname -r 确保 yum 包最新yum u
2020-03-28

freemarker 时间显示不正常 设置时区

项目在本地开发的时候显示正常,部署上服务器就一直差8个小时,最后发现freemarker官方文档有这样的说明time_zone:时区的名称来显示并格式化时间。 默认情况下,使用JVM的时区。 也可以是 Java 时区 API 接受的值,或者 "JVM default" (从 FreeMarker 2
2020-03-28
IDEA 2019.1 xml 不高亮

IDEA 2019.1 xml 不高亮

前几天更新了idea后,发现xml里的代码都没有了高亮,变得跟记事本一个德性了打开setting ,搜索 File Types,找到xml项, 查看下方的匹配格式,果然没有xml,(idea真是厉害)点击右方的+,输入*.xml,点击ok,解决问题
2020-03-28

npm install 淘宝镜像

npm install --registry=https://registry.npm.taobao.org
2020-03-28
Java中方法的参数传递机制

Java中方法的参数传递机制

来看一段代码 public class Man { private String name; private Integer age; public String getName() { return name; } publi
2020-03-28
基于自定义注解手写权限控制

基于自定义注解手写权限控制

方法一: AOP 方法二: 拦截器项目结构项目依赖<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-w
2020-03-28

Docker 部署 详细全过程 附代码

Docker 部署本站 全过程环境:CentOS7.61. 安装Docker其他版本CentOS可以参考这个https://help.aliyun.com/document_detail/187598.html查看本机内核版本,内核版本需高于 3.10uname -r 确保 yum 包最新yum u
2020-03-28

SpringBoot 启动普通java工程

引入依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.0.9</version> </dependency>
2020-03-28

Vue.js DOM操作

<template> <input type="button" @click="reply($event)" value="回复"> </template> export default { methods: { replyFun(e) {
2020-03-29
CentOS7编译调试OpenJDK12

CentOS7编译调试OpenJDK12

1. 下载源码https://hg.openjdk.java.net/jdk/jdk12点击左侧的browse,再点击zip,就可以下载zip格式的源码压缩包。unzip xxx.zip 解压文件2. 安装jdkyum install java-11-openjdk-devel -y3. 运行con
2020-04-23
编写自己的Spring Boot Starter

编写自己的Spring Boot Starter

1.新建一个maven项目命名规则统一是xxx-spring-boot-starter完整pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"
2020-06-29