标签 firewalld 下的文章

数百万 GitHub 项目易受依赖库劫持攻击

安全专家发现,数以百万计的 GitHub 项目易受依赖库劫持攻击,攻击者可以借此发动影响大量用户的供应链攻击。GitHub 上的用户名和项目或库的名字如果改变,为了避免破坏其它项目的依赖关系,GitHub 会创建一个重定向。但如果有人用旧的名字创建了账号,那么就会导致重定向无效。GitHub 可以防御部分此类攻击,但该防御方案可以被绕过。

消息来源:Aqua Sec
老王点评:我觉得 GitHub 应该更认真的解决这个问题,毕竟 GitHub 已经不仅仅是一个代码仓库,而是一个供应链的重要组成部分了。但从另外一个角度看,软件项目依赖这种不确定的供应链是不是也过于宽松了?

美国新数据显示,在家工作成为新常态

许多在大流行期间蜷缩在家里的白领工人已经回到办公室,但没有回到办公室的人特别多。对许多人来说,远程工作似乎是一种新常态。周四公布的美国经济数据显示,在家工作似乎已经成为一种趋势,特别是对女性和受过大学教育的人而言。2022 年的数据显示,34% 的 15 岁以上的人仍然在家里工作,54% 的人拥有学士或更高的学位。而美国旧金山市长已经 提议 将市中心荒废的购物中心改造为足球场,因为越来越多人不再回到市中心上班,旧金山的办公室空置率已达到 30 年来的最高水平。

消息来源:MSN
老王点评:不知道为什么美国人就不回去上班了,而我们似乎都赶紧回去了。

Firewalld 2.0 发布

开源防火墙守护程序 Firewalld 自 2011 年以来一直在开发,而两年前才达到 Firewalld 1.0 的里程碑。因此,发现 Firewalld 2.0 在今天发布有点令人惊讶。2.0 中最重要的变化解决了区域漂移的问题,即防火墙策略可能最终违反了 “数据包只进入一个区域” 的规则。此外,还增加了对 NFTables Flowtable 的支持,可以显著提高转发性能,将网络转发的 iperf 性能提高了约 59%。

消息来源:Phoronix
老王点评:看起来是 Firewalld 的开发在加速,不过我更觉得它是在飙版本号。看看 Firefox、Linux 内核等开源软件的版本号,看来开源软件对版本号的谦虚传统已经被丢弃了。

如果你运行的服务器有面向公众的 SSH 访问,你可能遇到过恶意登录尝试。本文介绍了如何使用两个实用程序来防止入侵者进入我们的系统。

为了防止反复的 ssh 登录尝试,我们来看看 fail2ban。而且,如果你不经常旅行,基本上停留在一两个国家,你可以将 FirewallD 配置为只允许从你选择的国家访问

首先,让我们为不熟悉这些应用程序的人员介绍一些术语,以完成这项工作:

fail2ban:一个守护进程,用于禁止发生多次认证错误的主机。fail2ban 将监控 SystemD 日志,以查找对任何已启用的“ 监狱 jail ”的失败的验证尝试。在达到指定失败次数后,它将添加一个防火墙规则,在配置的时间内阻止该特定 IP 地址。

FirewallD:一个带有 D-Bus 接口的防火墙守护进程,提供动态防火墙。除非你另行决定使用传统的 iptables,否则你已经在所有支持的 Fedora 和 CentOS 上安装了 FirewallD。

假定前提

  • 主机系统有一个互联网连接,并且要么是直接暴露在互联网上,要么是通过 DMZ(这两个都是非常糟糕的想法,除非你知道你在做什么),要么是有一个端口从路由器转发过来。
  • 虽然大部分的内容可能适用于其他系统,但本文假设当前系统是 Fedora(31 及以上)或 RHEL/CentOS 8 版本。在 CentOS 上,你必须用 sudo dnf install epel-release 启用 Fedora EPEL 仓库。

安装与配置

Fail2Ban

很有可能已经有某个 Firewalld 区已经允许 SSH 访问,但 sshd 服务本身默认没有启用。要手动启动它,并且不在启动时永久启用它:

$ sudo systemctl start sshd

或者在系统启动时启用,并同时启动它:

$ sudo systemctl enable --now sshd

下一步就是安装、配置、启用 fail2ban。和往常一样,安装可以通过命令行完成:

$ sudo dnf install fail2ban

安装完毕后,下一步就是配置“监狱”(你要以设置的任何阈值监视并禁止的服务)。默认情况下,IP 会被禁止 1 小时(这其实不够长)。最好的做法是使用 *.local 文件覆盖系统默认值,而不是直接修改 *.config 文件。如果我们查看我的 jail.local,我们可以看到:

# cat /etc/fail2ban/jail.local
[DEFAULT]

# "bantime" is the number of seconds that a host is banned.
bantime  = 1d

# A host is banned if it has generated "maxretry" during the last "findtime"
findtime  = 1h

# "maxretry" is the number of failures before a host get banned.
maxretry = 5

换成通俗的语言讲,就是在过去一小时内尝试 5 次后,该 IP 将被封禁 1 天。对于多次被封的 IP,也可以选择增加封禁时间,但这是另一篇文章的主题。

下一步是配置“监狱”。在本教程中显示的是 sshd,但其他服务的步骤大致相同。在 /etc/fail2ban/jail.d 中创建一个配置文件。这是我的文件:

# cat /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true

就这么简单! 很多配置已经在为 Fedora 构建的软件包中处理了(提示:我是当前的维护者)。接下来启用并启动 fail2ban 服务:

$ sudo systemctl enable --now fail2ban

希望没有立即出错,如果没有,请使用下面的命令检查 fail2ban 的状态:

$ sudo systemctl status fail2ban

如果它没有错误地启动,应该是这样的:

$ systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/usr/lib/systemd/system/fail2ban.service; disabled; vendor preset: disabled)
Active: active (running) since Tue 2020-06-16 07:57:40 CDT; 5s ago
Docs: man:fail2ban(1)
Process: 11230 ExecStartPre=/bin/mkdir -p /run/fail2ban (code=exited, status=0/SUCCESS)
Main PID: 11235 (f2b/server)
Tasks: 5 (limit: 4630)
Memory: 12.7M
CPU: 109ms
CGroup: /system.slice/fail2ban.service
└─11235 /usr/bin/python3 -s /usr/bin/fail2ban-server -xf start
Jun 16 07:57:40 localhost.localdomain systemd[1]: Starting Fail2Ban Service…
Jun 16 07:57:40 localhost.localdomain systemd[1]: Started Fail2Ban Service.
Jun 16 07:57:41 localhost.localdomain fail2ban-server[11235]: Server ready

如果是刚刚启动的,fail2ban 不太可能显示任何有意思的信息,但要检查 fail2ban 的状态,并确保“监狱”被启用,请输入:

$ sudo fail2ban-client status
Status
|- Number of jail:      1
`- Jail list:   sshd

sshd “监狱”的上级状态也会显示出来。如果启用了多个“监狱”,它们会在这里显示出来。

要查看一个“监狱”的详细状态,只需在前面的命令中添加“监狱”名称。下面是我的系统的输出,它已经运行了一段时间。我已经从输出中删除了被禁止的 IP:

$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 8
|  |- Total failed:     4399
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 101
   |- Total banned:     684
   `- Banned IP list:   ...

监控 fail2ban 日志文件是否有入侵尝试,可以通过“尾随”日志来实现:

$ sudo tail -f /var/log/fail2ban.log

