一, iptables的发展的及工作原理
1,iptables的发展
Version 1.0:ipfw/ipfirewall,这是iptables的前身,作者从freeBSD上移植过来的,能够工作在内核当中的,对数据包进行检测的一款简易访问控制工具。
Version 2.0:使用 ipfw/firewall 这个防火墙机制;
Version 2.2:使用的是ipchain/firewall 这个防火墙机制;
Version 2.4 与 2.6 :主要是使用iptables/netfilter 这个防火墙机制,不过在某些早期的 Version 2.4 版本的 distributions 当中,亦同时支持 ipchains (编译成为模块),好让用户仍然可以使用来自 2.2 版的 ipchains 的防火墙规划。不过,不建议在 2.4 以上的核心版本使用 ipchains !
使用uname -r可以查看自己的内核版本!
2,iptables的工作原理
在内核中工作的总共有五个位置,工作在tcp,ip协议栈的控制报文。
这五个位置也被称为五个钩子函数(hook functions),也叫五个规则链。
<code> 1.PREROUTING (路由前,进入/离开本机的内网接口) 2.INPUT (数据包进入本机内核口) 3.FORWARD (转发关卡) 4.OUTPUT(数据包流出本机内核口) 5.POSTROUTING(路由后,进入/离开本机的外网接口) </code>
这是NetFilter规定的五个规则链,任何一个数据包,只要经过本机,必将经过这五个链中的其中一个链。
如下图所示:
3,iptables 的表格 (table) 与链 (chain)
防火墙策略一般分为两种,一种叫“通”策略,一种叫“堵”策略,通策略,默认门是关着的,必须要定义谁能进。堵策略则是,大门是洞开的,但是你必须有身份认证,否则不能进。所以我们要定义,让进来的进来,让出去的出去,所以通,是要全通,而堵,则是要选择。当我们定义的策略的时候,要分别定义多条功能,其中:定义数据包中允许或者不允许的策略,filter过滤的功能,而定义地址转换的功能的则是nat选项。为了让这些功能交替工作,我们制定出了“表”这个定义,来定义、区分各种不同的工作功能和处理方式。
<code> filter (过滤器):主要跟进入 Linux 本机的封包有关,这个是预设的 table ! </code>
<code> INPUT:主要与想要进入我们 Linux 本机的封包有关; OUTPUT:主要与我们 Linux 本机所要送出的封包有关; FORWARD:这个咚咚与 Linux 本机比较没有关系, 他可以『转递封包』到后端的计算机中,与下列 nat table 相关性较高。 </code>
<code> nat (地址转换):是 Network Address Translation 的缩写, 这个表格主要在进行来源与目的之 IP 或 port 的转换,与 Linux 本机较无关,主要与 Linux 主机后的局域网络内计算机较有相关。 </code>
<code> PREROUTING:在进行路由判断之前所要进行的规则(DNAT/REDIRECT) POSTROUTING:在进行路由判断之后所要进行的规则(SNAT/MASQUERADE) OUTPUT:与发送出去的封包有关 </code>
<code> mangle (破坏者): </code>
这个表格主要是与特殊的封包的路由旗标有关, 早期仅有 PREROUTING 及 OUTPUT 链,不过从 kernel 2.4.18 之后加入了 INPUT 及 FORWARD 链。 由于这个表格与特殊旗标相关性较高,所以像咱们这种单纯的环境当中,较少使用 mangle 这个表格。
简单的关系可以由下图这么看:
iptables/netfilter(这款软件)是工作在用户空间的,它可以让规则进行生效的,本身不是一种服务,而且规则是立即生效的。而我们iptables现在被做成了一个服务,可以进行启动,停止的。启动,则将规则直接生效,停止,则将规则撤销。
iptables还支持自己定义链。但是自己定义的链,必须是跟某种特定的链关联起来的。在一个关卡设定,指定当有数据的时候专门去找某个特定的链来处理,当那个链处理完之后,再返回。接着在特定的链中继续检查。
二,iptables规则的写法
<code> NAME iptables — administration tool for IPv4 packet filtering and NAT SYNOPSIS iptables [-t table] {-A|-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] </code>
1,查看管理命令 “-L”
<code> 附加子命令 -n:以数字的方式显示ip,它会将ip直接显示出来,如果不加-n,则会将ip反向解析成主机名。 -v:显示详细信息 -vv -vvv :越多越详细 -x:在计数器上显示精确值,不做单位换算 --line-numbers : 显示规则的行号 -t nat:显示所有的关卡的信息,不指定-t选项,默认为filter表 </code>
查看本机的iptables规则可以使用:
<code> [root@localhost ~]# iptables -L -n --line-numbers </code>
2,链管理命令(这都是立即生效的)
<code> -P :设置默认策略的(设定默认门是关着的还是开着的) </code>
默认策略一般只有两种:
<code> [root@localhost ~]# iptables -P INPUT (DROP|ACCEPT) 默认是关的/默认是开的 </code>
比如:
<code> [root@localhost ~]# iptables -P INPUT DROP </code>
这就把默认规则给拒绝了。并且没有定义哪个动作,所以关于外界连接的所有规则包括Xshell连接之类的,远程连接都被拒绝了。
<code> -F: FLASH,清空规则链的(注意每个链的管理权限) [root@localhost ~]# iptables -t nat -F PREROUTING [root@localhost ~]# iptables -t nat -F 清空nat表的所有链 -N:NEW 支持用户新建一个链 [root@localhost ~]# iptables -N inbound_tcp_web 表示附在tcp表上用于检查web的。 -X: 用于删除用户自定义的空链 使用方法跟-N相同,但是在删除之前必须要将里面的链给清空昂了 -E:用来Rename chain主要是用来给用户自定义的链重命名 -E oldname newname -Z:清空链,及链中默认规则的计数器的(有两个计数器,被匹配到多少个数据包,多少个字节) [root@localhost ~]# iptables -Z :清空 </code>
3,规则管理命令
<code> -A:追加,在当前链的最后新增一个规则 -I num : 插入,把当前规则插入为第几条。 -I 3 :插入为第三条 -R num:Replays替换/修改第几条规则 格式:iptables -R 3 ………… -D num:删除,明确指定删除第几条规则 </code>
4,通用匹配:源地址目标地址的匹配
<code> -s:指定作为源地址匹配,这里不能指定主机名称,必须是IP IP | IP/MASK | 0.0.0.0/0.0.0.0 而且地址可以取反,加一个“!”表示除了哪个IP之外 -d:表示匹配目标地址 -p:用于匹配协议的(这里的协议通常有3种,TCP/UDP/ICMP) -i eth0:从这块网卡流入的数据 流入一般用在INPUT和PREROUTING上 -o eth0:从这块网卡流出的数据 流出一般在OUTPUT和POSTROUTING上 </code>
5,扩展匹配
隐含扩展:对协议的扩展
<code> -p tcp :TCP协议的扩展。一般有三种扩展 --dport XX-XX:指定目标端口,不能指定多个非连续端口,只能指定单个端口,比如 --dport 21 或者 --dport 21-23 (此时表示21,22,23) --sport:指定源端口 --tcp-fiags:TCP的标志位(SYN,ACK,FIN,PSH,RST,URG) 对于它,一般要跟两个参数: 1.检查的标志位 2.必须为1的标志位 --tcpflags syn,ack,fin,rst syn = --syn 表示检查这4个位,这4个位中syn必须为1,其他的必须为0。所以这个意思就是用于检测三次握手的第一次包的。对于这种专门匹配第一包的SYN为1的包,还有一种简写方式,叫做--syn -p udp:UDP协议的扩展 --dport 目标端口 --sport 源端口 -p icmp:icmp数据报文的扩展 --icmp-type: echo-request(请求回显),一般用8 来表示 所以 --icmp-type 8 匹配请求回显数据包 echo-reply (响应的数据包)一般用0来表示 </code>
显式扩展(-m): 扩展各种模块
<code> -m multiport: 离散的多端口匹配扩展 --source-ports --destination-ports --ports 合并多个端口: -m multiport --destination-ports 21,22,80 -j ACCEPT 例子: iptables -I INPUT -d 172.16.100.7 -p tcp -m multiport --dports 22,80 -j ACCEPT iptables -I OUTPUT -s 172.16.100.7 -p tcp -m multiport --sports 22,80 -j ACCEPT iprange: ip地址范围 [!] --src-range from[-to] [!] --dst-range from[-to] 例子: iptables -A INPUT -d 172.16.100.7 -p tcp --dport 23 -m iprange --src-range 172.16.100.1-172.16.100.100 -j ACCEPT iptables -A OUTPUT -s 172.16.100.7 -p tcp --sport 23 -m iprange --dst-range 172.16.100.1-172.16.100.100 -j ACCEPT time: 指定时间范围 --datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]] --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]] --timestart hh:mm[:ss] --timestop hh:mm[:ss] [!] --weekdays day[,day...] 例子: iptables -A INPUT -d 172.16.100.7 -p tcp --dport 901 -m time --weekdays Mon,Tus,Wed,Thu,Fri --timestart 08:00:00 --time-stop 18:00:00 -j ACCEPT iptables -A OUTPUT -s 172.16.100.7 -p tcp --sport 901 -j ACCEPT string: 字符串匹配 --algo {bm|kmp}:字符匹配查找时使用算法 --string "STRING": 要查找的字符串 --hex-string “HEX-STRING”: 要查找的字符,先编码成16进制格式 connlimit: 每IP对指定服务的最大并发连接数; [!] --connlimit-above [n] limit: 报文速率控制 --limit #[/second|/minute|/hour|/day] --limit-burst # state: 状态匹配 ip_conntrack, nf_conntrack --state NEW ESTABLISHED RELATED INVALID 法则: 1、对于进入的状态为ESTABLISHED都应该放行; 2、对于出去的状态为ESTABLISHED都应该放行; 3、严格检查进入的状态为NEW的连接; 4、所有状态为INVALIED都应该拒绝; # 不识别的服务 </code>
6,详解-j ACTION
常用的ACTION:
<code> DROP:悄悄丢弃 一般我们多用DROP来隐藏我们的身份,以及隐藏我们的链表 REJECT:明示拒绝 ACCEPT:接受 custom_chain:转向一个自定义的链 DNAT :目标地址转换 SNAT :源地址转换 MASQUERADE:源地址伪装 REDIRECT:重定向:主要用于实现端口重定向 MARK:打防火墙标记的 RETURN:返回 在自定义链执行完毕后使用返回,来返回原规则链。 </code>
7,状态检测:
什么是状态检测?对于整个TCP协议来讲,它是一个有连接的协议,三次握手中,第一次握手,我们就叫NEW连接,而从第二次握手以后的,ack都为1,这是正常的数据传输,和tcp的第二次第三次握手,叫做已建立的连接(ESTABLISHED),还有一种状态,比较诡异的,比如:SYN=1 ACK=1 RST=1,对于这种我们无法识别的,我们都称之为INVALID无法识别的。还有第四种,FTP这种古老的拥有的特征,每个端口都是独立的,21号和20号端口都是一去一回,他们之间是有关系的,这种关系我们称之为RELATED。所以我们的状态一共有四种:
<code> NEW ESTABLISHED RELATED :对于ftp服务非常有用。 INVALID [root@localhost ~]# iptables -A INPUT -d 192.168.2.101 -p tcp -m multiport --destination-ports 21,22,80 -m state --state NEW -j ACCEPT </code>
8,SNAT基于原地址的转换(在POSTROUTING链上做转换)
基于原地址的转换一般用在我们的许多内网用户通过一个外网的口上网的时候,这时我们将我们内网的地址转换为一个外网的IP,我们就可以实现连接其他外网IP的功能。
<code> [root@sta ~]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 222.24.51.147 </code>
9,DNAT目标地址转换(在PREROUTING链上做转换)
对于目标地址转换,数据流向是从外向内的,外面的是客户端,里面的是服务器端通过目标地址转换,我们可以让外面的ip通过我们对外的外网ip来访问我们服务器不同的服务器,而我们的服务却放在内网服务器的不同的服务器上。
<code> [root@localhost ~]# iptables -t nat -A PREROUTING -d 192.168.2.101 -p tcp --dport 80 -j DNAT --to-destination 172.16.10.8 #外网访问内网web服务器时,转发到网关 </code>
10,控制规则的存放以及开启
注意:你所定义的所有内容,当你重启的时候都会失效,要想我们能够生效,需要使用一个命令将它保存起来
<code> [root@localhost ~]# service iptables save </code>
它会保存在/etc/sysconfig/iptables这个文件中,或者使用:
<code> [root@localhost ~]# iptables-save > /etc/sysconfig/iptables [root@localhost ~]# iptables-restore < /etc/sysconfig/iptables.old </code>
开机的时候,它会自动加载/etc/sysconfig/iptabels
如果开机不能加载或者没有加载,而你想让一个自己写的配置文件(假设为iptables.2)手动生效的话:
<code> iptables-restore < /etc/sysconfig/iptables.2 </code>
则完成了将iptables中定义的规则手动生效。
三,总结
Iptables是一个非常重要的工具,它是每一个防火墙上几乎必备的设置,也是我们在做大型网络的时候,为了很多原因而必须要设置的。学好Iptables,可以让我们对整个网络的结构有一个比较深刻的了解,同时,我们还能够将内核空间中数据的走向以及linux的安全给掌握的非常透彻。我们在学习的时候,尽量能结合着各种各样的项目,实验来完成,这样对你加深iptables的配置,以及各种技巧有非常大的帮助。
四,iptables一些常用规则总结,在filter链进行的
放行本机的sshd服务,进出的都要放行:
<code> [root@www ~]# iptables -t filter -A INPUT -s 192.168.2.0/16 -d 192.168.2.101 -p tcp --dport 22 -j ACCEPT [root@www ~]# iptables -t filter -A OUTPUT -s 192.168.2.101 -d 192.168.2.0/16 -p tcp --sport 22 -j ACCEPT </code>
放行httpd服务
<code> [root@www ~]# iptables -I OUTPUT -s 192.168.2.101 -p tcp --sport 80 -j ACCEPT [root@www ~]# iptables -I INPUT -d 192.168.2.101 -p tcp --dport 80 -j ACCEPT </code>
放行本机端的流入流出
<code> [root@www ~]# iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -i lo -j ACCEPT [root@www ~]# iptables -A OUTPUT -s 127.0.0.1 -d 127.0.0.1 -o lo -j ACCEPT 不放行本机的流入与流出,访问本机的httpd服务,网页会出现Error establishing a database connection。 </code>
使别人可以ping通自己,但自己ping不同比人
<code> [root@www ~]# iptables -A INPUT -d 192.168.2.101 -p icmp --icmp-type 8 -j ACCEPT [root@www ~]# iptables -A OUTPUT -s 192.168.2.101 -p icmp --icmp-type 0 -j ACCEPT ACCEPT icmp -- 0.0.0.0/0 192.168.2.101 icmp type 8 接受外面的请求 ACCEPT icmp -- 0.0.0.0/0 192.168.2.101 icmp type 0 接受外面的响应 Chain FORWARD (policy DROP) target prot opt source destination Chain OUTPUT (policy DROP) target prot opt source destination ACCEPT tcp -- 192.168.2.101 192.168.2.0/24 tcp spt:22 ACCEPT icmp -- 192.168.2.101 0.0.0.0/0 icmp type 0 发送响应给外面 ACCEPT icmp -- 192.168.2.101 0.0.0.0/0 icmp type 8 发送请求 </code>
让别人ping通自己带检测
<code> [root@www netfilter]# iptables -A INPUT -d 192.168.2.101 -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED -j ACCEPT [root@www netfilter]# iptables -A OUTPUT -s 192.168.2.101 -p icmp --icmp-type 0 -m state --state ESTABLISHED -j ACCEPT </code>
ping本机时记录日志
<code> [root@www ~]# iptables -I INPUT 6 -d 192.168.2.101 -p icmp --icmp-type 8 -j LOG --log-prefix "----firewall log for icmp" </code>
如何放行工作于被动模式下的FTP服务?
<code> 1、确保iptables加载ftp协议支持的模块:ip_nat_ftp, ip_conntrack_ftp 编辑/etc/sysconfig/iptables-config文件,定义如下参数: IPTABLES_MODULES="ip_nat_ftp ip_conntrack_ftp" 2、放行请求报文的RELATED和ESTABLISHED状态,放行响应报文的ESTABLISHED状态; </code>
放行本机的tftp服务:
<code> iptables -A INPUT -s 172.16.0.0/16 -d 172.16.100.7 -p udp --dport 69 -j ACCEPT iptables -A OUTPUT -s 172.16.100.7 -d 172.16.0.0/16 -p udp --sport 69 -j ACCEPT </code>
放行本机dns服务(tcp和udp共8条规则):
<code> iptables -A INPUT -s 172.16.0.0/16 -d 172.16.100.7 -p udp --dport 53 -j ACCEPT #UDP响应· iptables -A OUTPUT -s 172.16.100.7 -d 172.16.0.0/16 -p udp --sport 53 -j ACCEPT iptables -A OUTPUT -s 172.16.100.7 -p udp --dport 53 -j ACCEPT #UDP转发 iptables -A INPUT -d 172.16.100.7 -p udp --sport 53 -j ACCEPT iptables -A INPUT -s 172.16.0.0/16 -d 172.16.100.7 -p tcp --dport 53 -j ACCEPT #UDP响应· iptables -A OUTPUT -s 172.16.100.7 -d 172.16.0.0/16 -p tcp --sport 53 -j ACCEPT iptables -A OUTPUT -s 172.16.100.7 -p tcp --dport 53 -j ACCEPT #UDP转发 iptables -A INPUT -d 172.16.100.7 -p tcp --sport 53 -j ACCEPT </code>
自定义链
<code> [root@www ~]# iptables -N clean_in # 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 </code>
利用iptables的recent模块来抵御DOS攻击,使五分钟之内连接数不能超过三个,否则五分钟内禁止连接
<code> 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 DROP </code>
1.第二句是记录访问tcp 22端口的新连接,记录名称为SSH
–set 记录数据包的来源IP,如果IP已经存在将更新已经存在的条目
SSH : 记录到ssh空间里
2.第三句是指SSH记录中的IP,300s内发起超过3次连接则拒绝此IP的连接。
–update 是指每次建立连接都更新列表;
–seconds必须与–rcheck或者–update同时使用
–hitcount必须与–rcheck或者–update同时使用
3.iptables的记录:/proc/net/ipt_recent/SSH
五,使用FORWARD链为连个网段转发数据包
<code> [root@cacti ~]# iptables -A FORWARD -s 192.168.0.0/16 -d 172.16.20.0/24 -p tcp --dport 22 -j ACCEPT [root@cacti ~]# iptables -A FORWARD -s 172.16.20.0/24 -d 192.168.0.0/16 -p tcp --sport 22 -j ACCEPT [root@cacti ~]# iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT [root@cacti ~]# iptables -A FORWARD -d 192.168.0.0/24 -p tcp -m multiport --dports 22,80 -m state --state NEW -j ACCEPT </code>