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 链上添加禁用规则
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
端口,而不是绑定宿主机的3308
端口
禁止容器访问宿主机
sudo iptables -I INPUT -s 172.17.0.3 -d 192.168.220.144 -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