[TOC]

0x00 Firewall 快速入门

(1)firewalld简介:
它是Linux上新用的防火墙软件它跟iptables防火墙是差不多的工具但比其更好使用与设置;

firewalld是centos7的一大特性,最大的好处有两个:支持动态更新,不用重启服务;第二个就是加入了防火墙的“zone”概念。
,也提供了支持网络/防火墙区域(zone)定义网络链接以及接口安全等级的动态防火墙管理工具;
在CentOS7.0中默认使用firewall代替了iptables service,使得软防火墙操作更加便利人性化,Firewalld有图形界面和字符命令界面;

firewalld 特点特性:

  • D-BUS 接口提供防火墙状态的信息,使防火墙的启用、停用或查询设置成为可能。
  • 它支持 IPv4, IPv6 防火墙设置以及以太网桥接,并且拥有运行时配置和永久配置选项
  • 区域:网络或者防火墙区域定义了连接的可信程度(加入了防火墙的“zone”区域概念)
  • 服务:服务可以是一系列本读端口、目的以及附加信息,也可以是服务启动时自动增加的防火墙助手模块;
  • ICMP 类型: Internet 控制报文协议 (ICMP) 被用以交换报文和互联网协议 (IP) 的错误报文
  • 直接接口: 主要用于服务或者应用程序增加特定的防火墙规则,即支持允许服务或者应用程序直接添加防火墙规则的接口(都是临时生效)
  • 运行时配置:运行时配置并非永久有效, 支持动态更新重启服务直接reload规则就行
  • 永久配置:永久配置存储在配置文件种,每次机器重启或者服务重启、重新加载时将自动恢复。


firewalld跟iptables比起来至少有两大好处:

  • firewalld可以动态修改单条规则,而不需要像iptables那样,在修改了规则后必须得全部刷新才可以生效。
  • firewalld在使用上要比iptables人性化很多,即使不明白“五张表五条链”而且对TCP/IP协议也不理解也可以实现大部分功能。

Tips:firewalld自身并不具备防火墙的功能,而是和iptables一样需要通过内核的netfilter来实现,即firewalld和 iptables一样都是作用于维护规则,而真正使用规则干活的是内核的netfilter,只不过firewalld和iptables的结构以及使用方法不一样罢了


Q:什么是区域?
网络区域定义了网络连接的可信等级。这是一个一对多的关系意味着一次连接可以仅仅是一个区域的一部分,而一个区域可以用于很多连接。

Q:哪个区域可用?
由firewalld 提供的区域按照从不信任到信任的顺序排序。

  • 丢弃(drop): 任何流入网络的包都被丢弃,不作出任何响应。只允许流出的网络连接。
  • 阻塞(block): 任何进入的网络连接都被拒绝,并返回 IPv4的icmp-host-prohibited报文或者IPv6的icmp6-adm-prohibited报文。只允许由该系统初始化的网络连接。
  • 公开(public): 用以可以公开的部分。你认为网络中其他的计算机不可信并且可能伤害你的计算机。只允许选中的连接接入。
  • 外部(externel): 用在路由器等启用伪装的外部网络。你认为网络中其他的计算机不可信并且可能伤害你的计算机。只允许选中的连接接入。
  • 隔离区(DMZ): 用以允许隔离区(dmz)中的电脑有限地被外界网络访问。只接受被选中的连接。
  • 工作(work): 用在工作网络。你信任网络中的大多数计算机不会影响你的计算机。只接受被选中的连接。
  • 家庭(home): 用在家庭网络。你信任网络中的大多数计算机不会影响你的计算机。只接受被选中的连接。
  • 内部(internal): 用在内部网络。你信任网络中的大多数计算机不会影响你的计算机。只接受被选中的连接。
  • 受信任的(trusted): 允许所有网络连接。