tail 是一个很好的命令行工具,默认情况下,它可以显示一个文件的最后 10 行。添加 -f 告诉它尾随文件,这是个观察一个仍在被写入的文件的很好方式。

由于输出的内容中有真实的 IP,所以这里不会提供样本,但它的可读性很高。INFO 行通常是登录的尝试。如果从一个特定的 IP 地址进行了足够多的尝试,你会看到一个 NOTICE 行显示一个 IP 地址被禁止。在达到禁止时间后,你会看到一个 NOTICE 解禁行。

注意几个警告行。最常见的情况是,当添加了一个禁止后,fail2ban 发现该 IP 地址已经在其禁止数据库中,这意味着禁止可能无法正常工作。如果是最近安装的 fail2ban 包,它应该被设置为 FirewallD 的富规则。这个包在 fail2ban-0.11.1-6 版本时从 ipset 方式切换到了富规则方式,所以如果你的 fail2ban 安装时间较早,它可能还在尝试使用 ipset 方式,这种方式使用的是传统的 iptables,不是很可靠。

FirewallD 配置

被动还是主动?

有两种策略可以分开或一起使用:被动地将单个 IP 地址或主动地根据来源国将子网永久列入黑名单。

对于被动方式,一旦 fail2ban 运行了一段时间,最好再运行 sudo fail2ban-client status sshd 来看看有哪些坏蛋。很可能会有很多被禁止的 IP 地址。选择一个,然后试着对它运行 whois。在输出结果中可能会有很多有趣的信息,但是对于这个方法来说,只有来源国是重要的。为了保持简单,让我们过滤掉除了国家以外的所有信息。

在这个例子中,我们将使用一些著名的域名:

$ whois google.com | grep -i country
Registrant Country: US
Admin Country: US
Tech Country: US
$ whois rpmfusion.org | grep -i country
Registrant Country: FR
$ whois aliexpress.com | grep -i country
Registrant Country: CN

使用 grep -i 的原因是为了使 grep 不区分大小写,而大多数条目都使用的是 “Country”,而有些条目则是全小写的 “country”,所以这种方法无论如何都能匹配。

现在知道了尝试入侵的来源国,问题是,“是否有来自这个国家的人有合法的理由连接到这台计算机?”如果答案是否定的,那么封锁整个国家应该是可以接受的。

从功能上看,主动式方法它与被动式方法没有太大区别,然而,来自有些国家的入侵企图是非常普遍的。如果你的系统既不放在这些国家里,也没有任何源自这些国家的客户,那么为什么不现在就把它们加入黑名单而是等待呢?(LCTT 译注:我的经验是,动辄以国家的范畴而列入黑名单有些过于武断。建议可以将该 IP 所属的 WHOIS 网段放入到黑名单,因为这些网段往往具有相同的使用性质,如都用于用户接入或 IDC 托管,其安全状况也大致相同,因此,如果有来自该网段的某个 IP 的恶意尝试,可以预期该网段内的其它 IP 也可能被利用来做这样的尝试。)

黑名单脚本和配置

那么如何做到这一点呢?用 FirewallD ipset。我开发了下面的脚本来尽可能地自动化这个过程:

#!/bin/bash
# Based on the below article
# https://www.linode.com/community/questions/11143/top-tip-firewalld-and-ipset-country-blacklist

# Source the blacklisted countries from the configuration file
. /etc/blacklist-by-country

# Create a temporary working directory
ipdeny_tmp_dir=$(mktemp -d -t blacklist-XXXXXXXXXX)
pushd $ipdeny_tmp_dir

# Download the latest network addresses by country file
curl -LO http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz
tar xf all-zones.tar.gz

# For updates, remove the ipset blacklist and recreate
if firewall-cmd -q --zone=drop --query-source=ipset:blacklist; then
    firewall-cmd -q --permanent --delete-ipset=blacklist
fi

# Create the ipset blacklist which accepts both IP addresses and networks
firewall-cmd -q --permanent --new-ipset=blacklist --type=hash:net \
    --option=family=inet --option=hashsize=4096 --option=maxelem=200000 \
    --set-description="An ipset list of networks or ips to be dropped."

# Add the address ranges by country per ipdeny.com to the blacklist
for country in $countries; do
    firewall-cmd -q --permanent --ipset=blacklist \
        --add-entries-from-file=./$country.zone && \
        echo "Added $country to blacklist ipset."
done

# Block individual IPs if the configuration file exists and is not empty
if [ -s "/etc/blacklist-by-ip" ]; then
    echo "Adding IPs blacklists."
    firewall-cmd -q --permanent --ipset=blacklist \
        --add-entries-from-file=/etc/blacklist-by-ip && \
        echo "Added IPs to blacklist ipset."
fi

# Add the blacklist ipset to the drop zone if not already setup
if firewall-cmd -q --zone=drop --query-source=ipset:blacklist; then
    echo "Blacklist already in firewalld drop zone."
else
    echo "Adding ipset blacklist to firewalld drop zone."
    firewall-cmd --permanent --zone=drop --add-source=ipset:blacklist
fi

firewall-cmd -q --reload

popd
rm -rf $ipdeny_tmp_dir

这个应该安装到 /usr/local/sbin,不要忘了让它可执行!

$ sudo chmod +x /usr/local/sbin/firewalld-blacklist

然后创建一个配置文件 /etc/blacklist-by-country

# Which countries should be blocked?
# Use the two letter designation separated by a space.
countries=""

而另一个配置文件 /etc/blacklist-by-ip,每行只有一个 IP,没有任何额外的格式化。

在这个例子中,从 ipdeny 的区文件中随机选择了 10 个国家:

# ls | shuf -n 10 | sed "s/\.zone//g" | tr '\n' ' '
nl ee ie pk is sv na om gp bn

现在只要在配置文件中加入至少一个国家,就可以运行了!

$ sudo firewalld-blacklist
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   142  100   142    0     0   1014      0 --:--:-- --:--:-- --:--:--  1014
100  662k  100  662k    0     0   989k      0 --:--:-- --:--:-- --:--:--  989k
Added nl to blacklist ipset.
Added ee to blacklist ipset.
Added ie to blacklist ipset.
Added pk to blacklist ipset.
Added is to blacklist ipset.
Added sv to blacklist ipset.
Added na to blacklist ipset.
Added om to blacklist ipset.
Added gp to blacklist ipset.
Added bn to blacklist ipset.
Adding ipset blacklist to firewalld drop zone.
success

要验证 FirewallD 黑名单是否成功,请检查 drop 区和 blacklist ipset。

$ sudo firewall-cmd --info-zone=drop
drop (active)
  target: DROP
  icmp-block-inversion: no
  interfaces:
  sources: ipset:blacklist
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

$ sudo firewall-cmd --info-ipset=blacklist | less
blacklist
  type: hash:net
  options: family=inet hashsize=4096 maxelem=200000
  entries:

第二条命令将输出所有的子网,这些子网是基于被封杀的国家而添加的,可能会相当长。

那么现在我该怎么做?

虽然在开始的时候,监控的频率会比较高,但随着时间的推移,入侵尝试的次数应该会随着黑名单的增加而减少。那么目标应该是维护而不是主动监控。

为此,我创建了一个 SystemD 服务文件和定时器,这样每月都会刷新由 ipdeny 维护的每个国家的子网。事实上,这里讨论的所有内容都可以从我的 pagure.io 项目中下载。

是不是很高兴你看完了整篇文章?现在只要把服务文件和定时器下载到 /etc/systemd/system/,并启用定时器就行了:

$ sudo systemctl daemon-reload
$ sudo systemctl enable --now firewalld-blacklist.timer

