Hack 和 / - Linux 故障排除,第二部分:本地网络

作者:Kyle Rankin

本专栏是致力于我最喜欢的主题之一:故障排除的系列文章的第二篇。因为我的专栏通常更侧重于技巧和窍门,而较少关注哲学和设计,所以我不会过多谈论解决问题的总体方法。相反,在本系列中,我描述了您可能在 Linux 系统上发现的一些常见问题类别,然后我讨论如何使用常用工具(其中大多数可能已在您的系统上)来隔离和解决每类问题。

在第一篇专栏中,我讨论了如何诊断服务器上的高负载问题,但事实是,如今,几乎每台 Linux 计算机都连接到网络,并且您遇到的大量问题都基于网络。本月,我专注于本地网络故障排除,尽管我是从服务器的角度编写的,但这些步骤中的大多数将适用于网络上的任何 Linux 机器。此外,因为本文的目的是展示如何更好地进行故障排除,所以我按从最低级别到最高级别的顺序列出每个步骤。在现实生活中,我可能会在这里和那里跳过一些步骤,以加快故障排除过程。

bill 宕机了

我在这里涵盖的通用问题是如何在同一网络上的一台机器无法与另一台机器通信时,追踪根本原因。对于此示例,假设我有两台名为 bill 和 shawn 的服务器。服务器 shawn 尝试通过端口 25(端口 25 用于通过 SMTP 发送电子邮件)与 bill 通信,但您知道吗,bill 没有响应。

是 shawn 还是 bill 出了问题?

在这种情况下,我可能会做的第一件事是在同一网络上找到另一台机器,并尝试从那里连接到 bill。如果我可以从同一网络上的另一台机器与 bill 通信,则问题很可能出在 shawn 或 shawn 和 bill 之间的网络上。如果我从同一网络上的另一台机器遇到相同的问题,则问题更有可能出在 bill 上,因此我将从那里开始进行故障排除。为了我可以讨论更多的故障排除步骤,让我们从 shawn 开始进行故障排除。

故障排除中最令人尴尬的事情之一是浪费一个小时才发现某些东西没有插好。因此,我执行的第一个步骤是确保 shawn 已插入网络。尽管我可以物理检查服务器上的端口,但如果服务器位于不同的城市,我可能会运行像 ethtool 这样的程序。 ethtool 为您提供了有关以太网设备的许多不同诊断信息。默认情况下,您只需以 root 身份运行 ethtool 并传递您要检查的以太网设备作为参数即可。在许多情况下,这将是 eth0

$ sudo ethtool eth0
Settings for eth0:
     Supported ports: [ TP ]
     Supported link modes:   10baseT/Half 10baseT/Full 
                               100baseT/Half 100baseT/Full 
                               1000baseT/Half 1000baseT/Full 
     Supports auto-negotiation: Yes
     Advertised link modes:  10baseT/Half 10baseT/Full 
                               100baseT/Half 100baseT/Full 
                               1000baseT/Half 1000baseT/Full 
     Advertised auto-negotiation: Yes
     Speed: 100Mb/s
     Duplex: Full
     Port: Twisted Pair
     PHYAD: 0
     Transceiver: internal
     Auto-negotiation: on
     Supports Wake-on: pg
     Wake-on: d
     Current message level: 0x000000ff (255)
     Link detected: yes

如您所见,ethtool 提供了各种信息,包括此机器支持 10 base T、100 base T 和千兆网络速度,但当前以 100 base T 全双工通信。要检查链路,只需查看最后一行“Link detected”。正如您在我的示例中看到的,检测到链路,因此我的电缆已插好,我可以继续下一步。

在完全跳过 ethtool 之前,值得一提的是,它不仅仅诊断链路问题。我在网络上发现的一个常见问题是主机网络速度低于正常速度。通常,您会在重启或停电后看到这种情况。通常发生的情况是,当接口连接到网络时,它会尝试自动协商它可以达到的最快速度。有时自动协商无法正常工作,在这种情况下,接口可能会退回到半双工模式,甚至可能退回到 10 base T!如果您知道您的网络可以支持 100 base T 全双工,则可以使用 ethtool 禁用自动协商并强制全双工。要对 eth0 执行此操作,您需要键入

