当前位置: 首页 > backend >正文

Docker安装的mysql限制ip访问

1.问题背景

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

2.排查过程

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

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-permanentsudo firewall-cmd --reload

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

2.查找问题根源

sudo iptables -L -n | grep 3306

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

继续查看DOCKER-USER

sudo iptables -L DOCKER-USER --line-numbers

在这里插入图片描述
是 DOCKER-USER 链默认的第一条,意思是:
如果没有其他规则匹配,就RETURN返回,继续走INPUT链的逻辑。
RETURN 相当于 退出当前链,不继续匹配 DOCKER-USER 后续规则了。

➡️所以后续我们添加的自定义规则(比如 DROP、ACCEPT)一定要加在 RETURN 之前!
如果加在 RETURN 之后,就永远到不了你的规则了,因为前面已经 RETURN 了,后面的根本不会执行。

举个例子:
现在 DOCKER-USER链是这样的:

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前):

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 表示插在最前面。

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

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策略

sudo iptables -L -n

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

🔥Chain DOCKER
🔥Chain DOCKER-USER

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

链名作用
DOCKERDocker自动管理的链:用来处理 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 能看到每条规则的编号,比如:

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号规则,方法如下:
因为每删一条,后面的编号都会往前移动,所以需要倒着删!

✅ 正确操作顺序:

iptables -D DOCKER-USER 3
iptables -D DOCKER-USER 2
iptables -D DOCKER-USER 1

先删3,再删2,再删1。
保证每次删除的都是你想删的那条!

为什么要倒着删?

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

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

for i in 3 2 1; doiptables -D DOCKER-USER $i
done

## 4.关于直接在文件中编辑policy的顺序 **1. 先导出iptables规则到文件**
sudo iptables-save > /tmp/iptables.rules

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

2. 打开并编辑
用你喜欢的编辑器,比如 vim 或 nano:

sudo vim /tmp/iptables.rules

文件内容大概长这样:

*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 规则排到最前面:

修改成:

*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测试!

#清空规则表
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端口

sudo yum install -y tcpdump   # centos/redhat
# 或
sudo apt install -y tcpdump   # ubuntu/debian

抓3306端口的流量

sudo tcpdump -i any port 3306

6. 关于ip段放行的建议

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网络(默认网络模式)一般是:

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网段?
可以在宿主机上执行:

docker network inspect bridge

输出例子:

[{"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

http://www.xdnf.cn/news/2830.html

相关文章:

  • [三分钟]web自动化测试(三):selenium自动化测试常用函数(下)
  • 基于蓝牙Beacon人员导航方案
  • 【Linux】第十二章 安装和更新软件包
  • 第七章:Server/Client Communication
  • 增量抽取的场景下,周期快照表最新分区的数据是如何生成?
  • 安卓开发学习随记
  • OpenCV 图形API(69)图像与通道拼接函数------将一个 GMat 类型的对象转换为另一个具有不同深度GMat对象函数convertTo()
  • vue3使其另一台服务器上的x.html,实现x.html调用中的函数,并向其传递数据。
  • kylin v10 + argo + ascend 310p多机多卡 pytorch distributed 训练
  • JavaWeb学习打卡-Day4-会话技术、JWT、Filter、Interceptor
  • WPF之Label控件详解
  • GoLand包的爆红问题解决
  • Coupang火箭计划深度攻略:eBay卖家突破韩国市场的三维数据作战模型
  • 面试算法高频08-动态规划-03
  • InitializingBean接口和@PostConstruct-笔记
  • Spring系列四:AOP切面编程 第二部分
  • EasyGBS国标GB28181设备管理软件打造园区安防高效解决方案
  • 【C++】类和对象(4)
  • 开源CMS系统的SEO优化功能主要依赖哪些插件?
  • java 和 C#操作数据库对比
  • Web技术与Apache网站部署
  • 知识付费平台:野兔YeTu
  • 静态库与动态库简介
  • CAD2008无法完成激活注册问题
  • LINE FRIENDS 正式与 Walrus 合作,全新 AI 驱动的游戏即将上线
  • maven私服配置
  • 如何创建并使用极狐GitLab 受保护分支?
  • 明远智睿SSD2351开发板:开启工业控制新征程
  • Linux[开发工具]
  • 短视频矩阵系统贴牌批量剪辑功能开发,支持OEM