via: https://fedoramagazine.org/protect-your-system-with-fail2ban-and-firewalld-blacklists/

作者:hobbes1069 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

FirewallD 是由红帽发起的提供了支持网络/防火墙 区域 zone 定义网络链接以及接口安全等级的动态防火墙管理工具。它支持 IPv4、IPv6 防火墙设置以及以太网桥接,并且拥有运行时配置和永久配置选项。它也支持允许服务或者应用程序直接添加防火墙规则的接口。

由于 FirewallD 项目本身的自由软件特性,像 Debian Linux 社区发行版已经默认在软件仓库中收录了该防火墙组件软件包。随着各个新 GNU/Linux 发行版中防火墙引擎逐步从 iptables 向 nftables 迁移,FirewallD 是目前唯一能够支持该两种防火墙后端引擎的前端服务组件,用户掌握以后可以方便的进行防火墙配置并很好的规避了从 iptables 向 nftables 迁移带来的学习恐慌。

笔者通过查阅 RedHat 8 发行版网络配置手册,并结合自己在 Debian Linux 10 社区版上进行 FirewallD 防火墙的实际配置使用,对该服务组件的功能和日常使用进行整理。希望通过该文能帮助其他 Linux 用户掌握该防火墙,并通过该防火墙提高主机测网络安全防御能力,打造可信的网络安全环境。

一、安装

在 Debian Linux 10 社区版中使用如下命令:

apt-get install firewall-applet firewall-config firewalld

就可以直接进行 FirewallD 防火墙软件组件包的安装,其中:

  • firewall-applet 为 FirewallD 托盘小程序,
  • firewall-config 为 FirewallD 图形化系统配置管理工具
  • firewalld 为 FirewallD 防火墙软件组件的主组件包,其中包含 firewall-cmdfirewall-offline-cmd 等命令行系统配置管理工具。

在 RedHat 8 下该防火墙组件默认已经进行了安装,如果用户进行特殊定制安装之后需要单独安装该软件组件可以使用命令

yum install firewall-config

直接进行安装即可。

笔者在两个系统装进行过安装对比,发现该软件组件包在两个系统上除了安装命令稍有差异外,其它从配置文件到 systemd 服务配置并没有任何区别。随后的内容将不再强调操作系统。

二、防火墙默认区域

  • Block(阻塞)
    任何对该区域的连接请求都会被以 IPv4 的 icmp-host-prohibited 信息或 IPv6 的 icmp6-adm-prohibited 信息所拒绝。只能从系统内部启动网络连接。
  • Dmz(隔离)
    用于你的隔离区内的电脑,此区域内可公开访问,可以有限地进入你的内部网络,仅仅接收经过选择的连接。
  • Drop(丢弃)
    对进入该区域的所有数据包丢弃,并且不进行任何回包,区域内主动发起连接的流入回程数据包允许通过,允许进行出方向的网络连接。
  • External(外部)
    用于在启用伪装的外部网络上使用,尤其路由器、防火墙认为在这个网络上的其它主机不可信。仅仅接收经过选择的连接。
  • Home(家庭)
    默认其他同区域内主机可信,仅仅接收经过选择的连接。同时默认放行 ssh、mdns、ipp-client、amba-client 与 dhcpv6-client 服务产生的连接。
  • Internal(内部)
    从描述中可以等同于家庭区域。
  • Public(公开)
    公共区域,也是防火墙配置的默认区域,防火墙认为该区域主机不可信。仅仅接收经过选择的连接。同时默认放行 ssh 与 dhcpv6-client 服务产生的连接。
  • Trusted(可信)
    可信区域,防火墙放行一切流量。等同于关闭防火墙功能。
  • Work(工作)
    工作区域,防火墙认为在这个网络上的其它主机不可信。仅仅接收经过选择的连接。同时默认放行 ssh、ipp-client 与 dhcpv6-client 服务产生的连接。

这些区域的命名不言自明,用户可以很快选择一个合适的安全区域,从而简化和避开很多安全问题。当然用户也可以根据自己的需要或者安全评估来根据自己的实际需求对相应安全域进行更个性化的配置,以适应自己的安全管理规范。尽管有些安全域的安全规则是相同的,但之所以还要在名字上有所区别,主要是为了从习惯上让用户更好区分不同域的独特使用场景,对用户来说更好理解和便于区分。

三、防火墙日常管理

3.1、查看防火墙当前状态

查询状态:

firewall-cmd --state

更多的防火墙系统服务状态信息可以使用

systemctl status firewalld

在你配置新的防火墙规则之前,你需要了解如何通过命令查看当前防火墙配置。查看防火墙当前配置可以通过图形界面或者在终端模式下使用命令进行。

在图形界面下可以直接通过点击应用程序“firewall-config”图标或者在终端窗口中输入 firewall-config 命令进行防火墙配置。如果当前用户为非 root 用户,系统将弹出管理员认证窗口,用户正确输入管理员密码后,防火墙配置窗口就会打开,用户即可以按照窗口界面提供的功能进行操作。

用户也可以在命令行下使用 firewall-cmd工具进行防火墙配置。命令行工具虽然学习起来需要一定的时间,不过该工具可以完全在系统处于终端模式下进行各种复杂的防火墙全功能配置,用户有必要进行认真的学习和掌握。

3.2、防火墙基础命令

FirewallD 使用了区域进行数据流的管理,当用户使用 firewall-cmd --list-all 命令时,如果没有使用 --zone 指定区域,那么系统将返回默认区域的当前配置状态。

默认区域由配置文件 /etc/firewalld/firewalld.conf 中的字段 DefaultZone 定义,初始状态下,默认区域被定义为 public(公共区域)。

用户可以使用命令:

firewall-cmd --get-zones

查看当前系统防火墙设置的的区域名列表,也可以使用命令:

firewall-cmd --get-default-zone

查看防火墙当前的默认区域;同时,可使用命令:

firewall-cmd --set-default-zone=[zonename]

或者通过直接编辑配置文件中 DefaultZone 字段的值进行默认区域的修改。

启动防火墙:

systemctl unmask firewalld
systemctl start firewalld

让防火墙随系统启动一起启动:

systemctl enable firewalld

停止防火墙:

systemctl stop firewalld

停止随系统启动:

systemctl disable firewalld

停止通过访问 firewalld D-Bus 接口和其他服务需要 firewalld 依赖导致的 firewalld 自动启动,更加干净的关闭 firewalld 服务:

systemctl mask firewalld

按照 RedHat 的官方文档定义,防火墙运行之后被称为运行时状态,保存了启动默认参数之后的配置被称为永久状态。在当前运行状态对防火墙进行的所有配置修改,系统即时生效,但重启后防火墙会恢复到它之前的永久状态,其实这一过程就是从保存之后的配置文件中加载相应配置参数的过程。

用户可以使用命令:

fiewall-cmd --runtime-to-permanent

对当前修改过的规则即时保存为永久配置,也可以使用命令 firewall-cmd --permanent 并在其后添加其它参数永久进行修改。

重新启动 firewalld 将关闭所有打开的端口并停止网络通信,需要使用命令:

firewall-cmd --reload

重新加载永久配置使之生效。

FirewallD 提供了一种系统受到攻击的紧急操作功能。假设攻击者对系统进行攻击,用户可以直接使用命令:

firewall-cmd --panic-on

关闭网络通信并且切断攻击者,而不用像之前那样通过物理拔除网线来进行断网操作,防止了系统在多网口环境中一次性插拔所有网线可能带来的混乱以及由此引发的系统恢复后延续问题。

