iptables已经发展成为一个功能强大的防火墙,它已具备通常只会在专有的商业防火墙中才能发现的大多数功能。例如,iptables提供了全面的协议状态跟踪、数据包的应用层检查、速率限制和一个功能强大的机制以指定过滤策略和提供NAT功能。我在工作中逐渐领略到它的强大,在此跟大家分享一下我工作中的经验。

021918390.png


iptables相关概念:

1、表

2、链

3、匹配条件

4、动作

5iptables语法

6、企业应用案例

(1)流量访问控制

(2)日志记录

1、表:

表是iptables构建块,它描述了其功能的大类,iptables共有4个表:filternatmangle、和raw。过滤规则应用于filterNAT规则应用于nat表,用于修改分组数据的特定规则应用于mangle表,而独立于Netfilter连接跟踪子系统起作用的规则应用于raw表。

2、链:

每个表都有自己的一组内置链,用户还可以对链进行自定义;当一个数据包由内核中的路由计算确定为指向本地linux系统,它将经过INPUT链的检查;OUTPUT链保留给有Linux系统自身生成的数据包;FORWARD链管理经过linux系统路由的数据包(即iptables防火墙用于连接两个网络,并且两个网络之间的数据包必须流经该防火墙)。nat表中的PREROUTINGPOSTROUTING分别用于在内核进行IP路由计算之前和之后修改数据包的头部。

3、匹配条件:

iptables匹配指的是数据包必须匹配的条件,只有当数据包满足所有的匹配条件时,iptables才会采取相应的动作;匹配分为通用匹配和扩展匹配:

通用匹配:

-s | --src | --source [!]  HOST/NET

-d |--dst | --destination [!] HOST/NET

#iptables -t filter -A INPUT -s 172.16.0.0/16 -d 172.16.1.1 -j ACCEPT

-i incoming_interface 指定报文进入接口

-o outgoing_interface 指定报文流出接口

-p {tcp|udp|icmp} 匹配指定协议

扩展匹配:

要使用"-m  扩展名称"来引用,而每个扩展模块一般都会有自己特有的专用选项。扩展又分为隐含扩展和显式扩展:

隐含扩展:

-p tcp

--sport | --source-port

--dport | --destination-port

1、不指定此项,则暗示所有端口

2、使用服务名或端口号,但名字必须是在/etc/services中定义的,因为iptables从这个文件里查找相应的端口号

3、可以使用连续的端口,如:--source-port22:80这表示从22到80的所有端 口,包括22和80。如果两个号的顺序反了也没关系,如:--source-port 80:22这和--source-port 22:80的效果一样。

4、可以省略第一个号,默认第一个是0,如:--source-port:80表示从0到80的 所有端口。

5、也可以省略第二个号,默认是65535,如:--source-port22:表示从22到 65535的所有端口

6、在端口号前加英文感叹号表示取反,注意空格,如:--source-port! 22表 示除22号之外的所有端口;--source-port ! 22:80表示从22到80(包括22和80)之 外的所有端口。

注意:这个匹配操作不能识别不连续的端口列表,如:--source-port! 22, 36, 80 这样的操作是由后面将要介绍的多端口匹配扩展来完成的。


--tcp-flags flag1,flag2,....    flag

例如:

--tcp-flags  SYN,ACK,RST,FIN  SYN     要检查此数据包的SYN,ACK,RST,FINSYN位必须为1,也就是初始化包。也可以用 --syn来表示


-p udp

--sport | --source-port

--dport | --destination-port

UDP是一种无连接协议,所 以在它打开、关闭连接以及在发送数据时没有多少标记要设置,它也不需要任何类型的确认

-p icmp

--icmp-type  8     echo-request

--icmp-type 0       echo-reply


显式扩展:

-m state--state

NEW表示包将要或已 经开始建立一个新的连接,或者是这个包和一个还没有在两端都有数据发送的连接有关。

ESTABLISHED意思是包是完全有效的,而 且属于一个已建立的连接,这个连接的两端都已经有数据发送。

RELATED说明包正在建立一个新的连接,这个连接是和一个已建立的连接相关的。比如FTP的数据连接的第一个包就是RELATED,以后的就是ESTABLISHED 。一定记住modprobe nf_conntrack_ftp

