当我尝试在 LXC 容器上加载一组大型 iptables 规则时,我遇到了一个奇怪的问题(它在虚拟机上运行良好)。
该容器正在运行 Linux Debian 12 bookworm。
我可以配置规则并使用以下命令保存它们:
/usr/sbin/netfilter-persistent save
但是,如果我尝试加载它们,我会收到此错误消息(文件长度为 694 个字符)
$ sudo iptables-restore < /etc/iptables/rules.v4
sendmsg() failed: Message too long
iptables-restore: line 692 failed: Message too long.
奇怪的是,如果我添加详细模式,它就可以正常工作
$ sudo iptables-restore -v < /etc/iptables/rules.v4 && echo ok
(...)
# Completed on Fri Sep 15 08:57:48 2023
ok
但是,如果我尝试加载一个大文件(33750 行),无论是否处于详细模式,我总是会收到“消息太长”错误。
所有加载测试在虚拟机(相同操作系统)上运行良好。
所以我想知道 LXC 中是否存在行数限制或内存限制?我尝试过,limits.conf
但还没有改变任何东西。
任何想法 ?
编辑以下是重现此行为的更多信息:
内核版本:
Linux xxxxxx 6.2.16-10-pve #1 SMP PREEMPT_DYNAMIC PMX 6.2.16-10 (2023-08-18T11:42Z) x86_64 GNU/Linux
一些软件包版本(客户容器):
ii iptables 1.8.9-2 amd64 administration tools for packet filtering and NAT
ii iptables-persistent 1.0.20 all boot-time loader for netfilter rules, iptables plugin
ii libip4tc2:amd64 1.8.9-2 amd64 netfilter libip4tc library
ii libip6tc2:amd64 1.8.9-2 amd64 netfilter libip6tc library
ii libnetfilter-conntrack3:amd64 1.0.9-3 amd64 Netfilter netlink-conntrack library
ii libxtables12:amd64 1.8.9-2 amd64 netfilter xtables library
ii netfilter-persistent 1.0.20 all boot-time loader for netfilter configuration
主机包:
ii lxc-pve 5.0.2-4 amd64 Linux containers userspace tools
ii lxcfs 5.0.3-pve3 amd64 LXC userspace filesystem
ii pve-lxc-syscalld 1.3.0 amd64 PVE LXC syscall daemon
小规则是:
# Generated by iptables-save v1.8.9 (nf_tables) on Fri Sep 15 08:57:48 2023
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:block_spam2 - [0:0]
:block_spam1 - [0:0]
:block_spam3 - [0:0]
:incoming_net - [0:0]
:sensitive_daemons - [0:0]
-A INPUT -j block_spam1
-A INPUT -j block_spam2
-A INPUT -j block_spam3
-A INPUT -j sensitive_daemons
-A INPUT -j incoming_net
-A INPUT -j sensitive_daemons
-A block_spam2 -s 1.0.1.0/24 -j DROP
-A block_spam2 -s 84.22.192.0/19 -j DROP
-A block_spam1 -s 103.39.156.0/22 -j DROP
-A block_spam1 -s 5.255.220.0/22 -j DROP
-A block_spam3 -s 87.245.234.136/32 -j DROP
-A block_spam3 -s 217.199.224.0/19 -j DROP
[...] 675 lines here : block_spam[1-3] with a uniq ip address [...]
-A incoming_net -d 192.168.1.248/29 -p tcp -m tcp --dport 80 -j ACCEPT
-A incoming_net -d 192.168.1.248/29 -p tcp -m tcp --dport 443 -j ACCEPT
-A incoming_net -d 192.168.1.248/29 -p tcp -j DROP
-A sensitive_daemons -s 192.168.1.248/29 -p tcp -m tcp --dport 22 -j DROP
-A sensitive_daemons -s 192.168.1.0/24 -d 192.168.1.24/32 -p tcp -m tcp --dport 22 -j ACCEPT
-A sensitive_daemons -p tcp -m tcp --dport 22 -j DROP
COMMIT
# Completed on Fri Sep 15 08:57:48 2023
答案1
您应该考虑使用 ipset 来保留 block_spam* 规则的主机/网络地址(并可能将它们合并为一个集合),这样会更快。或者直接转到 nftables 并使用内置集合。
答案2
如果您查看 sendmsg() 手册页,您会发现它实际上没有指示消息太大的响应。但是,如果消息缓冲区中没有足够的空间,它会返回 ENOBUFS - 类似,但不是同一件事。我怀疑这就是这里发生的事情。并且当没有任何东西清空消息缓冲区时会导致这种情况 - 套接字通信以某种方式失败。为什么 iptables-restore 会写入套接字?最有可能的是它试图写入日志条目(或一个大条目),但这主要是猜测。在大多数现代 Linux 上,“iptables-restore”是一个指向数据包过滤工具的几种实现之一的符号链接。
如果iptables-restore -v
有效,那么你有一个解决方法,但是拥有大量防火墙规则的最可能原因是你直接添加了有关单个客户端地址的规则。这对于少量地址来说没问题,但无法扩展。正如@Tomek 所说,使用ipset
是一个更好的解决方案(这确实可以扩展)。