Docker安装的mysql限制ip访问

1.问题背景

docker安装了mysql服务,服务器为Redhat9,我们希望通过防火墙规则直接限制访问的来源ip,只允许特定ip进行访问,其余ip需要被禁止。

2.排查过程

1.首先尝试了通过firewalld方式添加对应的防火墙规则,

bash 复制代码
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port protocol="tcp" port="3306" reject'

firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.190.126.111" port protocol="tcp" port="3306" accept'

sudo firewall-cmd --runtime-to-permanent

sudo firewall-cmd --reload

添加后发现其余IP依然可以访问,firewalld并未起作用。

2.查找问题根源

bash 复制代码
sudo iptables -L -n | grep 3306

发现docker默认添加了3306端口的放行规则,虽然我在 firewalld 设置了规则,但Docker加的iptables规则优先级更高,所以导致直接放行了。

继续查看DOCKER-USER

bash 复制代码
sudo iptables -L DOCKER-USER --line-numbers

是 DOCKER-USER 链默认的第一条,意思是:

如果没有其他规则匹配,就RETURN返回,继续走INPUT链的逻辑。

RETURN 相当于 退出当前链,不继续匹配 DOCKER-USER 后续规则了。

➡️所以后续我们添加的自定义规则(比如 DROP、ACCEPT)一定要加在 RETURN 之前!

如果加在 RETURN 之后,就永远到不了你的规则了,因为前面已经 RETURN 了,后面的根本不会执行。

举个例子:

现在 DOCKER-USER链是这样的:

bash 复制代码
Chain DOCKER-USER (1 references)
num  target  prot opt source    destination
1    RETURN  all  --  0.0.0.0/0  0.0.0.0/0

如果我们要加规则,比如:

允许 10.161.238.15 访问3306,再全部拒绝其他IP。

我们需要这么加(保证在RETURN前):

bash 复制代码
iptables -I DOCKER-USER 1 -s 10.161.238.15 -p tcp --dport 3306 -j ACCEPT
iptables -I DOCKER-USER 2 -p tcp --dport 3306 -j DROP

-I 是 插入,第一个参数是位置,1 表示插在最前面。

插完之后,链的顺序就会变成这样:

bash 复制代码
Chain DOCKER-USER (1 references)
num  target  prot opt source            destination
1    ACCEPT  tcp  --  10.161.238.15      0.0.0.0/0    tcp dpt:3306
2    DROP    tcp  --  0.0.0.0/0          0.0.0.0/0    tcp dpt:3306
3    RETURN  all  --  0.0.0.0/0          0.0.0.0/0

再次查看具体的iptables策略

bash 复制代码
sudo iptables -L -n

此时可以看到Chain DOCKER (3 references)和Chain DOCKER-USER (1 references)两部分,关于这两块内容下面是相关解释:

🔥Chain DOCKER
🔥Chain DOCKER-USER

这两个都是 Docker 启动时自己加的链,它们有不同的功能:

链名 作用
DOCKER Docker自动管理的链:用来处理 Docker 容器的端口映射,比如docker run -p 3306:3306。你不要直接改这里,Docker会自动覆盖。
DOCKER-USER 用户自定义规则链:这是Docker专门留给用户自己加规则的地方,Docker不会动这里。适合你加自己的防火墙规则,比如只让某些IP访问容器。

如果你想限制Docker的3306端口访问,应该:

✅ 加在 DOCKER-USER 链里!

🧠 为什么不能加在 DOCKER 链?

DOCKER 链是Docker内部维护的。

每次你启动、停止容器,Docker会重新生成这里的规则。

你手动加进去的,过一会儿就被覆盖掉了!!

所以官方推荐,如果你有自己的访问控制需求,去动 DOCKER-USER。

目的 加在哪
控制容器访问流量(Docker的端口映射) 加在 DOCKER-USER
控制本机服务(非Docker容器)访问流量 加在 INPUT

3.关于删除规则

用 iptables -L DOCKER-USER --line-numbers 能看到每条规则的编号,比如:

bash 复制代码
Chain DOCKER-USER (2 references)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  10.161.238.15         anywhere             tcp dpt:3306
2    ACCEPT     tcp  --  10.161.238.16         anywhere             tcp dpt:3306
3    ACCEPT     tcp  --  10.161.238.17         anywhere             tcp dpt:3306
4    DROP       all  --  anywhere              anywhere![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/9dce2c9bbc5b40b49dfe81613af58ea4.png)

🛠️ 你要删除 1-3号规则,方法如下:

因为每删一条,后面的编号都会往前移动,所以需要倒着删!

✅ 正确操作顺序:

bash 复制代码
iptables -D DOCKER-USER 3
iptables -D DOCKER-USER 2
iptables -D DOCKER-USER 1

先删3,再删2,再删1。

保证每次删除的都是你想删的那条!

为什么要倒着删?

如果你从1开始删,比如删了1,原来的2号规则就变成了新的1号,这样会乱掉,会误删!

✨如果想一口气删掉(比如脚本里),可以写:

bash 复制代码
for i in 3 2 1; do
  iptables -D DOCKER-USER $i
