我有一个基于 Linux 的进程控制器,有时会锁定到无法 ping 它的程度(即我可以 ping 它,然后在不对网络设置进行任何修改的情况下,它就不再可 ping 通)。
我很好奇,哪个进程/系统负责实际响应 ping?看来这个进程正在崩溃。
答案1
内核网络堆栈正在处理 ICMP 消息,这些消息是由ping
命令发送的。
如果您没有得到回复,除了网络问题或过滤,以及基于主机的过滤/速率限制/黑洞/等。这意味着机器可能因某些原因而过载,这可能是暂时的,或者内核崩溃,这种情况很少见,但可能会发生(硬件故障等),不一定是因为 ICMP 流量(但试图用此类流量使其过载)可以在服务器生命周期之初进行很好的测试,看看它如何维持事物)。在后一种内核崩溃的情况下,您应该在日志文件或控制台上有足够的信息。
另请注意,ping
检查服务是否在线的工具几乎总是错误的。出于多种原因,但主要是因为根据定义,它没有模拟真实的应用程序流量。例如,如果您需要检查网络服务器是否仍处于活动状态,则应该对其执行 HTTP 查询(TCP 端口 80 或 443),如果您需要检查邮件服务器,则执行 SMTP 查询(TCP 端口 25),如果DNS 服务器、UDP和对端口 53 等的 TCP 查询
答案2
没有用户态进程负责响应 ping。 Ping 只是发送 ICMP 回显数据包的实用程序。这些由内核的网络堆栈接收和处理
答案3
内核本身(不是任何用户进程)负责发送ICMP 回显回复回复消息ICMP 回显请求消息。因此,如果主机停止响应 ping,通常是由于以下原因造成的:
您和被 ping 的主机之间的网络连接可能已被切断。这可能是由于多种原因本身造成的:电缆的物理损坏、无线情况下的噪音、路由表损坏、您受到 DDoS 攻击、中间的路由器/交换机有问题等。在这种情况下,您可以通过以下方式开始故障排除在目标主机上使用
ethtool(8)
、iwconfig(8)
、route(8)
、ping(8)
其路由器等。tcpdump(8)
目标主机(或您和目标主机之间的任何路由器/防火墙)上的防火墙设置可能会限制 ping 数量(或流量流量)。这也可能是由于
fail2ban(8)
按需防火墙之类的工具造成的。看看iptables(8)
检查一下。目标主机出现软件/硬件故障。目标主机上的网络内核模块可能发生 OOPSed 和/或变得混乱,甚至整个内核可能发生 PANICked。您将在目标主机上看到有关 at in 的消息
dmesg(8)
,或者在物理控制台上看到屏幕输出(如果物理访问不切实际,则可以使用另一台具有串行控制台可以提供帮助。)如果内核 OOPS/PANIC 是问题所在,具有更好驱动程序的更新内核可能会有所帮助,或者您可以使用watchdog(8)
辅助驱动程序来解决系统锁定问题。或者您可以更换硬件部件。
答案4
一种让自己相信 Linux 内核直接处理它的有趣方法是观察它的内核设置:
tail /proc/sys/net/ipv4/icmp*
可能会输出类似以下内容:
==> /proc/sys/net/ipv4/icmp_echo_enable_probe <==
0
==> /proc/sys/net/ipv4/icmp_echo_ignore_all <==
0
==> /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts <==
1
==> /proc/sys/net/ipv4/icmp_errors_use_inbound_ifaddr <==
0
==> /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses <==
1
==> /proc/sys/net/ipv4/icmp_msgs_burst <==
50
==> /proc/sys/net/ipv4/icmp_msgs_per_sec <==
1000
==> /proc/sys/net/ipv4/icmp_ratelimit <==
1000
==> /proc/sys/net/ipv4/icmp_ratemask <==
6168
这已经表明 ICMP 是由内核处理的,因为/proc/sys
是一个用于配置和检查内核状态的特殊文件系统:/dev、/proc 和 /sys 中有什么?
接下来,如果您在典型的家庭调制解调器路由器后面的同一 LAN 上连接 2 台计算机,然后您可以通过ping
以下方式从计算机 A 到计算机 B:
ping 192.168.1.102
然后,您可以在计算机 B 上使用以下命令关闭 ping 回复:
echo 1 | sudo tee /proc/sys/net/ipv4/icmp_echo_ignore_all
一旦你这样做,ping
计算机 A 就会开始出现故障。并重新启用:
echo 0 | sudo tee /proc/sys/net/ipv4/icmp_echo_ignore_all
所以我们可以通过与内核对话来直接控制 ICMP。
icmp_echo_ignore_all
可以在 Ruslan 在评论中指出的内核代码中看到对 的引用https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/icmp.c?id=24cac7009cb1b211f1c793ecb6a462c03dc35818#n935
static bool icmp_echo(struct sk_buff *skb)
{
struct net *net;
net = dev_net(skb_dst(skb)->dev);
if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
struct icmp_bxm icmp_param;
icmp_param.data.icmph = *icmp_hdr(skb);
icmp_param.data.icmph.type = ICMP_ECHOREPLY;
icmp_param.skb = skb;
icmp_param.offset = 0;
icmp_param.data_len = skb->len;
icmp_param.head_len = sizeof(struct icmphdr);
icmp_reply(&icmp_param, skb);
}
/* should there be an ICMP stat for ignored echos? */
return true;
}
使用两台连接到家庭无线 LAN 的运行 Linux 6.5.0 的 Ubuntu 23.10 计算机进行测试。