{pve} 防火墙为保护您的 IT 基础设施提供了一种简单的方法。您可以为集群内的所有主机设置防火墙规则,或为虚拟机和容器定义规则。诸如防火墙宏、安全组、IP集和别名之类的功能有助于简化这项任务。

虽然所有配置都存储在集群文件系统上,但基于`iptables`的防火墙服务在每个集群节点上运行,因此提供了虚拟机之间的完全隔离。这种系统的分布式特性也比中央防火墙解决方案提供了更高的带宽。

防火墙完全支持IPv4和IPv6。IPv6支持是完全透明的,默认情况下我们会过滤两种协议的流量。因此,没有必要为IPv6维护一套不同的规则。

区域

Proxmox VE 防火墙将网络分为以下逻辑区域:

主机

集群节点的进出流量

虚拟机

特定虚拟机的流量出入

对于每个区域,您可以为进出流量定义防火墙规则。

配置文件

所有与防火墙相关的配置都存储在proxmox集群文件系统上。因此,这些文件会自动分发到所有集群节点上,并且当配置发生变化时,`pve-firewall`服务会自动更新底层的`iptables`规则。

你可以使用GUI配置任何东西(即*数据中心*→*防火墙*,或者在*节点*→*防火墙*上),或者你可以使用你喜欢的编辑器直接编辑配置文件。

防火墙配置文件包含许多键值对的部分。以`#开头的行和空白行被视为注释。各个部分以一个标题行开始,包含用[]`括起来的部分名称。

集群范围设置

集群范围内的防火墙配置存储在:

/etc/pve/firewall/cluster.fw

配置可以包含以下几个部分:

[OPTIONS]

这用于设置集群范围的防火墙选项。

ebtables`: <boolean> (default = 1)

在整个集群范围内启用ebtables规则。

enable`: `<integer> (0 - N)

在整个防火墙群集中启用或禁用。

log_ratelimit`: `[enable=]<1|0> [,burst=<integer>] [,rate=<rate>]

日志速率限制设置

burst`=<integer> (0 - N) (default = 5)

率先应用速率之前将始终被记录的一系列初始数据包 burst 包装

enable`=<boolean> (default = 1)

启用或禁用日志速率限制

rate`=<rate> (default = 1/second)

爆发令牌桶的填充频率

policy_in`: `<ACCEPT | DROP | REJECT>

输入策略。

policy_out`:`<接受 | 丢弃 | 拒绝>

输出政策。

[RULES]

这一部分包含了适用于所有节点的集群范围防火墙规则。

[IPSET <name>]

集群范围的IP集定义。

[GROUP <name>]

集群范围的安全组定义。

[ALIASES]

集群范围内的别名定义。

开启防火墙

默认情况下,防火墙是完全禁用的,因此你需要在这里设置启用选项:

[OPTIONS]
# enable firewall (cluster-wide setting, default is disabled)
enable: 1
Important
如果你启用防火墙,默认情况下所有主机的流量都会被阻止。唯一的例外是你的本地网络中的WebGUI(8006)和ssh(22)。

如果您想要从远程管理您的{pve}主机,您需要创建规则,允许那些远程IP通过网络GUI(端口8006)访问。您可能还想允许ssh(端口22),以及可能的SPICE(端口3128)。

Tip
请在启用防火墙之前,先通过SSH连接到其中一个{PVE}主机。这样如果出了什么问题,你仍然可以访问到主机。

为了简化这项任务,你可以创建一个名为“management”的IPSet,并在其中添加所有远程IP。这样就能创建所有必要的防火墙规则来实现从远程访问GUI。

主机特定配置

主机相关配置读取自:

/etc/pve/nodes/<nodename>/host.fw

如果你想要覆盖来自`cluster.fw`配置的规则,这会很有用。你还可以提高日志的详细性,以及设置与netfilter相关的选项。配置可以包含以下部分:

[OPTIONS]

这用于设置与主机相关的防火墙选项。

enable`: `<boolean>

启用主机防火墙规则。

log_level_in`: `<alert | crit | debug | emerg | err | info | nolog | notice | warning>

传入流量的日志级别。

log_level_out`: `<alert | crit | debug | emerg | err | info | nolog | notice | warning>

出站流量的日志级别。

