iptables 与 firewalld 防火墙

保障数据的安全性是继保障数据的可用性之后最为重要的一项工作。防火墙作为公网
与内网之间的保护屏障,在保障数据的安全性方面起着至关重要的作用。

防火墙管理工具

防火墙策略可以基于流量的源目地址、端口号、协议、应用等信息来定制,然后防火墙使用预先定制的策略规则监控出入的流量,若流量与某一条策略规则相匹配,则执行相应的处理,反之则丢弃。这样一来,就可以保证仅有合法的流量在企业内网和外部公网之间流动了。

在 RHEL 7 系统中,firewalld 防火墙取代了 iptables 防火墙。

iptables

策略与规则链

防火墙会从上至下的顺序来读取配置的策略规则,在找到匹配项后就立即结束匹配工作
并去执行匹配项中定义的行为(即放行或阻止)。如果在读取完所有的策略规则之后没有匹配
项,就去执行默认的策略。一般而言,防火墙策略规则的设置有两种:一种是“通”(即放行),
一种是“堵”(即阻止)。当防火墙的默认策略为拒绝时(堵),就要设置允许规则(通),否则
谁都进不来;如果防火墙的默认策略为允许时,就要设置拒绝规则,否则谁都能进来,防火墙
也就失去了防范的作用。
iptables 服务把用于处理或过滤流量的策略条目称之为规则,多条规则可以组成一个规则
链,而规则链则依据数据包处理位置的不同进行分类,具体如下:
➢ 在进行路由选择前处理数据包(PREROUTING);
➢ 处理流入的数据包(INPUT);
➢ 处理流出的数据包(OUTPUT);
➢ 处理转发的数据包(FORWARD);
➢ 在进行路由选择后处理数据包(POSTROUTING)。
一般来说,从内网向外网发送的流量一般都是可控且良性的,因此我们使用最多的就是 INPUT 规则链,该规则链可以增大人员从外网入侵内网的难度。

但是,仅有策略规则还不能保证社区的安全,保安还应该知道采用什么样的动作来处理
这些匹配的流量,比如“允许”、“拒绝”、“登记”、“不理它”。这些动作对应到 iptables 服务
的术语中分别是 ACCEPT(允许流量通过)、REJECT(拒绝流量通过)、LOG(记录日志信息)、
DROP(拒绝流量通过)。“允许流量通过”和“记录日志信息”都比较好理解,这里需要着重
讲解的是 REJECT 和 DROP 的不同点。就 DROP 来说,它是直接将流量丢弃而且不响应;
REJECT 则会在拒绝流量后再回复一条“您的信息已经收到,但是被扔掉了”信息,从而让流
量发送方清晰地看到数据被拒绝的响应信息

iptables 中基本的命令参数

-P 设置默认策略
-F 清空规则链
-L 查看规则链
-A 在规则链的末尾加入新规则
-I num 在规则链的头部加入新规则
-D num 删除某一条规则

-s 匹配来源地址 IP/MASK,加叹号“!”表示除这个 IP 外
-d 匹配目标地址
-i 网卡名称 匹配从这块网卡流入的数据
-o 网卡名称 匹配从这块网卡流出的数据
-p 匹配协议,如 TCP、UDP、ICMP
–dport num 匹配目标端口号
–sport num 匹配来源端口号

查看规则链

[root@linuxprobe ~]# iptables -L

清空规则链

[root@linuxprobe ~]# iptables -F

在日常运维工作中,经常会使用 ping 命令来检查对方主机是否在线,而向防火墙的
INPUT 规则链中添加一条允许 ICMP 流量进入的策略规则就默认允许了这种 ping 命令
检测行为。

[root@linuxprobe ~]# iptables -I INPUT -p icmp -j ACCEPT
[root@linuxprobe ~]# ping -c 4 192.168.10.10

删除之前一套,将默认策略设置允许

[root@linuxprobe ~]# iptables -D INPUT 1
[root@linuxprobe ~]# iptables -P INPUT ACCEPT
[root@linuxprobe ~]# iptables -L
Chain INPUT (policy ACCEPT)

只允许指定网段访问22端口,其它都拒绝

[root@linuxprobe ~]# iptables -I INPUT -s 192.168.10.0/24 -p tcp --dport 22 -j ACCEPT
[root@linuxprobe ~]# iptables -A INPUT -p tcp --dport 22 -j REJECT
[root@linuxprobe ~]# iptables -L

防火墙策略规则是按照从上到下的顺序匹配的,因此一定要把允许动作放到拒绝动作前面,否则所有的流量就将被拒绝掉,从而导致任何主机都无法访问我们的服务。这里提到的 22 号端口是 ssh 服务使用的

使用 iptables 命令配置的防火墙规则默认会在系统下一次重启时失效,如果
想让配置的防火墙策略永久生效,还要执行保存命令

[root@linuxprobe ~]# service iptables save

问题

  • docker网络iptables被清理导致容器无法访问外网

安装了Docker的机器,暴力执行iptables -F,会导致docker的规则全清,无法重启或者网络访问,暴力方法是重启docker,规则会重新添加进来。

firewalld

RHEL 7 系统中集成了多款防火墙管理工具,其中firewalld(Dynamic Firewall Manager of Linux
systems,Linux系统的动态防火墙管理器)服务是默认的防火墙配置管理工具,它拥有基于CLI(命
令行界面)和基于GUI(图形用户界面)的两种管理方式。

