iptables已经发展成为一个功能强大的防火墙,它已具备通常只会在专有的商业防火墙中才能发现的大多数功能。例如,iptables提供了全面的协议状态跟踪、数据包的应用层检查、速率限制和一个功能强大的机制以指定过滤策略和提供NAT功能。我在工作中逐渐领略到它的强大,在此跟大家分享一下我工作中的经验。
iptables相关概念:
1、表
2、链
3、匹配条件
4、动作
5、iptables语法
6、企业应用案例
(1)流量访问控制
(2)日志记录
1、表:
表是iptables构建块,它描述了其功能的大类,iptables共有4个表:filter、nat、mangle、和raw。过滤规则应用于filter、NAT规则应用于nat表,用于修改分组数据的特定规则应用于mangle表,而独立于Netfilter连接跟踪子系统起作用的规则应用于raw表。
2、链:
每个表都有自己的一组内置链,用户还可以对链进行自定义;当一个数据包由内核中的路由计算确定为指向本地linux系统,它将经过INPUT链的检查;OUTPUT链保留给有Linux系统自身生成的数据包;FORWARD链管理经过linux系统路由的数据包(即iptables防火墙用于连接两个网络,并且两个网络之间的数据包必须流经该防火墙)。nat表中的PREROUTING和POSTROUTING分别用于在内核进行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,FIN位,SYN位必须为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 设置ttl为64
--ttl-dec 1 将ttl减1
--ttl-inc 1 将ttl加1
用户自定义的链
5、iptables语法:
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、企业实施案例
拓扑如下所示
需求:
(1)、工作日上班时间不能使用QQ、BT、迅雷(周末时间可以);
(2)、对内部服务器进行访问控制,仅允许172.16.254.0/24 可以访问FTP和HTTP;
(3)、将公司的网站发布到网上;
(4)、保留内网近3个月的NAT日志;
在工作之后才发现linux的iptables功能是如此强大,举例来说,iptables拿来做NAT性能十分出色,之前听说有个单位用Cisco6509配的NAT板卡做NAT,并做日志,十分吃力,我在工作中发现用iptables做NAT,GE的接口能跑满
(1)编译netfilter和iptables支持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
1、Enable loadable module support------> [ ] Module signatureverification (EXPERIMENTAL)
2、Cryptographic API ------> [ ] In-kernel signature checker(EXPERIMENTAL)
# makemodules_install
# makeinstall
内核编译完成后,暂时不要修改默认启动,开机启动时,手动选择新内核:
#下载src.rpm的iptables,制作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
可以发现有匹配的包
2、添加允许QQ的流量,看有没有匹配,如果有,再改成DROP,过滤功能需要在FORWARD链进行处理,
[root@fw ~]# iptables-A FORWARD -s 192.168.10.0/24 -m layer7 --l7proto qq -j ACCEPT
[root@fw ~]# iptables-R FORWARD 1 -s 192.168.10.0/24 -m layer7 --l7proto qq -j REJECT
# 清空计数器,再登陆
[root@fw ~]# iptables -Z
(1)、工作日不能使用QQ、BT、迅雷,只可以访问公司内部服务器(周末时间可以);
# 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 可以访问FTP和HTTP;
#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
(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,
# 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的配置
做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]
在实现应用层过滤的时候,效果有时不明显,希望通过这篇博客抛砖引玉,共同交流和提高。