需要恢复网络通信时用户只要使用命令:

firewall-cmd --panic-off

关闭恐慌模式即可,用户也可以使用命令:

firewall-cmd --query-panic

查询防火墙当前恐慌模式的状态。

3.2、防火墙服务管理命令

用户可以通过命令行工具添加预定义的服务类型,防火墙会自动根据所需的端口并将其他设置修改为服务定义文件。

使用命令:

firewall-cmd --list-services

可以查看当前区域内被允许的服务。使用命令:

firewall-cmd --get-services

可以列出所有防火墙已经给定的预定义服务名称。使用命令:

firewall-cmd --add-service=<service-name>

可以添加具体服务,服务名称用户可以根据自己的实际需求从预定义服务名称中选取合适的服务名进行添加。完成之后用户可以使用命令:

firewall-cmd --runtime-to-permanent

将对运行时的修改保存为永久。用户可以通过命令 firewall-configfirewall-cmdfirewall-offline-cmd,或者通过直接将 /usr/lib/firewalld/services 目录的默认模板 XML 文件复制到 /etc/firewalld/services 目录中进行编辑来添加一个自定义服务类型。具体过程如下:

方法一:执行 firewall-cmd –new-service=service-name,系统将直接在 /etc/firewalld/services 目录下创建一个以 .xml 结尾的同名文件,自定义服务类型添加完成。

方法二:在相应目录使用编辑软件直接编辑好 XML 文件并执行 firewall-cmd --new-service-from-file=service-name.xml,系统将自动完成同名自定服务类型的添加。

端口作为特定系统服务的接收和区分网络流量并将其转发到系统服务的逻辑设备,系统守护进程通常侦听特定的服务端口。防火墙在默认的服务类型配置中已经定义了相应服务需要放行的对应的端口。当用户还需要在某个服务中放行特定的自定义端口或者端口段的时候可以通过 firewall-cmd 完成,格式如下:

firewall-cmd [--zone=zone_name] [--service=service_name] --add-port=port-number/port-type

这里需要说明的是 --zone--service 为可选参数,如果用户不添加这两个参数执行命令时相当与在默认区域中直接添加了端口,当只选取了 --zone 参数时,命令执行的结果是在指定区域直接添加端口,此时与服务状态无关。只有在使用 --service 参数时才是在相应的服务中添加端口。

当用户需要删除一个端口时可以使用如下命令:

# firewall-cmd [--zone=zone_name] [--service=service_name] --remove-port=port-number/port-type

当用户需要向不同区域添加服务时,用户可以通过如下步逐进行:

# firewall-cmd --add-service=ssh --zone=drop

该命令将向区域 drop 中添加 ssh 服务,其实质就是放行 ssh 服务定义中的默认 22 端口入站方向的流量及连接。

在多网络接口主机中,可以使用如下方法将指定的网络接口添加到需要的区域中,从而实现每个接口的安全连接区域要求,实现真正的区域化网络安全管理。

使用命令:

firewall-cmd --get-active-zones

查看当前激活的安全区域和相应的网络接口配置。使用命令

firewall-cmd --zone=work --change-interface=ens3p0

则将网卡 ens3p0 加入到了 work 区域,之后所有通过该网卡的流量将受到区域安全规则的约束和限制,该配置是即时生效的并且会自动保存为永久配置。

用户需要将某个网卡加入到特定安全区域也可以直接使用:

vi /etc/sysconfig/network-scripts/ifcfg-connection-name

并在该文件下加入 ZONE=zone-name 行,该网卡即属于特定的安全区域。

用户可以对安全区域进行默认规则设置,默热规则包括三个选项 ACCEPTREJECTDROP,其中 ACCEPT 选项将放行所有流量,REJECTDROP 选项将阻止所有进入该安全区域的流量,与 REJECT 不同的是 DROP 选项直接丢弃进入安全区域的数据包,并不会向该数据包的发起者回复任何信息。用户可以使用命令:

firewall-cmd --zone=zone-name --set-target=<default|ACCEPT|REJECT|DROP>

进行相应安全区域的默认规则设置。

3.3、使用区域根据来源来管理传入流量

你可以使用区域根据来源管理流入流量,这使你可以对传入流量进行排序,并将其路由到不同区域,以允许或禁止该流量可以到达的服务。

如果将源添加到区域,则该区域将变为活动状态,并且来自该源的任何传入流量将通过它。你可以为每个区域指定不同的设置,该设置将应用于来自给定来源的流量。即使你只有一个网络接口,也可以使用更多区域。

通过以下实例,我们可以将特定网段对 HTTP 的请求流量进行更细致的管理,使用命令:

firewall-cmd --zone=trusted --add-source=192.168.1.0/24

将该网段作为资源加入到 trusted 区中,通过命令:

firewall-cmd --zone=trusted --add-service=http

将 Web 服务添加到相同区域中,随后该目标地址产生的访问 Web 服务流量将可以顺利通过。

3.4、防火墙锁机制

为了防止本地程序比如 KVM 虚拟机组件对防火墙的修改,FirewallD 还提供了一种锁闭机制来防止本地程序或者服务组件对防火墙配置的修改,并且该命令只有 root 用户本身才可以执行。

用户可以使用命令:

firewall-cmd --query-lockdown

查询防火墙锁闭状态,当需要锁闭时可以直接执行命令:

firewall-cmd --lockdown-on

恢复到非锁闭状态时可以执行命令:

firewall-cmd --lockdown-off

四、后记

FirewallD 防火墙组件作为 RedHat 对自由软件社区的贡献之一,具有很好的普适性,希望通过本文的讲解使更多的用户开始熟悉该防火墙软件组件,并将其作为主机本地侧防护很好的技术手段,不断提高主机自身的 IPS 能力。在当今网络环境复杂的形势下让主机具有更好的安全性和可用性。

防火墙是你的计算机防止网络入侵的第一道屏障。为确保你的安全,请下载我们的备忘单。

合理的防火墙是你的计算机防止网络入侵的第一道屏障。你在家里上网,通常互联网服务提供会在路由中搭建一层防火墙。当你离开家时,那么你计算机上的那层防火墙就是仅有的一层,所以配置和控制好你 Linux 电脑上的防火墙很重要。如果你维护一台 Linux 服务器,那么知道怎么去管理你的防火墙同样重要,只要掌握了这些知识你才能保护你的服务器免于本地或远程非法流量的入侵。

安装防火墙

很多 Linux 发行版本已经自带了防火墙,通常是 iptables。它很强大并可以自定义,但配置起来有点复杂。幸运的是,有开发者写出了一些前端程序来帮助用户控制防火墙,而不需要写冗长的 iptables 规则。

在 Fedora、CentOS、Red Hat 和一些类似的发行版本上,默认安装的防火墙软件是 firewalld,通过 firewall-cmd 命令来配置和控制。在 Debian 和大部分其他发行版上,可以从你的软件仓库安装 firewalld。Ubuntu 自带的是 简单防火墙 Uncomplicated Firewall (ufw),所以要使用 firewalld,你必须启用 universe 软件仓库:

$ sudo add-apt-repository universe
$ sudo apt install firewalld

你还需要停用 ufw:

$ sudo systemctl disable ufw

没有理由不用 ufw。它是一个强大的防火墙前端。然而,本文重点讲 firewalld,因为大部分发行版都支持它而且它集成到了 systemd,systemd 是几乎所有发行版都自带的。

不管你的发行版是哪个,都要先激活防火墙才能让它生效,而且需要在启动时加载:

$ sudo systemctl enable --now firewalld

