iptables

防火墙设置iptables

iptables简介

iptables和netfilter的关系

iptables其实不是真正的防火墙,我们可以把它理解成一个客户端代理,一个Linux防火墙的管理工具,用户通过iptables这个代理,将用户的安全设定执行到对应的”安全框架”中,这个”安全框架”才是真正的防火墙,这个框架的名字叫netfilter
netfilter才是防火墙真正的安全框架(framework),netfilter位于内核空间。iptables其实是一个命令行工具,位于用户空间,我们用这个工具操作真正的框架。
iptables对应在内核中的模块应该是ip_tables,我们查看系统内核中ip_tables的信息的时候可以看到ip_tables.ko这个模块是在netfilter这个目录下的。
netfilter/iptables(下文中简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)等功能。

iptables规则概念

规则(rules) 其实就是网络管理员预定义的条件,规则一般的定义为“如果数据包头符合这样的条件,就这样处理这个数据包”。规则存储在内核空间的信息包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、ICMP)和服务类型(如HTTP、FTP和SMTP)等。
当数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept),拒绝(reject)和丢弃(drop)等。配置防火墙的主要工作是添加,修改和删除这些规则。
其中:

  • 匹配(match):符合指定的条件,比如指定的 IP 地址、端口、协议等。一条命令可以有多个匹配(条件),必须同时满足才会执行目标。
  • 丢弃(drop):当一个包到达时,简单地丢弃,不做其它任何处理。
  • 接受(accept):和丢弃相反,接受这个包,让这个包通过。
  • 拒绝(reject):和丢弃相似,但它还会向发送这个包的源主机发送错误消息。这个错误消息可以指定,也可以自动产生。
  • 目标(target):指定的动作,说明如何处理一个包,比如:丢弃,接受,或拒绝。只有匹配的数据包才会执行目标。
  • 跳转(jump):和目标类似,不过它指定的不是一个具体的动作,而是另一个链,表示要跳转到那个链上。
  • 规则(rule):一个或多个匹配及其对应的目标。iptables设置一条命令就是设置一条规则。

iptables的四表五链

表(tables):提供特定的功能,iptables内置了4个表,即filter表、nat表、mangle表和raw表,分别用于实现包过滤,网络地址转换、包重构(修改)和数据跟踪处理。
链(chains):是数据包传播的路径,每一条链其实就是众多规则中的一个检查清单,每一条链中可以有一条或数条规则。当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据 该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定义的默认策略来处理数据包。
Iptables采用“表”和“链”的分层结构,在Linux中现在是四张表五个链。下面罗列一下这四张表和五个链(注意一定要明白这些表和链的关系及作用)。

四表五链

规则表

  • filter表——三个链:INPUT、FORWARD、OUTPUT
     作用:过滤数据包。
     内核模块:iptables_filter。
  • Nat表——三个链:PREROUTING、POSTROUTING、OUTPUT
     作用:用于网络地址转换(IP、端口)
     内核模块:iptable_nat
  • Mangle表——五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
     作用:修改数据包的服务类型、TTL、并且可以配置路由实现QOS
     内核模块:iptable_mangle(别看这个表这么麻烦,咱们设置策略时几乎都不会用到它)
  • Raw表——两个链:OUTPUT、PREROUTING
     作用:决定数据包是否被状态跟踪机制处理
     内核模块:iptable_raw

规则链

1)INPUT——进来的数据包应用此规则链中的策略
2)OUTPUT——外出的数据包应用此规则链中的策略
3)FORWARD——转发数据包时应用此规则链中的策略
4)PREROUTING——对数据包作路由选择前应用此链中的规则
(记住!所有的数据包进来的时侯都先由这个链处理)
5)POSTROUTING——对数据包作路由选择后应用此链中的规则
(所有的数据包出来的时侯都先由这个链处理)

iptables传输数据包的过程

从网上找了两个流程图。


1)当一个数据包进入网卡时,它首先进入PREROUTING链,内核根据数据包目的IP判断是否需要转送出去。
2)如果数据包就是进入本机的,它就会沿着图向下移动,到达INPUT链。数据包到了INPUT链后,任何进程都会收到它。
3)如果数据包是要转发出去的,且内核允许转发,数据包就会如图所示向右移动,经过FORWARD链,然后到达POSTROUTING链输出。
4)本机上运行的程序可以发送数据包,这些数据包会经过OUTPUT链,然后到达POSTROUTING链输出。