$ sudo ethtool -s eth0 autoneg off duplex full
测试本地 IP 设置

在我们确认 shawn 已插入后,下一步是确认 shawn 上的 eth0 配置正确。为此,我将使用带有 eth0 参数的 ifconfig 命令。我应该返回我需要的所有网络信息,以确定 eth0 在 shawn 上是否设置正确

$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:17:42:c0:ff:ee  
          inet addr:10.1.1.9  Bcast:10.1.1.255  Mask:255.255.255.0
          inet6 addr: fe80::217:42ff:fe1f:18be/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:1 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:229 (229.0 B)  TX bytes:2178 (2.1 KB)

该命令有很多输出,但我会查看的第一行是输出的第二行。在那里,我可以看到 eth0 的 IP 地址是 10.1.1.9,其子网掩码是 255.255.255.0。如果机器应该具有与我在此处看到的不同的 IP 或子网掩码,则这可能是问题的原因。如果 eth0 完全没有配置 IP 或子网掩码,我可能会运行ifup eth0以启动接口,或者我可能会查看本地网络设置(Debian 或 Ubuntu 机器上的 /etc/network/interfaces,基于 Red Hat 的机器上的 /etc/sysconfig/network-scripts/ifcfg-eth0),以查看是否有任何设置不正确。如果我似乎无法启动接口,并且此主机从 DHCP 获取其 IP,我可能必须将故障排除重点转移到 DHCP 服务器。

测试本地子网

在您确认接口已连接到网络并且应该能够通信之后,下一步是测试您是否可以访问同一子网上的另一台主机——特别是您配置的网关(如果有)。为什么?好吧,如果您无法与同一子网上的主机通信,特别是如果您无法与网关通信,那么测试与本地子网外部主机的通信就没有任何意义。首先,我将使用 route 命令查看配置了哪些网关,然后我将使用 ping 查看是否可以访问网关

$ sudo route -n
Kernel IP routing table
Destination  Gateway   Genmask         Flags Metric Ref  Use Iface
10.1.1.0     *          255.255.255.0   U     0      0     0 eth0
default      10.1.1.1  0.0.0.0          UG    100    0     0 eth0

在此示例中,我有一个非常基本的路由表,以单词 default 开头的行定义了我的默认网关:10.1.1.1。在此步骤中,请务必将 -n 选项与 route 一起使用。如果不使用 -n 选项,route 将尝试将它列出的任何 IP 地址解析为主机名。除了 route 使用 -n 执行速度更快之外,如果您遇到网络问题,您甚至可能无法与您的 DNS 服务器通信,而且 DNS 故障排除是另一个专栏的主题。

因为我看到网关是 10.1.1.1,所以我将使用 ping 命令来确认我可以与该网关通信

$ ping -c 5 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=3.13 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=1.43 ms
64 bytes from 10.1.1.1: icmp_seq=3 ttl=64 time=1.79 ms
64 bytes from 10.1.1.1: icmp_seq=5 ttl=64 time=1.50 ms

--- 10.1.1.1 ping statistics ---
5 packets transmitted, 4 received, 20% packet loss, time 4020ms
rtt min/avg/max/mdev = 1.436/1.966/3.132/0.686 ms

此输出告诉我,我的机器至少可以与网关通信,并且大概可以与 10.1.1.x 网络中的其余部分通信。现在,如果我无法与网关通信,那可能意味着我的网络管理员很烦人,并且阻止了 ICMP 数据包。如果是这种情况,我将只选择同一子网上的另一台机器 (10.1.1.2-10.1.1.254) 并尝试 ping 它。如果我是网络管理员(因此没有阻止 ICMP),或者如果由于其他原因未阻止 ICMP,则此阶段的问题可能是某种 VLAN 问题,我必须在网络交换机本身上解决。

如果您运行 route 命令并且没有找到设置的默认网关,您可能会倾向于得出结论,这就是问题的根源。小心!这个结论可能为时过早。您看,如果 shawn 和 bill 在同一个子网上,我不需要配置默认网关即可让这些服务器通信。我不会在本专栏中介绍如何计算子网,但足以说明在我的示例中,如果 shawn 的 IP 为 10.1.1.9,子网掩码为 255.255.255.0,则 bill 的 IP 可以为 10.1.1.1 到 10.1.1.254,并且在同一子网上。在这种情况下,我可能只是直接 ping bill。理想情况下,我应该在同一个子网上有第三台主机,我也可以用它来 ping。这样,如果 bill 没有响应,但同一子网上的另一台主机响应了,我可以将 bill 缩小为可能的问题来源。

