一、iptables的常用选项及分类

1、命令格式

iptables [-t TABLE] COMMAND CHAIN [creteria] -j(jump) ACTION{ACCEPT,DROP,REJECT,SNAT,DNAT}
 -t {raw|mangle|nat|filter},默认filter

2、命令选项
 COMMAND:
 规则管理类
  -A,(append的意思)
  -I # (I表示insert的意思,#表示数字,以下相同)
  -D # (delete的意思)
  -R # (replace的意思)
 链管理类:
  -F (flush)(清空链)
  -N (new)(新建链)
  -X (delete)(删除自定义的空链)
  -E (rename)(对链重命名)
 默认策略:
  -P policy
 清空计数器:
  -Z,zero
  每条规则(包括默认策略)都有两个计数器:
   被此规则匹配到的所有数据包的个数;
   被此规则匹配到的所有数据包的大小之和;
 查看类:
  -L(list)
   -n,numeric(以纯数字的方式来显示,不做解析)
   -v,verbose(详细信息)
   -vv -vvv
   -x,exactly(显示精确值,不做单位换算)
   --line-numbers 
 匹配条件(creterial规则)
  基本匹配:
   -s (SOURCE:可以是IP,!NETWORK)
   -d (目标地址)
   -p{tcp|udp|icmp}
   -i INTERFACE(数据包的流入接口)
   -o OUTERFACE(数据包的流出接口)
 扩展匹配:(调用iptables的模块,以便扩展iptables匹配功能)
  隐含扩展
   -p tcp
    --sport PORT
    --dport PORT
     可以指定连续的端口;例如:--sport 22:80(表示从22到80的端口,一般不用)
    --tcp-flags(ACK,SYN,RST,FIN | SYN,ACK只检查前四个标志位,后组出现的为1)= --syn
     例如:--tcp-flags ACK,SYN,RST,FIN SYN,ACK,RST,FIN (不可能,丢弃)   
   -p UDP
    --sport PORT
    --dport PORT
   -p icmp
    --icmp-type
     8:echo-request(ping请求)
     0:echo-reply(ping回应)
     3:(表示ping不通)  
  显式扩展
   -m(指定调用的模块)
    state --state {NEW|ESTABLISHD|INVALIDE|RELATED}(指定iptables的状态),
    iptables各state解释如下:
     NEW(相当于tcp三次握手的第一次请求,是syn=1的包)
     ESTABLISHED
     INVALID
     RELATED(主要用于做ftp命令跟踪的)
     例如:对ssh连接的控制:
     (1)对客户端的请求进行限制:
     iptables -A INPUT -d 172.16.100.1 -p tcp -dport 22 -m state --state NEW,ESTABLISHE -j ACCEPT
     同理,限制web服务只需将端口号改为80即可。
     (2)对服务器的回应进行限制:
     #iptables -A OUTPUT -s 172.16.100.1 -p tcp -sport 22 -m state --state ESTABLISHD -j ACCEKPT
     (3)修改iptables的默认策略:
     iptables -P INPUT DROP
     iptables -P OUTPUT DROP
     (4)让自己可以ping通自己:
     #iptables -I INPUT 1 -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
     #iptablses -I OUTPUT 1 -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
    multiport(指定端口)
     --source-ports 22,53,80
     !--destination-ports
     --ports
     例如:可以将以下两个相同特征的规则合并为一个规则:
     ACCEPT    tcp  --  0.0.0.0/0   172.16.58.1   tcp dpt:22 state NEW,ESTABLISHED
     ACCEPT    tcp  --  0.0.0.0/0   172.16.58.1   tcp dpt:80 state NEW,ESTABLISHED
     #iptables -I INPUT 2 -d 172.16.58.1 -p tcp -m state --state NEW,ESTABLISHED -m
     multiport --destination-port 22,80 -j ACCEPT
     #iptables -D INPUT #(删除合并过的行)
     #iptables -I OUTPUT 1 -m state --state ESTABLISHED -j ACCEPT(这条命令表示不管是什么协议,什么端口,只要状态是ESTABLISHED都允许)
    iprange
     --src-range 172.16.100.190-172.16.100.210
     --dst-range
     例如:允许地址为172.16.100.190-172.16.100.210网段的地址访问web服务:
     #iptables -A INPUT -p tcp --dport 80 -m iprange --src-range 172.16.100.190-172.16.100.210 -m state --state NEW -j ACCEPT
    connlimit(表示限定每个主机的tcp连接数)
     --connlimit-above
     例如:同一台主机只允许建立两次ssh连接:
     #iptables -A INPUT -d 172.16.58.1 -p tcp --dport 22 -m state --state NEW -m connlimit ! --connlimit-above 2 -j ACCEPT (表示一台主机最多只允许两次新连接)
    limit (限定速率)
     --limit 1/second(限定多长时间能可以请求几次)
     --limit-burst(限定并发请求的总个数)
     例如:
     #iptables -A INPUT -d 172.16.58.1 -p tcp --deport 80 -m state --state NEW -m limit --limint 1/minite --limit-burst 3 -j ACCEPT
     为了使显示效果明显,可以将keepalive关掉。步骤如下(源码安装):
     可以修改 /etc/httpd/extra/httpd-default.conf文件中的:KeepAlive On改为KeepAlive Off 
    string
     --algo bm|kmp (指定算法)
     --string "STRING"(功能是拒绝网页中含有指定字符串的网页显示)
     例如:拒绝网页中含有“***”字样的网页显示:
     #iptables -A OUTPUT -s 172.16.58.1 -m string --algo kmp --string "***" -j REJECT
     (注意一定要在链OUTPUT中拒绝才生效)  
    time
     --timestart
     --timestop -j
     -days
     例如:限定只能在12点到下午2:30之间请求主机172.16.100.1的web服务:
     #iptables -A INPUT -d 172.16.100.1 -p tcp 80 -m state --state NEW,ESTABLISTHED -m time --timestart 12:00 --timestop 14:00 -j ACCEPT         