INVALID意味着这个包没有已知的流或连接与之关 联,也可能是它包含的数据或包头有问题。


-m limit

--limit 设置最大的平均速率,3/second  4/minute  5/hour   6/day

--limit-burst  Number 默认是5,类似缓冲区

-m mac

--mac-source 基于包的源MAC

-m mark

--mark 1匹配mark的值,

-mmultiport

--source-port  22,25,110.....

--destination-port 22,80,443,3306......

多端口匹配,最大15个,以逗号分开

--port  22,80,110

源和目的端口都是相同的匹配。

-m ttl

--ttl  60  ;根据ttl来匹配

-miprange

--src-range

--dst-range

-m string

--string "String"

--algo  kmp | bm

-m time

--datestart   YYYY[-MM[-DD[Thh[:mm[:ss]]]]]

-mtime --datestart 2007-12-24 --datestop 2007-12-27

-mtime --datestart 2007-01-01T17:00 --datestop 2007-01-01T23:59:59

--datestop   YYYY[-MM[-DD[Thh[:mm[:ss]]]]]

--timestart   hh:mm[:ss]

--timestop     hh:mm[:ss]

-mtime --timestart 12:30 --timestop 13:30

--weekdays   Mon,Tue....

--monthdays  1,2,3,......

-mtime --weekdays Fr --monthdays 22,23,24,25,26,27,28


4、动作:

   也称target,常用target

       DROP   丢弃

       REJECT  丢弃,并返回错误报文

       ACCEPT  允许

       RETURN 由子链返回到主链

       REDIRECT 端口重定向

       DNAT  对目的NAT

       SNAT   对源地址NAT

       MASQUERADE 伪装,用于动态获取IP上网的SNAT

       LOG  记录日志

       MARK  打标记

       TTL

       --ttl-set 64  设置ttl64

       --ttl-dec 1 ttl1

       --ttl-inc  1 ttl1

       用户自定义的链


5iptables语法:

   iptables  [-t ]  大写选项子命令  [序号]  链名匹配标准  -j  目标


iptables
       大写字母选项:子命令
       小写字母选项:用来匹配标准及其它;
       -t{filter|nat|mangle|raw}
       -L:list
               -n:数字格式显示IP和PORT;
               -v:详细信息, -vv,-vvv
               --line-numbers:显示链中规则的行号;
               -x:显示精确值,不要做单位换算;


       规则和默认策略都有两个计数器:
               packets:
               bytes:
表和链的对应关系:
       filter: INPUT, FORWARD,OUTPUT
       nat: PREROUTING, POSTROUTING,OUTPUT
       mangle:  PREROUTING, INPUT, FORWARD, OUTPUT,POSTROUTING
       raw: PREROUTING,OUTPUT
其它子命令:
       管理链:
               -F:清空链
                       iptables-F
               -P:设定默认策略
                       iptables-t filter -P INPUT{DROP|ACCEPT}
               -N:新建一条自定义链;
                       iptables-N FILTER_WEB
               -X:删除自定义的空链;
               -Z:计算器清零;
                       iptables-Z
               -E:重命名自定义链
       管理规则:
               -A:append
               -I[n]:插入为第n条规则
               -D[n]:删除第n条规则
               -R[n]: 替换第n条规则

保存配置文件:serviceiptables save ,默认保存在/etc/sysconfig/iptables中,也可以使用iptables-save > /root/fw.rule自定义存放位置。


6、企业实施案例

拓扑如下所示

022017938.png

需求:

(1)、工作日上班时间不能使用QQBT、迅雷(周末时间可以);

(2)、对内部服务器进行访问控制,仅允许172.16.254.0/24 可以访问FTPHTTP

(3)、将公司的网站发布到网上

(4)、保留内网近3个月的NAT日志;


在工作之后才发现linux的iptables功能是如此强大,举例来说,iptables拿来做NAT性能十分出色,之前听说有个单位用Cisco6509配的NAT板卡做NAT,并做日志,十分吃力,我在工作中发现用iptables做NAT,GE的接口能跑满

1)编译netfilteriptables支持layer7过滤

    # 获取相关软件包

http://125.39.91.72:6666/download/

|-- config-2.6.32-el6