log_nf_conntrack`: <boolean> (default = 0)

启用连接跟踪信息的记录。

ndp`: <boolean> (default = 0)

启用NDP(邻居发现协议)。

nf_conntrack_allow_invalid`: <boolean> (default = 0)

在连接跟踪中允许无效的数据包。

nf_conntrack_helpers`: <string> (default = ``)

为特定协议启用连接跟踪助手。支持的协议有:amanda, ftp, irc, netbios-ns, pptp, sane, sip, snmp, tftp

nf_conntrack_max`: <integer> (32768 - N) (default = 262144)

最大追踪连接数。

nf_conntrack_tcp_timeout_established`: <integer> (7875 - N) (default = 432000)

Conntrack 已建立超时。

nf_conntrack_tcp_timeout_syn_recv`: <integer> (30 - 60) (default = 60)

Conntrack同步接收超时。

nosmurfs`: `<boolean>

启用SMURFS过滤器。

protection_synflood`: <boolean> (default = 0)

启用synflood攻击保护

protection_synflood_burst`: <integer> (default = 1000)

根据源 IP 的 Synflood 保护速率爆发。

protection_synflood_rate`: <integer> (default = 200)

源IP的每秒SYN泛洪保护速率。

smurf_log_level```: ```<alert | crit | debug | emerg | err | info | nolog | notice | warning>

SMURFS过滤器的日志级别。

tcp_flags_log_level`: `<alert | crit | debug | emerg | err | info | nolog | notice | warning>

非法TCP标志过滤器的日志级别。

tcpflags`:<boolean>(默认值=0

过滤TCP标志的非法组合。

[RULES]

这一部分包含了针对主机的特定防火墙规则。

VM/容器配置

VM防火墙配置读取自:

/etc/pve/firewall/<VMID>.fw

包含以下数据:

[OPTIONS]

这用于设置虚拟机/容器相关的防火墙选项。

dhcp`: <boolean> (default = 0)

启用DHCP。

enable`: <boolean> (default = 0)

启用/禁用防火墙规则。

ipfilter`: `<boolean>

启用默认的IP过滤器。这等同于为每个接口添加一个空的ipfilter-net<id> ipset集。这样的ipset隐含地包含理智的默认限制,例如限制IPv6链路本地地址到从接口的MAC地址派生的那一个。对于容器,配置的IP地址将被隐含地添加。

log_level_in`: `<alert | crit | debug | emerg | err | info | nolog | notice | warning>

输入流量的日志级别。

log_level_out`: `<alert | crit | debug | emerg | err | info | nolog | notice | warning>

出站流量的日志级别。

macfilter`: <boolean> (default = 1)

启用/禁用MAC地址过滤。

