防火墙基础
包过滤型防火墙是在数据包流入流出 主机/网络 时通过某些事先定义好的规则来匹配数据包的各种信息(如IP,PORT等信息),进而对数据包的流向做出相应的处理动作,根据防火墙工作的位置又分为主机防火墙和网络防火墙。
在 Linux 2.4/2.6 上的主机防火墙由 iptables、netfilter 两部分组成。netfilter这个框架工作于内核空间,随内核启动而启动,它提供了五个hook function,在数据包必经的几个结点上监控、捕捉、过滤数据包。而对于iptables,它是工作于用户空间的工具(或者称之为服务),负责将用户操作通知给netfilter,netfilter收到这些信息,即时生效。之前提到的数据包必经的数据结点(即五个hook function的作用位置),主要是以下几个:
链名 | 位置 |
---|---|
PREROUTING | 主机数据包的入口,在路由决策(判断目的ip是否为本机)之前 |
INPUT | 内核空间进入用户空间的位置 |
OUTPUT | 用户空间进入内核空间的位置 |
FORWARD | 作转发动作所经过的节点 |
POSTROUTING | 主机数据包出口,在路由决策(判断从哪条路径出去)之后 |
网络防火墙是建立在在网络出口处,但是对于网内部(如局域网)的不合法行为是没有监测保护能力的,因此在局域网内部也会将主机防火墙开启,有必要时还会使用防火墙将局域网内重要的服务器与客户机隔离开,如下示意图:
防火墙也不仅只有包过滤的功能,对于不同功能,其数据包经过的数据链路也不一样。针对于不同功能,它有自己独有的规则,于是把这些功能所定义的规则的组和形式的称之为防火墙的表。
防火墙表 | 功能 | 经由链 |
---|---|---|
filter | 进行包过滤 | INPUT、OUTPUT、FORWARD |
nat | 网络地址转换 | PREROUTING、POSTROUTING、OUTPUT |
mangle | 解析、修改、封装报文 | PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING |
raw | 连接追踪(建议关闭) | PREROUTING, OUTPUT |
针对在同一链上配置了多种功能,那功能的执行顺序满足以下次序:
raw --> mangle --> nat --> filter
防火墙策略编写原则
在编写防火墙规则前要明确自己实现何种功能,根据此功能判断数据包流经哪些链,再按需定义防火墙策略。防火墙策略时自上而下逐条读取并匹配的,所以再编写防火墙策略时应该遵循以下规则:
1、同一类别(有交集)的规则,将范围小的放至上面
2、不同类别的规则,可能被匹配中次数较多的策略放上面
3、尽量合并可合并的策略,减小策略条目
4、设置默认策略
防火墙策略由两部分组成:报文匹配条件、匹配成功后的处理动作。匹配条件又分为基本匹配和扩展匹配,根据报文的特征信息匹配;处理动作有防火墙提供的内建处理动作,也可以使用自定义处理动作。
iptables命令的基本应用
链管理命令:
用法:iptables [-t table] OPTIONS
选项说明:
-F CHAIN:清空规则链上的所有规则,不指定链表示清空表上的所有规则链
-N NEW_CHAIN:创建自定义规则链
-X CHAIN:删除自定义规则链,不指定表示所有
-Z:将某些规则计数器清零,如pkts等
-E CHAIN NEW_CHAIN:重命名自定义链,仅限已被引用的自定义链
-P CHAIN POLICY:设置默认策略,如ACCEPT, DROP, REJECT
注:不使用-t指定表默认为filter表,随后不在说明此特性
例:
# iptables -t mangle -F
# iptables -N NEWCHAIN1
# iptables -E NEWCHAIN1 CHAIN1
规则管理命令:
用法:iptables [-t table] OPTIONS
选项说明:
-L:列出规则,配合以下选项使用
-n:显示ip与端口信息
-v:显示更多信息,此外还有-vv,-vvv
-x:以字节为单位显示统计数据数值,配合-v使用
--line-number:显示规则编号
-A CHAIN:追加规则至指定链尾部
-I CHAIN #:插入规则到链上指定位置
-D CHAIN #|CONDITION:删除规则
可指定具体的规则编号,表示删除某条规则
也可以按匹配条件删除,表示删除这一类规则
-R CHAIN #:替换某条规则
匹配条件相关选项:
-s IP|NETADDR:报文中的来源ip或网络
-d IP|NETADDR:报文中的目的ip或网络
-p tcp|udp|icmp:ip报文首部定义的协议
--dport:目的端口
--sport:源端口
--tcp-flags LIST1 LIST2:在LIST1给出的标志位中,同属于LIST2的标志位值为1,其余为0,这些标志位有:
SYN, ACK, FIN, RST, PSH, URG
对于icmp协议,后跟 --type-icmp # 通过给定数字表示其报文类型(如0:echo-reply,8:echo-request)
-i INTERFACE:数据报文的流入网络接口,限PREROUTING、INPUT、FORWARD链
-o INTERFACE:数据报文流出的网络接口,限FORWARD、OUTPUT、POSTROUTING链
注:在选项前可使用 ! 表示对匹配条件取反
处理动作相关选项:
-j TARGET:指定对前面匹配条件匹配到的数据报文作何处理,处理动作有:
ACCEPT: 接受
DROP: 丢弃
REJECT: 拒绝
RETURN: 返回调用链
REDIRECT:端口重定向
LOG: 记录日志
MARK:做防火墙标记
DNAT:目标地址转换
SNAT:源地址转换
MASQUERADE:地址伪装
例:(服务器IP:172.27.100.1,以下操作均针对于filter表INPUT链)
# iptables -L -n --line-number #显示filter表中的一些规则信息,并显示规则编号
# iptables -A INPUT ! -s 172.27.94/24 -d 172.27.100.1 -p tcp --dport 22 -j DROP
#除172.27.100网络以外的主机均可连接服务器 tcp/22 号端口
# iptables -I INPUT 1 -s 172.27.200.1 -d 172.27.100.1 -p tcp --dport 22 -j ACCEPT
#允许172.27.200.1连接主机tcp/22端口,并插入到第一条
# iptables -D INPUT 2 #删除第二条规则
注:更改防火墙规则时请确保更改后当前使用使用的远端主机能够正常与服务器通信。
iptables扩展应用:
用法:通常写在匹配条件的最后部分,使用 -m 选项指定扩展类型,紧接着跟上相关条件
扩展类型:
multiport:指定多个端口所用,最多15个
--dports PORT1,PORT2... :指定目标端口
--sports PORT1,PORT2... :指定源端口
--ports PORT1,PORT2... :指定端口,不考虑是目标还是源端口
例:对22,80端口 INPUT 方向放行
# iptables -A INPUT -p tcp -m multiport --dports 22,80 -j ACCEPT
iprange:指明连续的ip
--src-range IP1-IP2:源地址范围从IP1到IP2
--dst-range IP1-IP2:目标地址范围从IP1到IP2
例:仅对172.27.0.0至172.27.0.128开放22,80端口
# iptables -A INPUT -p tcp -m multiport --dports 22,80 -m iprange --src-range 172.27.0.0-172.27.0.128 -j ACCEPT
string:匹配报文中出现的字符串
--algo bm|kmp 指明使用何种字符串匹配算法,必须指定
--string 'STRING':指定匹配字符串
例:对报文中出现video的报文丢弃
# iptables -I OUTPUT -m string --algo bm --string 'video' -j DROP
time:根据报文到达的时间范围匹配
--datestart YYYY-MM-DDThh:mm:ss:起始时间,例:2019-7-1T00:00::00,年之后(不包括年)时间可省
--datestop YYYY-MM-DDThh:mm:ss:结束时间,格式同上
--timestart hh:mm:ss:起始时间,没有年月日,例:12:00:00,时之后(不包括时)的时间值可省
--timestop hh:mm:ss:结束时间,格式同上
--monthdays #,#... :指定在哪些月份
--weekdays #,#... :指定在每周的周几
例:每天凌晨4点至5点拒绝一切访问(INPUT)方向
# iptables -I INPUT 1 -m tim --timstart 4:00:00 --timestop 5:00:00 -j REJECT
connlimit:每个客户端并发连接数量匹配
--connlimit-above #:连接数量大于#
--connlimit-upto #:连接数量小于#
例:对并发连接大于10的请求进行拒绝
# iptables -I INPUT 1 -m connlimit --connlimit-above 10 -j REJECT
limit:收发报文的速率控制
--limit-burst #:空闲后的最大并发速率
--limit #/second|minute|hour|day:限制收发速率每单位时间#个
例:控制icmp接收速率每2秒一次,最大并发5个
# iptables -I INPUT 1 -p icmp --icmp-type 8 -m --limit-burst 5 --limit 30/minute -j ACCEPT
state:根据连接追踪状态进行匹配
--state STATE1,STATE2... :指明哪些状态,常用状态有:
NEW:新发出的请求
ESTABLISHED:已建立连接状态,在NEW状态之后
RELATED:相关的连接,如FTP协议的数据连接要以此来标识与命令连接关联,对其放行
INVALIED:无法识别的连接
例:对已建立连接的TCP 22,80端口放行
# iptables -I INPUT -p tcp -m multiport --dports 22,80 -m state --state ESTABLISHED -j ACCEPT
其他命令:
# iptables-save >/FILE_TO_SAVE:将当前防火墙规则备份至某文件
# iptables-restore </FILE_TO_READ:从某备份文件读取规则并应用
示例
1、仅开放服务器的FTP,SSH,HTTP服务
2、仅允许172.27网段的客户访问主机
3、不允许服务器利用上述服务端口主动连接其他主机
4、尽可能优化规则
# iptables -F #清空规则表
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#允许已建立的链接请求
# iptables -A INPUT -s 172.27.0.0/16 -d 172.27.100.1 -p tcp -m multiport --dports 21,22,80 -m state --state NEW -j ACCEPT
#允许172.27网段的主机通过tcp 21 22 80端口与服务器进行首次连接
# iptables -A OUTPUT -d 172.27.0.0/16 -p tcp -m state --state ESTABLISHED -j ACCEPT
#出口方向仅允许已建立的(22,80端口)链接通过
#说明:虽然出口方向限制仅局域网内已建立的链接可通过,
# 但是对于定义规则之前就已建立的局域网其他非法端口的链接是没有过滤能力的
# modprobe nf_conntrack_ftp
#装载FTP数据连接通过链接追踪方式检测,允许访问服务器所需要的模块
# iptables -P INPUT DROP
# iptables -P OUTPUT DROP
#设置默认策略
补充内容:tcp_wrapper
其实除了防火墙能进行访问控制,对于使用tcp_wrapper的应用程序,能在应用层对访问进行访问控制(调用了 libwrap 动态库的程序均可认为使用了tcp_wrapper,使用ldd命令查看程序调用了哪些库)。
它将允许访问与不允许访问的服务分别写入两个文件中,依次匹配这两个文件定义的内容:
/etc/hosts.allow
/etc/hosts.deny
如未特殊说明,hosts.allow文件定义的服务程序对匹配到的主机默认为允许,hosts.deny文件中定义的服务程序对匹配到的主机默认为拒绝,定义格式如下:
DAEMON_LIST: CLIENT_LIST [:OPTION]
字段解释:
DAEMON_LIST:服务对应的应用程序名称
CLIENT_LIST:客户端,可以是具体IP地址,也可以是网络地址,网络地址格式仅支持如下两种:
172.27.
172.27.0.0/255.255.0.0
注:ALL表示所有主机。此外,还有一个特殊字段:EXCEPT,后面跟上IP地址,表示匹配前面的IP(此时前面通常是网络或者ALL)并且不包括IP,例:
vsftpd: 172.27. EXCEPT 172.27.100.1 #表示匹配172.27网段的主机,但不包括172.27.100.1这台主机,此台主机的允许与否则取决于随后的匹配条目或者hosts.deny文件
OPTION:常用选项有:
allow:允许前面匹配得到的主机访问某服务,用于 hosts.deny文件
deny:拒绝前面匹配得到的主机访问某服务,用于hosts.allow文件
spawn:额外调用某应用程序,如常调用echo进行日志输出
例:/etc/hosts.allow
vsftpd: 172.27. :spawn /bin/echo `date` %c login %s, %d >>/var/log/vsftpd.login
注:%c:客户端地址;%s:服务端地址;%d:应用程序名