iptables 详解
一、防火墙综述
防火墙的主要作用就是对 进出入网络的数据包 进行检测。常见的有 3层防火墙,还有 7层防火墙
-
3层防火墙: 对于
TCP/IP的七层模型来讲,第三层是网络层,网络层的防火墙会对源地址和目标地址进行检测。 -
7层防火墙: 会对
源ip、目标ip、源端口、目标端口均进行校验。
二者对比,七层防火墙更加安全、功能更加强大。但同时也纯在效率更低的问题。
为简单理解。本文只考虑 filter表,对其他的表暂时不考虑
二、iptables 的工作原理
五链

iptables 是属于用户空间的东西,他的作用是定义规则。这些规则由处于内核态的 netfilter来读取并执行。而放在内核态的地方,必须要指定放入内核态的位置,即必须是 TCP/IP的协议栈经过的地方。 linux 中一共有 5 个位置
-
数据包从内核态流入用户态 input链
-
数据包从用户态流入内核态 output链
-
在内核态中:从一个接口流入另一个接口 forward链
-
进入本机的网络接口 prerouting
-
流出本机的网络接口 postrouting
chain 遍历优先级
- 收到目的地为本机的包:
prerouting -> input - 收到目的地为其他主机的包:
prerouting -> forword -> postrouting - 本机产生的包:
output -> postrouting
如果收到一个目的地为本机的包:首先会经过 prerouting 链上的 raw、mangle、nat 表;然后再经过 input 链上 mangle、filter、security、nat 表。最终到达本机的某个 socket
四表
iptables 的四个表raw,mangle,nat,filter(优先级由高到低)默认表是filter(没有指定表的时候就是filter表)。表和链之间属于 多对多 的关系。为简化理解。本文也只考虑 filter 表。
-
filter表:用来对数据包进行过滤,具体的规则要求决定如何处理一个数据包。其表内包括三个链:input、forward、output;- -
nat表:nat全称:network address translation网络地址转换,主要用来修改数据包的IP地址、端口号。其表内包括三个链:prerouting、postrouting、output; -
mangle表:主要用来修改数据包的服务类型,生存周期,为数据包设置标记,实现流量整形、策略路由等。其表内包括五个链:prerouting、postrouting、input、output、forward; -
raw表:主要用来决定是否对数据包进行状态跟踪。其表内包括两个链:output、prerouting;
如果收到一个目的地为本机的包:首先会经过 prerouting 链上的 raw、mangle、nat 表;然后再经过 input 链上 mangle、filter、security、nat 表。最终到达本机的某个 socket
三、iptables 的规则配置
iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作
-t<表>:指定要操纵的表;
-A:向规则链中添加条目;
-i:向规则链中插入条目;
-D:从规则链中删除条目;
-L:显示规则链中已有的条目
规则包括
-accept:接收数据包。
-DROP:丢弃数据包
-reject:拒绝
-REDIRECT:重定向、映射、透明代理。
-SNAT:源地址转换。
-DNAT:目标地址转换。
-MASQUERADE:IP伪装(NAT),用于ADSL。
-LOG:日志记录。
开放指定端口号:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT #允许访问80端口
删除某条规则
查看规则序号
iptables -L -n --line-number
删除指定防火墙规则
iptables -D INPUT 3 #删除INPUT的第三条已添加规则,这里3代表第几行规则
docker 与 iptables
配置 docker的时候,需要对网络进行隔离操作。详情可以查考使用IPTABLES熔断DOCKER CONTAINER中的服务
和 Docker and iptables两篇文文章
问题描述
用如下命令启动一个 docker 容器。将 mysql 的 3306 端口映射到主机 3308 端口。此时防火墙处于打开状态,但使用 mysql 客户端依旧可以远程连通容器,如何限制仅本机访问呢?
docker run -d --rm --name mysql_01 -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:latest
解决方案一
在启动容器的时候,直接绑定 ip地址 为 127.0.0.1
docker run -d --rm --name mysql_01 -p 127.0.0.1:3308:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:latest
再连接发现。外部已经访问了不来了。本机可通过 3308 端口正常访问 mysql。
绑定 127.0.0.1 本质上是绑定的本地网卡,而非外网网卡。其实就是本地的回环地址。同理:你也可以通过绑定外网 ip 的方式,确保只有能外网访问,而本地不能访问。
如上的改动,其实有个问题,就是如果使用容器内的服务访问 mysql 的话,也是访问不通的。
解决方案2
- 在 DOCKER-USER 链上按照IP和端口号添加禁用规则
sudo iptables -I DOCKER-USER -p tcp -d 172.17.0.2 --dport 3306 -j REJECT
172.17.0.2是 mysql 容器的 ip 地址,可以使用docker inpect命令查看- 在
DOCKER-USER链上,禁用的应该是3306端口,而不是绑定宿主机的3306端口
- 直接在 docker-user 链上按端口号禁用
sudo iptables -I DOCKER-USER -p tcp --dport 3306 -j REJECT
添加该规则后,宿主机外访问不通了,但在宿主机本省是可以访问通的。
禁止容器访问宿主机
访问宿主机,最终要走 input 链。
sudo iptables -I INPUT -s 172.17.0.3 -j REJECT
但此时该容器,访问其他容器还是通的,
参考连接
https://tinychen.com/20200414-iptables-principle-introduction/
https://arthurchiao.art/blog/deep-dive-into-iptables-and-netfilter-arch-zh/
https://blog.csdn.net/wangquan1992/article/details/100534543
https://www.cnblogs.com/rush-peng/p/17174337.html
https://www.cnblogs.com/klb561/p/9011546.html
浙公网安备 33010602011771号