本文主要学习iptables的一些学习,讲解一些四表五链的基本概念,同时通过iptables实现一下场景,比如反向代理端口、禁用域名、限制IP和端口访问。
iptables是Linux的防火墙管理工具而已,真正实现防火墙功能的是Netfilter,我们配置了iptables规则后Netfilter通过这些规则来进行防火墙过滤等操作
Netfilter模块:
它是主要的工作模块,位于内核中,在网络层的五个位置(也就是防火墙四表五链中的五链)注册了一些钩子函数,用来抓取数据包;把数据包的信息拿出来匹配各个各个链位置在对应表中的规则:匹配之后,进行相应的处理ACCEPT、DROP等等。
下面这张图很明了的说明了Netfilter和iptables之间的关系
请求报文要进入本机的某个应用程序,首先会到达iptables防火墙的PREROUTING链,然后又跟PREROUTING链转发到INPUT链,最后转发到所在的应用程序上。
PREROUTING—>INPUT—>PROCESS
请求报文读取完应用程序要从本机流出,首先要经过iptables的OUTPUT链,然后转发到POSTOUTING链,最后从本机成功流出
PROCESS—>OUTPUT—>POSTROUTING
请求报文经过本机向其他主机转发时,首先进入A主机的PREROUTING链,此时不会被转发到INPUT链,因为不是发给本机的请求报文,此时会通过FORWARD链进行转发,然后从A主机的POSTROUTING链流出,最后到达B主机的PREROUTING链
PREROUTING—>FORWARD—>POSTROUTING
iptables防火墙中表的概念:在一个链中会有很多的防火墙规则,我们将具有同一种类型的规则组成一个集合,这个集合就叫做表,表可以简单的列成是一些具有同样类型的规则的分组,例如关于IP地址转换的策略都放在一个表中、修改数据保报文的策略都放在一个表中。
表名 | 拥有的链名 |
---|---|
filter | INPUT、OUTPUT、FORWARD |
nat | INPUT、OUTPUT、PREROUTING、POSTROUTING |
manager | INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING |
raw |
OUTPUT、PREROUTING |
在Iptables防火墙中,表与链之间是存在优先级的关系的,因为每张表的作用都是不同的,一张表会同时存放在多个链中,当一条数据报文进入一个链后,会按照表的优先级顺序依次匹配对应的规则。
Iptables防火墙表的优先级顺序:raw—>mangle—>nat—>filter。
当数据报文进入PREROUTING链时,首先规匹配raw表中的规则,然后在匹配mangle表中的规则,最后在匹配nat表的规则,按照优先级顺序依次匹配。
iptables [-t 表名] 选项 [链名] [条件] [-j 控制类型]
-P 设置默认策略:iptables
-P INPUT (DROP|ACCEPT)
-F 清空规则链
-L 查看规则链
-A 在规则链的末尾加入新规则
-I num 在规则链的头部加入新规则
-D num 删除某一条规则
-s 匹配来源地址IP
/MASK
,加叹号
"!"
表示除这个IP外。
-d 匹配目标地址
-i 网卡名称 匹配从这块网卡流入的数据
-o 网卡名称 匹配从这块网卡流出的数据
-p 匹配协议,如tcp,udp,icmp
--dport num 匹配目标端口号
--sport num 匹配来源端口号
扩展模块:
-m 模块名 --state 状态
-m
模块:
-m
后面跟随要使用的模块的名称,例如-m state
表示使用连接状态模块。- 不同的模块提供不同的功能和选项,用于执行特定的任务,例如连接跟踪、端口匹配、时间匹配等。
--state
:
--state
是iptables
中连接状态模块的选项之一。- 用于指定数据包的连接状态条件。连接状态用于确定数据包是否与一个新连接、已建立连接、相关连接或无效连接相关联。
- 可能的连接状态包括
NEW
、ESTABLISHED
、RELATED
和INVALID
,分别表示新连接、已建立连接、相关连接和无效连接。- 使用
--state
选项,您可以根据连接状态来创建防火墙规则,以允许或拒绝数据包。例如,您可以使用--state NEW
允许新连接,--state ESTABLISHED
允许已建立连接通过等等。
NEW:表示数据包与尚未建立的新连接相关联。这通常用于允许传入的新连接建立。
ESTABLISHED:表示数据包与已经建立的连接相关联。这通常用于允许已建立的连接的数据包通过防火墙。
RELATED:表示数据包与已建立的连接相关联,但不是严格的 ESTABLISHED 连接。通常用于处理与已建立连接相关的辅助连接,如 FTP 数据通道或 ICMP错误消息。
INVALID:表示数据包无法识别为任何已知连接状态的一部分,通常是无效的数据包。
#查看nat表的规则
iptables -t nat -L
iptables -t nat -nvL --line-numbers
- -A 在最后一条规则后新增规则
- -I 默认将新规则插入到第一条
- -F 不指定<链名>,默认清空整个表的规则
- -D <链名> <规则编号> 删除指定编号的规则(使用--line-numbers可查看编号)
iptables -t filter -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
又或者在nat表达POSTROUTING链的第2条规则后增加一条规则
iptables -t nat -I POSTROUTING 3
iptables -t 表名 -F 链名
其中,表名可以是filter、nat、mangle、raw等,链名可以是INPUT、OUTPUT、FORWARD等。
例如,要清空filter表中INPUT链的所有规则,可以使用以下命令:
iptables -t filter -F INPUT
ps:注意这个操作是不可逆的,清空后所有的规则都将被删除。
删除INPUT链的规则标号6
iptables -t filter -D INPUT 6
iptables -A INPUT -s 192.168.10.0/24 -p tcp --dport 40000:60000 -j DROP
Ps:--dport参数中,区间用 : 符号分隔
iptables -A INPUT -s 10.10.10.10 -j DROP
#拒绝IP段的所有icmp且type为8的流量
iptables -A INPUT -s 10.10.10.10/24 -p icmp --icmp-type 8 -j DROP
ps:修改-p 后面的值,可替换协议,目前支持 TCP、UDP、ICMP、ICMPv6、esp、ah、sctp、udplite、all协议
白名单:先允许,再拒绝。
例如只允许192.168.0.0/16的ip段访问本机,其他ip的请求都拒绝,命令如下:
iptables -I INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -I INPUT -s 0.0.0.0/0 -j DROP
一般 iptables 自带的都有 string 模块,这个模块的作用就是匹配字符串,匹配到泛域名的 URL,然后就把数据包丢弃,就实现了屏蔽泛域名的功能。
比如限制www.baidu.com,命令如下:
iptables -A OUTPUT -m string --string "baidu.com" --algo bm --to 65535 -j DROP
命令行解释:
-m string
# 指定模块;
--string "youtube.com"
# 指定要匹配的字符串(域名、关键词等);
--algo bm
# 指定匹配字符串模式/算法(还有一种更复杂的算法:kmp);
--to 65535
# 指定端口,这里代表所有端口(1-65535);
-j DROP
# 指匹配到数据包后处理方式,这里是丢弃数据包。
yum install -y httpd-tools
命令如下,注意最后的斜杠 / 一定不能少。
ab -n 1000 -c 10 http://ip:port/
- -n 总共请求1000次
- -c 每次并发10个
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set --name HTTP --rsource
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 60 --hitcount 100 --name HTTP --rsource -j DROP
第一条规则:
iptables -A INPUT
:将规则附加到 INPUT 链,这是用于处理传入数据包的链。-p tcp
:指定规则适用于 TCP 数据包。--dport 80
:规则适用于目标端口为 80 的数据包(HTTP 端口)。-m state --state NEW
:规则仅适用于新连接。-m recent --set --name HTTP --rsource
:使用 recent 模块来设置一个名为 "HTTP" 的连接跟踪表,并将源地址加入 "HTTP" 表中。这个规则的作用是记录每个新连接的源地址。第二条规则:
iptables -A INPUT
:同样将规则附加到 INPUT 链。-p tcp
:依然指定规则适用于 TCP 数据包。--dport 80
:目标端口为 80 的数据包。-m state --state NEW
:仍然只适用于新连接。-m recent --update --seconds 60 --hitcount 100 --name HTTP --rsource -j DROP
:使用 recent 模块来检查 "HTTP" 表,如果源地址在最近 60 秒内建立了超过 100 个连接,则将数据包丢弃(-j DROP
)。这个规则的作用是如果某个源地址在短时间内建立了过多的连接,就丢弃该连接以减轻服务器的负载。这两个规则一起工作,首先记录每个新连接的源地址,然后检查 "HTTP" 表,如果某个源地址在短时间内建立了大量连接,就拒绝进一步的连接。这有助于保护服务器免受恶意流量的影响。请注意,您可以根据需要调整规则中的参数,例如
--seconds
和--hitcount
,以满足您的特定需求。
这个规则将在每个IP地址的每个60秒内限制HTTP连接到80端口的数量为100个。如果超过了这个限制,连接将被拒绝。
(1)限制端口总并发数
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 10 -j RJECT
ps:使用iptables的connlimit模块来实现限制80端口的并发量不超过10个,超过则拒绝连接。注意这里是对所有ip并发的总数进行限制的,不是对于单个ip的并发限制。
(2)限制单个IP端口并发数
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 10 --connlimit-mask 32 -j REJECT --reject-with tcp-reset
-A INPUT
:将规则附加到 INPUT 链,这是用于处理传入数据包的链。
-p tcp
:指定规则适用于 TCP 数据包。
--dport 80
:规则适用于目标端口为 80 的数据包(通常是 HTTP 端口)。
-m connlimit
:使用连接限制模块。
--connlimit-above 10
:规则指定当连接数超过 10 个时,应用此规则。这表示一旦有超过 10 个并发连接尝试访问端口 80,将应用这个规则。
--connlimit-mask 32
:--connlimit-above
选项的掩码。32
表示匹配整个 IPv4 地址空间。这意味着限制的是每个源 IP 地址的连接数,而不是整个网络。如果需要限制所有的IP的并发连接数,可以使用
--connlimit-mask 0
。
-j REJECT
:如果连接数超过 10,拒绝连接。
--reject-with tcp-reset
:拒绝连接时,发送 TCP RESET 包作为响应。
REJECT和DROP的区别:
REJECT
和DROP
是iptables中的两种不同的动作。
REJECT
会向源地址回送一条信息,告诉它被拒绝了,而DROP
则是默默地将数据包丢弃。所以使用REJECT
可以让源地址知道它的请求被拒绝了,而DROP
则会使源地址一直等待直到超时。分析:
- DROP 的处理效率明显比 REJECT 低。DROP 会导致客户端不停的发送 SYN 包到服务器,最终客户端等待 tcp timeout才停止发送数据包,会占用更多带宽。
- 从安全层面来考虑,DROP 不会向客户端返回任何数据包,无疑是最安全的。
要在 Linux 上开启端口转发,您需要启用内核的 IP 转发功能,并添加适当的防火墙规则(如果有防火墙)
echo "net.ipv4.ip_forward = 1" >>/etc/sysctl.conf
sysctl -p
本地端口转发,只涉及一台机器,比如外部访问本机的2222端口转发到本地的22端口
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j REDIRECT --to-port 22
添加上面的规则后,外部可以访问,但是本地127.0.0.1无法访问。因为本地的请求不经过PREROUTING
A的IP是10.122.131.225,B的IP是10.122.131.34, A和B是内网的互通的,现在一个外部IP(10.121.1.116)为C, C想通过访问B的2222端口从而访问到A的22端口
iptables -t nat -A POSTROUTING -d 10.122.131.225 -p tcp --dport 22 -j SNAT --to-source 10.122.131.34
PS:该命令很重要!规则的作用是修改数据包的源地址,将目标地址为 10.122.131.225 且目标端口为 22
(SSH端口)的 TCP 数据包的源地址改为 10.122.131.34
(1)单端口转发
iptables -t nat -A PREROUTING -s 10.121.1.116 -p tcp --dport 2222 -j DNAT --to-destination 10.122.131.225:22
规则的作用是修改数据包的目标地址和端口,将目标端口为 2222
的 TCP 数据包的目标地址改为 10.122.131.225,目标端口改为 22
ps:这两条都要在B机器上执行,因为它是外部访问的目标机器。
如果不想限制外部访问的来源是C,可以不指定-s选项。
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 10.122.131.225:22
这样任意外部ip访问都可以请求转发了。
针对上面的命令,如果是多端口转发,可以分为多对一和多对多的情况。
PS:经测试,iptables不支持在一条命令中实现不同主机的多端口的不同映射。比如同时将B的80转发到A的8080,将B的443转发到A的4443。
(1)多对一端口转发
例如将B的50000到60000的端口全部转发到A的443端口,命令如下
iptables -t nat -A PREROUTING -p tcp -m multiport --dport 50000:60000 -j DNAT --to-destination 10.122.131.225:443
ps:”–dports” 参数指定端口范围,使用冒号 “:” 表示起始端口和结束端口之间的范围。
(2)多对多端口转发
例如将B的50000到60000的端口全部转发到A的50000到60000的端口,命令如下:
iptables -t nat -A PREROUTING -p tcp -m multiport --dport 50000:60000 -j DNAT --to-destination 10.122.131.225:50000-60000
ps:设置范围的时候两者端口数量必须一致,保持一一对应 的关系,比如iptables -t nat -A PREROUTING -p tcp -m multiport --dport 80,443,8080 -j DNAT --to-destination 10.122.131.225:80,443,8080 如此设置是不行 的
当然多个端口也可以是不连续的,比如80、443、8080同端口转发,端口用逗号”,”隔开,–to-destination后面的ip不用再指定端口。
iptables -t nat -A PREROUTING -p tcp -m multiport --dport 80,443,8080 -j DNAT --to-destination 10.122.131.225
ps:–to-destination 参数后,使用”-“表示起始端口和结束端口之间的范围。
MASQUERADE作用是,从服务器的网卡上,自动获取当前ip地址来做NAT,就不用手动指定转换的目的IP了,实现了动态的SNAT。
iptables -t nat -A POSTROUTING -d 10.122.131.225 -p tcp --dport 22 -j SNAT --to-source 10.122.131.34
这条命令用MASQUERADE可以换成下面的写法:
iptables -t nat -A POSTROUTING -d 10.122.131.225-p tcp --dport 22 -j MASQUERADE
外部访问本机web服务,属于数据流入的操作,首先外部地址访问本地服务会经过 PREROUTIGN和INPUT链,虽然设置规则要近来源地址,但是PREROUTING链没有过滤的表,故而要在第二条链INPUT链做配置。
此流量属于数据流出的操作,会经过PREROUTING链和OUTPUT链,拒绝tcp流量,一般在filter表实现,而PREROUTING不包含filter表,故规则配置在OUTPUT链
来自本地内部网络的主机流量,属于属于数据转发请求,会经过 PREROUTING、FORWARD和POSTROUTING链,允许拒绝操作一般在filter表中实现,这里找距离目标端最近的链添加规则,也就是 FORWARD链进行配置
参考来源:iptables命令常用规则汇总 – Zgao's blog