由 NetworkManager 控制的网络连接
描述:防火墙不能够通过 NetworkManager 显示的名称来配置网络连接,只能配置网络接口;
如果在配置文件中没有配置区域,接口将配置到 firewalld 的默认区域。如果网络连接使用了不止一个接口,所有的接口都会应用到 fiwewalld。接口名称的改变也将由 NetworkManager 控制并应用到firewalld。

为了简此网络连接将被用作与区域的关系。

  • 当接口断开NM也告诉Firewall从区域中删除该接口;
  • 当firewalld 启动后将通知NM把网络连接增加到区域


注意事项:

  • 虽然Centos7 继续保留了iptables命令但不能使用,除非手动删除firewall再安装iptables否则不能继续使用以前的iptables配置方法
  • firewall daemon 无法解析由 iptables 和 ebtables 命令行工具添加的防火墙规则
  • 静态防火墙(system-config-firewall/lokkit)与 “守护进程” 不能同时使用

参考文档:https://fedoraproject.org/wiki/FirewallD/zh-cn
官方文档:https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Using_Firewalls.html#sec-Introduction_to_firewalld


(2) firewall安装与启动
默认环境:CentOS Linux release 7.6.1810 (Core)
字符界面管理工具:firewall-cmd
图形界面管理工具:firewall-config

1
2
3
4
5
yum install firewalld firewall-config bash-completion -y # bash-completion使用tab键补全命令提示
systemctl start firewalld.service #启动firewall
systemctl stop firewalld.service #停止firewall
systemctl enable firewalld.service #允许firewall开机启动
systemctl disable firewalld.service #禁止firewall开机启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 命令格式
firewall-cmd [选项 ... ]

通用选项
-h, --help # 显示帮助信息;
-V, --version # 显示版本信息. (这个选项不能与其他选项组合);
-q, --quiet # 不打印状态消息;

状态选项
--state # 显示firewalld的状态;
--reload # 不中断服务的重新加载;
--complete-reload # 中断所有连接的重新加载;
--runtime-to-permanent # 将当前防火墙的规则永久保存;
--check-config # 检查配置正确性;

日志选项
--get-log-denied # 获取记录被拒绝的日志;
--set-log-denied=<value> # 设置记录被拒绝的日志,只能为 'all','unicast','broadcast','multicast','off' 其中的一个;

# 安装验证
firewall-cmd --version #查看版本、帮助
firewall-cmd --help
firewall-cmd --state #查看状态
running


Firewall配置文件以及目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/usr/lib/firewalld/ #系统配置,尽量不要修改
cd /usr/lib/firewalld/services
#该目录中存放的是定义好的网络服务和端口参数,只用于参考不能修改。这个目录中只定义了一部分通用网络服务。
#在该目录中没有定义的网络服务,也不必再增加相关xml定义,后续通过管理命令可以直接增加。

/etc/firewalld/ #用户配置地址
/etc/firewalld/zones/ #此处为配置生效后保存的配置文件,一般建议修改前先备份。


#存储在此的系统或者用户配置文件可以是系统管理员通过配置接口定制的,也可以是手动定制的。这些文件将重载默认配置文件。
#从/usr/bin/firewalld上面目录中将需要使用的服务的xml文件拷至这个目录中,如果端口有变化则可以修改文件中的数值。
$cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>SSH</short>
<description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
<port protocol="tcp" port="22"/>
</service>


(3) firewall-cmd 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#因为 firewalld 动态管理规则集,所以它不会破坏现有的连接和会话。
firewall-cmd --reload #在不改变状态的条件下重新加载防火墙
#如果使用 --complete-reload ,状态信息将会丢失。这个选项应当仅用于处理防火墙问题时,例如,状态信息和防火墙规则都正常,但是不能建立任何连接的情况。

#获取支持的区域列表
$firewall-cmd --get-zones
block dmz drop external home internal public trusted work

#获取所有支持的服务
$firewall-cmd --get-services
#列举区域中启用的服务
firewall-cmd [ --zone=<zone> ] --list-services
firewall-cmd --list-service
ssh dhcpv6-client

