PREROUTING 链是 mangle 和 nat 表中用于修改数据包的报头信息的链。
具体来说,PREROUTING 链主要用于处理刚到达本机并在路由转发前的数据包。在该链上添加的规则可以检查数据包的目标地址、端口等信息,然后根据实际需求进行处理,例如将目标地址修改为本地 IP 地址或者其他网络设备的 IP 地址,从而实现端口映射或者 DNAT(Destination NAT)等功能。
PREROUTING 链常常用于以下场景:
POSTROUTING 链是 mangle、nat 和 raw 表中用于修改数据包的报头信息的链。该链主要用于处理将要离开本机的数据包,其作用是对数据包的源 IP 地址进行 NAT 转换或者修改规则的匹配等操作。
一般来说,POSTROUTING 链被用于以下场景:
INPUT 链是 filter 表中用于处理传入数据包的链。该链主要用于过滤本机接收到的数据包,控制对本机服务的访问。
具体来说,INPUT 链可以用于以下场景:
OUTPUT 链是 filter 表中用于处理传出数据包的链。该链主要用于过滤本机发送的数据包,控制本机对外部服务的访问。
具体来说,OUTPUT 链可以用于以下场景:
FORWARD 链是 filter 表中用于处理转发数据包的链。该链主要用于过滤经过本机进行转发的数据包,控制外部网络访问内部网络的流量。
具体来说,FORWARD 链可以用于以下场景:
Iptables 中的 raw 表用于在经过连接跟踪、NAT 和路由表处理之前对数据包进行处理,因此 raw 表的优先级最高:
在下面这张图中,可以很清晰的看到,raw 表的优先级都是最高的,并且由于他的“特定”用途,导致 raw 也只会被应用在 PREROUTING 和 OUTPUT 链上。
一旦用户在某个链上使用了 raw 表,则处理完 raw 表后将跳过 NAT 表和连接跟踪处理,即不再做地址转换和数据包的连接跟踪处理。这可以应用在那些不需要进行 NAT 的情况下,以提高性能 [2]。
例如,当一台 web 服务器面对大量的访问请求时,我们可以使用 raw 表,让 80 端口不再让 iptables 做数据包的连接跟踪处理,从而提高用户的访问速度。
下面举两个例子,来说明 raw 表中的规则是如何提高机器性能的
iptables -t raw -A PREROUTING -p tcp --syn -j CT --notrack这个规则的作用是将所有的 TCP SYN 数据包转发给 conntrack 模块进行处理,同时不做任何连接跟踪,进而消除了 TCP SYN Cookie 技术对系统性能的影响。
TCP SYN Cookie 是一种防范 SYN Flood 攻击的技术。在 TCP 三次握手过程中,客户端向服务器发送 SYN 数据包,服务器收到之后应该回复一个 SYN+ACK 数据包,并进入 SYN_RCVD 状态等待客户端的 ACK 确认。但是,如果攻击者向服务器发送大量的 SYN 数据包而不回复 ACK 确认,那么服务器就会不断地创建新的半连接队列,耗尽资源,最终导致系统崩溃。TCP SYN Cookie 技术可以有效地抵御这种攻击。
iptables -t raw -A PREROUTING -p icmp -j DROP这个规则的作用是将所有的 ICMP 数据包直接拒绝,从而有效地防止了 ICMP 攻击。
通过使用 raw 表,可以避免数据包经过 NAT 表、连接跟踪和路由表处理前的额外处理,进而提高系统的性能。例如,在上述两个例子中,我们可以直接将数据包传递给底层协议栈,而不需要进行 NAT 或连接跟踪等处理,从而提高了系统的处理速度和吞吐量。
filter 表是 iptables 中的默认表,当你不使用 -t 来指定具体的表时,就会默认使用 filter 表。
filter 主要用于过滤数据包,控制网络流量。
Filter 表中有三种链(chains):
在 Filter 表中,可以根据源 IP 地址、目标 IP 地址、协议类型、端口号等条件来设置规则或过滤器,以决定数据包是否允许通过。
iptables 中的 NAT(Network Address Translation)表用于实现网络地址转换,主要作用是修改数据包的源地址和目的地址,从而实现网络流量的调整和控制。
NAT 表包括三个链(chains):
NAT 表常用的功能有:
总的来说,NAT 表是 iptables 中非常重要的一部分,通过配置 NAT 规则,可以实现网络地址转换和端口映射等功能,从而方便地管理和控制网络流量,提高网络的安全性和性能。
iptables 中的 mangle 表用于指定如何处理数据包,主要作用是对数据包的报头进行修改、标记或重定向。mangle 表具有五个内建链(chains),分别是:
mangle 表的主要作用如下:
下面给一些 mangle 的具体规则
iptables -t mangle -A PREROUTING -s 192.168.1.100/32 -j MARK --set-mark 10iptables -t mangle -A POSTROUTING -p tcp --sport 80 -j MARK --set-mark 30
iptables -t mangle -A POSTROUTING -m mark --mark 30 -j CLASSIFY --set-class 1:10
iptables -t mangle -A POSTROUTING -m mark --mark 0 -j CLASSIFY --set-class 1:20
tc qdisc add dev eth0 root handle 1: htb
tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbps ceil 10mbps
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbps ceil 10mbps
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 5mbps ceil 10mbpsiptables -t mangle -A OUTPUT -p tcp -s 192.168.1.100/32 -j DELAY --delay 100msiptables -t mangle -A OUTPUT -p udp --dport 5000 -j TOS --set-tos Minimize-Delay这些规则只是示例,实际应用中需要根据具体需求进行调整。例如,第二个规则中的 Class-Based queuing(CBQ)算法可以替换为其他算法,如 Hierarchical Token Bucket (HTB) 算法、Stochastic Fair Queuing (SFQ) 算法等。
查询包含如下内容
# 不加 -t 表名,默认是 filter,
iptables -t 表名 -L [链名]另外,还有几个附加参数:
要注意的是,多个短选项是可以合并的,比如下面两条命令是等价的
iptables -n -v -L
iptables -nvL但长选项是不可以与短选项合并的
iptables --line -nvL增加一条命令有两种方式:
这里是插入的示例
# 插入在第 1 条
iptables -I INPUT -s 192.168.1.146 -j ACCEPT
# 插入在第 2 条
iptables -I INPUT 2 -s 192.168.1.146 -j ACCEPT这里是追加的示例
iptables -A INPUT -s 192.168.1.146 -j ACCEPT在执行此动作前,请明确自己在干什么,若有需要请注意保存规则
使用 -F 来清空指定表和链的规则:
iptables -t filter -F INPUT删除指定规则有两种方法:
而删除的参数是 -D ,下面分别举个例子
首先是根据规则编号删除
# 先使用 --line 查得规则编号
iptables -t <表名> --line -nvL
# 再指定编号去删除(注意要指定链)
iptables -t [表名] -D INPUT <编号>然后是匹配规则删除
# 先查询具体规则的命令,你也可以使用 iptables -nvL,但是命令要自己写,比较麻烦
iptables-save
# 然后删除(注意 -A 去除)
iptables -D [规则]修改规则也有两种方法:
第一种:在原来的规则上修改
使用 -R 参数来指定要修改哪条链上的第几条规则
命令语法:iptables -t 表名 -R 链名 规则序号 规则原本的匹配条件 -j 动作
示例:iptables -t filter -R INPUT 3 -s 192.168.1.146 -j ACCEPT第二种:删除后再加新规则
修改指定表的指定链的默认策略(默认动作),可以使用如下命令。
命令语法:iptables -t 表名 -P 链名 动作
示例:iptables -t filter -P FORWARD ACCEPT上例表示将filter表中FORWARD链的默认策略修改为ACCEPT
# 匹配多个 IP
iptables -t filter -I INPUT -s 192.168.1.111,192.168.1.118 -j DROP
# 匹配网段
iptables -t filter -I INPUT -s 192.168.1.0/24 -j ACCEPT
#匹配取反
iptables -t filter -I INPUT ! -s 192.168.1.0/24 -j ACCEPT# 匹配多个 IP
iptables -t filter -I OUTPUT -d 192.168.1.111,192.168.1.118 -j DROP
# 匹配网段
iptables -t filter -I INPUT -d 192.168.1.0/24 -j ACCEPT
#匹配取反
iptables -t filter -I INPUT ! -d 192.168.1.0/24 -j ACCEPT可以匹配的协议类型tcp、udp、udplite、icmp、esp、ah、sctp等(centos7中还支持icmpv6、mh)
#示例如下
iptables -t filter -I INPUT -p tcp -s 192.168.1.146 -j ACCEPT
iptables -t filter -I INPUT ! -p udp -s 192.168.1.146 -j ACCEPT匹配流入网卡,在OUTPUT链与POSTROUTING链中不能使用此选项。
#示例如下
iptables -t filter -I INPUT -p icmp -i eth4 -j DROP
iptables -t filter -I INPUT -p icmp ! -i eth4 -j DROP匹配流出网卡,在INPUT链与PREROUTING链中不能使用此选项。
#示例如下
iptables -t filter -I OUTPUT -p icmp -o eth4 -j DROP
iptables -t filter -I OUTPUT -p icmp ! -o eth4 -j DROP扩展匹配需要模块支持,常见的扩展模块有:
前面一级匹配条件中,-s 能匹配 ip,能匹配 ip 段,能匹配离散 ip,但不能匹配随意的连续 ip。
若想匹配随意的连续 ip,可以使用 iprange 模块
iptables -A INPUT -d 172.16.1.100 -p tcp --dport 80 -m iprange --src-range 172.16.1.5-172.16.1.10 -j DROP要使用扩展端口,必须先使用 -m 参数指定对应模块,如果你指定了协议,则默认会使用与协议同名的模块。
例如,下面两条命令等价
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp --sport 22 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --sport 22 -j REJECT在与协议同名的模块中,都支持对端口进行匹配,包括:
并且这些端口可以是一个连续的范围(以下例子中 dport 和 sport 通用,只举一个例子)
#示例如下
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22 -j REJECT
# 连续端口
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 22:25 -j REJECT
# 匹配 0-22 和 80-65535 的端口
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport :22 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 80: -j REJECT
# 端口匹配取反
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp ! --sport 22 -j ACCEPT如果要匹配不连续(离散)的端口,则需要用到 multiport 模块,但最多也只能指定15个端口
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dport 22,80 -j REJECTmac 模块可以指明源MAC地址,,适用于:PREROUTING, FORWARD,INPUT chains
iptables -A INPUT -s 172.16.0.100 -m mac --mac-source 00:50:56:12:34:56 -j ACCEPT
iptables -A INPUT -s 172.16.0.100 -j REJECT使用 string 模块,可以对报文中的应用层数据做字符串模式匹配检测。
示例如下
iptables -A OUTPUT -p tcp --sport 80 -m string --algo bm --from 62 --string "google" -j REJECT对应的参数解释
--algo {bm|kmp} 字符串匹配检测算法
bm:Boyer-Moore
kmp:
--from offset 开始偏移
--to offset 结束偏移
[!] --string pattern 要检测的字符串模式
[!] --hex-string pattern要检测字符串模式,16进制格式limit 模块有两个参数
–limit-burst:类比”令牌桶”算法,此选项用于指定令牌桶中令牌的最大数量
–limit:类比”令牌桶”算法,此选项用于指定令牌桶中生成新令牌的频率,可用时间单位有second、minute 、hour、day。
iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT
iptables -t filter -A INPUT -p icmp -j REJECTconnlimit 模块是 iptables 中的一个扩展模块,用于控制连接数,限制每个源 IP 地址的并发连接数。
使用 connlimit 模块可以有效地保护服务器免受 DDoS(分布式拒绝服务)攻击,防止某个 IP 地址通过大量并发连接造成服务器负载过高,影响正常的网络服务。
connlimit 模块的工作原理是通过检查 iptables 所匹配到的连接数来实现连接限制。用户可以设置多种参数,如 --connlimit-above 用于限制允许的最大连接数,--connlimit-mask 用于指定判断连接数的掩码,--connlimit-upto 用于限制每个 IP 地址的允许最大连接数。
下面是一个示例规则,用于限制每个 IP 地址在 TCP 端口 80 上的最大连接数为 10:
iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 10 -j DROP上述规则表示如果某个 IP 地址建立的连接数超过了 10,则将该 IP 地址的所有连接都丢弃。
除了限制连接数之外,还可以在特定情况下排除某些IP地址对于连接数控制的限制,例如允许某些代理服务器或特定的IP地址建立更多的连接。具体操作可以使用感叹号 "!" 对特定的IP地址进行标记以进行放开,例如:
iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 10 --connlimit-mask 32 ! -s 192.168.1.1 -j DROP这条规则允许IP地址为192.168.1.1的主机建立更多的连接,而其他主机则被限制连接数不超过10。
state 模块是iptables中的一个扩展模块,用于匹配TCP连接的状态。
TCP连接有多种状态,包括ESTABLISHED、NEW、RELATED、INVALID等。ESTABLISHED表示连接已经建立,可以进行正常的数据传输;NEW表示新的连接请求,即SYN标志位被设置;RELATED表示与已经建立的连接相关的连接,例如FTP传输和DNS查询使用的UDP连接;INVALID表示无效的连接,可能由于网络原因等导致的连接错误。
state模块可以帮助iptables根据连接状态进行过滤,从而有效地保护服务器免受攻击。
下面是一些常见的用法:
iptables -A INPUT -i eth0 -p all -m state --state RELATED,ESTABLISHED -j ACCEPTiptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p icmp --icmp-type echo-request -m state --state NEW,ESTABLISHED,RELATED -j ACCEPTiptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT使用 -j (即 jump)来指定动作,动作可以是内置动作,也可以是自定义动作
常规命令如下
iptables -I INPUT -s 192.168.1.146 -j ACCEPT常规命令如下
iptables -I INPUT -s 192.168.1.146 -j REJECT还可以用 –reject-with 来设置提示信息,可选值有:
当不设置任何值时,默认值为icmp-port-unreachable。
iptables -I INPUT -s 192.168.1.146 -j REJECT –reject-with icmp-host-unreachable常规命令如下
iptables -I INPUT -s 192.168.1.146 -j DROPLOG 可以用于记录匹配报文的记录,为了避免过多,匹配的规则应当越精准越好。
iptables -I INPUT -p tcp --dport 22 -J LOG日志默认会记录在 /var/log/message 中,当然,我们也可以将相关信息记录在指定的文件中,以防止iptables的相关信息与其他日志信息相混淆,修改/etc/rsyslog.conf文件(或者/etc/syslog.conf),在rsyslog配置文件中添加如下配置即可。
#vim /etc/rsyslog.conf
kern.warning /var/log/iptables.log加入上述配置后,报文的相关信息将会被记录到/var/log/iptables.log文件中。
完成上述配置后,重启rsyslog服务(或者syslogd),服务重启后,配置即可生效,匹配到的报文的相关信息将被记录到指定的文件中。
service rsyslog restartLOG动作也有自己的选项,常用选项如下(先列出概念,后面有示例)
注:–log-prefix对应的值不能超过29个字符。
注意事项:要实现两个不同段网络的互通,理论上只要开启机器上的路由转发功能即可实现(前提你的路由规则要规划好,详情见 https://www.zsythink.net/archives/1663)。之所以我们常用 SNAT 和 DNAT,都是为了实现隐藏 IP 的目的。 另:所有涉及路由转发的规则,都要事先执行命令:echo 1 > /proc/sys/net/ipv4/ip_forward,开启路由转发
假设网络内部有10台主机,它们有各自的IP地址,当网络内部的主机与其他网络中的主机通讯时,则会暴露自己的IP地址,如果我们想要隐藏这些主机的IP地址,该怎么办呢?
可以这么办:当网络内部的主机向外部发送报文时,当报文经过防火墙或路由器时,将报文的源IP修改为防火墙或者路由器的IP地址,显示的源IP地址则是路由器或者防火墙的,而不是那10台主机的IP地址。
通过这种方式,可以实现多台内网机器,都通过同一台网关机器与公网通信。
那么此时就会有一个问题:回程的报文,是如何回到内网机器的呢?
原来,在防火墙或路由器里有维护着一张 NAT 表:
因此,一个 SNAT规则,虽然,我们只写了 SNAT,但回程的 DNAT 其实是自动帮我们做了。
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP在上面学习 SNAT 的过程中,其实也涉及了 DNAT ,只是由于前半段是使用的 SNAT ,因此前面称之为 SNAT。
同样的,若前半段使用的是 DNAT,而后半段使用 SNAT,则这个过程称之为 DNAT。
SNAT 和 DNAT 在应用场景上有什么区别:
DNAT 的规则如下
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 公网端口 -j DNAT --to-destination 私网IP:端口号当我们做 SNAT 时, 回程的DNAT会自动帮我们处理,但做 DNAT 时,回程的 SNAT 却需要 我们自己处理
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP以上的 DNAT 是本机转他机,ip 发生变化,port 也发生变化(也可以不变化,但要指定)
其实还有另外一种情况,单纯的本机的上端口转发,使用的是 REDIRECT
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080配置完成上述规则后,其他机器访问本机的80端口时,会被映射到8080端口。
前面在配置 SNAT 时,我们都需要明确指定本地的公网 IP 是多少?
在大批量的机器部署过程中,会造成一些不方便,如果规则里可以自动获取网卡 IP,那就省事多了。
MASQUERADE 就是用来做这事情的,只要指定 -o 网卡,MASQUERADE 就会自动获取网卡上的 IP
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -o eth0 -j MASQUERADE当一条链中的规则数量非常多时,有针对 httpd ,也有针对 sshd 的,这样我们维护 iptables 规则就非常痛苦。
而自定义链,就是用 iptables 链的方式,来实现 “规则” 分组的功能。
使用如下命令来新建自定义链
iptables -t filter -N IN_WEB而此时还没有其他链引用 IN_WEB ,因此会显示 0 references
Chain IN_WEB (0 references)在自定义链中创建规则与内置链中一样
iptables -t filter -I IN_WEB -s 192.168.1.139 -j REJECT此时,虽然我们创建了规则,但由于 IN_WEB 还没有人引用,虽然该条规则是不会匹配到规则的
引用自定义链,就是把该链当成和 ACCEPT、REJECT 一样的动作就行。
意思是:匹配上的报文全部发往这些链中。
iptables -I input -p tcp --dport 80 -j IN_WEB若想把 IN_WEB 的链名改成 WEB ,可以使用 -E 参数
iptables -E IN_WEB WEB若想删除自定义链,可以使用 -X 命令
iptables -X WEB但要注意,若该链还在被引用者,则不能删除,需要你事先清除引用,即删除引用该链的规则
iptables -D INPUT 1iptables 是 Linux防火墙系统的重要组成部分,能够实现对网络数据包进出设备及转发的控制,应用在服务器、路由器等网络设备上,可以保障网络数据的安全与可靠性。
对于每个日常需要接触到 Linux 的开发人或运维来说,系统学习iptables是有必要的:
1、实现网络安全:iptables提供了一系列的过滤规则,可以限制外部主机对本地主机的访问,以及控制本地主机对外部主机的访问。通过配置iptables规则,可以过滤恶意流量,避免黑客攻击、病毒入侵等安全问题。
2、提高网络性能:通过使用iptables的QoS(Quality of Service)功能,可以对流量进行优化,使得关键业务的网络带宽得到更好的保障,从而提高网络性能和响应速度。
3、简化网络管理:通过iptables可以设置简单明了的规则,来实现对数据包的过滤和转发,从而达到灵活控制的效果。可以方便管理,减少管理员的工作负担。
4、符合行业标准:iptables是目前Linux平台网络安全的主流工具,学习iptables有助于符合相关行业标准和规范,例如PCI DSS(Payment Card Industry Data Security Standard)等。