无显示输出时重启 Linux
今天调试 PVE 的防火墙时玩脱了,之前开启的 SSH 因为网络问题断开了,没开个新的就在 WebUI 上把 Firewall 开启。
直接键盘显示器连上主机发现没有显示输出,狂按键盘 Ctrl + Alt + Del 居然触发了重启。安全关机也算救了回来吧。
回来后按 Proxmox VE Firewall 说明在集群防火墙页面添加一个名为 management 的 IPSet 就能避免以后被拦在外面了。
PVE Firewall 阻拦了 ICMPv6 响应
开启 PVE Host 的防火墙后,发现个奇怪的现象。从 PVE 向外 ping 没问题,但从外向内 ping 就被阻拦。
Chain PVEFW-HOST-IN (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo * ::/0 ::/0
50 11883 DROP all -- * * ::/0 ::/0 ctstate INVALID
0 0 ACCEPT all -- * * ::/0 ::/0 ctstate RELATED,ESTABLISHED
0 0 RETURN ipv6-icmp -- * * ::/0 ::/0 ipv6-icmptype 133
20 2560 RETURN ipv6-icmp -- * * ::/0 ::/0 ipv6-icmptype 134
1 72 RETURN ipv6-icmp -- * * ::/0 ::/0 ipv6-icmptype 135
0 0 RETURN ipv6-icmp -- * * ::/0 ::/0 ipv6-icmptype 136
0 0 RETURN 2 -- * * ::/0 ::/0
0 0 RETURN tcp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src tcp dpt:22
0 0 RETURN ipv6-icmp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src ipv6-icmptype 128
0 0 RETURN ipv6-icmp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src ipv6-icmptype 133
0 0 RETURN ipv6-icmp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src ipv6-icmptype 134
0 0 RETURN ipv6-icmp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src ipv6-icmptype 135
0 0 RETURN ipv6-icmp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src ipv6-icmptype 136
0 0 RETURN tcp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src tcp dpt:8006
0 0 RETURN tcp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src tcp dpts:5900:5999
0 0 RETURN tcp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src tcp dpt:3128
0 0 RETURN tcp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src tcp dpt:22
0 0 RETURN tcp -- * * ::/0 ::/0 match-set PVEFW-0-management-v6 src tcp dpts:60000:60050
2 152 RETURN all -- * * ::/0 ::/0
0 0 all -- * * ::/0 ::/0 /* PVESIG:s8wIEvSJZJINuAc5Bit+Y6u/CaU */通过对比开关前后的表现,定位到是 ctstate INVALID 这行拦截了 ICMPv6 返程。
也有人落下了相似的结论:
- Is there anyway to turn off the ctstate invalid DROP rule in pve-firewall? : r/Proxmox 但很可惜这个参数 不影响
PVEFW-HOST-IN的内容。 - ipv6 - Multicast ICMPv6 comes back with conntrack state invalid - Unix & Linux Stack Exchange
总之对于 PVE-Firewall 为什么把 -A PVEFW-HOST-IN -m conntrack --ctstate INVALID -j DROP 放在前面还是不得而知。
实际原因是 使用 MACVLAN 为主机同时分配静态 IP 并取得动态 IP 多网卡产生了回程非对称路由。最终我打算关掉 PVE 层的防火墙,让 Openwrt 来处理过滤。
Obsidian Linter 格式化斜体下划线和双引号时会添加前后空格
之前在 Obsidian Linter 设置过 Emphasis Style - Content Rules - Linter 的 ” 保持突出样式一致性 ” 为 underscore,想要和 * 粗体 * 使用的 asterisk 区分开。
但同时我又开启了 Space between Chinese Japanese or Korean and English or numbers -Spacing Rules - Linter 确保中日韩文与英文数字之间有一个空格,配置为 -+;:'"°%$)]。
代代 “你好”
效果是只要在英文符号边上多了个空格,就会在两边都加上,从而破坏 Markdown 格式
"你好"→" 你好 "*你好 *→* 你好 *
总之感觉是 bug。
把配置改为 -+;:'°%$)] 能缓解引号的问题,但下划线代表斜体还是有问题,只好继续用星号代表斜体了。
PVE 下的网桥应该关闭 multicast snooping
长久以来的问题和临时地解决方案终于有了结论:
- 给 Docker 配置完整的 IPv6 macvlan 网络环境
- 容器响应 IPv6 前缀变动并更新 DDNS
- 多接口在同一个 IPv6 网段下的冲突
- linux kernel - What is multicast snooping and why does it break UPnP/DLNA? - Unix & Linux Stack Exchange
PVE 的 Linux Bridge 默认启用了 multicast_snooping,在面对 NS 组播查询时,组播表没有对应的条目,网桥则默认丢弃。所以表现是 PVE 上能看到 neighbor solicitation 包,但 OpenWrt 上没这个包被转发过来。
关闭 snooping 验证一下
echo 0 > /sys/devices/virtual/net/vmbr0/bridge/multicast_snooping一些有用的调试命令
ip -6 maddrbridge -d mdb show routertcpdump -n icmp6
额外发现 ifupdown-addons-interfaces(5) — ifupdown2 — Debian bookworm — Debian Manpages 有自带的拓展语句直接支持了,不再需要魔法般的 post-up 语句。
auto vmbr0
iface vmbr0 inet dhcp
iface vmbr0 inet static
address 192.168.9.17/24
gateway 192.168.9.1
bridge-ports enp5s0
bridge-stp off
bridge-fd 0
bridge-mcsnoop no另一个办法是设置目标端口为 multicast_router
echo 2 > /sys/class/net/vmbr0/brif/veth104i0/multicast_router不过使用 multicast router 相比禁用 multicast snooping 在冷启动上处于劣势,要等个几秒。
而且还得计算虚拟网卡 veth104i0 的坐标。
$ ping 2409:8a1e:6940:7c20:be24:11ff:fea3:22a4
正在 Ping 2409:8a1e:6940:7c20:be24:11ff:fea3:22a4 具有 32 字节的数据:
无法访问目标主机。
无法访问目标主机。
来自 2409:8a1e:6940:7c20:be24:11ff:fea3:22a4 的回复: 时间=675ms
来自 2409:8a1e:6940:7c20:be24:11ff:fea3:22a4 的回复: 时间<1ms
2409:8a1e:6940:7c20:be24:11ff:fea3:22a4 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 2,丢失 = 2 (50% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 0ms,最长 = 675ms,平均 = 337ms我 PVE 上的 vmbr0 实际上只挂了个 OpenWrt,所以禁用 snooping 其实也没什么广播群发劣化效应。但我还是保留更佳实践,采用 router。
设置这个条目直接 hardcode 不行,因为 PVE 启动时容器还没启动。那么就需要个 pct hookscript 来在容器启动时,设置这个。
- How to use new hookscript feature? | Proxmox Support Forum
- pve-docs/examples/guest-example-hookscript.pl at master · proxmox/pve-docs
拎一个 AI 来 写代码,然后设置上就完了
#!/usr/bin/perl
# Enable multicast routing for a Proxmox VE container's network interface on vmbr0
# You can set this via pct/qm with
# pct set 104 --hookscript local:snippets/multicast-router.pl
use strict;
use warnings;
# First argument is the vmid
my $vmid = shift;
# Second argument is the phase
my $phase = shift;
if ($phase eq 'post-start') {
# 定义网桥名称 (通常是 vmbr0,根据实际情况修改)
my $bridge = "vmbr0";
# 定义可能的接口名称模式
# 1. veth${vmid}i0 : 对应 net0,防火墙关闭时
# 2. fwpr${vmid}p0 : 对应 net0,防火墙开启时
# 如果你的 OpenWrt 使用的是 net1,请相应修改为 i1 / p1
my @interfaces = ("veth${vmid}i0", "fwpr${vmid}p0");
# 稍微等待一下,防止脚本执行时内核还未完成接口创建
sleep(1);
foreach my $iface (@interfaces) {
# 构建 sysfs 路径
my $path = "/sys/class/net/$bridge/brif/$iface/multicast_router";
# 检查路径是否存在(即接口是否已连接到网桥)
if (-e $path) {
# 尝试写入 '2' (强制开启)
if (open(my $fh, '>', $path)) {
print $fh "2";
close $fh;
print "HOOK: Set multicast_router=2 for VM $vmid interface $iface\n";
last; # 找到一个即可退出循环
} else {
warn "HOOK: Failed to write to $path: $!\n";
}
}
}
}
exit(0);