Linux内核防火墙工作原理

介绍

Linux内核防火墙提供的防火墙功能通过netfilter框架实现,并提供了IPtables、Firewalld工具配置和修改防火墙的规则。
Netfilter是一个安全框架,可以实现包过滤,NAT(net addr trans 网络地址转换),网络连接跟踪等功能。
Netfilter是防火墙真正的安全框架,位于内核空间当中
Netfilter的通用框架不依赖于具体的协议,而是为每种网络协议定义一套钩子函数。这些钩子函数在数据包经过协议栈的几个关键点时被调用,在这几个点中,协议栈将数据包及钩子函数作为参数,传递给netfilter框架。
对于每种网络协议定义的钩子函数,任何内核模块都可以对每种协议的一个或多个钩子函数进行注册,实现连接。这样当某个数据包被传递给netfiler框架的时候,内核能检测到是否有有关模块对该协议和钩子函数进行了注册。如果发现注册信息,就调用该模块注册时使用的回调函数,然后对应模块取检查、修改、丢弃该数据包及指示netfilter将该数据包传入用户空间的队列。

netfilter的体系结构

在IPV4中有5个HOOK点,我们称为钓鱼点,因为在这些地方,可以设置钩子函数(鱼钩)来获取符合条件的数据包(鱼)。
5个HOOK点

HOOK点 说明 函数位置 应用举例
NF_IP_PRE_ROUTING 网络数据包进入系统,经过简单的检测后,数据包转交给该函数进行处理,然后根据系统设置的规则进行处理,如果数据包不被丢弃则交给路由函数进行处理。在该函数中可以替换IP包的目的地址,即DNAT

由网卡传入主机的数据包,在没有经过IP层路由之前,会先经过这个点 | ip_rcv() |
过滤拒绝服务攻\NAT\计算 | | NF_IP_LOCAL_IN | 所有发送给本机的数据包都要通过该函数进行处理,该函数根据系统设置的规则对数据包进行层处理,如果数据包不被丢弃则交给本地的应用程序

经过路由选择,要进入本机的数据包,会经过这个点 | ip_local_deliver()
在此处可进行碎片重组 | 防火墙过滤进入本机的包 | | NF_IP_FORWARD | 所有不是发送给本机的数据包都要通过该函数进行处理,该函数根据系统设置的规则对数据包进行处理,如果数据包不被丢弃则转至NF_IP_POST_ROUTING进行处理。

经过路由,不是发往本机的包,需要向外发送,会经过这个点 | ip_forward()
之后进入ip_send() | | | NF_IP_LOCAL_OUT | 所有从本地应用程序出来的数据包必须通过该函数进行处理,该函数根据系统设置的规则对数据包进行处理,如果数据包不被丢弃则交给路由函数进行处理

本机发往外部的数据包在经过路由之前会经过这个点 | ip_build_and_send_pkt()
ip_queue_xmit()
ip_build_xmit_slow()
ip_buid_xmit()
不同的上层协议会走不同的流程 | 防火墙过滤外发的数据包 | | NF_IP_POST_ROUTING | 所有数据包在发送给其他主机之前需要通过该函数进行处理,该函数根据系统设置的规则对数据包进行处理,如果数据包不被丢弃,则将数据包发送给数据链路层。在该函数中可以替换IP包的源地址,即SNAT。

本机发送出去的包,在路由后会经过此点 | ip_finish_output() | 包计数功能实现 |

image.png

包过滤

每个函数都可以对数据包进行处理,最基本的操作是对数据包进行过滤。
可以通过iptables工具来向内核模块注册多个过滤规则,并且指明过滤规则的优先级。
包过滤操作:

操作 说明
NF_ACCEPT 继续正常的传递包
NF_DROP 丢弃包,停止传包
NF_STOLEN 已经接管了包,不要继续传送
NF_QUEUE 排列包
NF_REPEAT 再次使用该钩子

包选择

在netfilter框架中已经创建了一个包选择系统,这个包选择系统默认注册了3个表
分别是过滤表filter表、网络地址转换NAT表和Mangle表
image.png

IPtables

介绍

用户空间的客户端代理,将用户空间的安全设定通过代理执行到Netfilter中,所以能够实现的是软件防火墙