下一步:探测 bill 的端口

如果 bill 响应 ping,则下一步是测试端口 25 是否在 bill 上打开。有几种不同的方法可以做到这一点,但 telnet 是最简单的方法之一,并且可能已经安装在您的机器上。假设 bill 的 IP 为 10.1.1.17;我将键入

$ telnet 10.1.1.17 25
Trying 10.1.1.17...
telnet: Unable to connect to remote host: Connection refused

如果 telnet 没有抱怨 Connection refused,而是开始输出 SMTP 命令,那么恭喜您,您没有网络问题!不利的一面是,这意味着您可能遇到某种 SMTP 问题,这可能更难排除故障。如果 telnet 抱怨 Connection refused,则端口 25 在远程机器上关闭(可能是 bill 上的 SMTP 服务未运行或未在该端口上侦听),或者防火墙正在阻止您。这就是像 nmap 这样的工具可以派上用场的地方,这也是我经常在想要测试端口是否可用时使用 nmap 而不是 telnet 的原因之一。

您看,许多防火墙配置为通过丢弃没有回复的数据包来阻止端口。因为通常服务器会发送基本回复以让您知道端口已关闭,所以如果数据包被丢弃,nmap 会将其标记为 filtered 而不是 closed

$ nmap -p 25 10.1.1.17

Starting Nmap 5.00 ( http://nmap.org ) at 2010-01-04 20:20 PST
Interesting ports on 10.1.1.17:
PORT   STATE  SERVICE
25/tcp filtered smtp

在这种情况下,nmap 说端口已过滤,这告诉我有一个防火墙正在阻止此端口。如果这些机器在不同的子网上,则网络之间可能有一个防火墙限制访问。因为我知道这些机器在同一个子网上,所以我假设 bill 上配置了一些 iptables 防火墙,需要检查。

直接测试 bill

假设我们认为问题出在 bill 上。在我对 bill 执行了与我对 shawn 执行的相同的网络故障排除之后,下一步是登录到 bill 并测试端口 25 是否打开并侦听连接。为此,我将使用 netstat 工具。 netstat 可用于输出有关机器上网络连接的各种信息。但在这种情况下,我将仅使用 -lnp 选项列出侦听端口和打开端口的进程,然后我将 grep 我感兴趣的端口,端口 25

$ sudo netstat -lnp | grep :25
tcp        0      0 0.0.0.0:25    0.0.0.0:*     LISTEN   1878/master

我最想关注的列是第四列,其中列出了端口 25 上打开的本地地址。在这种情况下,我可以看到它设置为 0.0.0.0:25,这意味着 bill 正在侦听所有可用接口上的端口 25 连接。如果我将邮件服务器设置为仅侦听 eth0,则这将设置为 10.1.1.17:25。另一方面,如果我看到它设置为 127.0.0.1:25,我可能已经找到了问题的原因:邮件服务器设置为仅侦听 localhost 地址 (127.0.0.1),并且不侦听来自外部网络的任何连接。在这种情况下,我将重新配置我的邮件服务器,使其侦听 eth0。如果我从上面的命令中没有得到任何输出,我就会知道我的问题是我的服务器根本没有运行(或者没有设置为侦听端口 25)。然后,我需要启动我的邮件服务器并排除它最初为何停止运行,或为何没有侦听正确端口的问题。

如您所见,网络故障排除可以将您引向各种有趣的方向。即使现在我也只是略微触及皮毛。在我的下一篇专栏中,我将把网络故障排除扩展到本地网络之外,并介绍如何追踪从本地网络到 Internet 本身的路由和 DNS 问题。

Kyle Rankin 是旧金山湾区的系统架构师,并且是许多本书的作者,包括The Official Ubuntu Server BookKnoppix HacksUbuntu Hacks。他目前是 North Bay Linux Users' Group 的总裁。

加载 Disqus 评论