注意每一个链对应的表都是不完全一样的,表和链之间是多对多的对应关系。但是不管一个链对应多少个表,它的表都是按照下面的优先顺序来进行查找匹配的。
表的处理优先级:raw>mangle>nat>filter。

iptables命令

语法规则

iptables [-t table] COMMAND [chain] CRETIRIA -j ACTION

-t table,是指操作的表,filter、nat、mangle或raw, 默认使用filter
COMMAND,子命令,定义对规则的管理,包括:增加,删除,插入,替换,显示等
chain, 指明链路,可以是五链,也可以是自定义的链
CRETIRIA, 匹配的条件或标准,包括协议、IP、端口、接口等条件
ACTION,操作动作,ACCEPT、DROP、REJECT

iptables命令

命令选项输入顺序

iptables [-t table] <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作

链管理

  • -N,--new-chain chain  新建一个自定义的规则链;
  • -X, --delete-chain [chain]  删除用户自定义的引用计数为0的空链;所以,在删除前要清空链。
  • -F, --flush [chain]  清空指定的规则链上的规则;
  • -E, --rename-chain old-chain new-chain  重命名链;
  • -Z, --zero [chain [rulenum]]  置零计数器;
  • -P, --policy chain target  设置链路的默认策略

注意:“,”分隔了两种用法,比如:新建链可以用命令-N,也可以用--new-chain。

规则管理

  • -A, --append chain rule-specification:追加新规则于指定链的尾部;
  • -I, --insert chain [rulenum] rule-specification:插入新规则于指定链的指定位置,默认为首部;
  • -R, --replace chain rulenum rule-specification:替换指定的规则为新的规则;
  • -D, --delete chain rulenum:根据规则编号删除规则;

查看规则

  • -L, --list [chain]:列出规则;
  • -v, --verbose:详细信息;
  • -vv, -vvv 更加详细的信息
  • -n, --numeric:数字格式显示主机地址和端口号;
  • -x, --exact:显示计数器的精确值;
  • --line-numbers:列出规则时,显示其在链上的相应的编号;
  • -S, --list-rules [chain]:显示指定链的所有规则;

匹配条件

匹配条件包括通用匹配条件和扩展匹配条件
通用匹配条件是指针对源地址、目标地址的匹配,包括单一源IP、单一源端口、单一目标IP、单一目标端口、数据包流经的网卡以及协议。
扩展匹配条件指通用匹配之外的匹配条件。
当一条规则里面有多个条件时,多个条件之间是与的关系,数据包只有满足所有的条件才会生效。

通用匹配条件

  • [!] -s, --source address[/mask][,...]:检查报文的源IP地址是否符合此处指定的范围,或是否等于此处给定的地址;
  • [!] -d, --destination address[/mask][,...]:检查报文的目标IP地址是否符合此处指定的范围,或是否等于此处给定的地址;
  • [!] -p, --protocol protocol:匹配报文中的协议,可用值tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh 或者 "all", 亦可以数字格式指明协议;
  • [!] -i, --in-interface name:限定报文仅能够从指定的接口流入;only for packets entering the INPUT, FORWARD and PREROUTING chains.
  • [!] -o, --out-interface name:限定报文仅能够从指定的接口流出;only for packets entering the FORWARD, OUTPUT and POSTROUTING chains.

注意:“!”表示取反,比如 "! -p tcp" 表示匹配非TCP协议。

扩展匹配条件-隐含扩展匹配

1. -p tcp:TCP协议的扩展

  • [!] --destination-port,--dport port[:port]:指定目标端口,不能指定多个非连续端口,只能指定单个端口,比如--dport 21 (表示端口21) 或者 --dport 21:23 (此时表示21,22,23)
  • [!] --source-port,--sport port[:port]:指定源端口
  • --tcp-fiags mask [comp]:TCP的标志位(SYN,ACK,FIN,PSH,RST,URG)
    mask:要检查的FLAGS list,以逗号分隔;
    comp:在mask给定的诸多的FLAGS中,其值必须为1的FLAGS列表,余下的其值必须为0;

2. -p udp:可直接使用udp协议扩展模块的专用选项:

  • [!] --source-port,--sport port[:port]
  • [!] --destination-port,--dport port[:port]