Netfilter和IPtables

  • Netfilter ——内核空间;是真正去实现软件防火墙功能
  • iptables—— 用户空间;是一个用户空间的客户端代理软件

  • Netfilter+IPTABLES组成linux平台下的包过滤防火墙(免费)

Netfilter是Linux操作系统核心层的一个数据包处理模块,IPTABLES没有守护进程,所以它不是一个服务,而是内核提供的功能:

  1. - 网络地址转换
  2. - 数据包内容修改
  3. - **数据包过滤的防火墙功能**

Iptables 基础

  • Iptables 根据它的rule进行匹配,对匹配到的规则的数据包进行action

    • accept(接收)、reject(拒绝)、drop(丢弃)
  • rule存储在内核空间的信息过滤表中,这些规则包括:SIP(源地址) DIP(目的地址) 传输协议 (tcp udp ICMP等)和服务类型(http ftp等)

  • Netfiller位于内核空间中,所有Iptables+Netfiller可以在内核空间中设置关卡,当用户去访问应用服务的时候,数据包时通过网卡流经内核空间之后到达用户空间。
  • 当一个主机接收到一个数据包的时候。Netfilter 怎么工作?

    - Netfilter 位于内核空间,是真正的防火墙,规则设置在Input和Output上
    - 网卡驱动是在内核空间中,Netfilter也是在内核空间中,是由iptables+Netfilter
    - 内核空间可以在内核空间设置“关卡”,
    - 当用户去访问应用服务的时候,数据包通过网卡,经过内核空间流入到用户空间
       - A:路由前 prerouting
       - B:转发   forward
       - C:路由后  postouting
    
  • 如果我们需要报文转发,不经过input链和output链

