iptables/netfilter详解
一、前言
1.防火墙(Firewall)是隔离工具;工作于主机或网络的边缘,对经由的报文根据预先定义的规则(识别条件)进行检测,
对于能够被规则匹配到的报文实行某预定义的处理机制的一套组件。
2.防火墙分类:
硬件防火墙:在硬件级别能部分防火墙,另一部分功能基于软件实现;
软件防火墙:应用软件处理逻辑运行通用硬件实现的防火墙;
主机防火墙:服务范围为当前主机;
网络防火墙:服务范围为局域网;
3.iptables/netfilter 包过滤型防火墙:
软件实现的主机或网络防火墙
二、iptables 的历史以及工作原理
1.1 iptables的发展: ip fw --> ip chains --> ip tables
iptables的前身叫ipfirewall (内核1.x时代),这是一个作者从freeBSD上移植过来的,能够工作在内核当中的,对数据包进行检测的一款简易访问控制工具。
但是ipfirewall工作功能极其有限(它需要将所有的规则都放进内核当中,这样规则才能够运行起来,而放进内核,这个做法一般是极其困难的)。
当内核发展到2.x系列的时候,软件更名为ipchains,它可以定义多条规则,将他们串起来,共同发挥作用,而现在,它叫做iptables,可以将规则组成一个列表,实现绝对详细的访问控制功能。
他们都是工作在用户空间中,定义规则的工具,本身并不算是防火墙。它们定义的规则,可以让在内核空间当中的netfilter来读取,并且实现让防火墙工作。
而放入内核的地方必须要是特定的位置,必须是tcp/ip的协议栈经过的地方。而这个tcp/ip协议栈必须经过的地方,可以实现读取规则的地方就叫做 netfilter(网络过滤器)
1.2 内核空间中选择了5个位置:
1.内核空间中:从一个网络接口进来,到另一个网络接口去的
2.数据包从内核流入用户空间的
3.数据包从用户空间流出的
4.进入/离开本机的外网接口
5.进入/离开本机的内网接口
2. iptables的工作机制
2.1 iptables/netfilter软件:
是实现主机或网络包过滤防火墙,其中iptables是位于用户空间的命令行程序,用于生成规则送往内核中的netfilter之上。
netfilter位于内核中tcp/ip协议栈上的一个防火墙框架framework;5个钩子函数。
2.2 netfilter:(hook function --> 钩子函数)
1.prerouting (路由前)
2.input (数据包流入口)
3.forward (转发关卡)
4.output (数据包出口)
5.postrouting (路由后)
2.3 iptables:(chain--> 链) 5
1.PREROUTING (路由前)
2.INPUT (数据包入口)
3.FORWARD (数据包转发)
4.OUTPUT (数据包出口)
5.POSTROUTING (路由后)
3.iptables防火墙策略
3.1 tables:功能--> 表 4
1.filter:过滤,防火墙。
2.nat:network address translation(网络地址转发),用于修改报文的源地址或目标地址,甚至是端口。
3.mangle:拆解报文,做出修改,并重新封装起来。
4.raw:关闭nat表上启用的连接追踪机制。
优先级次序(由高而低):
4.raw --> 3.mangle --> 2.nat --> 1.filter
3.2 功能<-->钩子<==>表<-->链 对应关系:
4.raw:PREROUTING-->路由后,OUTPUT-->流出
3.mangle:PREROUTING-->路由前,INPUT-->数据包入口,FORWARD-->转发,OUTPUT-->出口,POSTROUTING-->路由后
2.nat:PREROUTING-->路由前,INPUT--数据包入口,OUTPUT-->出口,POSTRUTING-->路由后
1.filter:INPUT-->数据包入口,FORWARD-->转发,OUTPUT--出口
3.3 报文流向:
1.到本机某进程的报文:PREROUTING --> INPUT
2.由本转发的报文:PREROUTING --> FORWARD --> POSTROUTING
3.由本机某进程发出的:OUTPUT --> POSTROUTING
3.4 规则的组成的部分:
1.匹配条件
2.网络层首部属性值 IP 首部数据包
3.传输层首部属性值 TCP 首部数据包
4.附加的条件
5.处理动作
3.5 TCP/IP协议栈:
1.数据链接层:物理到物理设备之间的通信;(MAC,Media Access Control)
2.网络层:源主机到目标主机之间的通信 IP
3.传输层:进程到进程之间的通信 TCP UDP
注意:
1.CentOS 5/6:iptables命令编写规则;
2.CentOS 7:firewalld; 使用需要关闭firewalld:systemctl disable firewalld.service
3.规则的次序非常关键,谁的规则越严格,应该放的越靠前,而检查规则的时候,是按照从上往下的方式进行检查的.
4. iptables规则写法
4.1 规则:根据指定的匹配条件来尝试匹配每个流经此处的报文,一旦匹配成功,就由规则后面指明的处理动作进行处理;
匹配条件:
基本匹配条件:简单检查IP、TCP、UDP等报文的某属性进行匹配的机制;
扩展匹配条件:需要借助于扩展模块进行的匹配条件指定即为扩展匹配;
处理动作:
基本动作:ACCEPT,DROP, ...
扩展动作:需要借助扩展模块进行的动作;
4.2 添加规则之时需要考量的问题:
1.报文的流经路径,判断添加规则至哪个链上。
2.确定要实现的功能,判断添加规则至哪个表上。
3.要指定的匹配条件,以用于匹配目标报文。
三、iptables命令详解
3.1 iptables命令的使用格式:
iptables [-t table] {-A|-C|-D} chain rule-specification
ip6tables [-t table] {-A|-C|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] -S [chain [rulenum]]
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
iptables [-t table] -N chain
iptables [-t table] -X [chain]
iptables [-t table] -P chain target
iptables [-t table] -E old-chain-name new-chain-name
rule-specification规则 = [matches...] [target]
match匹配 = -m matchname [per-match-options]
target目标 = -j targetname [per-target-options]
3.2 规则的编写格式:
iptables [-t table] COMMAND chain [-m matchname [per-match-options]] [-j targetname [per-target-options]]
1) -t table:
默认为filter;其它可用的有raw, mangle, nat;
2) COMMAND:
chain链:
-P:policy ['pls] ,策略,定义默认策略; 一般有两种选择,ACCEPT接受和DROP丢弃;
-N:new, 新建一条自定义的规则链;被内建链上的规则调用才能生效;[-j chain_name];
-X:drop, 删除自定义的引用计数为0的空链;
-F:flush, 清空所选链中的所有规则。如指定链名,则删除对应链的所有规则。如没有指定链名,则删除所有链的所有规则。
-E: 重命名自定义的引用计数和为0的链;
规则:
-A:append, 追加,在指定链的尾部追加一条规则;
-I:insert, 插入,在指定的位置(省略位置时表示链首)插入一条规则;
-D:delelte,删除,删除指定的规则;
-R:replace,替换,将指定的规则替换为新规则;不能仅修改规则中的部分,而是整条规则完全替换;
查看:
-L:list,列出表中的链上的规则;
-n:numeric,以数值格式显示;
-v:verbose,显示详细格式信息;
-vv, -vvv
-x:exactly,计数器的精确结果;
--line-numbers:显示链中的规则编号;
计数器:
规则,以及默认策略有专用的计数器;
记录被当前规则所匹配到的:
(1) 报文个数;
(2) 字节总数;
重置规则计数器:
-Z:zero,将指定链中的所有规则的包字节计数器清零。
chain:
(1) 内建链;
(2) 自定义链;
3)匹配条件:
多重条件:逻辑关系为“与”;
基本匹配条件:
[!] -s, --source address[/mask][,...]:检查报文中的源IP地址是否符合此处指定的地址或范围;
[!] -d, --destination address[/mask][,...]:检查报文中的目标IP地址是否符合此处指定的地址或范围;
[!] -p, --protocol protocol:
protocol:{tcp|udp|icmp}
[!] -i, --in-interface name: 数据报文的流入接口;INPUT, FORWARD and PREROUTING
[!] -o, --out-interface name:数据报文的流出接口; FORWARD, OUTPUT and POSTROUTING
扩展匹配条件:
隐式扩展:不用-m选项指出matchname匹配名称 即可使用此match的专用选项进行匹配
-p tcp:隐含了-m tcp;
[!] --source-port,--sport port[:port]:匹配报文中传输层的源端口;
[!] --destination-port,--dport port[:port]:匹配报文中传输层的目标端口;
[!] --tcp-flags mask comp
SYN,ACK,FIN,RST,URG,PSH;
mask:要检查的标志位列表,以逗号分隔;
comp:必须为1的标志位,余下的出现在mask列表中的标志位则必须为0;
--tcp-flags SYN,ACK,FIN,RST SYN
[!] --syn:检查TCP三次握手的第一次
相当于--tcp-flags SYN,ACK,FIN,RST SYN
-p udp:隐含了-m udp:
[!] --source-port,--sport port[:port]:匹配报文中传输层的源端口;
[!] --destination-port,--dport port[:port]:匹配报文中传输层的目标端口;
-p icmp:隐含了-m icmp:
[!] --icmp-type {type[/code]|typename}
8:echo-request 回显请求
0:echo-reply 回显应答
显式扩展:必须使用-m选项指出matchname,有的match可能存在专用的选项;
获取帮助:
CentOS 7:man iptables-extensions
CentOS 6:man iptables
示例
1.开放本机22端口,其它全drop
# iptables -A INPUT -s 172.16.0.0/16 -d 172.16.66.60 -p tcp --dport 22 -j ACCEPT
# iptables -A OUTPUT -d 172.16.0.0/16 -s 172.16.66.60 -p tcp --sport 22 -j ACCEPT
# iptables -P INPUT DROP
# iptables -P OUTPUT DROP
# iptables -P FORWARD DROP
2.开放本机ping端口,可以去ping别人
# iptables -A OUTPUT -s 172.16.66.60 -p icmp --icmp 8 -j ACCEPT
# iptables -A INPUT -d 172.16.66.60 -p icmp --icmp 0 -j ACCEPT
3.开放本机ping端口,允许别人ping
# iptables -A OUTPUT -s 172.16.66.60 -p icmp --icmp 0 -j ACCEPT
# iptables -A INPUT -d 172.16.66.60 -p icmp --icmp-type 8 -j ACCEPT
4.清空防火墙规则,需要修改默认规则,以免把自己关在门外。
# iptables -P INPUT ACCEPT
# iptables -P OUTPUT ACCEPT
# iptables -P FORWARD ACCEPT
# iptables -F
1、multiport扩展:
以离散或连续的方式定义多端口匹配条件;
[!] --source-ports,--sports port[,port|,port:port]...:指定多个源端口;
[!] --destination-ports,--dports port[,port|,port:port]...:指定多个目标端口;
[!] --ports port[,port|,port:port]...:指定多个端口;
示例:
1.允许指定端口进出
# iptables -A INPUT -d 172.16.66.60 -p tcp -m multiport --dports 22:23,80 -j ACCEPT
# iptables -A OUTPUT -s 172.16.66.60 -p tcp -m multiport --sports 22:23,80 -j ACCEPT
**2.添加默认规则,不允许任何人进入和出去
# iptables -A INPUT -d 172.16.66.60 -j DROP
# iptables -A OUTPUT -s 172.16.66.60 -j DROP
2、iprange扩展
以连续的ip地址范围指明连续的多地址匹配条件;
[!] --src-range from[-to]:源IP地址;
[!] --dst-range from[-to]:目标IP地址;
示例:允许连续的ip地址访问
# iptables -I INPUT 2 -d 172.16.66.60 -p tcp --dport 3306 -m iprange --src-range 172.16.66.80-172.16.66.90 -j ACCEPT
# iptables -I OUTPUT 2 -s 172.16.66.60 -p tcp --sport 3306 -m iprange --dst-range 172.16.66.80-172.16.66.90 -j ACCEPT
3、string扩展
对报文中的应用层数据做字符串匹配检测;
[!] --string pattern:要检测字符串模式;
[!] --hex-string pattern:要检测的字符串模式,16进制编码;
--algo {bm|kmp}
示例:是要不是在指定网段,而包含"admin"的网页字符串,都拒绝
# iptables -I OUTPUT -s 172.16.66.60 -p tcp --sport 80 -m iprange ! --dst-range 172.16.66.80-172.16.66.90 -m string --string "admin" --algo kmp -j REJECT
4、time扩展
根据报文到达的时间与指定的时间范围进行匹配度检测;
--datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]:起始日期时间;
--datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]: 结束日期时间;
--timestart hh:mm[:ss]
--timestop hh:mm[:ss]
[!] --monthdays day[,day...]
[!] --weekdays day[,day...]
# iptables -I INPUT -d 172.16.100.67 -p tcp --dport 23 -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays Tue,Thu,Sat -j ACCEPT
5、connlimit扩展
根据每客户端IP做并发连接数匹配;
--connlimit-upto n:连接数数量小于等于n,此时应该允许。
--connlimit-above n:连接数数量大于n,此时应该拒绝。
示例:
# iptables -A INPUT -d 172.16.100.67 -p tcp --dport 23 -m connlimit --connlimit-upto 2 -j ACCEPT
# iptables -A INPUT -d 172.16.66.60 -p tcp --dport 22 -j ACCEPT
# iptables -A INPUT -d 172.16.66.60 -j DROP
6、limit扩展
基于收发报文的速率进行匹配:-->令牌通算法
--limit rate[/second|/minute|/hour|/day]:平均速率
--limit-burst number:峰值速率
# iptables -I INPUT -d 172.16.66.60 -p icmp --icmp 8 -m limit --limit-burst 5 --limit 20/minute -j ACCEPT
7、state扩展
状态检测;连接追踪机制(conntrack);会自动记录new连接, 开启,会消耗大量内存。
INVALID:[nvld] 无法识别的状态;
ESTABLISHED ['stblt] 已建立的连接;
NEW: 新连接;
RELATED:[r'letd] 相关联的连接;
UNTRACKED: [n'trkt] 未追踪的连接;
示例:
# iptables -A INPUT -d 172.16.66.60 -m state --state ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -s 172.16.66.60 -m state --state ESTABLISHED -j ACCEPT
# iptables -A INPUT -d 172.16.66.60 -p tcp -m multiport --dports 22,23,80 -m state --state NEW -j ACCEPT
# iptables -A INPUT -d 172.16.66.60 -j DROP
# iptables -A OUTPUT -s 172.16.66.60 -j DROP
# iptables -I INPUT 3 -d 172.16.66.60 -p icmp --icmp-type 8 -m state --state NEW -j ACCEPT
8、nf_conntrack内核模块;使用功能自动装载模块
追踪到的连接:/proc/net/nf_conntrack文件中;
能追踪的最大连接数量定义在:/proc/sys/net/nf_conntrack_max
此值可自行定义,建议必要时调整到足够大;
不同的协议的连接追踪的时长:
/proc/sys/net/netfilter/
[!] --state STATE
如何开放被模式的ftp服务:
1) 装载追踪ftp协议的模块;
# find /lib/modules/3.10.0-327.el7.x86_64/ -iname "*conntrack*"
# modprobe nf_conntrack_ftp
# lsmod
2) 放行命令连接
# iptables -A INPUT -d 172.16.100.67 -p tcp -m state --state ESTABLISHED -j ACCEPT
# iptables -A INPUT -d 172.16.100.67 -p tcp --dport 21 -m state --state NEW -j ACCEPT
3) 放行数据连接
# iptables -A INPUT -d 172.16.100.67 -p tcp -m state --state RELATED -j ACCEPT
FORWARD :
# iptables -A FORWARD -j DROP
# iptables -I FORWARD -m state -state ESTABLISHED,RELATED -j ACCEPT
# iptables -I FORWARD 2 -s 192.168.11.0/24 -m state --state NEW -j ACCEPT
# iptables -I FORWARD 3 -d 192.168.11.2 -p tcp -m multiport --dports 21:23,80 -m state --state NEW -j ACCEPT
# modprobe nf_conntrack_ftp
4)处理动作(目标)
-j targetname [per-target-options]
targetname:
ACCEPT:接受;
DROP:丢弃;
REJECT:拒绝;
3.3 保存和重载规则:
iptables-save > /PATH/TO/SOME_RULE_FILE
iptables-restore < /PATH/FROM/SOME_RULE_FILE
3.4 CentOS 6:
保存规则:
service iptables save
自动保存规则至/etc/sysconfig/iptables文件中
重载规则:
server iptables restore
从/etc/sysconfig/iptables文件中重载规则
3.5 规则优化:
(1) 可安全放行所有入站及出站,且状态为ESTABLISHED的连接;
(2) 服务于同一类功能的规则,匹配条件严格的放前面,宽松放后面;
(3) 服务于不同类功能的规则,匹配报文可能性较大放前面,较小放后面;
(4) 设置默认策略;
(a) 最后一条规则设定;
(b) 默认策略设定;
iptables/netfilter网络防火墙:
在FORWARD链上定义规则,注意以下几个问题:
(1) 请求-响应均经由FORWARD链,要注意规则的方向性;
(2) 如果可以启用conntrack机制,建议将双方向的状态为ESTABLISHED的报文直接放行;
自定义链;
iptables -N chain_name
iptables -X chian_name
iptables -E old_name new_name
-j chain_name
示例:
创建链:
# iptables -N icmp_rules
# iptables -I FORWARD -p icmp -j icmp_rules
# iptables -A icmp_rules -j RETURN -->返回到主链上去
删除链:
# iptables -D FORWARD 1
# iptables -vnL
# iptables -F
# iptables -X icmp_rules
RETURN:
REDIRECT:端口重定向;
This target is only valid in the nat table, in the PREROUTING and OUTPUT chains, and user-defined chains which are only called from those chains.
--to-ports port[-port]:映射至哪个目标端口;
# iptables -t nat -A PREROUTING -d 172.16.66.60 -p tcp --dport 80 -j REDIRECT --to-port 8088
SNAT:源地址转换(隐藏内外主机)
This target is only valid in the nat table, in the POSTROUTING and INPUT chains, and user-defined chains which are only called from those chains.
--to-source [ipaddr[-ipaddr]][:port[-port]]
# iptables -t nat -A POSTROUTING -s 192.168.11.0/24 -j SNAT --to-soures 172.16.100.6
MASQUERADE 地址伪装(外网地址是动态时,使用)
This target is only valid in the nat table, in the POSTROUTING chain. It should only be used with dynamically assigned IP (dialup)
connections: if you have a static IP address, you should use the SNAT target.
DNAT:目标地址转换 (用于公开在网关之后的某台或某些主机)
This target is only valid in the nat table, in the PREROUTING and OUTPUT chains, and user-defined chains which are only called from those chains.
--to-destination [ipaddr[-ipaddr]][:port[-port]]
# iptables -t nat -A PREROUTING -d 172.16.100.7 -j DNAT --to-destination 192.168.11.2
# iptables -t nat -A PREROUTING -d 172.16.100.7 -j DNAT --to-destination 192.168.11.2:8089 端口映射
LOG:记录日志(先记录日志,在访问)
--log-prefix
--log-ip-options
# iptables -A INPUT -d 172.16.100.67 -p tcp --dport 8088 -j LOG --log-prefix " (to 8088) " --log-ip-options
示例:判断下述规则的意义
# iptables -N clean_in
# iptables -A clean_in -d 255.255.255.255 -p icmp -j DROP
# iptables -A clean_in -d 172.16.255.255 -p icmp -j DROP
# iptables -A clean_in -p tcp ! --syn -m state --state NEW -j DROP
# iptables -A clean_in -p tcp --tcp-flags ALL ALL -j DROP
# iptables -A clean_in -p tcp --tcp-flags ALL NONE -j DROP
# iptables -A clean_in -d 172.16.100.7 -j RETURN
# iptables -A INPUT -d 172.16.100.7 -j clean_in
# iptables -A INPUT -i lo -j ACCEPT
# iptables -A OUTPUT -o lo -j ACCEPT
# iptables -A INPUT -i eth0 -m multiport -p tcp --dports 53,113,135,137,139,445 -j DROP
# iptables -A INPUT -i eth0 -m multiport -p udp --dports 53,113,135,137,139,445 -j DROP
# iptables -A INPUT -i eth0 -p udp --dport 1026 -j DROP
# iptables -A INPUT -i eth0 -m multiport -p tcp --dports 1433,4899 -j DROP
# iptables -A INPUT -p icmp -m limit --limit 10/second -j ACCEPT
# iptables -t filter -A INPUT -s 172.16.0.0/16 -d 172.16.66.80 -j ACCEPT
# iptables -t filter -A OUTPUT -d 172.16.0.0/16 -s 172.16.66.80 -j ACCEPT
# iptables -vnL
# iptables -I INPUT -s 172.16.66.60 -d 172.16.66.80 -j REJECT
# iptables -R INPUT 1 -s 172.16.66.60 -d 172.16.66.80 -j DROP
补充:利用iptables的recent模块来抵御DOS攻击: 22,建立一个列表,保存有所有访问过指定的服务的客户端IP
ssh: 远程连接
# iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP
# iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
# iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j LOG --log-prefix "SSH Attach: "
# iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j DROP
1.利用connlimit模块将单IP的并发设置为3;会误杀使用NAT上网的用户,可以根据实际情况增大该值;
2.利用recent和state模块限制单IP在300s内只能与本机建立2个新连接。被限制五分钟后即可恢复访问。
下面对最后两句做一个说明:
1.第二句是记录访问tcp 22端口的新连接,记录名称为SSH
--set 记录数据包的来源IP,如果IP已经存在将更新已经存在的条目
2.第三句是指SSH记录中的IP,300s内发起超过3次连接则拒绝此IP的连接。
--update 是指每次建立连接都更新列表;
--seconds必须与--rcheck或者--update同时使用
--hitcount必须与--rcheck或者--update同时使用
3.iptables的记录:/proc/net/xt_recent/SSH
也可以使用下面的这句记录日志:
# iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --name SSH --second 300 --hitcount 3 -j LOG --log-prefix "SSH Attack"
练习题:INPUT和OUTPUT默认策略为DROP;
1、限制本地主机的web服务器在周一不允许访问;新请求的速率不能超过100个每秒;web服务器包含了admin字符串的页面不允许访问;web服务器仅允许响应报文离开本机;
2、在工作时间,即周一到周五的8:30-18:00,开放本机的ftp服务给172.18.0.0网络中的主机访问;数据下载请求的次数每分钟不得超过5个;
3、开放本机的ssh服务给172.18.x.1-172.18.x.100中的主机,x为你的学号,新请求建立的速率一分钟不得超过2个;仅允许响应报文通过其服务端口离开本机;
4、拒绝TCP标志位全部为1及全部为0的报文访问本机;
5、允许本机ping别的主机;但不开放别的主机ping本机;