#获取所有支持的ICMP类型
$firewall-cmd --get-icmptypes

#默认显示public区域
firewall-cmd [--zone=<zone>] --list-all #被用于默认不指定zone默认为public
firewall-cmd --list-all-zones #列出全部启用的区域的特性
#流入默认区域中配置的接口的新访问请求将被置入新的默认区域。当前活动的连接将不受影响。
#查看与设置默认zone
firewall-cmd --get-default-zone #获取默认区域名称
firewall-cmd --set-default-zone=<zone> # 设置默认区域

#获取活动的区域(zone与接口)
firewall-cmd --get-active-zones
firewall-cmd --get-zone-of-interface=<interface> #根据接口获取区域
firewall-cmd --get-zone-of-interface=ens192
public
#查询区域中是否包含某接口
firewall-cmd [--zone=<zone>] --query-interface=<interface> #返回接口是否存在于该区域。没有输出。
firewall-cmd --query-interface=ens192
yes

#将接口增加到区域
#如果接口不属于区域接口将被增加到区域。
#如果区域被省略了将使用默认区域接口在重新加载后将重新应用。
firewall-cmd [--zone=<zone>] --add-interface=<interface>

#修改接口所属区域
firewall-cmd [--zone=<zone>] --change-interface=<interface>
#这个选项与 --add-interface 选项相似,但是当接口已经存在于另一个区域的时候,该接口将被添加到新的区域。

#从区域中删除一个接口
firewall-cmd [--zone=<zone>] --remove-interface=<interface>


#启用应急模式阻断所有网络连接,以防出现紧急状况
firewall-cmd --panic-on #在 0.3.0 之前的 FirewallD版本中, panic 选项是 --enable-panic 与 --disable-panic.
firewall-cmd --panic-off #禁用应急模式
firewall-cmd --query-panic #查询应急模式

firewall-cmd --permanent [运行时区域] #将永久生效


(4)处理运行时区域
注意:运行时模式下对区域进行的修改不是永久有效的,重新加载或者重启后修改将失效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#启用区域中的一种服务
#如果未指定区域将使用默认区域。
#如果设定了超时时间,服务将只启用特定秒数。
#如果服务已经活跃,将不会有任何警告信息。
firewall-cmd [--zone=<zone>] --add-service=<service> [--timeout=<seconds>]
firewall-cmd --zone=home --add-service=ipp-client --timeout=60 #使区域中的 ipp-client 服务生效60秒:

#禁用区域中的某种服务
firewall-cmd [--zone=<zone>] --remove-service=<service>
firewall-cmd --zone=home --remove-service=http


#查询区域中是否启用了特定服务
firewall-cmd [--zone=<zone>] --query-service=<service>


#启用区域端口和协议组合
#此举将启用端口和协议的组合。端口可以是一个单独的端口 <port> 或者是一个端口范围 <port>-<port> 。协议可以是 tcp 或 udp。
firewall-cmd [--zone=<zone>] --add-port=<port>[-<port>]/<protocol> [--timeout=<seconds>]
#禁用端口和协议组合
firewall-cmd [--zone=<zone>] --remove-port=<port>[-<port>]/<protocol>
#查询区域中是否启用了端口和协议组合
firewall-cmd [--zone=<zone>] --query-port=<port>[-<port>]/<protocol>

#启用区域中的 IP 伪装功能
#私有网络的地址将被隐藏并映射到一个公有IP是地址转换的一种形式,常用于路由。由于内核的限制,伪装功能仅可用于IPv4
firewall-cmd [--zone=<zone>] --add-masquerade
firewall-cmd [--zone=<zone>] --remove-masquerade # 禁用区域中的 IP 伪装
firewall-cmd [--zone=<zone>] --query-masquerade #查询区域的伪装状态


