iptables 详解

一、防火墙综述

防火墙的主要作用就是对 进出入网络的数据包 进行检测。常见的有 3层防火墙,还有 7层防火墙

  • 3层防火墙: 对于 TCP/IP 的七层模型来讲,第三层是网络层,网络层的防火墙会对 源地址目标地址 进行检测。

  • 7层防火墙: 会对 源ip目标ip源端口目标端口均进行校验。

二者对比,七层防火墙更加安全、功能更加强大。但同时也纯在效率更低的问题。

为简单理解。本文只考虑 filter表,对其他的表暂时不考虑

二、iptables 的工作原理

五链

iptables 是属于用户空间的东西,他的作用是定义规则。这些规则由处于内核态的 netfilter来读取并执行。而放在内核态的地方,必须要指定放入内核态的位置,即必须是 TCP/IP的协议栈经过的地方。 linux 中一共有 5 个位置

  1. 数据包从内核态流入用户态 input链

  2. 数据包从用户态流入内核态 output链

  3. 在内核态中:从一个接口流入另一个接口 forward链

  4. 进入本机的网络接口 prerouting

  5. 流出本机的网络接口 postrouting

chain 遍历优先级

  • 收到目的地为本机的包: prerouting -> input
  • 收到目的地为其他主机的包:prerouting -> forword -> postrouting
  • 本机产生的包:output -> postrouting

如果收到一个目的地为本机的包:首先会经过 prerouting 链上的 raw、mangle、nat 表;然后再经过 input 链上 mangle、filter、security、nat 表。最终到达本机的某个 socket

四表

iptables 的四个表rawmanglenatfilter(优先级由高到低)默认表是filter(没有指定表的时候就是filter表)。表和链之间属于 多对多 的关系。为简化理解。本文也只考虑 filter 表。

  • filter表:用来对数据包进行过滤,具体的规则要求决定如何处理一个数据包。其表内包括三个链:inputforwardoutput;-

  • nat 表:nat全称:network address translation 网络地址转换,主要用来修改数据包的 IP地址端口号。其表内包括三个链:preroutingpostroutingoutput;

  • mangle表:主要用来修改数据包的服务类型,生存周期,为数据包设置标记,实现流量整形、策略路由等。其表内包括五个链:preroutingpostroutinginputoutputforward;

  • raw表:主要用来决定是否对数据包进行状态跟踪。其表内包括两个链:outputprerouting;

如果收到一个目的地为本机的包:首先会经过 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

posted @ 2023-05-12 23:51  沧海一声笑rush  阅读(276)  评论(0编辑  收藏  举报