扩展匹配条件-显示扩展匹配

显示扩展匹配必须用-m

-m option
1. 多端口匹配

multiport以离散或连续的方式定义多端口匹配条件,最多15个

  • [!] --source-ports,--sports port[,port,port:port]...:指定多个源端口,以逗号分隔
  • [!] --destination-ports,--dports port[,port|,port:port]...:指定多个目标端口
iptables -I INPUT -d 172.16.0.7 -p tcp -m multiport --dports 22,80,139,445,3306 -j ACCEPT
2. 多IP地址匹配

iprange以连续地址块的方式来指明多IP地址匹配条件

  • [!] --src-range from[-to]
  • [!] --dst-range from[-to]
iptables -I INPUT -d 172.16.0.7 -p tcp -m multiport --dports 22,80,139,445,3306 -m iprange --src-range 172.16.0.61-172.16.0.70 -j REJECT
3. 字符串匹配

string扩展模块对报文中的应用层数据做字符串模式匹配检测
字符匹配可以用来做URL过滤

  • --algo {bm|kmp}:字符串匹配检测算法。bm:Boyer-Moore;kmp:Knuth-Pratt-Morris
  • [!] --string pattern:要检测的字符串模式,只能处理明文数据
  • [!] --hex-string pattern:要检测的字符串模式,16进制格式
iptables -A OUTPUT -m string --string "baidu"  --algo bm -j DROP
4. time扩展模块

time扩展模块,根据时间段区匹配报文,如果报文到达的时间在指定的时间范围以内,则符合匹配条件。

  • --timestart hh:mm[:ss]
  • --timestop hh:mm[:ss]
  • [!] --weekdays day[,day...]
  • [!] --monthdays day[,day...]
  • --datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
  • --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
  • --kerneltz:使用内核配置的时区而非默认的UTC;
# 周末早上9点到下午6点不能浏览网页
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 6,7 --timestart 09:00:00 --timestop 18:00:00 -j REJECT
5. connlimit:限制同一IP的连接数

使用connlimit扩展模块,可以限制每个IP(或网段)地址同时链接到server端的链接数量,注意:我们不用指定IP,其默认就是针对”每个客户端IP”,即对单IP的并发连接数限制。

[!] --connlimit-above n    # 连接上限超过n个则匹配
[!] --connlimit-mask n     # 这组主机的掩码,默认是connlimit-mask 32 ,即每个IP。
[!] --connlimit-upto n    # 连接上限未达到n个则匹配

# 每个客户端IP的ssh并发连接数不能高于2
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-avove 2 -j REJECT
6. limit:限速
  • --limit rate[/second|/minute|/hour|/day] # 每秒/分钟/小时/天允许通过的数据包个数。
  • --limit-burst number # 最初的令牌数,默认是5个

想要理解limit模块的工作原理,我们需要先了解一下”令牌桶”算法,因为limit模块使用了令牌桶算法。
我们可以这样想象,有一个木桶,木桶里面放了5块令牌,而且这个木桶最多也只能放下5块令牌,所有报文如果想要出关入关,都必须要持有木桶中的令牌才行,这个木桶有一个神奇的功能,就是每隔6秒钟会生成一块新的令牌,如果此时,木桶中的令牌不足5块,那么新生成的令牌就存放在木桶中,如果木桶中已经存在5块令牌,新生成的令牌就无处安放了,只能溢出木桶(令牌被丢弃),如果此时有5个报文想要入关,那么这5个报文就去木桶里找令牌,正好一人一个,于是他们5个手持令牌,快乐的入关了,此时木桶空了,再有报文想要入关,已经没有对应的令牌可以使用了,但是,过了6秒钟,新的令牌生成了,此刻,正好来了一个报文想要入关,于是,这个报文拿起这个令牌,就入关了,在这个报文之后,如果很长一段时间内没有新的报文想要入关,木桶中的令牌又会慢慢的积攒了起来,直到达到5个令牌,并且一直保持着5个令牌,直到有人需要使用这些令牌,这就是令牌桶算法的大致逻辑。
那么,就拿刚才的”令牌桶”理论类比我们的命令,”–limit”选项就是用于指定”多长时间生成一个新令牌的”,”–limit-burst”选项就是用于指定”木桶中最多存放几个令牌的”。