ndp`: <boolean> (default = 0)

启用NDP(邻居发现协议)。

policy_in`: `<ACCEPT | DROP | REJECT>

输入策略。

policy_out`: `<接受 | 丢弃 | 拒绝>

输出策略。

radv`: `<boolean>

允许发送路由器通告。

[RULES]

这部分包含了虚拟机/容器的防火墙规则。

[IPSET <name>]

IP集合定义。

[ALIASES]

IP别名定义。

为虚拟机和容器启用防火墙

每个虚拟网络设备都有自己的防火墙启用标志。因此,您可以为每个接口选择性地启用防火墙。这需要额外于一般防火墙的 enable 选项。

防火墙规则

防火墙规则由方向(INOUT)和动作(ACCEPT, DENY, REJECT)组成。您还可以指定宏名称。宏包含预定义的规则集和选项。可以通过在规则前加上 | 来禁用它们。

防火墙规则语法
[RULES]

DIRECTION ACTION [OPTIONS]
|DIRECTION ACTION [OPTIONS] # disabled rule

DIRECTION MACRO(ACTION) [OPTIONS] # 使用预定义宏

以下选项可用于精确规则匹配。

--dest` `<string>

限制数据包的目的地址。这可以指单个IP地址、一个IP集(+ipsetname)或一个IP别名定义。您还可以指定一个地址范围,如 20.34.101.207-201.3.9.99,或一个IP地址和网络的列表(条目之间用逗号分隔)。请不要在这样的列表中混合IPv4和IPv6地址。

--dport` `<string>

限制TCP/UDP目的端口。你可以使用服务名称或简单数字(0-65535),如'/etc/services’中定义。端口范围可以用'\d+:\d+指定,例如'80:85,你也可以使用逗号分隔列表来匹配多个端口或范围。

--icmp-type` `<string>

指定ICMP类型。只有当协议等于’icmp’或者’icmpv6'/'ipv6-icmp’时有效。

--iface` `<string>

网络接口名称。您必须对虚拟机和容器使用网络配置键名(net\d+)。与主机相关的规则可以使用任意字符串。

--log` `<alert | crit | debug | emerg | err | info | nolog | notice | warning>

防火墙规则的日志级别。

--proto` `<string>

IP协议。您可以使用协议名称(tcp/udp)或在'/etc/protocols’中定义的简单数字。

--source` `<string>

限制数据包源地址。这可以指一个单独的IP地址、一个IP集(+ipsetname)或一个IP别名定义。您还可以指定一个地址范围,如 20.34.101.207-201.3.9.99,或者一个IP地址和网络的列表(条目之间用逗号隔开)。请不要在这样的列表中混用IPv4和IPv6地址。

--sport` `<string>

限制TCP/UDP源端口。您可以使用服务名称或简单的数字(0-65535),如'/etc/services’中所定义。端口范围可以用'\d+:\d+指定,例如'80:85,并且您可以使用逗号分隔的列表来匹配多个端口或范围。

这里有一些例子:

[RULES]
IN SSH(ACCEPT) -i net0
IN SSH(ACCEPT) -i net0 # 一条注释
IN SSH(ACCEPT) -i net0 -source 192.168.2.192 # 仅允许来自192.168.2.192的SSH
IN SSH(ACCEPT) -i net0 -source 10.0.0.1-10.0.0.10 # 接受IP范围内的SSH连接
IN SSH(ACCEPT) -i net0 -source 10.0.0.1,10.0.0.2,10.0.0.3 #接受IP列表中的ssh连接
IN SSH(ACCEPT) -i net0 -source +mynetgroup # 接受ipset mynetgroup中的ssh连接
IN SSH(ACCEPT) -i net0 -source myserveralias #接受别名myserveralias的ssh连接

|IN SSH(ACCEPT) -i net0 # disabled rule

IN  DROP # drop all incoming packages
OUT ACCEPT # accept all outgoing packages

安全组

安全组是一组规则的集合,在集群级别定义,可以用于所有虚拟机的规则中。例如,您可以定义一个名为“webserver”的组,其中包含开放“http”和“https”端口的规则。

# /etc/pve/firewall/cluster.fw

[group webserver]
IN  ACCEPT -p tcp -dport 80
IN  ACCEPT -p tcp -dport 443

然后,你可以将这个组添加到虚拟机的防火墙中

# /etc/pve/firewall/<VMID>.fw

[RULES]
GROUP webserver

IP别名

IP别名允许您将网络的IP地址与一个名称关联起来。然后,您可以引用这些名称:

  • 内部IP集定义

  • 在防火墙规则中的`source`和`dest`属性

标准IP别名 `local_network

这个别名已经自动定义。请使用以下命令来查看已分配的值:

# pve-firewall localnet
local hostname: example
local IP address: 192.168.2.100
network auto detect: 192.168.0.0/20
using detected local_network: 192.168.0.0/20

防火墙会自动设置规则,使用这个别名允许集群通信(corosync、API、SSH)所需的一切。

用户可以在`cluster.fw`别名部分中覆盖这些值。如果你在公共网络上使用单个主机,最好是明确指定本地IP地址。

#  /etc/pve/firewall/cluster.fw
[ALIASES]
local_network 1.2.3.4 # use the single IP address

IP 集

IP集合可用于定义网络和主机的群组。在防火墙规则的`source`和`dest`属性中,你可以使用`+name`来引用它们。

以下示例允许来自`management` IP集的HTTP流量。

IN HTTP(ACCEPT) -source +management

标准IP集`管理

这个IP集只适用于主机防火墙(不适用于虚拟机防火墙)。这些IP允许执行正常的管理任务({PVE} GUI、VNC、SPICE、SSH)。

本地集群网络会被自动添加到此IP集合中(别名 cluster_network),以便开启主机间的集群通信。(多播,ssh等)

# /etc/pve/firewall/cluster.fw

[IPSET管理]
192.168.2.10
192.168.2.10/24

标准IP集 `blacklist