理解防火墙的域

Firewalld 旨在让防火墙的配置工作尽可能简单。它通过建立 zone 来实现这个目标。一个域是一组的合理、通用的规则,这些规则适配大部分用户的日常需求。默认情况下有九个域。

  • trusted:接受所有的连接。这是最不偏执的防火墙设置,只能用在一个完全信任的环境中,如测试实验室或网络中相互都认识的家庭网络中。
  • homeworkinternal:在这三个域中,接受大部分进来的连接。它们各自排除了预期不活跃的端口进来的流量。这三个都适合用于家庭环境中,因为在家庭环境中不会出现端口不确定的网络流量,在家庭网络中你一般可以信任其他的用户。
  • public:用于公共区域内。这是个偏执的设置,当你不信任网络中的其他计算机时使用。只能接收选定的常见和最安全的进入连接。
  • dmz:DMZ 表示隔离区。这个域多用于可公开访问的、位于机构的外部网络、对内网访问受限的计算机。对于个人计算机,它没什么用,但是对某类服务器来说它是个很重要的选项。
  • external:用于外部网络,会开启伪装(你的私有网络的地址被映射到一个外网 IP 地址,并隐藏起来)。跟 DMZ 类似,仅接受经过选择的传入连接,包括 SSH。
  • block:仅接收在本系统中初始化的网络连接。接收到的任何网络连接都会被 icmp-host-prohibited 信息拒绝。这个一个极度偏执的设置,对于某类服务器或处于不信任或不安全的环境中的个人计算机来说很重要。
  • drop:接收的所有网络包都被丢弃,没有任何回复。仅能有发送出去的网络连接。比这个设置更极端的办法,唯有关闭 WiFi 和拔掉网线。

你可以查看你发行版本的所有域,或通过配置文件 /usr/lib/firewalld/zones 来查看管理员设置。举个例子:下面是 Fefora 31 自带的 FedoraWorkstation 域:

$ cat /usr/lib/firewalld/zones/FedoraWorkstation.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Fedora Workstation</short>
  <description>Unsolicited incoming network packets are rejected from port 1 to 1024, except for select network services. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <service name="samba-client"/>
  <port protocol="udp" port="1025-65535"/>
  <port protocol="tcp" port="1025-65535"/>
</zone>

获取当前的域

任何时候你都可以通过 --get-active-zones 选项来查看你处于哪个域:

$ sudo firewall-cmd --get-active-zones

输出结果中,会有当前活跃的域的名字和分配给它的网络接口。笔记本电脑上,在默认域中通常意味着你有个 WiFi 卡:

FedoraWorkstation
  interfaces: wlp61s0

修改你当前的域

要更改你的域,请将网络接口重新分配到不同的域。例如,把例子中的 wlp61s0 卡修改为 public 域:

$ sudo firewall-cmd --change-interface=wlp61s0 --zone=public

你可以在任何时候、任何理由改变一个接口的活动域 —— 无论你是要去咖啡馆,觉得需要增加笔记本的安全策略,还是要去上班,需要打开一些端口进入内网,或者其他原因。在你凭记忆学会 firewall-cmd 命令之前,你只要记住了关键词 changezone,就可以慢慢掌握,因为按下 Tab 时,它的选项会自动补全。

更多信息

你可以用你的防火墙干更多的事,比如自定义已存在的域,设置默认域,等等。你对防火墙越了解,你在网上的活动就越安全,所以我们创建了一个备忘单便于速查和参考。


via: https://opensource.com/article/20/2/firewall-cheat-sheet

作者:Seth Kenlon 选题:lujun9972 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

以下是如何使用 iptables 和 firewalld 工具来管理 Linux 防火墙规则。

这篇文章摘自我的书《Linux in Action》,尚未发布的第二个曼宁出版项目。

防火墙

防火墙是一组规则。当数据包进出受保护的网络区域时,进出内容(特别是关于其来源、目标和使用的协议等信息)会根据防火墙规则进行检测,以确定是否允许其通过。下面是一个简单的例子:

 title=

防火墙可以根据协议或基于目标的规则过滤请求。

一方面, iptables 是 Linux 机器上管理防火墙规则的工具。

另一方面,firewalld 也是 Linux 机器上管理防火墙规则的工具。

你有什么问题吗?如果我告诉你还有另外一种工具,叫做 nftables,这会不会糟蹋你的美好一天呢?

好吧,我承认整件事确实有点好笑,所以让我来解释一下。这一切都从 Netfilter 开始,它在 Linux 内核模块级别控制访问网络栈。几十年来,管理 Netfilter 钩子的主要命令行工具是 iptables 规则集。

因为调用这些规则所需的语法看起来有点晦涩难懂,所以各种用户友好的实现方式,如 ufw 和 firewalld 被引入,作为更高级别的 Netfilter 解释器。然而,ufw 和 firewalld 主要是为解决单独的计算机所面临的各种问题而设计的。构建全方面的网络解决方案通常需要 iptables,或者从 2014 年起,它的替代品 nftables (nft 命令行工具)。

iptables 没有消失,仍然被广泛使用着。事实上,在未来的许多年里,作为一名管理员,你应该会使用 iptables 来保护的网络。但是 nftables 通过操作经典的 Netfilter 工具集带来了一些重要的崭新的功能。

从现在开始,我将通过示例展示 firewalld 和 iptables 如何解决简单的连接问题。

使用 firewalld 配置 HTTP 访问

正如你能从它的名字中猜到的,firewalld 是 systemd 家族的一部分。firewalld 可以安装在 Debian/Ubuntu 机器上,不过,它默认安装在 RedHat 和 CentOS 上。如果您的计算机上运行着像 Apache 这样的 web 服务器,您可以通过浏览服务器的 web 根目录来确认防火墙是否正在工作。如果网站不可访问,那么 firewalld 正在工作。

你可以使用 firewall-cmd 工具从命令行管理 firewalld 设置。添加 –state 参数将返回当前防火墙的状态:

# firewall-cmd --state
running

默认情况下,firewalld 处于运行状态,并拒绝所有传入流量,但有几个例外,如 SSH。这意味着你的网站不会有太多的访问者,这无疑会为你节省大量的数据传输成本。然而,这不是你对 web 服务器的要求,你希望打开 HTTP 和 HTTPS 端口,按照惯例,这两个端口分别被指定为 80 和 443。firewalld 提供了两种方法来实现这个功能。一个是通过 –add-port 参数,该参数直接引用端口号及其将使用的网络协议(在本例中为TCP)。 另外一个是通过 –permanent 参数,它告诉 firewalld 在每次服务器启动时加载此规则:

# firewall-cmd --permanent --add-port=80/tcp
# firewall-cmd --permanent --add-port=443/tcp

–reload 参数将这些规则应用于当前会话:

# firewall-cmd --reload

查看当前防火墙上的设置,运行 –list-services

# firewall-cmd --list-services
dhcpv6-client http https ssh

假设您已经如前所述添加了浏览器访问,那么 HTTP、HTTPS 和 SSH 端口现在都应该是和 dhcpv6-client 一样开放的 —— 它允许 Linux 从本地 DHCP 服务器请求 IPv6 IP 地址。

使用 iptables 配置锁定的客户信息亭

我相信你已经看到了信息亭——它们是放在机场、图书馆和商务场所的盒子里的平板电脑、触摸屏和 ATM 类电脑,邀请顾客和路人浏览内容。大多数信息亭的问题是,你通常不希望用户像在自己家一样,把他们当成自己的设备。它们通常不是用来浏览、观看 YouTube 视频或对五角大楼发起拒绝服务攻击的。因此,为了确保它们没有被滥用,你需要锁定它们。