相较于传统的防火墙管理配置工具,firewalld 支持动态更新技术并加入了区域(zone)的
概念。简单来说,区域就是 firewalld 预先准备了几套防火墙策略集合(策略模板),用户可以
根据生产场景的不同而选择合适的策略集合,从而实现防火墙策略之间的快速切换。

firewalld 中常见的区域名称(默认为 public)以及相应的策略规则如下

trusted  允许所有的数据包
home 拒绝流入的流量,除非与流出的流量相关;而如果流量与 ssh、mdns、ipp-client、amba-client 与    dhcpv6-client 服务相关,则允许流量
internal  等同于 home 区域
work 拒绝流入的流量,除非与流出的流量数相关;而如果流量与 ssh、ipp-client 与
dhcpv6-client 服务相关,则允许流量
public 拒绝流入的流量,除非与流出的流量相关;而如果流量与 ssh、dhcpv6-client 服务相关,则允许流量
external  拒绝流入的流量,除非与流出的流量相关;而如果流量与 ssh 服务相关,则允许流量
dmz  拒绝流入的流量,除非与流出的流量相关;而如果流量与 ssh 服务相关,则允许流量
block  拒绝流入的流量,除非与流出的流量相关
drop  拒绝流入的流量,除非与流出的流量相关

基本使用

启动:  systemctl start firewalld
查状态:systemctl status firewalld 
停止:  systemctl disable firewalld
禁用:  systemctl stop firewalld
在开机时启用一个服务:systemctl enable firewalld.service
在开机时禁用一个服务:systemctl disable firewalld.service
查看服务是否开机启动:systemctl is-enabled firewalld.service
查看已启动的服务列表:systemctl list-unit-files|grep enabled
查看启动失败的服务列表:systemctl --failed

firewall-cmd

命令参数

--get-default-zone  查询默认的区域名称
--set-default-zone=<区域名称> 设置默认的区域,使其永久生效
--get-zones  显示可用的区域
--get-services  显示预先定义的服务
--get-active-zones  显示当前正在使用的区域与网卡名称
--add-source=  将源自此 IP 或子网的流量导向指定的区域
--remove-source=  不再将源自此 IP 或子网的流量导向某个指定区域
--add-interface=<网卡名称>  将源自该网卡的所有流量都导向某个指定区域
--change-interface=<网卡名称> 将某个网卡与区域进行关联
--list-all  显示当前区域的网卡配置参数、资源、端口以及服务等信息
--list-all-zones  显示所有区域的网卡配置参数、资源、端口以及服务等信息
--add-service=<服务名>  设置默认区域允许该服务的流量
--add-port=<端口号/协议>  设置默认区域允许该端口的流量
--remove-service=<服务名>  设置默认区域不再允许该服务的流量
--remove-port=<端口号/协议>  设置默认区域不再允许该端口的流量
--reload  让“永久生效”的配置规则立即生效,并覆盖当前的配置规则
--panic-on  开启应急状况模式
--panic-off  关闭应急状况模式

与 Linux 系统中其他的防火墙策略配置工具一样,使用 firewalld 配置的防火墙策略默认
为运行时(Runtime)模式,又称为当前生效模式,而且随着系统的重启会失效。如果想让配

置策略一直存在,就需要使用永久(Permanent)模式了,方法就是在用 firewall-cmd 命令正常
设置防火墙策略时添加–permanent 参数,这样配置的防火墙策略就可以永久生效了。但是,
永久生效模式有一个“不近人情”的特点,就是使用它设置的策略只有在系统重启之后才
能自动生效。如果想让配置的策略立即生效,需要手动执行 firewall-cmd --reload 命令。

firewall-cmd 是 firewalld 防火墙配置管理工具的 CLI(命令行界面)版本

查看状态

#firewall-cmd --state

查看当前使用区域

[root@linuxprobe ~]# firewall-cmd --get-default-zone

启用某个服务

# firewall-cmd --zone=public --add-service=https //临时

# firewall-cmd --permanent --zone=public --add-service=https //永久
# firewall-cmd --reload

开放端口

永久
# firewall-cmd --permanent --zone=public --add-port=8080-8081/tcp 
# firewall-cmd --reload  # 重新加载后才能生效

临时
# firewall-cmd --zone=public --add-port=8080-8081/tcp

查看开启的端口和服务

查看服务
# firewall-cmd --zone=public --list-services
查看端口
# firewall-cmd  --zone=public --list-ports

设置ip 192.168.0.4/24 访问 http

firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.0.4/24" service name="http" accept"

汇总

# 开启防火墙
systemctl start firewalld.service

# 防火墙开机启动
systemctl enable firewalld.service

# 关闭防火墙
systemctl stop firewalld.service

# 查看防火墙状态
firewall-cmd --state

# 查看现有的规则
iptables -nL
firewall-cmd --zone=public --list-ports

# 重载防火墙配置
firewall-cmd --reload

# 添加单个单端口
firewall-cmd --permanent --zone=public --add-port=81/tcp

# 添加多个端口
firewall-cmd --permanent --zone=public --add-port=8080-8083/tcp

# 删除某个端口
firewall-cmd --permanent --zone=public --remove-port=81/tcp

# 针对某个 IP开放端口
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="6379" accept"
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.0.233" accept"

# 删除某个IP
firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.1.51" accept"

# 针对一个ip段访问
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.0.0/16" accept"
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="9200" accept"

# 添加操作后别忘了执行重载
firewall-cmd --reload