done

4.关于直接在文件中编辑policy的顺序 **1. 先导出iptables规则到文件**

bash 复制代码
sudo iptables-save > /tmp/iptables.rules

这样你就得到了一个标准文本文件 /tmp/iptables.rules,可以直接用文本编辑器打开编辑。

2. 打开并编辑

用你喜欢的编辑器,比如 vim 或 nano:

bash 复制代码
sudo vim /tmp/iptables.rules

文件内容大概长这样:

bash 复制代码
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p tcp --dport 22 -j ACCEPT
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 3306 -j DROP
COMMIT
-A INPUT ... 表示添加一条规则到 INPUT 链。

你可以直接剪切、粘贴这些 -A 开头的行,调整它们的上下顺序。

比如想让 3306 的 DROP 规则排到最前面:

修改成:

bash 复制代码
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p tcp --dport 3306 -j DROP
-A INPUT -p tcp --dport 22 -j ACCEPT
-A INPUT -p tcp --dport 80 -j ACCEPT
COMMIT

3. 保存退出

4. 清空iptables并重新导入新规则

⚠️ 注意:清空后如果规则不对可能断掉SSH,要小心,可以开一个额外的console测试!

bash 复制代码
#清空规则表
sudo iptables -F

#先测试是否有语法错误
sudo iptables-restore --test < /tmp/iptables.rules

#正式导入
sudo iptables-restore < /tmp/iptables.rules

5. 关于如何确定mysql的访问ip是多少

1. 通过sql查询最近的访问记录,但这个方式不太全,如果某些库没有在请求那么会被漏掉,所以最好自己整理一下所有库的应用来源IP。

SELECT distinct host FROM information_schema.processlist;

2. 抓包查看具体是哪个IP在访问3306端口

bash 复制代码
sudo yum install -y tcpdump   # centos/redhat
# 或
sudo apt install -y tcpdump   # ubuntu/debian

抓3306端口的流量

bash 复制代码
sudo tcpdump -i any port 3306

6. 关于ip段放行的建议

bash 复制代码
iptables -I DOCKER-USER 1 -s 10.197.216.x -p tcp --dport 3306 -j ACCEPT && \
iptables -I DOCKER-USER 2 -s 10.197.216.x -p tcp --dport 3306 -j ACCEPT && \
iptables -I DOCKER-USER 3 -s 172.17.0.0/16 -p tcp --dport 3306 -j ACCEPT && \
iptables -I DOCKER-USER 4 -p tcp --dport 3306 -j DROP

后续追加新的policy需要用-I来添加到最前面,否则不会生效

iptables -I DOCKER-USER -s 10.161.238.15 -p tcp --dport 3306 -j ACCEPT

也可以直接指定插入的index,即插入到哪个位置,index=2即插入到目前的第一条和第二条中间

iptables -I DOCKER-USER 2 -s 10.161.238.15 -p tcp --dport 3306 -j ACCEPT

其中上面的第三条是比较特殊的,由于我在抓包时发现部分来源IP为172.17.0.0/16开头,而这个网段是来自于docker

Docker默认bridge网络(默认网络模式)一般是:

bash 复制代码
172.17.0.0/16

容器起的时候,默认分配的IP就是 172.17.x.x 这种。

所以如果防火墙放行整个 172.17.0.0/16,就能统一解决问题。

有的系统或复杂网络环境,Docker可能用其他网段(比如 172.18.0.0/16),这取决于 Docker 网络配置,但默认就是172.17.0.0/16。

🛠 怎么确认自己机器的Docker网段?

可以在宿主机上执行:

bash 复制代码
docker network inspect bridge

输出例子:

bash 复制代码
[
    {
        "Name": "bridge",
        "Id": "...",
        "IPAM": {
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        }
    }
]

✅ 这里 "Subnet": "172.17.0.0/16" 就是默认的 Docker 网络段。

相关引用文档

https://blog.csdn.net/lumia98/article/details/111276451

相关推荐
南川琼语1 小时前
TCP概念+模拟tcp服务器及客户端
linux·服务器·网络·tcp/ip
rainFFrain6 小时前
(MySQL)库的操作
数据库·mysql
SunTecTec9 小时前
Flink Docker Application Mode 命令解析 - 修改命令以启用 Web UI
大数据·前端·docker·flink
好记忆不如烂笔头abc9 小时前
HTTPSConnectionPool(host=‘files.pythonhosted.org‘, port=443): Read timed out.
docker
白山云北诗9 小时前
什么是 DDoS 攻击?高防 IP 如何有效防护?2025全面解析与方案推荐
网络协议·tcp/ip·ddos·高防ip·ddos攻击怎么防·高防ip是什么
郭不耐10 小时前
PostgreSQL与MySQL哪个适合做时空数据分析?
mysql·postgresql·数据分析
内网渗透10 小时前
OpenWrt 与 Docker:打造轻量级容器化应用平台技术分享
linux·docker·容器·openwrt·软路由
qq_3392822311 小时前
docker打开滚动日志
运维·docker·容器
YH.12 小时前
MySQL 主从复制
mysql