一种方法是应用某种信息亭模式,无论是通过巧妙使用 Linux 显示管理器还是控制在浏览器级别。但是为了确保你已经堵塞了所有的漏洞,你可能还想通过防火墙添加一些硬性的网络控制。在下一节中,我将讲解如何使用iptables 来完成。

关于使用 iptables,有两件重要的事情需要记住:你给出的规则的顺序非常关键;iptables 规则本身在重新启动后将无法保持。我会一次一个地在解释这些。

信息亭项目

为了说明这一切,让我们想象一下,我们为一家名为 BigMart 的大型连锁商店工作。它们已经存在了几十年;事实上,我们想象中的祖父母可能是在那里购物并长大的。但是如今,BigMart 公司总部的人可能只是在数着亚马逊将他们永远赶下去的时间。

尽管如此,BigMart 的 IT 部门正在尽他们最大努力提供解决方案,他们向你发放了一些具有 WiFi 功能信息亭设备,你在整个商店的战略位置使用这些设备。其想法是,登录到 BigMart.com 产品页面,允许查找商品特征、过道位置和库存水平。信息亭还允许进入 bigmart-data.com,那里储存着许多图像和视频媒体信息。

除此之外,您还需要允许下载软件包更新。最后,您还希望只允许从本地工作站访问 SSH,并阻止其他人登录。下图说明了它将如何工作:

 title=

*信息亭业务流由 iptables 控制。 *

脚本

以下是 Bash 脚本内容:

#!/bin/bash
iptables -A OUTPUT -p tcp -d bigmart.com -j ACCEPT
iptables -A OUTPUT -p tcp -d bigmart-data.com -j ACCEPT
iptables -A OUTPUT -p tcp -d ubuntu.com -j ACCEPT
iptables -A OUTPUT -p tcp -d ca.archive.ubuntu.com -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j DROP
iptables -A OUTPUT -p tcp --dport 443 -j DROP
iptables -A INPUT -p tcp -s 10.0.3.1 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -s 0.0.0.0/0 --dport 22 -j DROP

我们从基本规则 -A 开始分析,它告诉 iptables 我们要添加规则。OUTPUT 意味着这条规则应该成为输出链的一部分。-p 表示该规则仅使用 TCP 协议的数据包,正如 -d 告诉我们的,目的地址是 bigmart.com-j 参数的作用是当数据包符合规则时要采取的操作是 ACCEPT。第一条规则表示允许(或接受)请求。但,往下的规则你能看到丢弃(或拒绝)的请求。

规则顺序是很重要的。因为 iptables 会对一个请求遍历每个规则,直到遇到匹配的规则。一个向外发出的浏览器请求,比如访问 bigmart.com 是会通过的,因为这个请求匹配第一条规则,但是当它到达 dport 80dport 443 规则时——取决于是 HTTP 还是 HTTPS 请求——它将被丢弃。当遇到匹配时,iptables 不再继续往下检查了。(LCTT 译注:此处原文有误,径改。)

另一方面,向 ubuntu.com 发出软件升级的系统请求,只要符合其适当的规则,就会通过。显然,我们在这里做的是,只允许向我们的 BigMart 或 Ubuntu 发送 HTTP 或 HTTPS 请求,而不允许向其他目的地发送。

最后两条规则将处理 SSH 请求。因为它不使用端口 80 或 443 端口,而是使用 22 端口,所以之前的两个丢弃规则不会拒绝它。在这种情况下,来自我的工作站的登录请求将被接受,但是对其他任何地方的请求将被拒绝。这一点很重要:确保用于端口 22 规则的 IP 地址与您用来登录的机器的地址相匹配——如果不这样做,将立即被锁定。当然,这没什么大不了的,因为按照目前的配置方式,只需重启服务器,iptables 规则就会全部丢失。如果使用 LXC 容器作为服务器并从 LXC 主机登录,则使用主机 IP 地址连接容器,而不是其公共地址。

如果机器的 IP 发生变化,请记住更新这个规则;否则,你会被拒绝访问。

在家玩(是在某种一次性虚拟机上)?太好了。创建自己的脚本。现在我可以保存脚本,使用 chmod 使其可执行,并以 sudo 的形式运行它。不要担心“igmart-data.com 没找到”之类的错误 —— 当然没找到;它不存在。

chmod +X scriptname.sh
sudo ./scriptname.sh

你可以使用 cURL 命令行测试防火墙。请求 ubuntu.com 奏效,但请求 manning.com 是失败的 。

curl ubuntu.com
curl manning.com

配置 iptables 以在系统启动时加载

现在,我如何让这些规则在每次信息亭启动时自动加载?第一步是将当前规则保存。使用 iptables-save 工具保存规则文件。这将在根目录中创建一个包含规则列表的文件。管道后面跟着 tee 命令,是将我的sudo 权限应用于字符串的第二部分:将文件实际保存到否则受限的根目录。

然后我可以告诉系统每次启动时运行一个相关的工具,叫做 iptables-restore 。我们在上一章节(LCTT 译注:指作者的书)中看到的常规 cron 任务并不适用,因为它们在设定的时间运行,但是我们不知道什么时候我们的计算机可能会决定崩溃和重启。

有许多方法来处理这个问题。这里有一个:

在我的 Linux 机器上,我将安装一个名为 anacron 的程序,该程序将在 /etc/ 目录中为我们提供一个名为 anacrontab 的文件。我将编辑该文件并添加这个 iptables-restore 命令,告诉它加载那个 .rule 文件的当前内容。当引导后,规则每天(必要时)01:01 时加载到 iptables 中(LCTT 译注:anacron 会补充执行由于机器没有运行而错过的 cron 任务,因此,即便 01:01 时机器没有启动,也会在机器启动会尽快执行该任务)。我会给该任务一个标识符(iptables-restore),然后添加命令本身。如果你在家和我一起这样,你应该通过重启系统来测试一下。

sudo iptables-save | sudo tee /root/my.active.firewall.rules
sudo apt install anacron
sudo nano /etc/anacrontab
1 1 iptables-restore iptables-restore < /root/my.active.firewall.rules

我希望这些实际例子已经说明了如何使用 iptables 和 firewalld 来管理基于 Linux 的防火墙上的连接问题。


via: https://opensource.com/article/18/9/linux-iptables-firewalld

作者:David Clinton 选题:lujun9972 译者:heguangzhi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

现在的新闻里充斥着服务器被攻击和数据失窃事件。对于一个阅读过安全公告博客的人来说,通过访问错误配置的服务器,利用最新暴露的安全漏洞或通过窃取的密码来获得系统控制权,并不是件多困难的事情。在一个典型的 Linux 服务器上的任何互联网服务都可能存在漏洞,允许未经授权的系统访问。

因为在应用程序层面上强化系统以防范任何可能的威胁是不可能做到的事情,而防火墙可以通过限制对系统的访问提供了安全保证。防火墙基于源 IP、目标端口和协议来过滤入站包。因为这种方式中,仅有几个 IP/端口/协议的组合与系统交互,而其它的方式做不到过滤。

Linux 防火墙是通过 netfilter 来处理的,它是内核级别的框架。这十几年来,iptables 被作为 netfilter 的用户态抽象层(LCTT 译注: userland,一个基本的 UNIX 系统是由 kernel 和 userland 两部分构成,除 kernel 以外的称为 userland)。iptables 将包通过一系列的规则进行检查,如果包与特定的 IP/端口/协议的组合匹配,规则就会被应用到这个包上,以决定包是被通过、拒绝或丢弃。

