7.1. 介绍
防火墙(Firewall),也称防护墙,是由Check Point创立者Gil Shwed于1993年发明并引入国际互联网(US5606668(A)1993-12-15)。
它是一种位于内部网络与外部网络之间的网络安全系统。一项信息安全的防护系统。按照给定的规则,允许或者限制网络报文通过。
本次课程重点介绍通过iptables工具添加“规则”, (主机防火墙由用户态iptables工具+内核态netfilter模块实现)
TcpWrapper 也可以达到“允许或是限制网络报文通过”的目标。一般称作轻量级防火墙,应用简单。
7.2. Iptables 主机防火墙
先看几个概念
7.2.1. 4表5链N规则
- 基本概念
我们先看, 当客户端浏览器访问web服务器时, 一个客户端的数据报文和服务器的交互流程可简单如下图所示:
为了使防火墙达到“防火”(包过滤)的目的, 我们需要在数据报文流经的路径上,设置一下关卡: 所有进出的报文都流经这些关卡, 在“关卡”上设置“条件”, 报文经检查后,符合放行条件的才放行, 符合阻拦条件的报文被阻止。
这些关卡,在iptables中称之为链, 这些条件,我们称之为规则, 所谓的配置防火墙,就是在相应的链中添加规则。
-
5链
所谓5链, 就是linux系统设置了5道关卡,分别对应于: “输入”(INPUT)、“输出”(OUTPUT)、“路由前”(PREROUTING)、“转发”(FORWARD)、“路由后”(POSTROUTING)
一个数据报文的完整场景如下图所示:
根据实际的场景,数据报文的流向:
(外网)到本机的报文: PREROUTING -> INPUT
由本机(路由器)转发的报文: PREROUTING -> FORWARD -> POSTROUTING
本机进程发出的报文: OUTPUT -> POSTROUTING
-
链和规则的关系
我们把“关卡”称之为链, 在关卡中我们设置规则, 还可以设置多条规则, 当我们把多条规则串到一起的时候,就形成了链。
防火墙的作用呢,就是对经过的报文匹配“规则”, 然后执行对应的操作(放行、阻拦)
-
4表
表, 为了实现特定的功能,需要在几个不同的关卡中配置相应的规则,这几个不同关卡就合称表。
系统内置4个表:
filer: 数据包过滤, INPUT、FORWARD、OUTPUT
nat: 网络地址转换(映射),PREROUTING、INPUT、OUTPUT、POSTROUTING
managle: 报文拆解,修改报文并重新封装:PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
raw:关闭链接追踪机制等:PREROUTING、INPUT、OUTPUT
(新版内核中增加内置表 security)
- 4表-5链-规则总结
表、链、 规则之间的关系,见下图
7.2.2. iptables基本用法
添加一条规则的写法
格式: iptables [-t table] COMMAND chain CRETERIA -j TARGET
-
-t table : 4表, 默认filter
- filter
- nat
- ...
-
COMMAND:定义如何对规则进行管理
- ...
-
chain: 指定链
- PREROUTING
- INPUT
- FORWARD
- OUTPUT
- POSTROUTING
-
CRETERIA: 指定匹配准则(ip、协议、端口)
- ...
-
-j TARGET :指定如何进行处理 (DROP or ACCEPT)
- ACCEPT 允许防火墙接收数据包
- DROP 防火墙丢弃包
实例:不允许192.168.16.35 访问我的主机
itcast@itcast $iptables -t filter -A INPUT -s 192.168.16.35 -j DROP
7.2.2.1. COMMAND详解
-
规则查看 -L
- 基本格式:
iptables [-t table] -L
- 基本格式:
itcast@itcast $ sudo iptables -t filter -L -n # -n, 以点分10进制显示filter表的IP地址
itcast@itcast $ sudo iptables -t filter -L --line-numbers # --line-numbers, 显示filter表中规则的行号
-
配置默认策略 -P
- 基本格式:`iptables [-t table] -P chain (DROP|ACCEPT)`
itcast@itcast $ sudo iptables -t filter -P INPUT DROP #配置filter表,INPUT链默认规则为DROP
-
追加规则
- 基本格式:
iptables [-t table] -A chain CRETIRIA -j ACTION
以禁止访问外网web界面为列
- 基本格式:
# 添加规则
itcast@itcast $ sudo iptables -t filter -A OUTPUT -p tcp --dport 80 -j DROP
-
删除规则
- 基本格式:
iptables [-t table] -D chain NUM
- 基本格式:
# 删除规则
itcast@itcast $ sudo iptables -t filter -L OUTPUT --line-number #获取num
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- anywhere anywhere tcp dpt:http
itcast@itcast $ sudo iptables -t filter -D OUTPUT 1 #删除
itcast@itcast $ sudo iptables -t filter -D OUTPUT -p tcp --dport 80 -j DROP # 也是删除
itcast@itcast $ sudo iptables -t filter -L OUTPUT --line-number #查看
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
- 插入规则
- 基本格式:
iptables [-t table] -R NUM chain CRETIRIA -j ACTION
- 基本格式:
# 插入规则
itcast@itcast $ sudo iptables -t filter -A OUTPUT -p tcp --dport 81 -j DROP
itcast@itcast $ sudo iptables -t filter -L OUTPUT --line-number
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- anywhere anywhere tcp dpt:81
itcast@itcast $ sudo iptables -t filter -I OUTPUT 1 -p tcp --dport 82 -j DROP #插入
itcast@itcast $ sudo iptables -t filter -L OUTPUT --line-number
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- anywhere anywhere tcp dpt:82 # 82在前
2 DROP tcp -- anywhere anywhere tcp dpt:81
itcast@itcast $ sudo iptables -t filter -A OUTPUT -p tcp --dport 83 -j DROP ##追加
itcast@itcast $ sudo iptables -t filter -L OUTPUT --line-number
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- anywhere anywhere tcp dpt:82
2 DROP tcp -- anywhere anywhere tcp dpt:81
3 DROP tcp -- anywhere anywhere tcp dpt:83 ##83在后
- 清空规则 -F
- 基本格式:
iptables [-t table] -F chain
- 基本格式:
#清空filter表中的OUTPUT链
itcast@itcast $ sudo iptables -t filter -F OUTPUT
# 清空filter中的所有链
itcast@itcast $ sudo iptables -t filter -F
7.2.2.2. CRETERIA详解
“条件”的匹配模式很多,我们介绍两类,一类是基于IP的匹配条件,一类是基于协议的匹配条件
-
基于IP的匹配
基于IP匹配,就是以源地址、目标地址为匹配条件的匹配
-
-s 指定作为源地址匹配
- IP : 192.168.16.35
- IP/MASK: 192.168.16.0/24
-
-d 表示匹配目标地址
-
-
基于协议匹配
-
-p tcp :TCP协议, 可带三种扩展
- --dport XX-XX:指定目标端口,
- --dport 21 指定单个端口,
- --dport 21-23 (此时表示21,22,23) --sport:指定源端口
-
-p udpUDP协议, 支持两种扩展
- --dport
- --sport
-
-p icmp: icmp数据报文, 支持一种扩展
- --icmp-type: 指定icmp类型
- --icmp-type echo-request : 也可以用 --icmp-type 8
-
-
基于网络设备接口的匹配
-
-i eth0:从这块网卡流入的数据
- 流入一般用在INPUT和PREROUTING上
-
-o eth0:从这块网卡流出的数据
- 流出一般在OUTPUT和POSTROUTING上
-
- 综合实例: 只要是来自于172.16.0.0/16网段的都允许访问我本机的172.16.100.1的SSHD服务
#定义进来的:
iptables -t filter -A INPUT -s 172.16.0.0/16 -d 172.16.100.1 -p tcp --dport 22 -j ACCEPT
#定义出去的:
iptables -t filter -A OUTPUT -s 172.16.100.1 -d 172.16.0.0/16 -p tcp --dport 22 -j ACCEPT
`
7.2.3. 牛刀小试
7.2.3.1. ssh远程登录实战
ssh服务端
# 允许接受ssh客户请求
itcast@itcast $ sudo iptables -t filter -A INPUT -p tcp -dport 22 -j ACCEPT
# 允许发送本地主机的SSH相应
itcast@itcast $ sudo iptables -t filter -A OUTPUT -p tcp -sport 22 -j ACCEPT
# 禁止接受ssh客户请求
itcast@itcast $ sudo iptables -t filter -A INPUT -p tcp -dport 22 -j DROP
ssh客户端 (禁止通过ssh访问某主机, 是防止成为“跳板机”)
# 允许发送向远程主机的SSH请求
iptables -A OUTPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
# 禁止发送向远程主机的SSH请求
iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j DROP
# 接收的数据包源端口为22
$ iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
-m state: 启用状态匹配模块(state matching module)
–-state: 状态匹配模块的参数。 当SSH客户端第一个数据包到达服务器时,状态字段为NEW;建立连接后数据包的状态字段都是ESTABLISHED
7.2.3.2. Web服务实战
服务端
# 允许接收远程主机的HTTP请求
$ iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
# 允许发送本地主机的HTTP响应
$ iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
# 允许特定IP访问
iptables -A INPUT -s 172.16.100.1 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
浏览器端
禁止当前主机访问IP为xxx的web服务
iptables -A OUTPUT -d 10.01.10.23 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j DROP
7.2.3.3. ping attack防护
ping attack 一般两种类型, 一种是向目标主机发送ping命令测试数据包时,目标主机都需要耗费一定的系统资源进行应答回复(DOS), 还有一种是通过把报文分割成片段,向目标主机发送大于65536字节的ICMP包,而后在目标主机上重组, 最终导致目标主机缓冲区溢出,发生瘫痪故障。
简单而有效的防护措施,在防火墙过滤到ICMP报文。
ping 发送echo-request (ICMP type 8), 如目标主机在线存活, 则接受到echo-replay (icmp type 0)
服务器端
禁止其他主机,ping 当前主机
iptables -A INPUT -p icmp --icmp-type 8 -j DROP
iptables -A OUTPUT -p icmp --icmp-type 0 -j DROP
允许其他主机ping当前主机
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
客户端
禁止ping其他主机
iptables -A OUTPUT -p icmp --icmp-type echo-request -j DROP
iptables -A INPUT -p icmp --icmp-type echo-reply -j DROP
小扩展:对于127.0.0.1比较特殊,我们需要明确定义它
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
7.2.4. 拓展知识
7.2.4.1. 规则保存和恢复
我们之前添加的防火墙规则, 当系统重启的时候都会失效。 因此系统重启后,需要有个防火墙规则恢复的操作。
- 关机前,保存当前防火墙规则
itcast@itcast $ pwd
/home/itcast
itcast@itcast $ sudo iptables-save > ./iptables.rules
- 开机后,恢复之前保存的防火墙规则
itcast@itcast $ sudo iptables-restore < /home/itcast/iptables.rules
7.2.4.2. 规则的生效顺序
规则的次序非常关键,谁的规则越严格,应该放的越靠前,而检查规则的时候,是按照从上往下的方式进行检查的。
-
牢记以下三点式理解iptables规则的关键:
- Rules包括一个条件和一个目标(target)
- 如果满足条件,就执行目标(target)中的规则或者特定值。
- 如果不满足条件,就判断下一条Rules。
- 如果全部Rules都不匹配, 则执行默认Target (系统默认ACCEPT)
-
将默认策略改成DROP:
$ iptables -P INPUT DROP
$ iptables -P OUTPUT DROP
$ iptables -P FORWARD DROP
7.2.4.3. 帮助
-
Iptables 帮助
- man iptables
- man iptables-externsion
7.3. TCP Wrapper: 轻量级的防火墙应用
tcp wrappers为那些链接libwrap.so库的服务,提供了 由xinetd这支superdaemon管理的服务提供了安全性。由xinetd super daemon管理的服务以及支持libwrap模块的服务都可以使用它tcp wrappers进行安全控制。
可以通过使用tcp wrappers结合防火墙(iptables)提供更加安全的系统保护。
7.3.1. tcp wrappers的配置
7.3.1.1. 配置文件
tcp wrappers的配置文件有两个,一个是/etc/hosts.allow,一个是/etc/hosts.deny。
-
/etc/hosts.allow:允许指定的客户端对指定的服务访问。
-
/etc/hosts.deny:拒绝指定的客户端对指定的服务访问。
修改完成之后,不需要重新启动服务,就会立即生效。
配置规则的有效次序
- 默认策略是允许 (即没有在hosts.allow和hosts.deny中出现的,允许通过。)
- 先查看hosts.allow
- 再查看hosts.deny。
7.3.1.2. 文件配置规则
每一个控制文件都可以包含多行,按照定义的顺序处理每一行,找到匹配后就跳出该规则。
以#开始的表示注释,
如果一行写不完可以使用反斜线(\),进行续行,表示上一行的延续。
hosts.allow和hosts.deny定义格式如下:
daemon_list : client_list [ : shell_command ]
- daemon_list: 指定由TCP wrappers需要控制的服务名称。比如 sshd, 如果该服务是由xinetd管理的服务,要写启动脚本的名称,如/etc/xinetd.d/telnet。
下述为tftp服务的配置文件:/etc/xinetd.d/tftp
如果要想使用tcp wrappers控制tftp的话,需要在hosts.allow或hosts.deny文件中,写上tftp的启动脚本:/use/sbin/in.tftpd
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
-
- client_list:指定tcpwrappers需要控制哪些客户端对哪些服务的访问。
可以用如下方法表示:
-
单一主机:192.168.0.1,表示的是192.168.0.1这台主机。
-
指定网段:192.168.0.或者是192.168.0.0/255.255.255.0表示的是192.168.0.0/24整个网段。
-
指定DNS后缀:.frame.com,所有DNS后缀为.frame.com的主机。
-
指定FQDN:server.frame.com ,表示的是FQDN为server.frame.com的主机。
-
所有客户端:ALL
7.3.2. 牛刀小试
一般就是通过"白名单制度", 就是在hosts.deny中禁止所有的client访问,在hosts.allow中,开启允许访问的client
7.3.2.1. ssh防护实战
- 允许 192.168.16.3访问
$ cat /etc/hosts.allow
sshd:192.168.16.3
$ cat /etc/hosts.deny
ALL: ALL
- 允许172.16.0.0/16 网段访问sshd服务(放行sshd服务)
$ cat /etc/hosts.allow
sshd:172.16.0.0/16
$ cat /etc/hosts.deny
ALL: ALL
### 确认服务是否支持tcp wrappers ###
> 不是所有的服务,都支持tcp wapper, 只有链接了libwrap.so库的服务,才可以通过tcpwrapper防护。
确认ssh是否支持tcp warpper
```bash
$ ldd /usr/sbin/sshd | grep "wrap"
libwrap.so.0 => /lib/x86_64-linux-gnu/libwrap.so.0 (0x00007fe251bed000)
上述表明sshd这个服务是支持tcp wrappers的。如果没有libwrap,则表示该服务不支持tcp wrappers。
确认xinet是否支持tcp warpper
[root@test01 ~]# ldd $(which sshd) | grep libwrap
libwrap.so.0 => /lib64/libwrap.so.0 (0x00007fa039d12000)
确认inetd是否支持tcp warpper
$ ldd /usr/sbin/tcpd | grep wrap
libwrap.so.0 => /lib/x86_64-linux-gnu/libwrap.so.0 (0x00007f23d5f4b000)
`
7.3.3. 帮助
-
TcpWrappers帮助
- man hosts_access (or man hosts.allow)
- man hosts_options
- man tcpd