#启用区域的 ICMP 阻塞功能
#此举将启用选中的 Internet 控制报文协议 (ICMP) 报文进行阻塞。 ICMP 报文可以是请求信息或者创建的应答报文,以及错误应答。
firewall-cmd [--zone=<zone>] --add-icmp-block=<icmptype> #[echo-request和echo-reply]
firewall-cmd [--zone=<zone>] --remove-icmp-block=<icmptype> #禁止区域的 ICMP 阻塞功能
firewall-cmd [--zone=<zone>] --query-icmp-block=<icmptype> #查询区域的 ICMP 阻塞功能


#在区域中启用端口转发或映射
#端口可以映射到另一台主机的同一端口,也可以是同一主机或另一主机的不同端口。端口号可以是一个单独的端口 <port> 或者是端口范围 <port>-<port> 。协议可以为 tcp 或udp 。目标端口可以是端口号 <port> 或者是端口范围 <port>-<port> 。目标地址可以是 IPv4 地址。受内核限制,端口转发功能仅可用于IPv4。
firewall-cmd [--zone=<zone>] --add-forward-port=port=<port>[-<port>]:proto=<protocol> { :toport=<port>[-<port>] | :toaddr=<address> | :toport=<port>[-<port>]:toaddr=<address> }

#禁止区域的端口转发或者端口映射
firewall-cmd [--zone=<zone>] --remove-forward-port=port=<port>[-<port>]:proto=<protocol> { :toport=<port>[-<port>] | :toaddr=<address> | :toport=<port>[-<port>]:toaddr=<address> }

#查询区域的端口转发或者端口映射
firewall-cmd [--zone=<zone>] --query-forward-port=port=<port>[-<port>]:proto=<protocol> { :toport=<port>[-<port>] | :toaddr=<address> | :toport=<port>[-<port>]:toaddr=<address> }

#例: 将区域 home 的 ssh 转发到 127.0.0.2 使其能进行连接
firewall-cmd --zone=home --add-forward-port=port=22:proto=tcp:toaddr=127.0.0.2


(5)直接选项
直接选项主要用于使服务和应用程序能够增加规则,规则不会被保存在重新加载或者重启之后必须再次提交。
传递的参数 < args > 与 iptables, ip6tables 以及 ebtables 一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#将命令传递给防火墙。
firewall-cmd --direct --passthrough { ipv4 | ipv6 | eb } <args>

# 为表 <table> 增加一个新链 <chain> 。
firewall-cmd --direct --add-chain { ipv4 | ipv6 | eb } <table> <chain>
--remove-chain #从表 <table> 中删除链 <chain> 。 参数同上
--query-chain #查询 <chain> 链是否存在与表 <table>. 如果是,返回0,否则返回1. 参数同上
#获取用空格分隔的表 <table> 中链的列表。
firewall-cmd --direct --get-chains { ipv4 | ipv6 | eb } <table>


#为表 <table> 增加一条参数为 <args> 的链 <chain> ,优先级设定为 <priority>。
firewall-cmd --direct --add-rule { ipv4 | ipv6 | eb } <table> <chain> <priority> <args>
#从表 <table> 中删除带参数 <args> 的链 <chain>。
firewall-cmd --direct --remove-rule { ipv4 | ipv6 | eb } <table> <chain> <args>
firewall-cmd --direct --query-rule { ipv4 | ipv6 | eb } <table> <chain> <args> #查询 带参数 <args> 的链 <chain> 是否存在表 <table> 中
#获取表 <table> 中所有增加到链 <chain> 的规则,并用换行分隔。
firewall-cmd --direct --get-rules { ipv4 | ipv6 | eb } <table> <chain>


(6)命令行配置富规则

1
2
3
4
5
#查看富规则
firewall-cmd --list-rich-rules

#创建富规则
firewall-cmd --add-rich-rule 'rule family=ipv4 source address=源地址 service name=服务名称 log prefix="fpt" level=info accept' --permannet