二、开放被动模式下的FTP服务
 主动模式下:
  tcp, 20(20号端口用于数据传输),21(21号端口用于控制连接)
 被动模式:
  tcp, 21(用于控制连接) >1023(端口号大于1023的随机端口用于数据传输)
  所以在被动模式下,无法指定数据传输的端口,于是引入了RELATED状态。RELATED主要用于追踪与其相关的端口
 ftp工作在主动模式或者被动模式与客户端的请求有关。
 具体步骤如下:
  1、先开放ssh:
   iptables -A INPUT -i lo -j ACCEPT
   iptables -A OUTPUT -i lo -j ACCEPT(先开放本地连接)
   
   iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
   iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT(放行所有的ESTABLISHED连接)
   
   iptables -A INPUT -d 172.16.100.1 -p tcp --dport 22 -m state --state NEW -m connlimit ! --connlimit-above 3 -j ACCEPT  (放行ssh连接,并将其最大连接数设为3)
   
   iptables -P INPUT DROP
   iptables -P OUTPUT DROP (将默认策略设置为禁止)
     
    iptables -L -n -v (查看iptables详细信息)
  2、开放ftp服务:
   注意要开放被动模式下的服务需要用到,ftp的追踪模块:
   #cat /etc/sysconfig/iptables-config(查看iptables需要的模块,主要是ip_nat_ftp模块,属于内核模块)
   #lsmod | grep ftp (查看是否加载ftp模块)
   #modprobe ip_nat_ftp(加载ftp模块)
   #lsmod | grep ftp (查看模块是否被加载)
   这样RELATED就可以被使用了:
   iptables -A INPUT -d 172.16.100.1 -p tcp --dport 21 -m state --state NEW -j ACCEPT(允许21号端口进入,即:开放控制连接)
   iptables -A INPUT -m state --state RELATED -j ACCEPT
   iptables -A OUTPUT -m state --state RELATED -j ACCEPT
       
三、iptables规则永久生效的方法 
 首先要明白iptables不是服务,是命令。但是在Redhat中将iptables的控制脚本放在/etc/rc.d/init.d/iptables中,这样iptables就可以用service命令来控制了,但是service iptables start(表示启用保存的规则)service iptables stop(表示清空链)。在redhat中:
  /etc/sysconfig/iptables(默认情况将规则保存在此文件中)
  /etc/sysconifg/iptables-conifg(向iptables脚本提供配置文件)
 将iptables的规则保存下来:
 (1)service iptables save(把iptables生效的所有配置文件保存至/etc/sysconifg/iptables文件中)
 (2)iptables-save >/etc/sysconifg/iptables.test(明确保存在哪个文件中)
 (3)iptables-restore </etc/sysconfig/iptables.test( 启用指定文件中定义的规则)
 在自定义的文件中,规则可以写在脚本中: 
 写完脚本,执行就行了,开机自动启动,则将其放在/etc/local文件中就可以了。 