|--netfilter-layer7-v2.22.tar.gz(此文件为RHEL5的内核补丁)

|--iptables-1.4.20.tar.bz2

|--iptables-1.4.7-10.el6.src.rpm

|--iptables-1.4.7-9.el6.src.rpm

|--l7-protocols-2009-05-28.tar.gz

`-- netfilter-layer7-v2.23.tar.bz2(此文件为RHEL6的内核补丁)

https://www.kernel.org/下载内核

linux-2.6.32-358.el6.tar.bz2

#安装编译环境

# yum groupinstall"Development tools" "Server platform development" -y

#解压新内核至/usr/src 并创建链接

# tar xflinux-2.6.32-358.el6.tar.bz2 -C /usr/src/

# ln -svlinux-2.6.32-358.el6 linux

#解压netfilter并给内核打补丁

# tar xfnetfilter-layer7-v2.23.tar.bz2 -C /usr/src

# cd linux

# patch  -p1 <../netfilter-layer7-v2.23/kernel-2.6.32-layer7-2.23.patch

patching filenet/netfilter/Kconfig

Hunk #1 succeeded at894 (offset 99 lines).

patching filenet/netfilter/Makefile

…… ……

Hunk #1 succeeded at116 (offset -2 lines).

patching fileinclude/linux/netfilter/xt_layer7.h


#拷贝当前系统的配置文件,以此为基础,编译新内核

# cp /boot/config-2.6.32-358.el6.x86_64 ./.config

# 开始编译,

# makemenuconfig

Networkingsupport -----> Networking options ------> Network packet filteringframework(Netfilter)---->Core Netfilter Configuration-----><M>"layer7" match support

可选步骤:

GeneralSetup -------> Local version - append to kernel release

如果远程编译,建议使用screen命令另开一个终端,防止网络故障导致编译失败,

# yum -yinstall screen

# screen

使用Ctrl +A +D,脱离当前终端

# screen -ls  查看当前有几个screen

There is a screen on:

28604.pts-1.localhost        (Detached)


# screen  -r  默认打开第一个

# screen -r  28604 ,打开指定的screen

# 开始编译

# make

# 编译内核需要大量的时间,(半小时到一个小时不等,视系统配置而定,可以先看下面内容)

# make过程中出现如下错误

perl: warning: Fallingback to the standard locale ("C").

 CC     fs/ioprio.o

perl: warning: Settinglocale failed.

perl: warning: Pleasecheck that your locale settings:

       LANGUAGE = (unset),

       LC_ALL = (unset),

       LC_NUMERIC = "C",

       LC_COLLATE = "C",

       LANG = "en"

   are supported and installed on your system.

解决方案:

# vi /etc/default/locale

LC_ALL="C"


或许还会遇到:

make[2]:***[crypto/signature/ksign-pulickey.o] Error 1

make [1]:*** [crypto/signature] Error  2

make :*** [crypto] Error 2

解决办法:


清理不完整的编译,并取消相关选项

# makeclean

# makemenuconfig

1Enable loadable module support------> [  ] Module signatureverification (EXPERIMENTAL)

2Cryptographic API  ------>  [  ] In-kernel signature checker(EXPERIMENTAL)

# makemodules_install

# makeinstall

内核编译完成后,暂时不要修改默认启动,开机启动时,手动选择新内核:

022058897.png


#下载src.rpmiptables,制作rpm包并更新旧版本iptables

iptables的补丁也在netfilter-layer7-v2.23.tar.bz2,只支持1.4.3以后的版本

安装src.rpm包:

#建立安装src.rpm类型的包的用户

#useradd  mockbuild

# rpm -ivh   iptables-1.4.7-9.el6.src.rpm


# cd  /root/rpmbuild/SOURCES

# tar xfiptables-1.4.7.tar.bz2

# cd iptables-1.4.7/extensions

# layer7的补丁文件拷到iptables-1.4.7中,并重新生成tar.bz2

# cp/usr/src/netfilter-layer7-v2.23/iptables-1.4.3forward-for-kernel-2.6.20forward/*./

# tar jcf iptables-1.4.7.tar.bz2 iptables-1.4.7/*

# rm -rfiptables-1.4.7

# cd  /root/rpmbuild/SPECS

# vi iptables.spec

Release: 10%{?dist}此处可以修改一下版本,以示区别(可选)

找到编译参数设置:修改最后--with-ksource=/usr/src/linux

./configure --enable-devel--enable-libipq --bindir=/bin --sbindir=/sbin         --sysconfdir=/etc --libdir=/%{_lib}--libexecdir=/%{_lib} --mandir=%{_m       andir} --includedir=%{_includedir}--with-xtlibdir=/%{_lib}/xtables-%{ve       rsion} --with-ksource=/usr/src/linux

注意:要等内核编译完成后再编译iptables


[root@localhostrpmbuild]# cd RPMS/

[root@localhost RPMS]# cd x86_64/

[root@localhostx86_64]# ls

iptables-1.4.7-10.el6.x86_64.rpm

iptables-debuginfo-1.4.7-10.el6.x86_64.rpm

iptables-devel-1.4.7-10.el6.x86_64.rpm

iptables-ipv6-1.4.7-10.el6.x86_64.rpm

#更新系统已经安装的iptables

[root@localhostx86_64]# rpm -Uvh iptables-1.4.7-10.el6.x86_64.rpmiptables-ipv6-1.4.7-10.el6.x86_64.rpm

Preparing...               ########################################### [100%]

  1:iptables              ########################################### [ 50%]

  2:iptables-ipv6         ########################################### [100%]

# layer7protocol复制到系统中

# cd /root/iptables/

# tar xfl7-protocols-2009-05-28.tar.gz

# cdl7-protocols-2009-05-28

# make install

要想l7filter生效,需开启一个内核参数,但此参数需要在有一条layer7的配置之后才会自动加载:

可以先写一条iptables,如:

iptables -t filter -AINPUT -d 172.16.1.1 -p tcp -m layer7 --l7proto qq  -j REJECT

[root@localhost protocols]# sysctl -a | grep net.netfilter.nf_conntrack_acct

kernel.acct =4        2        30

net.netfilter.nf_conntrack_acct = 0

将此参数写入/etc/sysctl.conf中,顺便开启路由转发功能:

net.ipv4.ip_forward = 1

net.netfilter.nf_conntrack_acct = 1

# sysctl -p使配置生效

使用service iptables restart之后,也要执行sysctl -p 命令,因为net.netfilter.nf_conntrack_acct的值会变成0;


开始调试防火墙:

注意,先不要着急把默认策略设为DROP,先允许ssh管理流量通过,

# INPUT方向上允许ssh新建会话

[root@fw ~]# iptables-A INPUT -s 192.168.10.0/24 -d 192.168.10.254 -p tcp --dport 22 -m state--state NEW -j ACCEPT

# INPUT方向允许以及建立连接的流量

[root@fw ~]# iptables-I INPUT -m state --state ESTABLISHED -j ACCEPT

# OUTPUT方向上允许ssh等已经建立连接的流量

iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT


测试QQ

1、首先设置NAT让内网用户可以上网:

[root@fw ~]# iptables-t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT --to 172.16.1.254

可以发现有匹配的包

022619450.png

2、添加允许QQ的流量,看有没有匹配,如果有,再改成DROP,过滤功能需要在FORWARD链进行处理,

[root@fw ~]# iptables-A FORWARD -s 192.168.10.0/24 -m layer7 --l7proto qq -j ACCEPT

022733964.png


[root@fw ~]# iptables-R FORWARD 1 -s 192.168.10.0/24 -m layer7 --l7proto qq -j REJECT

# 清空计数器,再登陆

[root@fw ~]# iptables -Z

022927267.png


(1)、工作日不能使用QQBT、迅雷,只可以访问公司内部服务器(周末时间可以);

# iptables -AFORWARD -s 192.168.10.0/24 -m time --weekdays Mon,Tue,Wed,Thu,Fri  -m time --timestart 08:30:00  --timestop 18:30:00  -m layer7 --l7proto qq  -j DROP

# iptables -AFORWARD -s 192.168.10.0/24 -m time --weekdays Mon,Tue,Wed,Thu,Fri  -m time --timestart 08:30:00  --timestop 18:30:00  -m layer7 --l7proto xunlei  -j DROP

# iptables -AFORWARD -s 192.168.10.0/24 -m time --weekdays Mon,Tue,Wed,Thu,Fri  -m time --timestart 08:30:00  --timestop 18:30:00  -m layer7 --l7proto http  -j DROP

#禁止访问某个网站

iptables -A FORWARD -s192.168.10.0/24 -m time --weekdays Mon,Tue,Wed,Thu,Fri  -m time --timestart 08:30:00  --timestop 18:30:00  -m string --string="baidu.com"--algo kmp  -j DROP

# 禁止下载电影

# iptables -AFORWARD -s 192.168.10.0/24 -m time --weekdays Mon,Tue,Wed,Thu,Fri  -m time --timestart 08:30:00  --timestop 18:30:00  -m string --string=".avi" --algokmp  -j DROP

(2)、对内部服务器进行访问控制,仅允许192.168.10.10 可以访问FTPHTTP

#modprobe  nf_conntrack_ftp

iptables -A FORWARD -s192.168.10.10 -d 192.168.80.0/24 -m state --state ESTABLISHED -j ACCEPT

iptables -A FORWARD -s192.168.10.10 -d 192.168.80.0/24 -p tcp -m multiport --dport 21,80 -m state--state NEW -j ACCEPT

iptables -A FORWARD -s192.168.10.10 -d 192.168.80.0/24 -p tcp -m state --state RELATED -j ACCEPT

iptables -A FORWARD -s192.168.80.0/24 -d 192.168.10.10 -p tcp -m multiport --sport 21,80 -m state--state ESTABLISHED -j ACCEPT

023100207.png

(3)、将公司的网站和ftp发布到网上;

# modprobe ip_nat_ftp

iptables -t nat -APREROUTING -d 172.16.1.254 -p tcp --dport 21 -j DNAT --to 192.168.80.12:21

iptables -t nat -APREROUTING -d 172.16.1.254 -p tcp --dport 80 -j DNAT --to 192.168.80.11:80


iptables -A FORWARD -d192.168.80.0/24 -p tcp -m multiport --dport 21,80 -m state --state NEW -jACCEPT

iptables -A FORWARD -d192.168.80.0/24 -p tcp -m state --state ESTABLISHED -j ACCEPT

iptables -A FORWARD -D192.168.80.0/24 -p tcp -m state --state RELATED -j ACCEPT

iptables -A FORWARD -d192.168.80.0/24 -p tcp -m state --state RELATED -j ACCEPT

iptables -A FORWARD -s192.168.80.0/24 -p tcp -m state --state ESTABLISHED -j ACCEPT


#不允许DMZ区域主机主动发起连接

[root@fw ~]# iptables-A FORWARD -i eth1 -s 192.168.80.0/24 -m state --state NEW -j DROP


# 一款好用的流量实时监测工具----  ifstat,

023407669.png

# tar  xf ifstat-1.1.tar.gz

# cd ifstat-1.1

# ./configure

# make &&make install

# ifstat -b     bit/s,不加参数是KB/s,其他用法参见man  ifstat


(4)、保留内网的NAT日志;

NAT性能十分出色,一些二级运营商就是用的Linux来做NAT,只需一台普通配置的机器,就可以完成NAT跟日志的处理:下图是DELL R310的配置

030004219.png

030241908.png

NAT日志需要下载额外的包

http://125.39.91.72:6666/download

   conntrack-tools-1.0.0.tar_.bz2

   libnetfilter_conntrack-1.0.0.tar.bz2

   libnfnetlink-1.0.0.tar.bz2

1、安装   libnfnetlink-1.0.0.tar.bz2

# tar xf libnfnetlink-1.0.0.tar.bz2

# cd libnfnetlink-1.0.0

# ./configure&& make && make install

#安装完查看下/usr/local/lib/pkgconfig/目录下有没有libnfnetlink.pc这个文件,有说明该软件安装好了

#设置变量PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/,并export导出

vi /etc/rc.local 添加以下内容

exportPKG_CONFIG_PATH=/usr/local/lib/pkgconfig/

export PKG_CONFIG_PATH

2、安装libnetfilter_conntrack-1.0.0.tar.bz2

# tar xf libnetfilter_conntrack-1.0.0.tar.bz2

# cd libnetfilter_conntrack-1.0.0

# ./configure&& make && make install

3、安装conntrack-tools-1.0.0.tar_.bz2

# tar xf conntrack-tools-1.0.0.tar_.bz2

# cd conntrack-tools-1.0.0

# ./configure --prefix=/usr/ && make&& make install

建立conntrackd配置文件存放目录,并将配置文件模版拷进来

# mkdir/etc/conntrackd

# viconntrackd.conf

General {

Nice-1

HashSize8192

HashLimit65535

LockFile/var/lock/conntrack.lock

UNIX{

Path/var/run/conntrackd.ctl

Backlog20

}

NetlinkBufferSize262142

NetlinkBufferSizeMaxGrowth655355

Filter{

ProtocolAccept {

TCP

UDP                #此处原文件有#,去掉#号UDP连接也记录

}

AddressIgnore {

IPv4_address127.0.0.1 # loopback

}

}

}

Stats {

LogFile/home/logs/iptable_log #日志文件保存位置,注意此处目录要存在才能启动服务

}

最后,创建日志存放目录

# mkdir /home/logs/

启动服务 conntrackd –d

停止服务 conntrackd –k

脚本1    createymd.py     #作用:生成年月日时嵌套目录,保存定时切割的日志

        使用方法:

        后边跟四位年份,如  python createymd.py  2014


脚本2    poll_log.sh        #作用:切割日志,保存到对应日期时间目录,并压缩

        用法: 将下边一行内容通过crontab –e写入crond,设置为每小时的58分执行,要找后两分钟的日志请去查看下一个小时的日志

               58      *      *       *       *      /home/logs/poll_log.sh &> /dev/null



注:以上脚本使用的前提:

1.        日志保存到/home/logs/,且文件名为iptable_log,这个在conntrackd.conf配置文件中设置

2.        脚本1建议放到/home/logs/目录,脚本2必须放到/home/logs/目录

3.        脚本1请在每年元旦前执行以产生来年日志保存目录

4.        脚本2写入到crond任务后,需要servicecrond start开启服务

效果如下:

[root@fw logs]# tail iptable_log

Mon Sep  2 14:09:36 2013        tcp     6 src=172.16.1.51 dst=172.16.1.254 sport=36219 dport=80 packets=5bytes=365 src=192.168.80.11 dst=172.16.1.254 sport=80 dport=36219 packets=5bytes=571 [ASSURED]

Mon Sep  2 14:09:36 2013        tcp     6 src=172.16.1.51 dst=172.16.1.254 sport=36220 dport=80 packets=5bytes=365 src=192.168.80.11 dst=172.16.1.254 sport=80 dport=36220 packets=5bytes=571 [ASSURED]

Mon Sep  2 14:09:36 2013        tcp     6 src=172.16.1.51 dst=172.16.1.254 sport=36221 dport=80 packets=5bytes=365 src=192.168.80.11 dst=172.16.1.254 sport=80 dport=36221 packets=5bytes=571 [ASSURED]

Mon Sep  2 14:09:36 2013        tcp     6 src=172.16.1.51 dst=172.16.1.254 sport=36222 dport=80 packets=5bytes=365 src=192.168.80.11 dst=172.16.1.254 sport=80 dport=36222 packets=5bytes=571 [ASSURED]

Mon Sep  2 14:09:36 2013        tcp     6 src=172.16.1.51 dst=172.16.1.254 sport=36223 dport=80 packets=5bytes=365 src=192.168.80.11 dst=172.16.1.254 sport=80 dport=36223 packets=5bytes=571 [ASSURED]

Mon Sep  2 14:09:36 2013        tcp     6 src=172.16.1.51 dst=172.16.1.254 sport=36224 dport=80 packets=5bytes=365 src=192.168.80.11 dst=172.16.1.254 sport=80 dport=36224 packets=5bytes=571 [ASSURED]

Mon Sep  2 14:09:36 2013        tcp     6 src=172.16.1.51 dst=172.16.1.254 sport=36225 dport=80 packets=5bytes=365 src=192.168.80.11 dst=172.16.1.254 sport=80 dport=36225 packets=5bytes=571 [ASSURED]


在实现应用层过滤的时候,效果有时不明显,希望通过这篇博客抛砖引玉,共同交流和提高。