0x01 Firewall实例

1.ICMP禁Ping机器与启动ping通信:

1
2
3
4
5
6
7
8
#禁ping 方法规则
firewall-cmd --permanent --add-rich-rule='rule protocol value=icmp drop'

#查看是否有此规则
firewall-cmd --query-rich-rule='rule protocol value='icmp' drop'

#开启pin(临时生效) - 删除方法
firewall-cmd --remove-rich-rule='rule protocol value=icmp drop'

WeiyiGeek.禁ping

WeiyiGeek.禁ping


2.对于服务的开发与停止在 FirewallD 的服务名称暂时开放ftp或者ssh服务

1
2
3
4
5
6
7
8
9
10
11
firewall-cmd --zone=public --add-service=ftp --permanent     # 永久开放 ftp 服务
firewall-cmd --remove-service=ftp --permanent # 永久关闭服务
firewall-cmd --zone=public --remove-service=ssh --permanent #从public区域中移除服务
firewall-cmd --zone=public --add-service=ssh --permanent
firewall-cmd --reload #最后生效配置(必须执行):
firewall-cmd --query-service ftp # 查询服务的启用状态
no
firewall-cmd --zone=public --query-service=ssh #查询是不是开放成功:
yes
#删除ssh服务允许通过firewalld防火墙(由于我正在使用远程ssh所以不关闭对ssh流量的通过)
firewall-cmd --zone=public --remove-service=ssh --permanent

WeiyiGeek.开放服务

WeiyiGeek.开放服务


3.查看所有开放端口服务配置信息(默认public区域),查看public区域中所有打开的端口:

1
2
$firewall-cmd --zone=public --list-all
$firewall-cmd --zone=public --list-ports

WeiyiGeek.区域信息查看

WeiyiGeek.区域信息查看


4.添加接口到区域和设置更改区域的接口

1
2
3
4
$firewall-cmd --get-active-zones 查看区域信息(公共接口): 
$firewall-cmd --get-zone-of-interface=eth0 #查看指定接口的所属区域:
$firewall-cmd --zone=public --add-interface=eth0 #永久生效再加上 --permanent 然后reload防火墙
$firewall-cmd --zone=internal --change-zone=p3p1 #所属的zone为internal区域,临时修改接口为p3p1

WeiyiGeek.区域接口

WeiyiGeek.区域接口


5.查询包拒绝状态,以及更新防火墙规则(及重新加载配置,不用重启服务:)

1
2
3
4
5
6
7
8
9
10
11
#如果是远程的机器执行上面的规则会立刻断开网络连接,必须紧记不能随便执行。如果你只是虚拟机或者物理机器登陆就可以执行来调试。
firewall-cmd --query-panic
#拒绝所有包:
firewall-cmd --panic-on
#取消拒绝状态:
firewall-cmd --panic-off

#下面更新防火墙参数两者的区别就是第一个无需断开连接就是firewalld特性之一动态添加规则,第二个需要断开连接类似重启服务
firewall-cmd --reload #动态添加规则
firewall-cmd --complete-reload #会重启服务
service firewalld restart


  1. 指定开放端口和协议并关闭
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    firewall-cmd --zone=public --add-port=80/tcp --permanent #永久生效没有permanent参数重启后失效
    firewall-cmd --reload #重新载入配置生效

    #查看是否添加成功
    firewall-cmd --zone=public --query-port=80/tcp #查看指定的端口的开放情况
    $firewall-cmd --zone=public --list-ports #查看全部开放端口
    80/tcp
    firewall-cmd --zone=public --remove-port=80/tcp --permanent #移除允许的端口,删除80端口TCP流量通过许可

    #也能添加一个范围的端口
    firewall-cmd --zone=public --add-port=4990-4999/udp #添加4990-4999 udp端口


  1. 流量转发:端口转发可以将指定地址访问指定的端口时,将流量转发至指定地址的指定端口,转发的目的如果不指定 ip 的话就默认为本机;如果指定了 ip 却没指定端口,则默认使用来源端口
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # vi/etc/sysctl.conf 把net.ipv4.ip_forward=0改成net.ipv4.ip_forward=1
    sed -i '/net.ipv4.ip_forward/ s/\(.*= \).*/\11/' /etc/sysctl.conf

    # (1) 将同一台服务器上80端口的流量转发至8080
    firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080
    #如果要将端口转发到另外一台服务器上,在需要的区域中激活 masquerade
    firewall-cmd --zone=public --add-masquerade

    # (2) 例子中是将本地的80端口的流量转发到IP地址为:10.0.10.15 的远程服务器上的8080端口。
    firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=10.0.10.15

    # (3)
    firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080 # 将80端口的流量转发至8080
    firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.0.1 # 将80端口的流量转发至192.168.0.1
    firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.0.1:toport=8080 # 将80端口的流量转发至192.168.0.1的8080端口