Firewalld 是最新的 netfilter 用户态抽象层。遗憾的是,由于缺乏描述多区域配置的文档,它强大而灵活的功能被低估了。这篇文章提供了一个示例去改变这种情况。

Firewalld 的设计目标

firewalld 的设计者认识到大多数的 iptables 使用案例仅涉及到几个单播源 IP,仅让每个符合白名单的服务通过,而其它的会被拒绝。这种模式的好处是,firewalld 可以通过定义的源 IP 和/或网络接口将入站流量分类到不同 区域 zone 。每个区域基于指定的准则按自己配置去通过或拒绝包。

另外的改进是基于 iptables 进行语法简化。firewalld 通过使用服务名而不是它的端口和协议去指定服务,使它更易于使用,例如,是使用 samba 而不是使用 UDP 端口 137 和 138 和 TCP 端口 139 和 445。它进一步简化语法,消除了 iptables 中对语句顺序的依赖。

最后,firewalld 允许交互式修改 netfilter,允许防火墙独立于存储在 XML 中的永久配置而进行改变。因此,下面的的临时修改将在下次重新加载时被覆盖:

# firewall-cmd <some modification>

而,以下的改变在重加载后会永久保存:

# firewall-cmd --permanent <some modification>
# firewall-cmd --reload

区域

在 firewalld 中最上层的组织是区域。如果一个包匹配区域相关联的网络接口或源 IP/掩码 ,它就是区域的一部分。可用的几个预定义区域:

# firewall-cmd --get-zones
block dmz drop external home internal public trusted work

任何配置了一个网络接口和/或一个的区域就是一个 活动区域 active zone 。列出活动的区域:

# firewall-cmd --get-active-zones
public
  interfaces: eno1 eno2

Interfaces (接口)是系统中的硬件和虚拟的网络适配器的名字,正如你在上面的示例中所看到的那样。所有的活动的接口都将被分配到区域,要么是默认的区域,要么是用户指定的一个区域。但是,一个接口不能被分配给多于一个的区域。

在缺省配置中,firewalld 设置所有接口为 public 区域,并且不对任何区域设置源。其结果是,public 区域是唯一的活动区域。

Sources (源)是入站 IP 地址的范围,它也可以被分配到区域。一个源(或重叠的源)不能被分配到多个区域。这样做的结果是产生一个未定义的行为,因为不清楚应该将哪些规则应用于该源。

因为指定一个源不是必需的,任何包都可以通过接口匹配而归属于一个区域,而不需要通过源匹配来归属一个区域。这表示通过使用优先级方式,优先到达多个指定的源区域,稍后将详细说明这种情况。首先,我们来检查 public 区域的配置:

# firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eno1 eno2
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
# firewall-cmd --permanent --zone=public --get-target
default

逐行说明如下:

  • public (default, active) 表示 public 区域是默认区域(当接口启动时会自动默认),并且它是活动的,因为,它至少有一个接口或源分配给它。
  • interfaces: eno1 eno2 列出了这个区域上关联的接口。
  • sources: 列出了这个区域的源。现在这里什么都没有,但是,如果这里有内容,它们应该是这样的格式 xxx.xxx.xxx.xxx/xx。
  • services: dhcpv6-client ssh 列出了允许通过这个防火墙的服务。你可以通过运行 firewall-cmd --get-services 得到一个防火墙预定义服务的详细列表。
  • ports: 列出了一个允许通过这个防火墙的目标端口。它是用于你需要去允许一个没有在 firewalld 中定义的服务的情况下。
  • masquerade: no 表示这个区域是否允许 IP 伪装。如果允许,它将允许 IP 转发,它可以让你的计算机作为一个路由器。
  • forward-ports: 列出转发的端口。
  • icmp-blocks: 阻塞的 icmp 流量的黑名单。
  • rich rules: 在一个区域中优先处理的高级配置。
  • default 是目标区域,它决定了与该区域匹配而没有由上面设置中显式处理的包的动作。

一个简单的单区域配置示例

如果只是简单地锁定你的防火墙。简单地在删除公共区域上当前允许的服务,并重新加载:

# firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client
# firewall-cmd --permanent --zone=public --remove-service=ssh
# firewall-cmd --reload

在下面的防火墙上这些命令的结果是:

# firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eno1 eno2
  sources:
  services:
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
# firewall-cmd --permanent --zone=public --get-target
default

本着尽可能严格地保证安全的精神,如果发生需要在你的防火墙上临时开放一个服务的情况(假设是 ssh),你可以增加这个服务到当前会话中(省略 --permanent),并且指示防火墙在一个指定的时间之后恢复修改:

# firewall-cmd --zone=public --add-service=ssh --timeout=5m

这个 timeout 选项是一个以秒(s)、分(m)或小时(h)为单位的时间值。

目标

当一个区域处理它的源或接口上的一个包时,但是,没有处理该包的显式规则时,这时区域的 目标 target 决定了该行为:

  • ACCEPT:通过这个包。
  • %%REJECT%%:拒绝这个包,并返回一个拒绝的回复。
  • DROP:丢弃这个包,不回复任何信息。
  • default:不做任何事情。该区域不再管它,把它踢到“楼上”。

在 firewalld 0.3.9 中有一个 bug (已经在 0.3.10 中修复),对于一个目标是除了“default”以外的源区域,不管允许的服务是什么,这的目标都会被应用。例如,一个使用目标 DROP 的源区域,将丢弃所有的包,甚至是白名单中的包。遗憾的是,这个版本的 firewalld 被打包到 RHEL7 和它的衍生版中,使它成为一个相当常见的 bug。本文中的示例避免了可能出现这种行为的情况。

优先权

活动区域中扮演两个不同的角色。关联接口行为的区域作为接口区域,并且,关联源行为的区域作为源区域(一个区域能够扮演两个角色)。firewalld 按下列顺序处理一个包:

  1. 相应的源区域。可以存在零个或一个这样的区域。如果这个包满足一个 富规则 rich rule 、服务是白名单中的、或者目标没有定义,那么源区域处理这个包,并且在这里结束。否则,向上传递这个包。
  2. 相应的接口区域。肯定有一个这样的区域。如果接口处理这个包,那么到这里结束。否则,向上传递这个包。
  3. firewalld 默认动作。接受 icmp 包并拒绝其它的一切。

这里的关键信息是,源区域优先于接口区域。因此,对于多区域的 firewalld 配置的一般设计模式是,创建一个优先源区域来允许指定的 IP 对系统服务的提升访问,并在一个限制性接口区域限制其它访问。

一个简单的多区域示例

为演示优先权,让我们在 public 区域中将 http 替换成 ssh,并且为我们喜欢的 IP 地址,如 1.1.1.1,设置一个默认的 internal 区域。以下的命令完成这个任务:

# firewall-cmd --permanent --zone=public --remove-service=ssh
# firewall-cmd --permanent --zone=public --add-service=http
# firewall-cmd --permanent --zone=internal --add-source=1.1.1.1
# firewall-cmd --reload

这些命令的结果是生成如下的配置:

# firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eno1 eno2
  sources:
  services: dhcpv6-client http
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
# firewall-cmd --permanent --zone=public --get-target
default
# firewall-cmd --zone=internal --list-all
internal (active)
  interfaces:
  sources: 1.1.1.1
  services: dhcpv6-client mdns samba-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
# firewall-cmd --permanent --zone=internal --get-target
default

在上面的配置中,如果有人尝试从 1.1.1.1 去 ssh,这个请求将会成功,因为这个源区域(internal)被首先应用,并且它允许 ssh 访问。

