1 前言
防火墙(Firewall),就是一个隔离工具,工作于主机
或者网络
的边缘,对于进出本主机或本网络的报文,根据事先定义的检查规则做匹配检测,对于能够被规则匹配到的报文作出相应处理的组件 , 就称之为防火墙,即可称为主机防火墙
和网络防火墙
其主机防火墙工作于主机的边缘, 网络防火墙工作于网络的边缘. 从防火墙实现的方法又可以划分为软件防火墙
和硬件防火墙
. 其软件防火墙纯软件逻辑实现,而硬件防火墙能实现硬件层实现封包或者解包, 但离不开软件的辅助. 目前市场上比较常见的三层, 四层的防火墙,叫网络层的防火墙, 七层的防火墙, 其实就是代理层的网关.从设计上来讲, 七层防火墙更加安全,但是却带来了效率更低.所以市场的能用方案为两者结合,而又由于我们都需要从防火墙所控制的这个口来访问, 所以防火墙的工作效率就成了用户能够访问数据多少的一个最重要的控制,配置的不好甚至有可能成为流量的瓶颈.
2 iptables的发展
iptables的前者叫ipfirewall(内核1.X时代),这是一个作者从freeBSD移值过来的, 能够工作在内核当中, 对数据包进行检测的一款简易访问控制工具, 但是ipfirewall工作极其有限(它需要将所有的规则都放进内核中, 这样规则才能够运行起来,而放进内核,这个做法一般是极其困难). 当内核发展到2.X系列的时候, 软件更名为ipchains, 它可以定义多条规则 , 将他们串进来,共同发挥作用,被称之为iptables. 可以将规则组成一个列表,实现绝对详细的访问控制功能.
他们都是工作在用户空间中, 定义规则的工具本身并不算是防火墙, 它们定义的规则,可以让在内核空间中的netfilter
来读取,并实现让防火墙工作,而放进的地方必须要是特定的位置,必须是tcp/ip协议栈的地方, 而这个tcp/ip协议栈必须经过的地方, 可以实现读取规则的功能称之为netfilter(网络过滤器)
作者一共在内核空间中选择了5个位置
从一个网络接口进来, 到另一个网络接口去的
数据包从内核流入用户空间的
数据包从用户空间流出的
进入/离开本机的外网接口
进入/离开本机的内网接口
iptables是工作在用户空间中的, 它可以编写规则, 其是一个rules until工具, 通过ipfw(firewall framework)在内核中生成系统规则(其是通过系统调用完成),再由ipchains工具将规则写入内核空间中,并写入netfilter.
3 iptables的工作机制
从上面知道了作者选择的5个位置, 来作为控制的地方, 其实前三个位置已经基本上能够将路径彻底封锁了, 但是为什么已经在进出的口设置了关卡后还要在内部卡呢 ? 由于数据包尚未进行路由决策,还不知道数据要走向那里, 所以在进出口是没有办法实现数据过滤的. 所以要在内核空间里设置转发的关卡. 进入用户空间的关卡,从用户空间出去的关卡, 那么,既然他们没什么用,那我们为什么还要设置他们呢? 因为我们在做NAT和DNAT的时候,目标地址转换必须在路由之前转换, 所以我们在外网而后内网的接口进行设置关卡.
这五个位置也被称为五个钩子函数(hook functions),也叫五个内置规则链
1
PREROUTING(路由前)
2
INPUT(数据包流流入入)
3
FORWARD(转发)
4
OUTPUT(数据包流出)
5
POSTROUTING(路由后)
工作原理图:
在不同链可实现的不同功能,从功能划分:
filter
: 过滤,防火墙,做包过滤nat
: network address translation,网络地址转换,修改源或目标IP, 也可以改端口mangle
: 拆解报文, 做出修改,并且重新封装起来(不修改IP或端口)raw
: 关闭nat表上启用的连接追踪功能
表的优先级,依次顺序为:
raw
mangel
nat
filter
不同的功能应用的链:
raw
: PREROUTING OUTPUTmangle
: PREROUTING INPUT FORWARD OUTPUT POSTROUTINGnat
: PREROUTING (INPUT) OUTPUT POSTROUTINGCentos 7上可以在INPUT上实现nat功能
filter
: INPUT OUTPUT FORWARD
从报文流向经过的链
流入 : PREROUTING—→INPUT
流出 : OUTPUT—→POSTROUTING
转发 : PREROUTING-→FORWARD-→POSTROUTING
路由功能发生的时刻:
当报文进入本机后, 判断目标主机是谁? 当报文离开本机前, 判断经由那个接口送往下一站?
iptables的链
内置链: 每个对应一个勾子函数(hook function)
自定义链: 用于对内置链的扩展和补充,可实现更灵活的规则管理机制,被内置链关联,必须由内置链调用才会生效
iptables添加规则时的考量点:
要实现那种功能,raw mangle filter, 判断添加到那张表上
报文流经过的路径: 判断添加到那个链上
链上的规则次序,即是检查的次序, 因此隐含一定的应用法则:
同类规则(访问同一应用),匹配范围小的放在上面
不同类规则(访问不同应用),匹配到报文频率较大的放在上面
将那此可由一条规则描述的多个规则合并进来
设置默认策略
iptables的规则匹配法则
规则匹配从上而下依次匹配, 如果匹配到了相关的规则, 则应用并不检查以下的规则, 当所有的规则都未匹配到时, 则应用默认策略
iptables命令
使用通用格式
iptables [-t tables] COMMAND chain [-m matchname [per-match-options]] -j targetname [per-target-options]
COMMAND
链管理
ACCEPT
: 接受DROP
: 丢弃REJECT
: 拒绝~]# iptables -P FORWARD ACCEPT ~]# iptables -P FORWARD DROP
-N
: new,自定义一条新的规则链~]# iptables -N in_icmp
-X
: delete/drop, 删除自定义的规则链,指明名字删除一个, 不指明将删除多个~]# iptables -X in_icmp
-P
: policy, 设置默认策略, 指明是黑名单还是白名单,对于filter表中的链而方, 其默认策略有:-E
: 重命名自定义链, 引用计数不为0的自定义链, 不能被重命名或者删除~]# iptables -E OLD_NAME NEW_NAME
规则管理
匹配到的报文个数
匹配到的所有报文的大小之和(字节数)
指明链,即清空指定链上的规则
不指明链, 即清空所有链上的规则
指明替换号
指明替换规则本身
指明规则号删除
指明规则本身
-A
: append, 追加规则-I
: insert, 插入规则,需要指明位置,省略时表示第一条-D
: delete, 删除规则-R
: replace, 替换指定链上的指定规则-F
: flush, 清空指定的规则链-Z
: zero, 置零
查看
-n
: numberic ,以数据格式显示地址和端口-v
: verbose ,详细信息-x
: exactly(精确的),显示计数器结果的精确值--line-numbers
: 显示规则的序号vv
vvv
-L
: list, 列出指定链上的所有规则
china
PREROUTING
INPUT
FORWARD
OUTPUT
POSTROUTING
匹配条件
基本匹配条件
无需加载任何模块,由iptables/netfilter自行提供
[!]-s, --source address[/mask][,...]
检查报文中源IP地址, 是否符合此处指定的地址或范围
[!]-d, --destination address[/mask][,...]
检查报文中的目标IP地址,是否符合此处指定的地址或范围
[!]-p, --protocol protocol
表明在传输层应用的协议,其可以有tcp,udp,udplite,icmp,icmpv6, esp,ah,sctp,mh 或者all
[!]-i, --in-interface name
只能应用于数据报文流入的接口,INPUT,FORWARD and PREROUTING chains
[!]-o, --out-interface name
只能应用于数据报文流出的接口,OUTPUT,FORWARD POSTROUTING
隐匿扩展
不需要手动加载扩展模块,因为它们是对协议的扩展,所以但凡使用
-p
指明了协议,就表示已经指明了要扩展的模块[!] --icmp {type[/code] | typename}
echo-request === 8
echo-replay === 0
ping别人: 出去==8 , 进来==0 别人ping我: 出去==0 , 进来==8
[!] --source-port --sport port[:port]
[!] --destination-port --dport port[:port]
匹配报文的源端口,可以是端口范围
匹配报文的目标端口,可以是端口范围
[!]--source-port, --sport port[:port]
[!]--destination-port, --dport port[:port]
[!]--tcp-flags mask comp
--syn
: 匹配第一次握手,相当于 —tcp-flags syn,ack,fin,rst syn
匹配报文的源端口,可以是端口范围
匹配报文的目标端口,可以是端口范围
mask : 必须要检查的标识位,必须以,号分隔
comp : 必须为1的标识位,必须以,号分隔
--tcp-flags syn,ack,fin,rst syn : 表示要检查的标识位为syn,ack,fin,rst. 但syn必须为1,余下的必须为0,其是匹配每一次握手 iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP iptables -A INPUT -p tcp !--syn -m state --state NEW -j DROP #不是TCP第一次握手,但状态又是new的报文
tcp
udp
icmp
显示扩展
必须使用
-m
选项手动加载模块, 其扩展模块路径为:/lib64/xtables,其中大写的为目标扩展,小写的为规则扩展Centos 6 : man iptables
Centos 7 : man iptables-extensions
获取扩展选项帮助
multiport扩展
: 以离散方式定义多端口匹配,但最多指定15个端口指定多个目标及源端口
指定多个目标端口
指定多个源端口
[!] --source-ports, --sports port[,port | ,port:port]
[!] --destination-ports, --dports port[,port | ,port:port]
--ports port[,port | ,port:port]
示例: iptables -A INPUT -s 172.16.0.0/16 -d 172.16.100.67 -p tcp -m multiport --dports 22,80 -j ACCEPT
iprange扩展
: 指明连续的(不一般不能整个网络)ip地址范围目标IP地址
源IP地址
[!] --src-range from[-to]
[!] --dst-range from[-to]
示例: iptables -A INPUT -d 172.16.100.67 -p tcp --dport 80 -m iprange --src-range 172.16.100.5-172.16.100.10 -j DROP iptables -A INPUT -s 172.16.36.71 -p tcp -m multiport --dport 53,80 -m iprange --dst-range 172.16.36.70-172.16.36.75 -j DROP
string 扩展
: 对报文中的应用层数据,做字符串模式匹配检测--alog {bm | kmp}
: 字符串匹配检测算法[!] --string pattern
: 要检测的字符串模式[!] --hex-string pattern
: 要检测的字符串模式,16进制格式示例 iptables -A OUTPUT -s 172.16.36.61 -p tcp --sport 80 -m string --algo bm --string "gay" -j REJECT
time 扩展
: 根据报文到达时间与指定的时间范围进行匹配--datestart YYYY[-MM-DD[Thh[:mm[:ss]]]]
--datestop YYYY[-MM-DD[Thh[:mm[:ss]]]
--timestart hh:mm[:ss]
--timestop hh:mm[:ss]
[!]--monthdays day,[day….]
[!]--weekdays day[,day…]
--kerneltz
: 使用内核的时间,而非默认的UTC时区(Centos 7)示例: iptables -A INPUT -s 172.16.0.0/16 -d 172.168.100.67 -p tcp --dport 80 -m time --timestart 14:30 --time-stop 18:30 --weekdays sat,sun -j DROP 每周的星期几可以使用数据表示方法: 1,2,3,4,5,6,7 可以使用离散取值方法
connlimit 扩展
: 对每客户端IP做并发连接数量匹配--connlimit-upto n
: 当现在的连接数量低于或等于这个数量(n),就匹配--connlimit-above n
: 当现有的连接数量大于这个数量, 就匹配示例: iptables -A INPUT -d 172.16.36.61 -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
limit扩展
: 基于收发报文的速率做匹配--limit rate [/second | /minute | /hour]
: 平均速率--limit-burst NUMBER
: 峰值数量,默认5个示例: iptables -A INPUT -d 172.16.100.67 -p icmp --icmp-type 8 -m limit --limit 3/minute --limit-burst 5 -j ACCEPT
state扩展
需手动加载nf_conntrack_ftp :
modprobe nf_conntrack_ftp
示例如下
iptables -A INPUT -d 172.16.36.61 -m state --state ESTABLISHED -j ACCEPT iptables -A INPUT -d 172.16.36.61 -p tcp -m multimport 22,80 -m state --state NEW -j ACCEPT iptables -A INPUT -d 172.16.36.61 -p tcp -m state --state RELATED -j ACCEPT iptables -A OUTPUT -s 172.16.36.61 -m state --state ESTABLISHED -j ACCEPT
修改max的内核参数 , vim /etc/sysctl.conf
net.ipv4.nf_conntrack_max = 393216 net.ipv4.netfilter.nf_conntrack_max = 393216
降低nf_conntrack timout时间, vim /etc/sysctl.conf
net.ipv4.netfilter.nf_conntrack_tcp_timeout_established = 300 net.ipv4.netfilter.nf_conntrack_tcp_timeout_time_wait = 120 net.ipv4.netfilter.nf_conntrack_tcp_timeout_close_wait = 60 net.ipv4.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
/proc/sys/net/netfilter
/porc/net/nf_conntrack
/proc/sys/net/nf_conntrack_max
NEW
: 新发起的请求ESTABLISHED
: new状态之后,连接追踪模板中为其建立的条目失效之前期间内所有的通信状态RELATED
: 相关的连接,如FTP协议中的命令连接与数据连接之间的关系INVALID
: 无效的连接,如tcp状态全为1或者全为0的连接UNTRACKED
: 未进行追踪的连接
根据连接追踪机制,查检连接的状态, 跟TCP没有关系,是内核中netfilter实现, 能实现tcp,udp,icmp的连接追踪,内核会记录每一个连接(放置在内存中),谁,通过什么协议, 访问什么服务, 访问的时间,这种机制被称之为conntrack机制.也正是有了state扩展,iptables成为了有连接追踪的防火墙,安全性是更高. 是由state扩展提供,库文件为ibxt_conntrack.so. 追踪连接功能在内核的内存空间中,把出去和进来的连接通过模板建立关联关系. 追踪本机的请求和响应之间的关系,状态如下几种:
调整连接追踪功能所容纳的最大连接数量:
已经追踪到的并记录下来的连接:
不同协议的连接追踪状态时长(可修改)
[!] --state STATE
: 多个state可以使用,号分隔iptables -A INPUT -d 172.168.100.67 -p tcp -m multiport --dport 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -s 172.16.100.67 -p tcp -m multiport --sport 22,80 -m state --state ESTABLISHED -j ACCEPT iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP
iptables的连接追踪表最大容量为/proc/sys/ipv4/ip_conntrack_max, 链接达到各种状态的超时后,会从表中删除,当模板满载时, 后续的链接可能会超时,可以有如下两种解决方法(但加大max值, 也会加大内存的压力)
如何放行被动模式的ftp服务
target的分类
ACCEPT
: 接受DROP
: 丢弃REJECT
: 拒绝RETURN
: 返回调用链REDIRECT
: 端口重定向LOG
: 记录日志--log-level LEVEL
: 日志的等级--log-prefix FREFIX
: 日志的提示语句的前缀iptables -A INPUT -d 172.16.36.61 -p tcp --dport 21 -j LOG --log-prefix "netfilter log"
MASK
: 做防火墙标记DNAT
: 目标地址转换SNAT
: 源地址转换MASQUERADE
: 地址伪装用户自定义链
自定义链的使用方法
iptables -N in_icmp iptables -A INPUT -j in_icmp iptables -A in_icmp -j RETURN
iptables的配置及服务管理
配置管理
Centos 6
service iptables save : 将规则保存至/etc/sysconfig/iptables文件中, 默认保存路径
iptables-save > /path/to/some_rules_file(适用于Centos 7)
iptabes-restore < /etc/sysconfig/iptables(适用于Centos 7)
用规则文件保存各规则,至/etc/rc.d/rc.local文件,开机可自动加载
服务管理
Centos 6
start : 读取事先保存的规则 , 并应用于netfilter上
stop : 清空netfilter的规则 , 以及还原默认策略
status : 显示生效的规则
restart : 先清空netfilter的规则 , 再读取规则
serivce iptables {start|stop|restart|status}
Centos 7
systemctl {start|stop|disable} firewalld.service
iptables nat功能
nat(network adress tanslate),其可以分为SANT,DNAT,PNAT.NAT的诞生是为了解决内网主机的安全, 但后期又应用于IPV4地址不够用,发挥了很大的作用
SNAT
客户端访问公网时,才需做源地址转换,发生的位置为:POSTROUTING或者OUTPUT
DNAT
本地网络中的某一主机上的某服务开放给公网的用户访问,时,发生的位置为:PREROUTING, 也可以完成端口映射
PNAT
发布服务的端口重定向,80-→8080
nat表的target
SNAT
--to-source [ipaddr[-ipaddr]][:port[-port]]
示例: iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -j SNAT --to-source 172.16.100.67
--random
: 随机选一个源地址
MASQUERADE
当源地址转换时, 当地址为动态获取时, MASQUERADE可自行判断要转换的地址(其有额外开销,如果是静态地址,建议不要使用)
示例: iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -j MASQUERADE
DNAT
--to-destination [ipaddr[-ipaddr]][:port[-port]]
示例: iptables -t nat -A PREROUTING -d 172.16.0.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.1:80
常见用法:
iptables -L -n -v : 查看规则 iptables -t nat -L -n : 查看nat规则 iptables -F : 清除规则 iptables -t nat -F PREROUTING : 清除nat的PREROUTING规则 iptables -Z : 清除所有的计数器 iptables -Z INPUT 1 : 清除指定规则的计数器 watch -n1 'iptables -L -n -v' : 动态监控iptables的数据信息 tcpdump -i eth1 tcp port 80 and host 172.16.36.61 : 抓取eth1接口tcp协议的80端口并且与172.16.36.61主机相关的报文
补充:利用iptables的recent模块来抵御DOS攻击: 22,建立一个列表,保存有所有访问过指定的服务的客户端IP
ssh: 远程连接, 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 LOG --log-prefix "SSH Attach: " 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内只能与本机建立2个新连接。被限制五分钟后即可恢复访问。 下面对最后两句做一个说明: 1.第二句是记录访问tcp 22端口的新连接,记录名称为SSH --set 记录数据包的来源IP,如果IP已经存在将更新已经存在的条目 2.第三句是指SSH记录中的IP,300s内发起超过3次连接则拒绝此IP的连接。 --update 是指每次建立连接都更新列表; --seconds必须与--rcheck或者--update同时使用 --hitcount必须与--rcheck或者--update同时使用 3.iptables的记录:/proc/net/xt_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
练习:INPUT和OUTPUT默认策略为DROP;
1、限制本地主机的web服务器在周一不允许访问;新请求的速率不能超过100个每秒;web服务器包含了admin字符串的页面不允许访问;web服务器仅允许响应报文离开本机; iptables -P OUTPUT DORP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -d 172.16.36.61 -p tcp --dport 80 -m time --weekdays 2,3,4,5,6,7 -m limit --limit 100/second -j ACCEPT iptables -A OUTPUT -s 172.16.36.61 -p tcp --sport 80 -m string --algo bm --string "admin" -j DROP (string的关键字过滤,一定要做在output链上, 在回应报文中才应该会有内容) iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT 2、在工作时间,即周一到周五的8:30-18:00,开放本机的ftp服务给172.16.0.0网络中的主机访问;数据下载请求的次数每分钟不得超过5个; ~]# modprobe nf_conntrack_ftp (需要使用related的连接状态,需要挂载此模块) iptables -P OUTPUT DORP iptables -P OUTPUT DROP iptables -P FORWARD DROP ~]# iptables -A INPUT -s 172.16.0.0/16 -p tcp --dport 21 -m time --weekdays 1,2,3,4,5 --timestart 8:30 --timestop 18:00 -m limit --limit 5/minute -m state --state NEW -j ACCEPT ~]# iptables -A INPUT -s 172.16.0.0/16 -p tcp -m state --state RELATED -j ACCEPT ~]# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT 3、开放本机的ssh服务给172.16.x.1-172.16.x.100中的主机,x为你的学号,新请求建立的速率一分钟不得超过2个;仅允许响应报文通过其服务端口离开本机; iptables -P OUTPUT DORP iptables -P OUTPUT DROP iptables -P FORWARD DROP ~]# iptables -A INPUT -m state --state ESTABLISHED,NEW -j ACCEPT ~]# iptables -A INPUT -d 172.16.36.61 -p tcp --dport 22 -m iprange --src-range 172.16.36.1-172.16.36.100 -m connlimit --connlimit-above 2/minute -j DROP ~]# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT 4、拒绝TCP标志位全部为1及全部为0的报文访问本机; iptables -P OUTPUT DORP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP 5、允许本机ping别的主机;但不开放别的主机ping本机; ~]# iptables -A OUTPUT -p icmp --icmp-type 8 -j ACCEPT ~]# iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT (如果INPUT上放行了ESTABLISHED,就不需要再放行代码为0的)
练习:判断下述规则的意义:
# iptables -N clean_in # iptables -A clean_in -d 255.255.255.255 -p icmp -j DROP # iptables -A clean_in -d 172.16.255.255 -p icmp -j DROP # 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 # iptables -A INPUT -d 172.16.100.7 -j clean_in # iptables -A INPUT -i lo -j ACCEPT # iptables -A OUTPUT -o lo -j ACCEPT(如果在OUTPUT上允许了state为ESTABLISHED的连接, 就不需要再放行,直接可以通过 等同 # iptables -A INPUT -d 127.0.0.1 -j ACCEPT # iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT (如果在OUTPUT上允许了state为ESTABLISHED的连接, 就不需要再放行,直接可以通过) # iptables -A INPUT -i eth0 -m multiport -p tcp --dports 53,113,135,137,139,445 -j DROP # iptables -A INPUT -i eth0 -m multiport -p udp --dports 53,113,135,137,139,445 -j DROP # iptables -A INPUT -i eth0 -p udp --dport 1026 -j DROP # iptables -A INPUT -i eth0 -m multiport -p tcp --dports 1433,4899 -j DROP# iptables -A INPUT -p icmp -m limit --limit 10/second -j ACCEPT
本文转自 tianya1993 51CTO博客,原文链接:http://blog.51cto.com/dreamlinux/1837664,如需转载请自行联系原作者