如果配置好端口转发之后不能用,可以检查下面两个问题:

  • 比如我将 80 端口转发至 8080 端口,首先检查本地的 80 端口和目标的 8080 端口是否开放监听了
  • 其次检查是否允许伪装 IP,没允许的话要开启伪装 IP

补充说明:

  • 当我们想把某个端口隐藏起来的时候,就可以在防火墙上阻止那个端口访问,然后再开一个不规则的端口,之后配置防火墙的端口转发,将流量转发过去。
  • 端口转发还可以做流量分发,一个防火墙拖着好多台运行着不同服务的机器,然后用防火墙将不同端口的流量转发至不同机器。


  1. 伪装IP
    防火墙可以实现伪装IP的功能,下面的端口转发就会用到这个功能。
    1
    2
    3
    firewall-cmd --query-masquerade    # 检查是否允许伪装IP 
    firewall-cmd --add-masquerade # 允许防火墙伪装IP
    firewall-cmd --remove-masquerade # 禁止防火墙伪装IP


  1. rich-rule的规则的定义
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #添加拒绝某个IP访问ssh端口。
    firewall-cmd --add-rich-rule "rule family=ipv4 source address=10.0.10.1 service name='ssh' reject"
    # rule :规则
    # family:ipv4 指定ipv4的地址
    # source address=10.0.10.1 要拒绝的IP,可以是IP或者是IP段
    # service name=’ssh’指定的是ssh服务
    # drop :就是此条规则的执行方法是丢弃

    #我更喜欢直接丢弃:
    firewall-cmd --add-rich-rule "rule family=ipv4 source address=10.0.10.1 service name='ssh' drop"
    firewall-cmd --add-rich-rule='rule family=ipv4 source address=10.0.10.1 port port=22 protocol=tcp reject'

    #表示允许来自此IP允许通过防火墙
    firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.10.1" accept'

    #允许一个IP(10.0.10.1)仅能通过指定端口(8080-8090)访问到目标(10.0.10.13):
    firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.10.1" destination address="10.0.10.13/32" port port="8080-8090" protocol="tcp" accept'

    #移除规则相对麻烦些
    firewall-cmd --remove-rich-rule='rule family="ipv4" source address="10.0.10.1" destination address="10.0.10.13/32" port port="80" protocol="tcp" accept'

    #允许管理员在172.31.1.2主机通过ssh远程管理内网的192.168.31.83主机(所用端口为23456)
    firewall-cmd --add-rich-rule 'rule family=ipv4 source address=172.31.1.2 forward-port port=23456 protocol=tcp to-port=10211 to-addr=192.168.31.83' --permanent --zone=external


  1. 直接模式
    1
    2
    3
    # FirewallD包括一种直接模式,使用它可以完成一些工作,例如打开TCP协议的9999端口
    firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 9000 -j ACCEPT
    firewall-cmd --reload