如果有人尝试从其它的地址,如 2.2.2.2,去访问 ssh,它不是这个源区域的,因为和这个源区域不匹配。因此,这个请求被直接转到接口区域(public),它没有显式处理 ssh,因为,public 的目标是 default,这个请求被传递到默认动作,它将被拒绝。

如果 1.1.1.1 尝试进行 http 访问会怎样?源区域(internal)不允许它,但是,目标是 default,因此,请求将传递到接口区域(public),它被允许访问。

现在,让我们假设有人从 3.3.3.3 拖你的网站。要限制从那个 IP 的访问,简单地增加它到预定义的 drop 区域,正如其名,它将丢弃所有的连接:

# firewall-cmd --permanent --zone=drop --add-source=3.3.3.3
# firewall-cmd --reload

下一次 3.3.3.3 尝试去访问你的网站,firewalld 将转发请求到源区域(drop)。因为目标是 DROP,请求将被拒绝,并且它不会被转发到接口区域(public)。

一个实用的多区域示例

假设你为你的组织的一台服务器配置防火墙。你希望允许全世界使用 httphttps 的访问,你的组织(1.1.0.0/16)和工作组(1.1.1.0/8)使用 ssh 访问,并且你的工作组可以访问 samba 服务。使用 firewalld 中的区域,你可以用一个很直观的方式去实现这个配置。

public 这个命名,它的逻辑似乎是把全世界访问指定为公共区域,而 internal 区域用于为本地使用。从在 public 区域内设置使用 httphttps 替换 dhcpv6-clientssh 服务来开始:

# firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client
# firewall-cmd --permanent --zone=public --remove-service=ssh
# firewall-cmd --permanent --zone=public --add-service=http
# firewall-cmd --permanent --zone=public --add-service=https

然后,取消 internal 区域的 mdnssamba-clientdhcpv6-client 服务(仅保留 ssh),并增加你的组织为源:

# firewall-cmd --permanent --zone=internal --remove-service=mdns
# firewall-cmd --permanent --zone=internal --remove-service=samba-client
# firewall-cmd --permanent --zone=internal --remove-service=dhcpv6-client
# firewall-cmd --permanent --zone=internal --add-source=1.1.0.0/16

为容纳你提升的 samba 的权限,增加一个富规则:

# firewall-cmd --permanent --zone=internal --add-rich-rule='rule family=ipv4 source address="1.1.1.0/8" service name="samba" accept'

最后,重新加载,把这些变化拉取到会话中:

# firewall-cmd --reload

仅剩下少数的细节了。从一个 internal 区域以外的 IP 去尝试通过 ssh 到你的服务器,结果是回复一个拒绝的消息。它是 firewalld 默认的。更为安全的作法是去显示不活跃的 IP 行为并丢弃该连接。改变 public 区域的目标为 DROP,而不是 default 来实现它:

# firewall-cmd --permanent --zone=public --set-target=DROP
# firewall-cmd --reload

但是,等等,你不再可以 ping 了,甚至是从内部区域!并且 icmp (ping 使用的协议)并不在 firewalld 可以列入白名单的服务列表中。那是因为,icmp 是第 3 层的 IP 协议,它没有端口的概念,不像那些捆绑了端口的服务。在设置公共区域为 DROP 之前,ping 能够通过防火墙是因为你的 default 目标通过它到达防火墙的默认动作(default),即允许它通过。但现在它已经被删除了。

为恢复内部网络的 ping,使用一个富规则:

# firewall-cmd --permanent --zone=internal --add-rich-rule='rule protocol value="icmp" accept'
# firewall-cmd --reload

结果如下,这里是两个活动区域的配置:

# firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eno1 eno2
  sources:
  services: http https
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
# firewall-cmd --permanent --zone=public --get-target
DROP
# firewall-cmd --zone=internal --list-all
internal (active)
  interfaces:
  sources: 1.1.0.0/16
  services: ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
        rule family=ipv4 source address="1.1.1.0/8" service name="samba" accept
        rule protocol value="icmp" accept
# firewall-cmd --permanent --zone=internal --get-target
default

这个设置演示了一个三层嵌套的防火墙。最外层,public,是一个接口区域,包含全世界的访问。紧接着的一层,internal,是一个源区域,包含你的组织,它是 public 的一个子集。最后,一个富规则增加到最内层,包含了你的工作组,它是 internal 的一个子集。

这里的关键信息是,当在一个场景中可以突破到嵌套层,最外层将使用接口区域,接下来的将使用一个源区域,并且在源区域中额外使用富规则。

调试

firewalld 采用直观范式来设计防火墙,但比它的前任 iptables 更容易产生歧义。如果产生无法预料的行为,或者为了更好地理解 firewalld 是怎么工作的,则可以使用 iptables 描述 netfilter 是如何配置操作的。前一个示例的输出如下,为了简单起见,将输出和日志进行了修剪:

# iptables -S
-P INPUT ACCEPT
... (forward and output lines) ...
-N INPUT_ZONES
-N INPUT_ZONES_SOURCE
-N INPUT_direct
-N IN_internal
-N IN_internal_allow
-N IN_internal_deny
-N IN_public
-N IN_public_allow
-N IN_public_deny
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
-A INPUT -p icmp -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j REJECT --reject-with icmp-host-prohibited
... (forward and output lines) ...
-A INPUT_ZONES -i eno1 -j IN_public
-A INPUT_ZONES -i eno2 -j IN_public
-A INPUT_ZONES -j IN_public
-A INPUT_ZONES_SOURCE -s 1.1.0.0/16 -g IN_internal
-A IN_internal -j IN_internal_deny
-A IN_internal -j IN_internal_allow
-A IN_internal_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
-A IN_internal_allow -s 1.1.1.0/8 -p udp -m udp --dport 137 -m conntrack --ctstate NEW -j ACCEPT
-A IN_internal_allow -s 1.1.1.0/8 -p udp -m udp --dport 138 -m conntrack --ctstate NEW -j ACCEPT
-A IN_internal_allow -s 1.1.1.0/8 -p tcp -m tcp --dport 139 -m conntrack --ctstate NEW -j ACCEPT
-A IN_internal_allow -s 1.1.1.0/8 -p tcp -m tcp --dport 445 -m conntrack --ctstate NEW -j ACCEPT
-A IN_internal_allow -p icmp -m conntrack --ctstate NEW -j ACCEPT
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public -j DROP
-A IN_public_allow -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
-A IN_public_allow -p tcp -m tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT

在上面的 iptables 输出中,新的链(以 -N 开始的行)是被首先声明的。剩下的规则是附加到(以 -A 开始的行) iptables 中的。已建立的连接和本地流量是允许通过的,并且入站包被转到 INPUT_ZONES_SOURCE 链,在那里如果存在相应的区域,IP 将被发送到那个区域。从那之后,流量被转到 INPUT_ZONES 链,从那里它被路由到一个接口区域。如果在那里它没有被处理,icmp 是允许通过的,无效的被丢弃,并且其余的都被拒绝。

结论

firewalld 是一个文档不足的防火墙配置工具,它的功能远比大多数人认识到的更为强大。以创新的区域范式,firewalld 允许系统管理员去分解流量到每个唯一处理它的分类中,简化了配置过程。因为它直观的设计和语法,它在实践中不但被用于简单的单一区域中也被用于复杂的多区域配置中。


via: https://www.linuxjournal.com/content/understanding-firewalld-multi-zone-configurations

作者:Nathan Vance 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出