iptables 使用备忘
2020-07-15 tech network kernel linux 39 mins 7 图 13803 字
转自 http://www.zsythink.net/archives/1199,内容有删减。
一、防火墙
防火墙大体分为主机防火墙和网络防火墙。
主机防火墙:针对于单个主机进行防护。
网络防火墙:往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网。
网络防火墙和主机防火墙并不冲突,可以理解为,网络防火墙主外(集体), 主机防火墙主内(个人)。
从物理上讲,防火墙可以分为硬件防火墙和软件防火墙。
硬件防火墙:在硬件级别实现部分防火墙功能,另一部分功能基于软件实现,性能高,成本高。
软件防火墙:应用软件处理逻辑运行于通用硬件平台之上的防火墙,性能低,成本低。
二、iptables 概念
Netfilter 是 Linux 操作系统核心层内部的一个数据包处理模块,它具有如下功能:
- 网络地址转换(Network Address Translate)
- 数据包内容修改
- 数据包过滤的防火墙功能
iptables 是一个命令行工具,位于用户空间,我们用这个工具操作 netfilter。iptables并没有一个守护进程,所以不是真正意义上的服务。
iptables 有四表五链的概念。我一般这么去理解,表是逻辑上的分类(或简单理解成数据库的表),链是物理上的分类,在数据包生命周期各个阶段的处理。
报文在匹配iptables的规则的时候,是按照固定的顺序进行的,既不是按照表的顺序执行,也不是按照检查点的顺序执行。
structure-of-iptables中做了非常详细的说明。
五链(本机收到的请求报文的流向):
-
到本机某进程的报文:PREROUTING –> INPUT,具体来说是:
raw.PREROUTING -> mangle.PREROUTING -> nat.PREROUTING -> mangle.INPUT -> filter.INPUT
-
由本机转发的报文:PREROUTING –> FORWARD –> POSTROUTING,具体来说是:
raw.PREROUTING -> mangle.PREROUTING -> nat.PREROUTING -> mangle.FORWARD -> filter.FORWARD -> mangle.POSTROUTING -> nat.POSTROUTING
-
由本机的某进程发出报文(通常为响应报文):OUTPUT –> POSTROUTING
raw.OUTPUT -> mangle.OUTPUT -> nat.OUTPUT -> filter.OUTPUT -> mangle.POSTROUTING ->nat.POSTROUTING
四表:
- filter表:控制本机数据包的进出,可看做防火墙(默认表);内核模块:iptables_filter
- nat表:network address translation,网络地址转换功能;内核模块:iptable_nat
- mangle表:拆包并修改标志位,重新封装;iptable_mangle
- raw表:关闭nat表上启用的连接追踪机制;iptable_raw
表和链之间的包含关系如下:
filter:
Chain INPUT
Chain FORWARD
Chain OUTPUT
nat:
Chain PREROUTING
Chain INPUT
Chain OUTPUT
Chain POSTROUTING
mangle:
Chain PREROUTING
Chain INPUT
Chain FORWARD
Chain OUTPUT
Chain POSTROUTING
raw:
Chain PREROUTING
Chain OUTPUT
为了更方便的管理,我们还可以在某个表里面创建自定义链,将针对某个应用程序所设置的规则放置在这个自定义链中,但是自定义链接不能直接使用,只能被某个默认的链当做动作去调用才能起作用。
三、iptables 规则的增删查改
iptables命令的语法如下:
iptables -t [表名]
<-A | I | D | R> 链名
[规则编号]
[-i | o 网卡名称]
[-p 协议]
[-s 源ip地址 | 源子网]
[--sport 源端口]
[-d 目标ip地址 | 目标子网]
[--dport 目标端口]
<-j target>
-
-A
新增一条规则,该规则增加到规则列表的最后一行,使用该参数时不能使用规则编号 -
-I
插入一条规则,如果指定了规则编号,原本该位置上的规则会向后顺序移动,如果没有指定规则编号,将在第一条规则前插入 -
-D
从规则列表中删除一条规则,可以输入完整的规则进行删除,也可以直接指定规则编号进行删除 -
-R
替换某条规则,规则被替换时不会改变其顺序,必须指定要替换的规则编号 -
规则编号
规则列表的第一条规则的编号为1 -
-i
指定数据包进入的网卡,-o
指定数据包输出的网卡 -
-p
指定规则应用的协议,可以是tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh
-
-s
指定源主机的IP地址或子网地址,格式为address[/mask][,...]
-
-d
指定指定目标主机的IP地址或子网地址,格式为address[/mask][,...]
-
-j target
即
--jump target
决定符合条件的包到何处去。target可以指定另一个链,常用的Target/Jumps包含:
ACCEPT
表示允许包,即满足匹配条件的包被允许,并且不会再匹配当前链中的其他规则或同一个表内的其他规则,但这个包还会通过其他表中的链DROP
表示丢弃包,即将符合条件的包丢弃,不会再向下走。效果就是包被阻塞,不会像发送者返回任何信息。REJECT
表示拒绝包,REJECT和DROP类似,在阻塞包时会向发送者返回错误信息。REDIRECT
表示将数据包重定向到本机或另一台主机的某个端口,通常用来实现透明代理或对外开放内网的某些服务SNAT
源地址转换,即改变数据包的源地址DNAT
目标地址转换,即改变数据包的目标的地址LOG
将符合规则的数据包相关规则信息记录在日志中,便于管理员分析问题
在iptables的世界中,常用的匹配条件是报文的”源地址”、”目标地址”、”源端口”、”目标端口”等,常用的动作有ACCEPT(接受)、DROP(丢弃)、REJECT(拒绝)。
1 查询规则
标准用法:
iptables -t filter -L INPUT
- -t: table,选择表,默认 filter表
- -L: List,显示链,默认 全部链,区分大小写。
显示的信息为:
- target:规则对应的target,往往表示规则对应的”动作”,即规则匹配成功后需要采取的措施。
- prot:表示规则对应的协议,是否只针对某些协议应用此规则。
- opt:表示规则对应的选项。
- source:表示规则对应的源头地址,可以是一个IP,也可以是一个网段。
- destination:表示规则对应的目标地址。可以是一个IP,也可以是一个网段。
其它常用参数:
- -v: 显示更多属性信息
- pkts:对应规则匹配到的报文的个数。
- bytes:对应匹配到的报文包的大小总和。
- in:表示数据包由哪个接口(网卡)流入,我们可以设置通过哪块网卡流入的报文需要匹配当前规则。
- out:表示数据包由哪个接口(网卡)流出,我们可以设置通过哪块网卡流出的报文需要匹配当前规则。
- -n: source和destination中不对 IP 地址进行解析,直接显示IP地址。
- –line-numbers: 显示规则的编号
头部Chain INPUT后面有一串括号括起来的内容,具体含义为:
- policy表示当前链的默认策略,上图的默认策略为ACCEPT
- packets表示当前链(上图为INPUT链)默认策略匹配到的包的数量,0 packets表示默认策略匹配到0个包。
- bytes表示当前链默认策略匹配到的所有包的大小总和。(使用 -x 参数可以显示精确计数值)
2 删除规则
清空 filter 表 INPUT 链的规则:
iptables -F INPUT
- -F:Flush,清空某链条,默认全部链条。
iptables -t filter -D INPUT 3
- -D: delete ,删除某行规则。
3 增加规则
注意,规则的前后顺序很重要!匹配到前一条,就会按照前一条的动作执行了,很有可能不会执行后面的规则条目了。
与查询规则类似:
iptables -t filter -I INPUT ! -s xxx.xxx.xxx.xxx/xx -j DROP
- -t:table,选择表,默认为filter表
- -I: Insert,插入链的头部
- -A: Append,插入链的尾部
- -s: source,源地址
- -j: jump,条件匹配时的动作
- !: 条件取反
4 修改规则
实际上修改规则命令我平时几乎不用,宁愿先删除规则,再添加。
iptables -t filter -R INPUT 1 -s xxx.xxx.xxx.xxx -j DROP
- -R: replace,选择链条 第几条。
5 恢复、保存规则
上文中的iptables的修改都是临时性的,系统重启后就会失效。为了确保重启后规则和我们预设的一致,可以配置一个iptables的rules文件,基于这个文件进行配置变更,通过恢复再保存的方式,进行配置管理。
# 预先将规则写入/etc/iptables.test.rules 文件
echo "/sbin/iptables-restore < /etc/iptables.up.rules" > /etc/network/if-pre-up.d/iptables && chmod +x /etc/network/if-pre-up.d/iptables
iptables-restore < /etc/iptables.test.rules;
iptables-save > /etc/iptables.up.rules;
6、处理动作
处理动作在iptables中被称为target(这样说并不准确,我们暂且这样称呼),动作也可以分为基本动作和扩展动作。
此处列出一些常用的动作,之后的文章会对它们进行详细的示例与总结:
ACCEPT:允许数据包通过。
DROP:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应。
REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。
SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。
MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。
DNAT:目标地址转换。
REDIRECT:在本机做端口映射。
LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配。
7. 匹配条件
当一条规则中存在多个匹配条件时,报文必须同时满足这些条件,才算做被规则匹配。
-
IP地址 -s/-d
可以使用”叹号”进行取反,也能够同时指定多个IP地址,使用”逗号”隔开。地址包括源地址 -s 和目的地址 -d
iptables -t filter -I INPUT ! -s 10.0.0.0/16 -j DROP
-
协议类型 -p
-p: 默认为全部,支持 tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh
-
网卡接口 -i/-o
-i选项只能用于PREROUTING链、INPUT链、FORWARD链,它只是用于判断报文是从哪个网卡流入的,所以只能在上图中”数据流入流向”的链中与FORWARD链中存在,OUTPUT链与POSTROUTING链,都不能使用-i选项。
当主机有多块网卡时,可以使用-o选项,匹配报文将由哪块网卡流出。-o选项只能用于FORWARD链、OUTPUT链、POSTROUTING链中。
-
扩展匹配
基本匹配条件我们可以直接使用,而如果想要使用扩展匹配条件,需要指定相应的扩展模块。
-
端口 –dport/–sport,使用模块tcp。
-p tcp -m tcp --dport 22:25
-m tcp表示使用tcp扩展模块(模块同名可省)
-
multiport 可指定多个离散的端口
-p tcp -m kultiport --dports 22,36,88
-
iprange 指定”一段连续的IP地址范围”
iptables -t filter -I INPUT -m iprange --src-range 192.168.1.127-192.168.1.146 -j DROP iptables -t filter -I OUTPUT -m iprange --dst-range 192.168.1.127-192.168.1.146 -j DROP iptables -t filter -I INPUT -m iprange ! --src-range 192.168.1.127-192.168.1.146 -j DROP
-
string 指定要匹配的字符串
iptables -t flilter -I INPUT -m string --algo bm --string "ooxx" -j ACCEPT
-
time 规定时间
很少用
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT iptables -t filter -I OUTPUT -p tcp --dport 443 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 6,7 -j REJECT iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --monthdays 22,23 -j REJECT iptables -t filter -I OUTPUT -p tcp --dport 80 -m time ! --monthdays 22,23 -j REJECT iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays 6,7 -j REJECT iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 5 --monthdays 22,23,24,25,26,27,28 -j REJECT iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --datestart 2017-12-24 --datestop 2017-12-27 -j REJECT
-
connlimit,限制每个IP地址同时链接到server端的链接数量
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j REJECT iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 10 --connlimit-mask 27 -j REJECT
- connlimit-above 连接数
- connlimit-mask 掩码
-
limit,使用令牌桶算法,对”报文到达速率”限制。
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 REJECT
- limit 10/minute: 1分钟生成10个令牌放行。
- minute
- second
- hour
- day
- –limit-burst 3:最多同时存在3个令牌。
- limit 10/minute: 1分钟生成10个令牌放行。
-
tcp-flags,根据tcp请求头标志位限制。
很少用,不解释了。
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT iptables -t filter -I OUTPUT -p tcp -m tcp --sport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN,ACK -j REJECT iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN -j REJECT iptables -t filter -I OUTPUT -p tcp -m tcp --sport 22 --tcp-flags ALL SYN,ACK -j REJECT
-
udp 很少用,不解释了。
-
icmp 很少用,不解释了。
-
state 常用。
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
对于state模块的连接而言,”连接”其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED
NEW:连接中的第一个包,状态就是NEW,我们可以理解为新连接的第一个包的状态为NEW。
ESTABLISHED:我们可以把NEW状态包后面的包的状态理解为ESTABLISHED,表示连接已建立
RELATED:关联包
INVALID:无法识别,或者这个包没有任何状态
UNTRACKED:报文未被追踪,无法找到相关的连接。
-
recent,用于限制一段时间内的连接数。recent模块在 iptables 里面维护了一个地址列表,这个地址列表可以通过”–set”、”–update”、”–rcheck”、”–remove”四种方法来修改列表。
本部分参考链接:
–name 设定列表名称,即设置跟踪数据库的文件名. 默认DEFAULT; –rsource 源地址,此为默认。 只进行数据库中信息的匹配,并不会对已存在的数据做任何变更操作; –rdest 目的地址; –seconds 指定时间内. 当事件发生时,只会匹配数据库中前”几秒”内的记录,–seconds必须与–rcheck或–update参数共用; –hitcount 命中次数. hits匹配重复发生次数,必须与–rcheck或–update参数共用; –set 将地址添加进列表,并更新信息,包含地址加入的时间戳。 即将符合条件的来源数据添加到数据库中,但如果来源端数据已经存在,则更新数据库中的记录信息; –rcheck 检查地址是否在列表,以第一个匹配开始计算时间; –update 和rcheck类似,以最后一个匹配计算时间。 如果来源端的数据已存在,则将其更新;若不存在,则不做任何处理; –remove 在列表里删除相应地址,后跟列表名称及地址。如果来源端数据已存在,则将其删除,若不存在,则不做任何处理;
例1:限制无法ssh直接连接服务器,需先用较大包ping一下,此时在15秒内才可以连接上:
iptables -P INPUT DROP iptables -A INPUT -s 127.0.0.1/32 -j ACCEPT iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -p icmp --icmp-type 8 -m length --length 128 -m recent --set --name SSHOPEN --rsource -j ACCEPT iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --rcheck --seconds 15 --name SSHOPEN --rsource -j ACCEPT
例2: 限制每ip在一分钟内最多对服务器只能有8个http连接
iptables -I INPUT -p tcp --dport 80 -d 192.168.10.10 -m state --state NEW -m recent --name httpuser --set iptables -A INPUT -m recent --update --name httpuser --seconds 60 --hitcount 9 -j LOG --log-prefix 'HTTP attack: ' iptables -A INPUT -m recent --update --name httpuser --seconds 60 --hitcount 9 -j DROP
例3: SSH连接,每个IP每小时只限连接5次
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --rcheck --seconds 3600 --hitcount 5 -j DROP -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --set -j ACCEPT
或:
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT //必须添加这个前提条件才能生效! -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --set -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name SSHPOOL --rcheck --seconds 3600 --hitcount 5 -j DROP
例4: SSH 开门暗语
# 记录日志,前缀SSHOPEN: iptables -A INPUT -p tcp --dport 50001 --syn -j LOG --log-prefix "SSHOPEN: " # 目标端口tcp 50001的新数据设定列表为sshopen返回TCP重置,并记录源地址。 iptables -A INPUT -p tcp --dport 50001 --syn -m recent --set --name sshopen --rsource -j REJECT --reject-with tcp-reset # 开启SSH端口,15秒内允许记录的源地址登录SSH。 iptables -A INPUT -p tcp --dport 22 --syn -m recent --rcheck --seconds 15 --name sshopen --rsource -j ACCEPT #开门钥匙 nc host 50001 telnet host 50001 nmap -sS host 50001
例5: SSH 开门暗语2
#记录日志,前缀SSHOPEN: iptables -A INPUT -p icmp --icmp-type 8 -m length --length 78 -j LOG --log-prefix "SSHOPEN: " #指定数据包78字节,包含IP头部20字节,ICMP头部8字节 iptables -A INPUT -p icmp --icmp-type 8 -m length --length 78 -m recent --set --name sshopen --rsource -j ACCEPT iptables -A INPUT -p tcp --dport 22 --syn -m recent --rcheck --seconds 15 --name sshopen --rsource -j ACCEPT #开门钥匙 ping -s 50 ip #linux主机的ip ping -l 50 ip #windows主机的ip
-
四、自定义链
自定义链是为了更好管理iptables规则而存在的。自定义链并不能直接使用,被默认链引用才能够使用。
-
创建自定义链
iptables -t filter -N KELU
-
引用自定义链
iptables -t filter -I INPUT -p tcp --dport 80 -j KELU
-
重命名自定义链
iptables -E KELU YUKI
-
删除自定义链
删除自定义链需要满足两个条件
1、自定义链没有被引用
2、自定义链中没有任何规则
iptables -X KELU
五、iptables 动作
ACCEPT、DROP、REJECT、LOG、SNAT、DNAT、MASQUERADE、REDIRECT
前三个没什么好记录的。如果想要NAT功能能够正常使用,需要开启Linux主机的核心转发功能。
echo 1 > /proc/sys/net/ipv4/ip_forward
LOG
LOG动作会将报文的相关信息记录在/var/log/message文件中,LOG动作只负责记录匹配到的报文的相关信息,不负责对报文的其他处理。一般放到链条的最后,记录被拒绝的请求。
LOG动作也有自己的选项
- –log-level选项可以指定记录日志的日志级别,可用级别有emerg,alert,crit,error,warning,notice,info,debug。
- –log-prefix选项可以给记录到的相关信息添加”标签”之类的信息,以便区分各种记录到的报文信息,方便在分析时进行过滤。
- 注:–log-prefix对应的值不能超过29个字符。
# log iptables denied calls (access via 'dmesg' command)
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables input denied: " --log-level 7
-A FORWARD -m limit --limit 5/min -j LOG --log-prefix "iptables forward denied: " --log-level 7
SNAT
网络内部的主机可以借助SNAT隐藏自己的IP地址,共享公网IP
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 192.168.1.146
DNAT
配置DNAT,可以通过公网IP访问局域网内的服务。
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 公网端口 -j DNAT --to-destination 私网IP:端口号
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 8080 -j DNAT --to-destination 10.1.0.1:80
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP
MASQUERADE
可以把MASQUERADE理解为动态的、自动化的SNAT,如果没有动态SNAT的需求,没有必要使用MASQUERADE,因为SNAT更加高效。
当我们拨号网上时,每次分配的IP地址往往不同,不会长期分给我们一个固定的IP地址,如果这时,我们想要让内网主机共享公网IP上网,就会很麻烦,因为每次IP地址发生变化以后,我们都要重新配置SNAT规则,这样显示不是很人性化,我们通过MASQUERADE即可解决这个问题,MASQUERADE会动态的将源地址转换为可用的IP地址,其实与SNAT实现的功能完全一致,都是修改源地址,只不过SNAT需要指明将报文的源地址改为哪个IP,而MASQUERADE则不用指定明确的IP,会动态的将报文的源地址修改为指定网卡上可用的IP地址
iptables -t nat -I POSTROUTING -s 10.1.0.0/16 -o eth0 -j MASQUERADE
REDIRECT
使用REDIRECT动作可以在本机上进行端口映射
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080