Featured image of post 一次愚蠢的网络配置导致的傻逼问题

一次愚蠢的网络配置导致的傻逼问题

一次愚蠢的网络配置导致的傻逼问题

前言

作为一个经常折腾网络的人,我总认为自己对网络配置已经驾轻就熟。然而,最近的一次"小操作"却给我上了生动的一课,提醒我即使是最基础的网络配置,稍有不慎也会导致令人头疼的问题。

问题描述

事情是这样的,我有一台服务器,内网IP地址为192.168.50.100。然后我买了一个物联网上网卡,内网IP为 192.168.0.100,为了正确配置多网卡上网的分流,我去修改了服务器的netplan:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
network:
  ethernets:
    enp6s0:
      dhcp4: true
      routes:
        - to: 10.0.0.0/8
          via: 192.168.50.1
        - to: 192.168.50.0/24
          via: 192.168.50.1
      nameservers:
        addresses:
          - 192.168.50.1
    enx344b50000000:
      dhcp4: true
      routes:
        - to: default
          via: 192.168.0.1
          metric: 50
      nameservers:
        addresses:
          - 192.168.0.1
  version: 2

请注意上面的 to: 192.168.50.0/24 这条规则,这条规则的意思是:发往192.168.50.0/24网段的所有流量,都要经过网关192.168.50.1转发。

配置完成后,我发现局域网内的设备突然无法通过内网IP访问这台服务器上的服务了。

但奇怪的是,通过路由器IP访问却可以(路由器配置了DMZ主机)。具体表现为:

  1. 其他设备可以ping通这台服务器
  2. 这台服务器自己可以通过 192.168.50.100 走nginx访问到http服务
  3. 其他设备可以通过 10.xx.xx.xx 走nginx访问到http服务
  4. 其他设备无法通过 192.168.50.100 访问到http服务

问题分析

经过长达1个小时排查,我终于意识到问题出在哪里。。。这是一个典型的路由配置错误,而且错得相当愚蠢。

正常情况下的网络通信

在正常情况下,同一局域网内(同一网段)的设备通信是不需要经过网关的。比如,当192.168.50.100想要与192.168.50.200通信时,它会直接在局域网内发送数据包,通过ARP协议找到对方的MAC地址,然后直接通信。

这是因为操作系统会根据目标IP和本机IP以及子网掩码判断:目标是否在同一网段。如果在同一网段,就直接在局域网内通信,不需要经过网关。

错误配置后的情况

但我的错误配置改变了这一行为。我手动添加了一条路由规则,强制要求所有发往192.168.50.0/24网段的流量都要经过网关192.168.50.1

这就导致了以下荒谬的情况:

  1. 当服务器(192.168.50.100)想要与同网段的设备(如192.168.50.200)通信时
  2. 它不再直接在局域网内发送数据包
  3. 而是将数据包发送给网关192.168.50.1
  4. 期望网关能够帮它转发到目标设备

但问题是,网关通常不会转发同一网段内的流量!因为按照正常的网络设计,同网段设备应该直接通信,不需要网关参与。

这种配置最终导致了单向通信问题:其他设备发送到192.168.50.100的数据包仍然遵循正常路由,但192.168.50.100的回复却走错误的路由,导致无法正常通信。

而且这种错误非常隐蔽。。其他设备访问192.168.50.100时,ping可以通,curl结果是 Connection reset by peer,然后去看 nginx 的日志,发现状态码是499,光看日志还以为是 nginx 配置问题。

解决方案

解决这个问题非常简单:删除那条错误的路由规则。

Licensed under CC BY-NC-SA 4.0