四、网络防火墙的实现
 1、保证两个网络之间是联通的,主要考虑一下几个因素:
 (1)查看主机或者网络的路由表,确保网关制定好。
 (2)确保防火墙处于转发状态。
  方法一、编辑/etc/sysctl.conf文件。将 net.ipv4.ip_forward的值改为1。(永久有效)
  方法二、也可以通过查看/proc/sys/net/ipv4/ip_forward来将其修改为1使其临时生效。
 2、举例说明用法:
  (1)拒绝ping命令:
  #iptables -A FORWARD -p icmp --icmp-type 8 -j REJECT
  (2)做ftp服务器的规则
  允许ssh服务:
  #iptables -A FORWARD -d 192.168.100.2 -p tcp --dport 22 -m state --state NEW -j ACCEPT
  #iptalbes -I FORWARD 1 -m -state --state ESTABLISHED -j ACCEPT
  开放ftp服务器:
   (1)开放21号端口:
   #iptables -A FORWARD -d 192.168.100.2 -p tcp --dport 21 -m state --state NEW -j ACCEPT
   (2)开放数据连接:
   #iptables -R FORWARD 1 -m state --state ESTABLISHED,RELATED -j ACCEPT
  让192.168.100.2能够接受ping命令
  #iptables -A FORWARD -d 192.168.100.2 -p icmp --icmp-type 8 -m limit --limit 3/second --limit-burst=3 -m state --state NEW -j ACCEPT
 3、nat的转换:
  在POSTROUTING上做源地址(SNAT)转换,例如:
   #iptables -t nat -A POSTROUTING -s 172.16.0.0/16 -j SNAT --to-source 192.168.100.1
   以上规则表示将来自172.16.0.0网络的主机全部转换成192.168.100.1。
   -j MASQUERADE(不用指定转换的地址,但消耗更多的资源)
  在PREROUTING上做DNAT转换,注意:做源地址转换一般都要指定协议和端口号。例如:
   #iptables -t nat -A PREROUTING -d 172.16.100.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.100.2
  端口转换,例如:
   #iptables -t nat -A PREROUTING -d 172.16.100.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.100.2:8080
   表示访问172.16.100.1的所有主机,都将其转换为192.168.100.2:8080
 4、-j LOG(表示防火墙做日志记录)
   --log-prefix "DATA for web"(标记为哪个服务做日志记录)注意日志规则一定要在其他规则匹配到之前。
   例如:iptables -t nat -I PREROUTING 1 -p tcp -dprot 80 -j LOG --log-prefix "Date For Web:"
   此时日志记录在:/var/log/messages中了。但是:如果web服务器非常繁忙,会产生大量的磁盘I/O操作,所
   以可以采用以下方法,每隔一段时间记录一次就行了。于是可以将上述规则更新如下:
   #iptables -t nat -R PREROUTING 1 -d 172.16.100.1 -p tcp -dport 80 -m limit --limit 3/minute --limit-burst=3 -j LOG --log-prefix "Data For Web:"
   这样就表示每分钟记录3次就行了。
  
五、利用iptables的recent模块来抵御DOS***
 以限制ssh远程连接为例:
  (1)#iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP
  (2)#iptables -I INPUT  -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
  (3)#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内只能与本机建立3个新连接。被限制一分钟后即可恢复访问。 
  下面对最后两句做一个说明:
  1.第一句是记录访问tcp 22端口的新连接,记录名称为SSH
   --set 记录数据包的来源IP,如果IP已经存在将更新已经存在的条目
  2.第三句是指SSH记录中的IP,300s内发起超过3次连接则拒绝此IP的连接。
   --update 是指每次建立连接都更新列表;
   --seconds必须与--rcheck或者--update同时使用
   --hitcount必须与--rcheck或者--update同时使用
  3.iptables的记录:/proc/net/ipt_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"