限制每分钟最多放行10个icmp包
iptables -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT
但是我测试发现ping命令的数据包一直可以通过。为什么会这样呢?原来是默认策略是放行,报文会匹配链中的每一条规则,如果没有任何一条规则能够匹配到,则匹配默认动作(链的默认策略)。所以我们需要把默认策略设置成REJECT。
正确的命令:

iptables -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT
iptables -A INPUT -p icmp -j REJECT
7. state:收发包的状态

[!] --state state

state的值可以是:INVALID, ESTABLISHED, NEW, RELATED or UNTRACKED.
NEW: 新连接请求;
ESTABLISHED:已建立的连接;
INVALID:无法识别的连接,包没有办法被识别,或者这个包没有任何状态
RELATED:相关联的连接,当前连接是一个新请求,但附属于某个已存在的连接;
UNTRACKED:未追踪的连接;当报文的状态为Untracked时通常表示无法找到相关的连接

state模块用在什么地方呢?
我们试想一下这么一个场景,我们只允许局域网中的某台PC(192.168.0.100)访问外部的网站,其余的PC不允许访问外网,那我们应该如何设置呢?如果只对源IP进行匹配,放行源IP是192.168.0.100的PC,但是我们访问外网是一个交互的过程,即当192.168.0.100发起连接或者请求时,server会有响应,如果只设置源IP是192.168.0.100,很显然无法完成交互的,需要把server的IP也设置为允许,但是我们把外网的源IP也加入accept中也不现实,因为外网很多,我们不能把所有的都加进去吧,而且,我们想要允许接收的是外网的响应报文,过滤掉外网主动发起的报文。
那么,用–tcp-flags去匹配tcp报文的标志位,把外来的”第一次握手”的请求拒绝,是不是也可以呢?显然也不可以,因为如果对方使用的是UDP协议或者ICMP协议呢?
所以,我们需要解决的问题是:怎样判断这些报文是为了回应我们之前发出的报文,还是主动向我们发送的报文呢?
我们可以通过iptables的state扩展模块解决上述问题。

state模块的“连接”和TCP/IP协议簇的连接不是一个概念,在TCP/IP中,TCP是面向连接的,有3次握手和4次挥手,UDP和ICMP是无连接的。但是对于state来说,只要两台设备(更精确来说是两个socket)有“你来我往”的通信就算是建立连接了,所以对state模块来说TCP/UDP/ICMP都是有连接的。
对于state模块的连接而言,”连接”其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED。
NEW:连接中的第一个包,状态就是NEW,我们可以理解为新连接的第一个包的状态为NEW。
ESTABLISHED:我们可以把NEW状态包后面的包的状态理解为ESTABLISHED,表示连接已建立。

state连接示意图

RELATED是相关联的连接,举个例子:比如FTP服务,FTP服务端会建立两个进程,一个命令进程,一个数据进程。命令进程负责服务端与客户端之间的命令传输(我们可以把这个传输过程理解成state中所谓的一个”连接”,暂称为”命令连接”)。数据进程负责服务端与客户端之间的数据传输 ( 我们把这个过程暂称为”数据连接” )。但是具体传输哪些数据,是由命令去控制的,所以,”数据连接”中的报文与”命令连接”是有”关系”的。那么,”数据连接”中的报文可能就是RELATED状态,因为这些报文与”命令连接”中的报文有关系。
注:如果想要对ftp进行连接追踪,需要单独加载对应的内核模块nf_conntrack_ftp,如果想要自动加载,可以配置/etc/sysconfig/iptables-config文件

回到上面的问题,如果只放行响应报文?
iptables -t filter -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

参考:iptables详解(8):iptables扩展模块之state扩展

易错点

默认丢弃只允许某些通过

iptables要只允许某些IP,切记先放行这些IP,最后拒绝所有IP,顺序不能乱,且拒绝规则不可少
iptables是按照规则顺序进行匹配的,一旦遇到匹配的规则(拒绝或者允许),对这个端口/服务的规则就不往下走了。

参考

linux iptables man
iptables命令使用详解
IPtables之三:显式扩展规则
iptables的四表五链与NAT工作原理
centos下iptables防火墙规则用法和概述
iptables命令的使用
iptables详解(5):iptables匹配条件总结之二(常用扩展模块)

posted @ 2021-08-16 18:28  sun_ning  阅读(286)  评论(0)    收藏  举报