Iptables 详解
Iptables的历史
历史版本
与Linux内核各版本集成的防火墙历史版本:
2.0.X内核:ipfwadm
2.2.X内核:ipchains
2.4.X内核:iptables
iptables的工作原理
iptables由用户空间的命令行程序和位于内核中的tcp/ip协议栈的报文处理框架两部分组成。工作在用户空间中,定义规则,让在内核空间当中的netfilter来读取,并且实现让防火墙工作。而放入内核的地方必须是tcp/ip的协议栈经过的地方。而这个tcp/ip协议栈必须经过的地方,可以实现读取规则的地方就叫做 netfilter.(网络过滤器)
内核空间中的五个位置:
内核空间中:从一个网络接口进来,到另一个网络接口去的
数据包从内核流入用户空间的
数据包从用户空间流出的
进入/离开本机的外网接口
进入/离开本机的内网接口
iptables的工作机制
iptables有五个钩子函数(hook function)也叫做规则链
PREROUTING(路由前)
INPUT(数据包流入口)
FORWARD(转发管卡)
OUTPUT(数据包出口)
POSTROUTING(路由后)
这是NetFilter定义的五个规则链,任何一个数据包,只要经过本机,必须经过这五个链中的其中一个链
iptables的策略
iptables的四个表的功能
filter定义过滤(允许或不允许)
nat 定义地址转换的(修改报文的源地址或目标地址)
mangle功能:修改报文原数据 (拆解报文,做出修改,并重新封装超来)
raw 关闭nat表上启用的连接追踪机制
它们所关联的规则链
iptables规则
iptables规则介绍
iptables规则是根据指定的匹配条件来尝试匹配每个流经此处的报文,一旦匹配成功,就由规则后面指明的处理动作进行处理。
匹配条件
基本匹配条件
简单检查IP、TCP、UDP等报文的某属性进行匹配的机制
扩展匹配条件
需要借助于扩展模块进行的匹配条件指明即为扩展匹配
处理动作
基本动作
ACCEPT DORP REJECT …
扩展动作
需要借助扩展模块进行的动作
添加规则时需要考量的问题
(1) 报文的流经路径,判断添加规则至哪个链上
(2) 确定要实现的功能,判断添加规则至哪个表上
(3) 要指定的匹配条件,以用于匹配目标报文
iptables使用的命令格式
man 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 = -jtargetname [per-target-options] table 默认为filter表,其它可用的有nat,mangle, raw
链
-P policy 策略,定义默认策略,一般有两种选择,ACCEPT和DROP
-N new 新建一条自定义的规则链,被内建链上的规则调用才能生效
-Xdrop 删除自定义的引用计数为0的空链
-Fflush 清空指定的链
-E重命名自定义的引用计数和0的链
规则
-A:append 追加,在指定链的尾部追加一条规则
-I:insert 插入,在指定的位置(省略位置时表示链首)插入一条规则
-D:delete删除,删除指定的规则
-R: replace 替换,将指定的规则替换为新规则,不能仅修改规则中的部分,而是整条规则全部替换
查看
-L: list 列出表中的链上的规则
-n: number 以数值格式显示
-v: verbose 显示详细格式信息,支持-vv–vvv
-x: exactly 计数器的精确结果
--line-numbers 显示链中的规则编号
计数器
-Z:zero 重置规则计数器
iptables匹配规则
基本匹配条件
[!] -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 --tcp-flagsSYN,ACK,FIN,RST SYN 检查第一次握手,SYN=1 --tcp-flags SYN,ACK,FIN,RST SYN,ACK 检查第二次握手,SYN=1,ACK=1 mask 要检查的标志位列表,以逗号分隔 comp 必须为1的标志位,余下的出现在mask列表中的标志位则必须为0 [!] –syn 相当于检查第一次握手,SYN=1 --tcp-flags SYN,ACK,FIN,RST SYN -p udp 隐含了-m udp [!] --source-port --sport port[:port] 匹配报文中传输层的源端口 [!] --destincation-port --dport port[:port] 匹配报文中传输层的目的端口 -p icmp [!] --icmp-type {type[/code]|typename} 8: echo-request 0: echo-reply
显式扩展
必须使用-m选项指出matchname; 有的match可能存在专用的选项
multiport扩展
以离散或连续的方式定义多端口匹配条件
[!] --source-ports,--sports port[,port|,port:port]... [!] --destination-ports,--dports port[,port|,port:port]... [!] --ports port[,port|,port:port]...
举例:
iptables -A INPUT -d 172.16.100.67 -p tcp -m multiport --dports22:23,80 -j ACCEPT iptables -A OUTPUT -s 172.16.100.67 -p tcp -m multiport --sports22:23,80 -j ACCEPT iptables -A INPUT -d 172.16.100.67 -j DROP iptables -A OUTPUT -s 172.16.100.67 -j DROP
iprange扩展
以连续的IP地址范围指明连续的多地址匹配条件;
[!] --src-range from[-to] [!] --dst-range from[-to]
举例:
iptables -I INPUT 2 -d 172.16.100.67 -p tcp --dport 3306 -miprange --src-range 172.16.100.61-172.16.100.70 -j ACCEPT iptables -I OUTPUT 2 -s 172.16.100.67 -p tcp --sport 3306 -miprange --dst-range 172.16.100.61-172.16.100.70 -j ACCEPT
string扩展
对报文中的应用层数据做字符串检测
[!] --string pattern 要检测字符串模式 [!] --hex-string pattern 要检测的字符串模式, 16进程编码 --algo {bm|kmp} 字符串匹配算法 iptables -I OUTPUT -s 172.16.100.67 ! -p tcp --sport 80 -miprange ! --dst-range 172.16.100.61-172.16.100.70 -m string --string"admin" --algo kmp -j REJECT
time扩展
根据报文到达的时间与指定的时间范围进行匹配检测
--datestartYYYY[-MM[-DD[Thh[:mm[:ss]]]]] 起始日期时间 --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]] 结束日期时间 --timestart hh:mm[:ss] 起始时间 --timestop hh:mm[:ss] 结束时间 [!] --monthdays day[,day...] [!] --weekdaysday[,day...]
iptables -I
只允许周二、周四、周六的工作时间访问telnet服务(因为前面有一个大的范围是放开的,现在要取反)应该先定义时间 然后再日期
(1) iptables -I INPUT -d 172.16.100.67 -p tcp --dport 23 -mtime --timestop 18:00:00 --timestop 08:59:59 -j REJECT (2) iptables -I INPUT -d 172.16.100.67 -p tcp --dport 23 -mtime ! --weekdays Tue,Thu,Sat -j REJECT 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
connlimit扩展
根据每客户端IP做并发连接数匹配
--connlimit-upto n 连接数数量小于等于n,此时应该允许 --connlimit-above n 连接数数量大于等于n,此时应该拒绝
需要先添加22端口放行 只允许23号端口放行2个连接
iptables -A INPUT -d 172.16.100.67 -p tcp --dport 22 -j ACCEPT iptables -A INPUT -d 172.16.100.67 -p tcp --dport 23 -m --connlimit-upto 2 -j ACCEPT
limit扩展
基于收发报文的速率进行匹配
--limitrate[/second|/minute|/hour|/day] 平均速率 --limit-burst number 峰值速率 iptables -I INPUT -d 172.16.100.67 -p icmp --icmp-type 8-m limit --limit-burst 5 --limit 20/minute -j ACCEPT
第一次5个最大的,然后后面3秒一个
OUTPUT默认为开放
使用hping工具测试
state扩展
状态检测,连接追踪机制(conntrack)
INVALID
无法识别的状态
ESTABLISHED
已建立的连接
NEW
新连接
RELATED
相关联的连接
UNTRACKED
未追踪的连接
modinfo nf_conntrack 追踪模块
modprobe nf_conntrack
装载追踪模块
lsmod
显示所有装载的模块
cat /proc/net/nf_conntrack
nf_conntrack内核模块
追踪到的连接/proc/net/nf_conntrack文件中
能追踪的最大连接数量定义在/proc/sys/net/nf_conntrack_max
此值可自行定义,建议必要时调整到足够大
不同协议的连接追踪的时长
ls /proc/sys/net/netfilter/
[!] --state STATE
示例
iptables -A INPUT -d 172.16.100.67 -m state --stateESTABLISHED -j ACCEPT iptables -A OUTPUT -s 172.16.100.67 -m state --stateESTABLISHED -j ACCEPT iptables -A INPUT -d 172.16.100.67 -p tcp -m multiport--dports 22,23,80,3306 -m stat --state NEW -j ACCEPT iptables -A INPUT -d 172.16.100.67 -j DROP iptables -A OUTPUT -s 172.16.100.67 -j DROP iptables -I INPUT 3 -d 172.16.100.67 -p icmp --icmp-type 8 -mstate --state NEW -j ACCEPT
因为出去的ESTABLISHED已经放行
放行被动模块的ftp
modprobe nf_conntrack_ftp 装载ftp追踪模块
iptables -R INPUT 1 -d 172.16.100.67 -m state --state ESTABLISHED,RELATED -j ACCEPT
如何开放被动模式的ftp服务
(1) 装载追踪ftp协议的模块 modprobe nf_conntrack_ftp (2) 放行命令连接 iptables -A INPUT -d 172.16.100.67 -p tcp -m state --stateESTABLISHED -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 --stateESTABLISHED,RELATED -j ACCEPT
规则的保存
CentOS 7
iptables-save > /path/to/some_rule_file
iptables-restore
CentOS 6
保存规则
service iptables save
自动保存规则至/etc/sysconfig/iptables文件中
重载规则
service iptables restore
从/etc/sysconfig/iptables文件中重载规则
规则优化
(1) 可安全放行所有入站及出站,且状态为ESTABLISHED的连接
(2) 服务于同一类功能的规则,匹配条件严格的放前面,宽松的放后面
(3) 服务于不同类功能的规则,匹配报文可能性较大的放前面,较小放后面
(4) 设置默认策略
(a) 最后一条规则设定
(b) 默认策略设定
练习:INPUT和OUTPUT默认策略为DROP
iptables准备工作(默认策略修改为DROP,开放ssh策略)
iptables –X 清空所有自定义空链 iptables –t nat –F iptables –t raw –F iptables –t filter–F iptables –t mangle-F iptables -IINPUT -p tcp --dport 22 -j ACCEPT //开放22端的INPUT链 iptables -I OUTPUT -p tcp --sport 22 -j ACCEPT//开放22端口的OUTPUT链 iptables-P INPUT DROP //修改INPUT链的默认规则为DROP iptables-P OUTPUT DROP //修改OUTPUT链的默认规则为DROP
1. 限制本机主机的web服务器在周一不允许访问;新请求的速率不能超过100个每秒;web服务器包含了admin字符串的页面不允许访问;web服务器仅允许响应报文离开本机
iptables -I INPUT -d 192.168.99.54 -p tcp--dport 80 -m state --state ESTABLISHED -j ACCEPT iptables -I INPUT -d 192.168.99.54 -p tcp --dport 80 -mstate --state NEW -m limit --limit 100/second -m time ! --weekdays Mon -jACCEPT iptables -A OUTPUT -s 192.168.99.54 -p tcp --sport 80 -mstate --state ESTABLISHED -m string ! --string "admin" --algo kmp -jACCEPT
2. 在工作时间,即周一至周五的8:30-18:00,开放本机的ftp服务给192.168.0.0网络中的主机访问,数据下载请求的次数每分钟不得超过5个
[root@centos7 ~]# lsmod | grepnf_conntrack_ftp [root@centos7 ~]# modprobe nf_conntrack_ftp [root@centos7 ~]# lsmod | grep nf_conntrack_ftp nf_conntrack_ftp 18638 0 nf_conntrack 105745 8nf_nat,nf_nat_ipv4,nf_nat_ipv6,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_ftp,nf_conntrack_ipv4,nf_conntrack_ipv6 iptables -I INPUT 4 -d 192.168.99.54 -s192.168.99.0/24 -p tcp --dport 21 -m state --state NEW,ESTABLISHED -m time --weekdaysMon,Tus,Wed,Thu,Fri --timestart 08:30:00 --timestop 18:00:00 -j ACCEPT
iptables -A INPUT -d 192.168.99.54 -s192.168.99.0/24 -p tcp -m state --state RELATED -m limit --limit 5/min -jACCEPT iptables-A INPUT -d 192.168.99.54 -s 192.168.99.0/24 -p tcp -m state --stateESTABLISHED -j ACCEPT iptables -A OUTPUT -d 192.168.99.54 -s192.168.99.0/24 -p tcp -m state --state ESTABLISHED -j ACCEPT
3. 开放本机的ssh服务给192.168.99.1-192.168.99.100中的主机,新请求建立的速率一分钟不得超过2个,仅允许响应报文通过其服务端口离开本机
iptables -A INPUT -p tcp -m iprange --src-range192.168.99.1-192.168.99.100 -m limit --limit 2/min --dport 22 -j ACCEPT iptables -A OUTPUT -p tcp -m iprange --dst-range192.168.99.1-192.168.99.100 -m state ! --state NEW --sport 22 -j ACCEPT
然后删除开始准备的ssh规则
iptables –-line-numbers -L iptables –D INPUT [num] iptables –D OUTPUT [num]
4. 拒绝TCP标志位全为1及全部为0的报文访问本机
iptables -A INPUT -d 192.168.99.54 -p tcp --tcp-flags ALLALL -j DROP iptables -A OUTPUT -s 192.168.99.54 -p tcp --tcp-flagsALL NONE -j DROP
5. 允许本机ping别的主机,但不开放别的主机ping本机
iptables -A INPUT -p icmp --icmp-type 0 -d192.168.99.54 -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type 8 -s192.168.99.54 -j ACCEPT
显示iptables 规则
[root@centos7 ~]# iptables -vnL --line-numbers Chain INPUT (policy DROP 280 packets, 53114 bytes) num pkts bytes target prot opt in out source destination 1 33 1992 ACCEPT tcp -- * * 0.0.0.0/0 192.168.99.54 tcp dpt:80 state NEW limit: avg 100/sec burst 5 TIME on Tue,Wed,Thu,Fri,Sat,Sun UTC 2 226 22265 ACCEPT tcp -- * * 0.0.0.0/0 192.168.99.54 tcp dpt:80 state ESTABLISHED 3 0 0 ACCEPT tcp -- * * 192.168.99.0/24 192.168.99.54 tcp dpt:21 state NEW,ESTABLISHED TIME from 08:30:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri UTC 4 0 0 ACCEPT tcp -- * * 192.168.99.0/24 192.168.99.54 state RELATED limit: avg 5/min burst 5 5 1630 165K ACCEPT tcp -- * * 192.168.99.0/24 192.168.99.54 state ESTABLISHED 6 2 120 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.99.1-192.168.99.100 limit: avg 2/min burst 5 tcp dpt:22 7 3 252 ACCEPT icmp -- * * 0.0.0.0/0 192.168.99.54 icmptype 0 8 0 0 DROP tcp -- * * 0.0.0.0/0 192.168.99.54 tcp flags:0x3F/0x3F Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy DROP 30 packets, 2152 bytes) num pkts bytes target prot opt in out source destination 1 100 5907 ACCEPT tcp -- * * 192.168.99.54 0.0.0.0/0 tcp spt:80 state ESTABLISHED STRING match ! "admin" ALGO name kmp TO 65535 2 825 142K ACCEPT tcp -- * * 192.168.99.54 192.168.99.0/24 state ESTABLISHED 3 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 192.168.99.1-192.168.99.100 ! state NEW tcp spt:22 4 3 252 ACCEPT icmp -- * * 192.168.99.54 0.0.0.0/0 icmptype 8 5 0 0 DROP tcp -- * * 192.168.99.54 0.0.0.0/0 tcp flags:0x3F/0x00