只需要:prerouting链,forward链,postrouting链

     - Input链和output链 :作用域数据包用户空间和内核空间的流入流出
     - preouting链 forward链 postouing链 :在内核空间中关于数据包的流入流出及转发
        - preouting链![image.png](https://cdn.nlark.com/yuque/0/2020/png/407678/1582127647159-1bc5c1c0-6bc8-46b2-b403-63d8c2842c67.png#align=left&display=inline&height=629&margin=%5Bobject%20Object%5D&name=image.png&originHeight=629&originWidth=1082&size=75797&status=done&style=none&width=1082)
           - 做判断,目标是否为本机,如果本地,发给input链
           - 如果不是交由forward链

image.png

常见应用场景

  • 到本地的某个进程的报文:prerouting ——> input ——>output ——>psotrouting
  • 由本地转法的报文:prerouting ——>forward ——>postrouting
  • 由本地响应的报文的流向:output ——>postrouting

  • 防火墙的作用在于对经过的报文进行规则匹配,然后执行相应的动作;那么如果有多个“规则”组合到一起,我们就称之为“链”
  • 每经过一条链,则需要把所有的规则匹配一遍,符合条件的规则,则执行相应的动作
  • 多个规则组成链,经过链的数据报文需要将规则匹配一遍,一旦匹配到符合条件的规则就执行动作

  • 每个链上都有一串规则,但是又许多类似的规则,这些规则可能是:

    - 对ip或端口进行过滤
    - 对报文进行修改
    - 对网络地址进行转换等
    
     将这些实现相似功能的规则放在一起,它们的集合叫表,多张表的规则的集合叫做链<br />iptables所有的规则的定义,都是定义到不同的表中
    
  • iptables 提供的表

名称 作用 内核模块
raw表 关闭nat上启用的连接追踪机制 iptables_raw
mangle表 拆解报文,做出修改,并重新封装,内核模块 iptables_mangle
nat表 网络地址转化 iptables_nat
filter表 负责过滤功能,(包括防火墙使用的表) iptables_filter

- 优先级顺序;
- raw——>mangle——>nat——>filter
- 优先级越高的表中的规则优先匹配处理


- 所有定义的规则都在这四张表中

表链关系

每个链只能拥有某些规则,也就是某些表

链——表

PREROUTING raw mangle nat
INPUT mangle filter nat
FROWARD magle filter
OUTPUT raw mangle nat filter
PSTROUTING mangle nat

实际使用的过程中,往往是以表为操作入口,操作的时候,通过表,查询所定义的规则,以及该表的规则所用与”链”

表——链

raw表 preouting,output
mangle表 prerouting,input,forward,output,pistrouting
nat表 input,output,postrouting,prerouting
filter表 input,forward,output

ps:
1.当一个数据包经过一个链的时候,会将当前链的所有规则都依次匹配,而定义的规则会都汇聚到表当中,匹配的时候,因为总有优先匹配,所以表就拥有了优先级
2.在Linux主机当中,如果想要支持转发,需要开启内核中的ip_forward

  • [root@localhost net]# cat /proc/sys/net/ipv4/ip_forward

0

  • 0关闭 1开启

    规则

    匹配条件+动作
  • 定义:根据指定的匹配条件来尝试匹配每个流经此处的数据报文,一旦匹配成功,则由后面的指定处理动作进行 处理

    匹配条件

    • 基本匹配条件 SIP DIP 等等
    • 拓展匹配条件 sport dprot 等等
    • 拓展匹配条件也是Netfilter中的一部分,只不过是以模块的形式存在,如果要使用需要依赖相应的模块

      处理动作

      常用动作
ACCEPT 允许数据包通过
DROP 直接丢弃数据包,无任何回应消息
REJECT 拒绝数据包通过,必要时会发出数据发送端一个响应的拒绝消息
SNAT 源地址转换,解决内网用户同一个公网地址的上网问题
MASQUERADE 是snat的一种特殊形式,适用于动态的,临时会变的ip
DNAT 目的地址转换,解决外部网络访问内部局域网中的服务
REDIECT 在本地端口做端口映射(在docker中用的多)
LOG 在/var/log/message文件中记录日志信息,然后将数据包传递给下一个规则,不对数据包进行任何的操作,只记录,让下一条规则去匹配

iptables的相关操作

规则查询

以filter进行实际的操作,fileter表负责过滤数据报文,eg:禁止(允许)哪些ip地址访问哪些端口等

  - -t:指定表类型     raw mangle nat filter
  - -L:列出表中的规则,默认所有的链规则
  - -v:显示详细信息
  - -x:显示数字信息
  - -n:将信息以数字形式显示
  - --line-number:显示有序号
[root@localhost ~]# iptables -t filter -vxL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
    pkts      bytes target     prot opt in     out     source               destination         
    1710   123282 ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
      10      740 ACCEPT     all  --  lo     any     anywhere             anywhere            
      80     7954 INPUT_direct  all  --  any    any     anywhere             anywhere            
      80     7954 INPUT_ZONES_SOURCE  all  --  any    any     anywhere             anywhere            
      80     7954 INPUT_ZONES  all  --  any    any     anywhere             anywhere            
       0        0 DROP       all  --  any    any     anywhere             anywhere             ctstate INVALID
      77     7802 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-host-prohibited
policy:当前链的默认策略
packets:当前链默认策略匹配到包的数量
bytes:当前默认策略匹配到的包的大小,-x显示精确的计数值

pkts:对应匹配到的报文数     
bytes :对应匹配到的报文大小
target :规则对应的“动作”
prot:规则对应的“协议” , all所有协议
opt:规则对应的选项
in:数据包由哪个网卡(接口)流入,any任意网卡都生效,指定相应的网卡进行规则匹配策略
out:数据包由哪个网卡(接口)流出,any任意网卡都生效,指定相应的网卡进行规则匹配策略
source: 规则对应的源地址(ip地址或网段)              
destination:规则对应的目标地址(ip地址或网段)

源地址和目标地址都是anywhere,因此iptables默认进行了名称解析,把anywhere解析成0.0.0.0

规则操作

增加规则:

  • -A:追加规则(latest)
  • -I:插入规则(first)+[number] 可以插入到指定位置
  • -s:匹配条件中的源地址
  • -j:匹配条件中的动作

    • iptables -t -A <匹配条件> -j

          eg:<br />禁止ping 172.16.0.1
      
      - iptables -t filter  -A INPUT  -s  172.16.0.1/24 -j REGECT
      

禁止ping 172.16.0.1 192.168.10.10

        - iptables -t filter -A INPUT -s 172.16.0.1 -j REJUCT
        - iptables -t filter -I INPUT -s 192.168.10.10 -j DROP

删除规则:

  • -D:删除指定‘链’中的规则+[num]指定规则
  • -F:删除操作,删除所有操作
    • 方法一:根据具体的匹配条件去删除规则
      • iptables -t filter -D INPUT -s 192.168.10.2 -j DROP
    • 方法二:可以根据规则的number进行删除
      • iptables -t filter -D INPUT 2

修改操作:

  • -R :修改指定规则
  • -P:修改链的默认策略
    • [root@test ~]# iptables -t filter -R INPUT 1 -s 172.16.10.0/24 -j ACCEPT
    • [root@test ~]# iptables -t filter -P FORWARD DROP

保存规则:

  - iptables‐save > /etc/sysconfig/iptables #系统启动后导入的规则

导入规则:

  - iptables ‐restore < /etc/sysconfig/iptables

匹配条件

基本匹配条件

  - -s:指定源地址
  - -d:指定目标地址
  - -p:指定协议
  - -i /-o:指定网卡的流入和流出
        - -i:用于网卡流入,PREROUTING,INPUT,FORWARD
        -  -o:用于网卡流出,OUPTUT, POSTROUTING

拓展匹配条件:需要拓展模块支持

  - -m [模块名]:去使用拓展模式,定义拓展匹配条件

  - tcp/udp 拓展模式:
        - --dport :指定目的端口
        - --sport:指定源端口

  - iprange拓展模块:    
     - --src-range:指定源ip地址段
     - --dest-range:指定目的IP地址段
     - 192.168.0.0/24-192.168.31.0/24

  - string模块:指定需要匹配报文中的字符串
     - --algo:指定匹配算法(bm和kmp)
     - --string:指定需要匹配的字符串

  - time模块:时间段匹配,如果报文在到达时间范围内,则符合匹配条件
     - --timestart[起始时间]          --timestop[结束时间]
     - --weekadys:指定周
     - --mouthdays:指定月
     - --datestart[指定日期]           --datestop[结束日期]

  - connlimit模块:限制每个IP地址同时连接到server端的连接数量,不需要指定ip地址,默认就是针对每个客户端ip地址
        - connlimit-above   限制每个客户端ip的并发连接数量,,如果高于此数量则执行此响应动作
        - connlimit-upto  限制每个客户端IP的并发连接数量,如果低于数量则执行响应动作
           - iptables -t fliter -I  INPUT -m connlimit --connlimit-above 2 -j REJUCT

eg:ssh连接:
限制每个客户端IP的ssh并发链接数量高于2都被拒绝

              -  ‐m connlimit ‐‐connlimit‐above 2 ‐j REJECT        

限制每个客户端ip的ssh连接并发连接数低于2时,都被接收

              - -p tcp --dport 22 -m connlimit --connnlimit-upto 2 -j -ACCEPT
              -  ‐p tcp ‐‐dport 22 ‐m connlimit‐‐connlimit‐above 2 ‐‐connlimit‐mask 24 ‐j REJECT           限制24网段的链接数量为2,配合后更加的灵活 

  - limit模块:对“报文到达的速率”进行限制的,就是限制单位时间内流入包的数量
     - -m limit --limit [速率]
     - 速率:
        - /second
        - /minute
        - /hour
        - /day
        - ‐‐limit‐burst 空闲时可放行的包的数量,默认为5;而默认生成令牌的速度为每6s一个

  - state 模块:对于连接报文中的状态可以分为::NET, ESTABLISHED, RELATED, INVALID, UNTARCKED
     - 通过匹配连接状态,从而定义过滤规则
     -  NEW:连接中的第一个包,状态就是NEW              
     - ESTABLISHED:把NEW状态包后面的包的状态理解为ESTABLISHED,表示已经建立连接              RELATED:与“命令连接”中的报文有关系的,比如FTP服务,有两个进程,一个命令进程,一个数据 进程            
     -  INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,我们是能够主动屏蔽状态为 INVALID的报文              
     - UNTRACKED:表示报文未被追踪时的状态,当报文的状态为UNTRACKED时通常表示无法找到相关连接            
     -  iptables ‐t filter ‐I INPUT ‐m state ‐‐state ESTABLISHED,RELATED ‐j ACCEPT            
     -  iptables ‐t filter ‐I INPUT ‐m state ‐j REJECT            
     -   表示只有回应我们的报文能够通过防火墙,如果是别人主动发送过来的新报文,则无法通过防火墙。  

自定义链

当默认链的规则非常多的时候,不方便我们管理,如果INPUT链中存放着几百条规则,有针对http、ftp服务,当我们想修改http规则的时候,为了方便管理,则需要去创建自定义链

创建自定义链

  • iptables -t filter -N [chain_name]
    • -N:创建自定义链
    • 增删改查同模式链的方法
      • iptables ‐t filter ‐I my_chain ‐s 192.168.139.1 ‐j REJECT
      • iptables ‐I INPUT ‐p icmp ‐j my_chain ps:表示引用链,禁ping
      • http服务,只允许192.168.10.0/24以及172.16.0.0/16的客户端访问
        • iptables -t filter -N http
        • 1.iptables -t filter -A http -s 192.168.10.0/24 -j ACCEPT
        • 2.iptables -t filter -A http -s 172.16.0.0/16 -j ACCEPT
[root@localhost ~]# iptables -t filter -N lars
[root@localhost ~]# iptables -t filter -A lars -s 192.168.0.0/24 -j DROP
[root@localhost ~]# iptables -t filter -I INPUT -j lars
[root@localhost ~]# ping 192.168.0.7
PING 192.168.0.7 (192.168.0.7) 56(84) bytes of data.
^C
--- 192.168.0.7 ping statistics ---
10 packets transmitted, 0 received, 100% packet loss, time 9003ms

删除自定义链
iptables -t filter -F httpd # 1.清除自定义链中的规则
iptables -t filter -D INPUT 1 # 2.删除引用自定义链中的相关规则
iptables -t filter -X httpd # 3.通过-X参数删除自定义链

     - ps:满足以下要求:
                 - 自定义链中没有任何模式的链引用,即自定义链的引用数为0
                 - 自定义链中没有任何规则,自定义链为空

iptables规则保存和恢复

  • 保存规则:
    • iptables-save > /etc/sysconfig/iptables
    • iptables-save > /iptables/input1
  • 恢复规则:
    • IP tables-restore < /iptables/input1

Firewalld

介绍

Firewalld是一个支持定义网络区域(zone)及接口安全等级的动态防火墙管理工具。
利用Firewalld,用户可以实现防火墙、代理服务器以及网络地址转换

它具备IPv4和IPv6防火墙的设备支持。
它支持以太网桥
图形化配置工具:firewall-config
命令行配置工具:firewall-cmd
配置文件在/usr/lib/firewalld和/etc/firewalld目录中的XML文件中

firewalld和iptables的关系

相同点:

  • firewalld和IP tables一样本身不具备防火墙工具,而是将用户空间的安全设定执行到内核空间中的Netfilter(安全框架)

差异:
1.firewalld service 在/usr/lib/firewalld/(系统配置)和/etc/firewalld/(用户配置)
iptables /etc/sysconfig/iptables 中储存配置
2.iptables每一个单独更改意味着清除旧的规则和从/etc/sysconfig/iptables读取新的配置文件
3.firewallde 不在创建任何新的规则,仅仅运行规则中的不同之处,因此firewalld可以在运行时间内,改变设置而不丢失现有的连接

NetworkManager服务:通知firewanlld一个接口归属某个区域,新加入的接口被分配到默认区域中

防火墙区域 zone

数据包首先从本地接口中进入,接下来将进入接口所对应的区域。
ps:一个网络接口只能与一个区域对应,即一个接口不能同时加入两个或以上的区域。
当数据包进入区域后,防火墙会根据区域内的规则进行逐一过滤,只有符合规则的数据包才能通过区域到达本机应用
不同区域对于网络连接的设置规范不同,系统中实际存在9个区域
从信任到不信任排列

区域 说明
trusted(信任区域) 信任所有网络连接
internal(内部区域) 用于企业等的内部网络,基本信任内部网络中的计算机不会威胁计算机安全
home(家庭区域) 基本信任家庭网络中的计算机不会危害计算机的安全
work(工作区域) 基本信任工作网络中的计算机不会危害计算机的安全
dmz(非军事区域) 隔离区,此区域内的计算机可以公开访问,可以有限地进入内部网络
external(外部区域) 通常是使用了伪装的外部网络,该区域内的计算机可能会危害计算机的安全
public(公共区域) 在公共区域使用,该区域内的计算机可能会危害计算机安全
block(阻塞区域) 拒绝,任何进入的网络连接都将被拒绝,并返回IPV4或IPV6的拒绝报文
drop(丢弃) 任何进入的网络连接都将被丢弃,没有任何回复

ps:最终决定连接是否被放行是区域中的规则,而不是区域中的描述。

firewalld管理操作

每个zone都有一套规则集,对每个接收到的请具体使用哪个zone,firewalld有三种方法来判断

  • source 源地址优先级最高
  • interface 接收请求的网卡
  • firewall.conf 中配置的默认zone
[root@localhost ~]# cat /etc/firewalld/firewalld.conf | grep Zone
DefaultZone=public

firewalld-cmd命令

管理防火墙

查看默认zone firewall-cmd —get-default-zone
查看firewall的状态 firewall-cmd —state
查看当前活动的区域 firewall-cmd —get-active-zones
查看可用区域 firewall-cmd —get-zones
列出public域的所有配置 [root@localhost ~]# firewall-cmd —zone=public —list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens37 ens33
sources:
services: ssh dhcpv6-client
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
列出所有区域的配置 firewall-cmd —list-services
列出所有预定的服务 firewall-cmd —get-services
设置默认域 firewall-cmd —set-default-zone=
[root@localhost ~]# firewall-cmd —set-default-zone=public
Warning: ZONE_ALREADY_SET: public
success
设置网络地址到指定域 firewalld-cmd —zone = —add -source =
删除指定区域的网络地址 firewalld-cmd —zone= —remove-source =

管理操作

| 添加,改变,删除网络接口到指定域中(域中会有一条规则) |
- firewall-cmd —list-interfaces
- firewall-cmd —add-interface
- [root@localhost ~]# firewall-cmd —add-interface en0
success
- firewall-cmd —change -interface
- firewall-cmd —remove -interface
- firewall-cmd —query-interface
| | —- | —- | | 添加、删除、列出服务 |
- firewalll-cmd —get-services 列出所有预定的服务
- firewall-cmd ‐‐add‐service
- firewall-cmd —list-services 列出所有区域的配置
- firewall-cmd ‐‐remove‐service
- firewall-cmd —query-service
- firewall-cmd ‐‐permanent 表示是否永久生效
| | 列出、添加、删除端口 |
- firewall-cmd —list-ports
- firewall-cmd —add-port []/
[root@localhost ~]# firewall-cmd —add-port=22/tcp
success
删除sh服务的时候,添加tcp的 仍旧可以用ssh进行连接
- firewall-cmd ‐‐remove‐port []/
- firewall-cmd —query-port [-]/
| | 永久生效 | —permanent | | 重载防火墙 | firewall-cmd -‐reload |

添加服务 修改/usr/lib/firewalld/service/…xml文件 之后直接交给iptables/netfilter
添加端口 在iptables/netfilter中执行

系统配置firewalld的配置:/usr/lib/firewalld/

  • 用户配置firewalld的配置:/etc/firewalld/
  • 去将系统配合cp一份到用户配置当中进行修改
    ftp服务器自定义端口1121,需要在work zone下放行 ftp做法。
    方法一:
    [root@localhost ~]# cp /usr/lib/firewalld/services/ftp.xml /etc/firewalld/services
    [root@localhost ~]# vi /etc/firewalld/services/ftp.xml                   
    <port protocol="tcp" port="1121"/>  
    [root@localhost ~]# cp /usr/lib/firewalld/zones/work.xml /etc/firewalld/zones/ 
    [root@localhost ~]# cp /usr/lib/firewalld/zones/work.xml /etc/firewalld/zones/                 
    <service name="ftp"/>  
    [root@localhost ~]# firewall‐cmd ‐‐reload  重新加载! 
    [root@localhost ~]# firewall‐cmd ‐‐zone=work ‐‐list‐service 
    [root@localhost ~]# firewall‐cmd ‐‐service=ftp ‐‐get‐ports ‐‐permanent 
    方法二: 
    firewall‐cmd ‐‐zone=work ‐‐add‐service=ftp ‐‐permanent  
    firewall‐cmd ‐‐zone=work ‐‐service=ftp ‐‐add‐port=1121/tcp ‐‐permanent