来自这些IP的流量会被每个主机和虚拟机的防火墙丢弃。

# /etc/pve/firewall/cluster.fw

[IPSET 黑名单]
77.240.159.182
213.87.123.0/24

标准 IP 集 `ipfilter-net*

这些过滤器属于虚拟机的网络接口,主要用于防止IP欺骗。如果接口有这样的过滤器集,那么任何源IP与其接口相应的ipfilter集不匹配的传出流量都将被丢弃。

对于配置了IP地址的容器,如果这些集合存在(或通过虚拟机防火墙的*选项*标签中的通用`IP过滤`选项激活),则隐含包含了关联的IP地址。

对于虚拟机和容器,它们也隐含包含了标准的MAC派生的IPv6链路本地地址,以便允许邻居发现协议正常工作。

/etc/pve/firewall/<VMID>.fw

[IPSET ipfilter-net0] # 仅允许特定的IP地址在net0上
192.168.2.10

服务和命令

防火墙在每个节点上运行两个服务守护进程。

  • pvefw-logger:NFLOG守护进程(ulogd的替代品)。

  • pve-firewall: 更新iptables规则

还有一个命令行指令,名为`pve-firewall`,可用于启动和停止防火墙服务:

pve-firewall start

# pve-firewall stop

要获取状态,请使用:

# pve-firewall status

上述命令读取并编译所有防火墙规则,因此如果您的防火墙配置中包含任何错误,您将看到警告。

如果你想查看生成的iptables规则,可以使用:

iptables-save

默认防火墙规则

默认防火墙配置过滤了以下流量:

数据中心进站/出站的丢弃/拒绝操作

如果防火墙的输入或输出策略设为DROP或REJECT,那么以下流量仍被允许通过所有集群中的{pve}主机:

  • 回环接口上的流量

  • 已建立的连接

  • 使用IGMP协议的流量

  • 允许管理主机通过TCP流量访问端口8006以便访问网页界面

  • 允许管理主机通过TCP流量访问5900到5999端口范围内的VNC网络控制台的流量

  • 管理主机的TCP流量经过3128端口连接到SPICE代理。

  • 允许管理主机通过TCP协议访问22端口以使用ssh进行远程访问

  • 在集群网络中的UDP流量到端口5405-5412用于corosync

  • 集群网络中的UDP组播流量

  • ICMP流量类型3(目的地不可达)、4(拥塞控制)或11(超时)。

即使启用了日志记录,以下流量也会被丢弃,但不会被记录:

  • 连接状态无效的TCP连接

  • 不涉及corosync的广播、多播和任播流量,即不通过5405-5412端口传送的流量。

  • 向端口43的TCP流量

  • 向端口135和445的UDP流量

  • UDP流量到端口范围137至139

  • UDP流量从源端口137到端口范围1024至65535

  • UDP流量到端口1900

  • TCP流量到端口135、139和445

  • 源自源端口53的UDP流量

剩余的流量分别被丢弃或拒绝,并且也会被记录。这可能会根据在*防火墙* → *选项*中启用的额外选项而有所不同,如NDP、SMURFS和TCP标志过滤。

请检查输出的结果

# iptables-save

system command to see the firewall chains and rules active on your system. This output is also included in a System Report, accessible over a node’s subscription tab in the web GUI, or through the pvereport command-line tool.

VM/CT 进入/离开 丢弃/拒绝

此操作将丢弃或拒绝所有传送至虚拟机的流量,但根据设置的配置,对于DHCP、NDP、路由器广告、MAC和IP过滤等有一些例外。用于丢弃/拒绝数据包的相同规则从数据中心继承而来,而针对主机接受的进/出流量的例外则不适用。

再次提醒,你可以使用iptables-save (见上文)来检查所有应用的规则和链条。

防火墙规则记录

默认情况下,防火墙规则过滤的流量日志记录功能是禁用的。要启用日志记录,必须在*Firewall* → Options*中为传入和/或传出流量设置`loglevel`。这可以为主机以及VM/CT防火墙单独进行设置。通过这种方式,启用了{PVE}的标准防火墙规则的日志记录,并且可以在*Firewall → *Log*中观察到输出。此外,对于标准规则,只有一些被丢弃或拒绝的数据包会被记录(参见默认防火墙规则)。

loglevel` 并不影响记录了多少过滤后的流量。它改变了一个 LOGID,这个 LOGID 被作为前缀附加到日志输出上,以便更容易进行过滤和后处理。

loglevel` 是以下标识之一:

loglevel LOGID

nolog

 — 

emerg

0

alert

1

crit

2

err

3

warning

4

notice

5

info

6

debug

7

一个典型的防火墙日志输出看起来像这样:

VMID 日志ID 链 时间戳 策略:数据包详情

在主机防火墙的情况下,VMID 等于 0。

用户定义的防火墙规则日志记录

为了记录用户自定义防火墙规则过滤掉的数据包,可以为每条规则单独设置一个日志级别参数。这使得可以以细粒度的方式记录日志,并且与在*防火墙* → *选项*中为标准规则定义的日志级别独立。

在创建或修改规则的过程中,每个单独规则的`loglevel`可以通过web用户界面轻松地定义或更改,也可以通过相应的`pvesh` API调用来设置。

此外,可以通过在防火墙配置文件中给选择的规则添加 -log <loglevel> 来设置日志级别(参见 可能的日志级别)。

例如,下面两者是相同的:

IN REJECT -p icmp -log nolog
IN REJECT -p icmp

然而

IN REJECT -p icmp -log debug

产生一个用`debug`级别标记的日志输出。

小技巧和窍门

如何允许FTP

FTP是一种旧式协议,它使用21端口和其他一些动态端口。因此,你需要一个规则来接受21端口。此外,你需要加载`ip_conntrack_ftp`模块。所以请运行:

modprobe ip_conntrack_ftp

/etc/modules 文件中添加 ip_conntrack_ftp(以便在重启后仍能工作)。

Suricata IPS 集成

如果你想使用[Suricata IPS](入侵防御系统),这是可能的。

数据包只有在防火墙接受(ACCEPT)之后才会被转发到入侵防御系统(IPS)。

被拒绝/丢弃的防火墙数据包不会发送到入侵防护系统(IPS)。

在Proxmox主机上安装Suricata:

# apt-get install suricata
# modprobe nfnetlink_queue

不要忘记在下次重启时将`nfnetlink_queue`添加到`/etc/modules`中。

然后,通过以下方式为特定虚拟机启用IPS:

# /etc/pve/firewall/<VMID>.fw

[OPTIONS]
ips: 1
ips_queues: 0

ips_queues`将为这个虚拟机绑定一个特定的CPU队列。

可用队列在此定义

# /etc/default/suricata
NFQUEUE=0

IPv6笔记

防火墙包含一些IPv6特定的选项。需要注意的一点是,IPv6不再使用ARP协议,而是使用在IP层工作的NDP(邻居发现协议),因此需要IP地址才能成功。为此,使用从接口的MAC地址派生的链路本地地址。默认情况下,`NDP`选项在主机和虚拟机级别上都是启用的,以允许发送和接收邻居发现(NDP)数据包。

除了邻居发现之外,NDP还被用于其他一些事情,比如自动配置和路由器广告。

默认情况下,虚拟机被允许发送路由请求消息(以查询路由器),并接收路由器广告包。这使它们能够使用无状态自动配置。另一方面,除非设置了“允许路由器广告”(radv: 1)选项,否则虚拟机不能宣告自己为路由器。

就NDP所需的链接本地地址而言,还有一个可以启用的“IP过滤器”(ipfilter: 1)选项,其效果与为每个虚拟机的网络接口添加一个包含相应链接本地地址的`ipfilter-net*` ipset相同。(有关详细信息,请参见标准IP集`ipfilter-net*`部分。)

{pve}使用的端口

  • Web接口:8006(TCP,HTTP/1.1 over TLS)

  • VNC Web控制台:5900-5999(TCP,WebSocket)

  • SPICE代理:3128(TCP)

  • sshd(用于集群操作):22(TCP)

  • rpcbind: 111(UDP)

  • sendmail: 25 (TCP, outgoing)

  • corosync集群流量:5405-5412 UDP

  • 实时迁移(虚拟机内存和本地磁盘数据):60000-60050(TCP)