☰
别只懂连WiFi:Linux网络排查、TCP/IP协议栈与跨网传输实战
2026/9/28 5:22:46 网站建设 项目流程

很多朋友第一次在笔记本上装 Linux,做完的第一件事就是打开右上角的网络菜单,输对 WiFi 密码,看到图标变成实心、能刷出网页,就觉得自己“会网络”了。但现实往往是:你连上了家里的 WiFi,想访问同一局域网里另一台 Linux 机器上的服务,卡住了;想从公司内网传个大文件到家里主机,更是一脸懵。这时候你才发现,“能连 WiFi”和“懂 Linux 网络”之间,隔着的正是 TCP/IP 协议栈、局域网通信和跨网传输这部分硬骨头。

这篇内容就是要把这块硬骨头掰开揉碎。我会从“连 WiFi”这个表象出发,一路讲到 IP 地址、子网掩码、ARP、路由、NAT,再用 iperf3、nc、rsync 这些 Linux 下最常用的工具做实测验证。适合刚入门 Linux 但不想停留在“敲命令”层面的朋友,也适合那些玩嵌入式板子、随身 WiFi、ESP8266 这类设备时总被网络问题卡住的人。看完之后,你至少能做到:给 Linux 配静态 IP 不再发怵、自己能定位“同网段通而跨网段不通”的原因、能用一条命令在局域网里传完一个几 GB 的文件。

1. 先建立整体认知:一个数据包的“旅行路线”

1.1 你平时“连 WiFi”到底完成了什么

先说个容易忽略的事实:当你点开 WiFi、输入密码、看到“已连接”那一刻,其实只完成了两件事。

第一件事是无线网卡和路由器之间完成了 802.11 协议的握手。这个过程涉及认证、关联,最终你的无线网卡被分配到无线信道里,可以收发无线电波。但这时候你还没有 IP 地址,严格来说连可被网络寻址的“身份”都没有拿到。

第二件事是 DHCP 自动配置。路由器作为 DHCP 服务器,给你这台 Linux 机器分配了一个局域网内的 IP 地址,比如 192.168.1.100,同时下发子网掩码、默认网关、DNS 服务器地址。你可以在终端里用ip addr看到完整的网卡配置,用cat /etc/resolv.conf看到 DNS 配置。

这两件事完成之后,你才真正“入了网”。但很多人对这个过程毫无感知,因为图形界面把一切都隐藏了。于是遇到问题时,他们只会重启路由器,而不会去看配置到底在哪一层出了问题。所以我一直建议:在 Linux 下折磨自己的第一步,就是把“点鼠标连 WiFi”改成用命令配置网络。

另外,这个“连 WiFi”的阶段只解决了“接入”的问题——也就是让你进入了一个局域网。至于你要访问的服务器在同一个网段还是在另一个网段,数据要怎么走,那完全是另一套逻辑。早期我在实验室里折腾嵌入式板子,经常出现“板子明明连上了 WiFi 热点,但主机就是 ping 不通”的怪事,根源就是只注意了接入层,忽略了 IP 地址分配和路由,走了不少弯路。

1.2 局域网通信和跨网传输的本质区别

把所有网络通信归纳成两类场景,很多问题就清晰了。

第一类是局域网通信,也就是数据包根本不经过路由器转发,只在同一个二层网络内流动。这里的“同一网络”指的不是同一个 WiFi 热点,而是同一个网段。比如两台电脑都连着家里同一个路由器,IP 分别是 192.168.1.10 和 192.168.1.20,子网掩码都是 255.255.255.0,那它们就属于同一个网段。A 要访问 B,数据直接在交换机或无线 AP 层面就转发了,不需要“出网”。

第二类是跨网传输,目标 IP 和你不在同一个网段,数据包必须交给默认网关——也就是路由器——由路由器帮你把数据送到目的地。比如你访问一个网站,或者访问公司另一个网段的服务器,都属于这一类。这里的核心角色是路由器和路由表。

如果你只知道“连 WiFi”,你只接触到了网络最浅的那层皮毛。局域网通信要求你理解 IP 地址、子网掩码、ARP、MAC 地址表;跨网传输要求你理解路由、网关、TTL,甚至 NAT。标题里说的“别只懂连 WiFi”,说的就是把认知从“接入层”拉高到“网络层”和“传输层”。

我个人的体会是,初学者最容易犯的错误是:把所有网络问题都归咎于“没网”。实际上很多“访问不了”的问题,恰恰是局域网内部的路由或 ARP 解析问题,和外网根本没关系。学会区分“局域网”和“跨网”这两个场景,等于先给问题画了一个圈,排查范围立刻缩小一半。

1.3 掌握 TCP/IP 的正确姿势:把模型当“快递流水线”

TCP/IP 模型有四个层次:应用层、传输层、网络层、网络接口层。很多教材把这四层讲得像四个并列的概念,背完就忘。换个思路,把它想象成一条快递发货流水线,你就永远不会忘。

应用层的进程把要发送的数据(比如一段文字、一个文件)交给系统;传输层负责任务分配给谁——也就是端口号,TCP 还会给数据编上序号、确认号,保证不丢不重;网络层负责填上“寄件人地址”和“收件人地址”,也就是源 IP 和目的 IP;网络接口层负责真正把数据变成电信号或无线电波送出去,还要填上下一站的“门牌号”——MAC 地址。

最关键的认知是:每一层只关心自己那部分职责,并对上层屏蔽细节。你写 HTTP 请求时根本不用管 TCP 是怎么重传的;TCP 也不用管 IP 数据包到底走的是 WiFi 还是网线;IP 层也不用管底层的帧格式是 Ethernet 还是 802.11。这就是分层设计的意义。

理解模型之后,你排查网络问题就有了路线图。网页打不开,先看应用层(DNS、HTTP);连接卡住,看传输层(TCP 握手超时、端口不通);跨网不通,看网络层(路由、网关);完全没反应,看网络接口层(网线、WiFi 信号、MAC 地址)。后面我讲的所有排查技巧,本质上都是按这个路线图走的。

2. TCP/IP 协议栈层层拆解:数据是如何被“套娃”的

2.1 四层模型不是让背的,是数据被加工的四道工序

有了整体认知之后,我们把每一层的具体活儿看清楚。假设你在一台 Linux 机器上执行curl http://example.com,这个请求从产生到离开网卡,经过了四道加工工序。

应用层:curl 进程构造 HTTP GET 请求字符串,调用系统 socket 接口,把数据交给内核。此时数据只是一串字节。

传输层:内核协议栈的 TCP 模块给这串字节加上 TCP 头部。头部里有源端口(随机生成的,比如 34567)、目的端口(80)、序列号、确认号、窗口大小等。加上 TCP 头的这块数据叫“TCP 段”。如果数据太大,TCP 还会先按 MSS(最大分段大小)切块,每一块都有独立的序列号。

网络层:IP 模块再给 TCP 段加上 IP 头部。头部里有源 IP、目的 IP、TTL、协议编号(TCP 是 6,UDP 是 17)等。加了 IP 头之后叫“IP 数据包”。这一层的主要工作就是寻址和选路。

网络接口层:网卡驱动拿到 IP 数据包后,根据下一跳的 MAC 地址封装成以太网帧(或 WiFi 帧)。帧头有源 MAC、目的 MAC、类型字段,帧尾还有 CRC 校验。数据到这里才真正被物理发送出去。

接收端的处理顺序是反过来的:网卡收到帧,验 CRC、剥帧头,得到 IP 包;IP 层剥 IP 头,看协议号是 TCP 就交给 TCP 模块;TCP 模块剥 TCP 头,按端口号找到对应进程;应用进程最终拿到原始数据。

这个过程就像一个快递包裹被层层套上信封和封皮。有个很经典的比喻:数据在每一层都被“贴上标签”,接收端每经过一层就撕掉一个标签。你只需要记住,TCP 头和 IP 头的区别在于:TCP 头解决的是“进程与进程”之间的通信,IP 头解决的是“主机与主机”之间的通信。所以抓包时最常看到的组合是“源 IP + 源端口 → 目的 IP + 目的端口”,四元组缺一不可。

2.2 用 Linux 自带命令“看见”每一层

理论说多了容易飘,我们来点实际的。Linux 系统里有一堆原生命令,可以让你直观看到每一层的数据。

想看 IP 层和网络接口配置,用ip addr。它会列出网卡名、MAC 地址(link/ether)、IPv4 和 IPv6 地址。我想强调的一点是,很多人习惯用ifconfig,但现代 Linux 发行版里iproute2已经是标配,ip命令的功能和信息完整性远超ifconfig,建议尽早换过来。

想看路由表,也就是网络层的“选路依据”,用ip route。输出结果里最关键的是default via那一行,它就是默认网关。数据包目的地址无法匹配任何路由条目时,都会走这一条。

想看 TCP 连接状态,用ss -tnp。-t表示 TCP,-n用数字显示端口不解析服务名,-p显示对应的进程。输出的每一行都是一个 TCP 连接的“当前快照”,你可以看到 LISTEN、ESTABLISHED、TIME_WAIT 这些状态。

想看 ARP 缓存表(IP 到 MAC 的映射),用ip neigh。它列出的是本机最近通信过的邻居。比如你 ping 了一下同网段的主机,这里就会多一条REACHABLE状态的记录。

想抓包直接看协议头,用tcpdump。比如tcpdump -i eth0 -nn -c 20 tcp port 80,抓到 HTTP 流量后,你可以亲眼看到源 IP、目的 IP、端口号、TCP 标志位。我第一次用 tcpdump 亲眼看到 TCP 三次握手的 SYN、SYN-ACK、ACK 三个包时,之前背的那些协议状态瞬间通了。

还有几个辅助命令值得熟悉:ping用于查网络层连通性,traceroute或mtr用于看跨网路径,nc用于测试端口连通性,ethtool用于查看物理链路协商速率。这些工具组合起来,基本能覆盖 99% 的日常排查场景。

2.3 一条 HTTP 请求从应用到网线的完整流程

把上面四层串起来,看一条真实请求的完整生命周期。

你在 Linux 终端输入curl -v http://192.168.1.20/index.html。注意我用了 IP 而不是域名,省去 DNS 解析步骤,先把核心链路看清楚。

第一步,curl 调用 socket API,创建一个 TCP socket,并向 192.168.1.20 的 80 端口发起连接。内核 TCP 模块发出 SYN 包,目标端口 80,源端口是系统随机选择的临时端口。

第二步,IP 模块封装 IP 头。源 IP 是 192.168.1.10,目的 IP 是 192.168.1.20。它先做判断:目的 IP 和源 IP 是不是同网段?用子网掩码 255.255.255.0 一算,网络号相同,所以是直连路由,下一跳就是目的主机自己。

第三步,网络接口层发出 ARP 请求,查询 192.168.1.20 对应的 MAC 地址。拿到 MAC 后,构造以太网帧,源 MAC 是你的网卡 MAC,目的 MAC 是目标主机的 MAC,然后通过网线或 WiFi 发送。

第四步,目标主机收到帧后逐层解包:网卡剥帧头,IP 层看到目的 IP 是自己,剥 IP 头,把 TCP 段交给 TCP 模块;TCP 模块发现端口 80 有进程在监听,完成 TCP 三次握手。

第五步,curl 发送 HTTP GET 请求,服务器返回响应,curl 显示内容。整个过程看起来很快,但每一层都在井然有序地工作。

这个例子还有几个细节值得注意。比如 192.168.1.10 和 192.168.1.20 的通信不经过路由器,但如果目标改成 192.168.2.20,同一套流程里,ARP 查询的目标就从“目的主机”变成了“默认网关”,这是同网段和跨网段通信的分水岭。这个区别我下面会展开讲。

3. 局域网通信实战:同网段的数据送达

3.1 同网段判断:子网掩码与网络号计算的实操

判断两台主机是否在同一个局域网,标准做法是把 IP 和子网掩码做按位与运算,得到网络号。网络号相同,就在同一网段。

举个例子。A 的 IP 是 192.168.1.10/24,B 的 IP 是 192.168.1.20/24。24 表示子网掩码是 255.255.255.0,前 24 位是网络位。把 192.168.1.10 和 255.255.255.0 按位与,得到 192.168.1.0;B 也算出来是 192.168.1.0。网络号相同,A 和 B 同网段。

如果 B 的 IP 是 192.168.2.20/24,网络号就是 192.168.2.0,和 A 的 192.168.1.0 不同,A 就不能直接访问 B,必须把数据交给网关。

Linux 下用ip addr就能看到子网掩码,注意它显示的写法是/24而不是 255.255.255.0。换算关系很简单:/24 就是 255.255.255.0,/16 就是 255.0.0.0,/8 就是 0.0.0.0 对应 255.0.0.0 写反了其实是 255.0.0.0 是 /8)。为了不犯迷糊,我通常会直接在终端里用ipcalc命令,输入 IP 和掩码,它会自动算出网络号、广播地址和可用主机范围。比如:

ipcalc 192.168.1.10/24

输出里会明确写着 Network: 192.168.1.0/24、Broadcast: 192.168.1.255、HostMin 和 HostMax。没有ipcalc的话,先用apt install ipcalc或yum install ipcalc装上,排查子网时非常省事。

一定要记住一个结论:同网段通信时,数据包的目标 MAC 是目的主机的 MAC;跨网段通信时,数据包的目标 MAC 是网关的 MAC,但 IP 头里的目的 IP 始终是最终目标主机的 IP。这句话是整个网络通信的分水岭,也是我面试 Linux 岗位时最常拿来问候选人的一个问题。

3.2 ARP:局域网里怎么用 MAC 地址“找人”

知道了目标 IP,怎么找到目标主机的 MAC 地址?靠的就是 ARP。

ARP 协议的工作方式很朴素:主机 A 向同一个广播域里发一个 ARP 请求,内容大概是“谁的 IP 是 192.168.1.20?请告诉你的 MAC 地址”。这个请求会以广播的形式发到局域网里的每一台主机。目标主机收到后,发现问的是自己,就回一个单播 ARP 应答:“192.168.1.20 的 MAC 地址是 xx:xx:xx:xx:xx:xx”。

A 收到应答后,把这条映射存进本机的 ARP 缓存表,之后一段时间内再跟 B 通信就不用重新问了。你可以用ip neigh看到这些缓存。

关于 ARP,有几个实操中特别容易踩的坑。

第一个坑是 ARP 缓存过期。默认情况下缓存条目会超时,过期后需要重新请求。如果你改了某台机器的 IP,但局域网里另一台机器的 ARP 缓存还停留在旧映射,就会出现“IP 通但就是连不上”的怪现象。解决方法是排查时主动清空无效缓存:

ip neigh flush all

这条命令会把整个 ARP 缓存清掉,让系统重新学习。我处理很多莫名其妙的局域网故障,第一步都是先 flush ARP 缓存,往往能解决一半问题。

第二个坑是 ARP 广播的范围。ARP 请求只能在一个广播域内传播,这也是为什么跨网段时你不能直接 ARP 请求目标主机,只能把包交给网关,让网关在它的网段里重新 ARP。理解了这个,就理解了为什么三层转发必须靠路由器。

第三个坑是无线场景下的“AP 隔离”。很多家用路由器默认开启了“ AP 隔离”(也叫客户端隔离),这种情况下无线设备之间不允许直接通信,一律通过路由器转发。如果你的两台 Linux 机器都连着 WiFi,互相 ping 不通,先不要怀疑防火墙,先去路由器后台看看有没有开启隔离功能。这个问题我踩过一次,当时折腾了半天 ARP,最后发现是路由器的默认设置。

3.3 交换机的 MAC 表与广播域

你说“同网段通信不经过路由器”,那数据在局域网里怎么走的?答案是交换机(或无线 AP)。

交换机的核心是一张 MAC 地址表,记录着每个端口连接了哪些 MAC 地址。它的学习过程很直接:收到一个源 MAC 为 X 的帧从端口 1 进来,就记一条“X 在端口 1”;以后要发给 X 的帧,直接往端口 1 发,不用广播。

如果交换机查不到目的 MAC 在哪个端口,就会把帧在除了入口以外的所有端口上转发一次,这叫“未知单播泛洪”。收到帧的主机发现目的 MAC 不是自己,就直接丢弃,只有真正的主机才会响应。

这个机制解释了局域网通信的很多现象。比如你用 tcpdump 在同网段抓包,可能看到很多不是发给你的广播帧;比如你用两台电脑直连网线,不需要交换机也能通信,因为网卡本身处理点对点。理解 MAC 表之后,你就知道在一个规模不大的局域网里,数据包是靠 MAC 地址表一级一级“接力”送到的,而不是靠 IP 地址。

说到广播域,还有个值得知道的概念:广播帧(比如 ARP 请求)会传遍整个二层网络。如果广播域范围太大,广播风暴就会让网络瘫痪。所以大型网络会用 VLAN 把广播域切小,这也是“局域网”概念在工程上的边界来源。对于家庭和小型实验室来说,整个路由器背后的二层网络通常就是一个广播域,这也是“同网段直接通信”的前提。

3.4 在 Linux 上配置静态 IP 并验证连通性

理论知识铺垫得差不多了,来个动手环节:手动配置静态 IP。为什么非要学这个?因为 DHCP 虽然方便,但在服务器、嵌入式设备、自组网场景下并不总是可靠,而且配置静态 IP 的过程能让你彻底搞懂 IP、子网掩码、网关三者的关系。

不同发行版的配置方式不一样,但思路一致。以 Debian/Ubuntu 的 netplan 为例(Ubuntu 18.04 以后的默认网络管理方式),先在/etc/netplan/目录下找到*.yaml文件,编辑它:

network: version: 2 ethernets: eth0: addresses: - 192.168.1.10/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: - 114.114.114.114

然后执行:

sudo netplan apply

这条命令会重新应用网络配置。验证一下:ip addr show eth0看 IP 是否生效;ip route show看默认路由;ip neigh show看是否学到了网关的 MAC。然后再执行:

ping -c 4 192.168.1.1

能通说明网卡到网关的链路没问题。再用arp -a或ip neigh看到网关的 MAC 条目,说明 ARP 也正常。

如果你用的是 RHEL/CentOS 系的 NetworkManager,可以用nmcli命令完成同样的事:

nmcli connection modify eth0 ipv4.addresses 192.168.1.10/24 nmcli connection modify eth0 ipv4.gateway 192.168.1.1 nmcli connection modify eth0 ipv4.dns 114.114.114.114 nmcli connection modify eth0 ipv4.method manual nmcli connection up eth0

配置静态 IP 最常见的错误就是子网掩码和网关不匹配。比如 IP 是 192.168.1.10/24,网关却填成 192.168.2.1,这种配置下同网段通信没问题,但跨网完全不通。我建议每次配完都执行ip route确认路由表正确,而不是只看 IP 地址有没有变。

4. 跨网传输硬核逻辑:网关、路由与 NAT

4.1 跨网段的“快递中转站”:路由器怎么选路

从这一节开始进入标题里“跨网传输”的部分。跨网通信的关键角色是路由器,它的工作就是“选路”。

假设你的 Linux 机器(192.168.1.10/24)想访问另一台服务器(172.16.5.8/24)。本机计算网络号后发现目标不在同一个网段,于是把数据包交给默认网关 192.168.1.1。网关收到包后,看目的 IP 是 172.16.5.8,查阅自己的路由表,决定应该把包从哪个接口转发出去。

路由器选路的依据就是路由表。路由表里包含目标网络、子网掩码、下一跳地址、出接口和优先级。一个家用路由器通常有三类路由:直连路由(它自己接口所在的网段)、静态路由(管理员手动配置的)和动态路由(通过 OSPF 等协议学习到的)。匹配时按“最长前缀匹配”原则,也就是路由条目里网络掩码越长越精确,优先级越高。

对于 Linux 下的跨网通信,你至少要知道怎么看本机路由表:

route -n

输出结果里有个关键点:如果目标 IP 能匹配到一条非默认路由,就走那条;匹配不到,就 fallback 到0.0.0.0的默认路由,交给默认网关。所以当你发现跨网不通时,第一反应应该是:看路由表里有没有通向目标网段的条目,看默认网关是否正确。

还有一个容易被忽略的细节:路由器转发 IP 包时,源 IP 和目的 IP 通常不会变(除非做 NAT),但数据链路层的源 MAC 和目的 MAC 会在每一跳重新封装。这个细节解释了为什么你在 A 机器抓包,看到的是 A 到网关的 MAC;在中间路由器抓包,看到的是路由器之间接口的 MAC。很多初学者在中间设备上抓包,发现目的 MAC 不对,就误以为包发错了,其实是因为没理解“MAC 逐跳变、IP 全程不变”的原则。

4.2 Linux 路由表实操:route 与 ip route

我强烈建议把route和ip route都学会,因为旧文档里route出现频率极高,但新系统更推荐ip route。

ip route的常用操作有这几个。

查看路由表:

ip route show

输出类似:

default via 192.168.1.1 dev eth0 proto static 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

第二行是直连路由,意思是通向 192.168.1.0/24 这个网段的包直接从 eth0 发出去,不需要网关。第一行是默认路由,所有无法匹配更精确条目的包都交给 192.168.1.1。

添加静态路由:

ip route add 172.16.5.0/24 via 192.168.1.2 dev eth0

这条命令的意思是:访问 172.16.5.0/24 网段时,下一跳交给 192.168.1.2。常见场景是公司内网有多个网段,Linux 机器作为终端需要通过一台内网路由器访问其他网段。

删除路由:

ip route del 172.16.5.0/24

注意使用ip route add添加的路由默认是临时的,重启后消失。要持久化,需要写进发行版的网络配置文件。netplan 里就是我在上一节写的routes段落。这个“重启丢失”的坑非常常见,我见过不止一次有人配完了路由当时能用,重启服务器后整个内网又断了,就是没注意持久化。

查看某条具体路由的匹配结果,可以用:

ip route get 172.16.5.8

这条命令会显示内核为这个目的地址实际选中的路由条目。排查跨网问题的时候,先用ip route get看走哪条路,比盲猜快得多。

4.3 NAT:内网出得去、外网回得来的“伪装术”

现在到了最容易被忽视、但又是跨网传输里最绕不开的概念:NAT。

家庭宽带下,你的路由器从运营商那里拿到的通常是一个公网 IP(或者经过运营商层层 NAT 之后的 IP),而你家里的所有设备都是私有 IP,比如 192.168.1.x。这些私有 IP 在公网上是不能被直接路由的。那内网设备怎么访问外网?靠的就是 NAT。

NAT 的核心动作是:当内网设备(192.168.1.10)访问外网时,路由器把数据包的源 IP 从 192.168.1.10 改成路由器自己的公网 IP,同时记录下这个映射关系。外网服务器回复时,把包发给路由器,路由器再根据映射记录,把目的 IP 改回 192.168.1.10,转交给内网设备。

Linux 下实现 NAT 最常用的是 iptables 的 MASQUERADE。比如一台 Linux 机器作为路由器,内网接口是 eth1(192.168.1.1),外网接口是 eth0(假设是公网 IP),需要开启 IP 转发:

echo 1 > /proc/sys/net/ipv4/ip_forward

然后配置 NAT:

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

这条命令的意思是:从 eth0 接口出去的流量,做源地址伪装。MASQUERADE 和 SNAT 的区别在于:SNAT 需要写死源 IP,而 MASQUERADE 会自动取出口 IP,特别适合出口 IP 动态变化的场景,比如家用宽带的 PPPoE 拨号。

很多玩嵌入式开发和局域网服务器的人都纠结过一个问题:为什么内网机器能访问外网,但外网访问不了内网机器?原因就是 NAT 表里默认只记录了“内网主动发起的连接”的映射,外网主动发来的包根本没有对应映射,路由器会直接丢弃。要解决“外网访问内网”,必须用端口转发,见下一节。

4.4 端口转发(DNAT):主动开一扇门

端口转发做的事正好和 NAT 相反:它允许外部主机访问内网里的某台机器的某个端口。用 iptables 实现叫 DNAT。

假设你的 Linux 网关有公网 IP,内网有一台 Web 服务器 192.168.1.100 监听 80 端口,你想让外面的人通过“公网 IP:8080”访问这个服务。命令如下:

iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80

同时还要放行 FORWARD 链的流量:

iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT

做完之后,外部请求到达网关的 8080 端口,会被转到内网服务器的 80 端口。要注意的是,如果内网设备访问网关的 8080 端口,走的链是 OUTPUT 而不是 PREROUTING,所以有时会遇到“外部能进、内网自己访问反而失败”的情况,需要额外加一条规则。这个细节不写出来,很多人调试时会被绕进去。

家用路由器后台里的“端口映射”或“虚拟服务器”设置,本质就是 DNAT。明白这个底层机制后,你在 Linux 上配置端口转发时就不会只背命令,而是能理解每一步的含义。

关于端口转发,有两条经验之谈。第一,转发端口时一定不要暴露默认的 SSH 22 端口到公网,除非你足够了解暴力破解的风险;即使要开放,也应该改用证书认证并换个高位端口。第二,端口转发只是“开了一扇门”,访问者能不能安全进出还取决于应用本身的认证和加密,不要以为配了 DNAT 就等于配好了完整的安全策略。

4.5 Linux 小实验:把一台 Linux 变成路由器

理论讲了一堆,不如动手做。我建议你拿两台虚拟机做一个小实验:用一台双网卡的 Linux 当路由器,让另一台单网卡的 Linux 通过它访问一个外部网段。

实验拓扑大概是这样:主机 A 有两个网卡,eth0 连着外网(比如 192.168.50.0/24),eth1 连着内网(192.168.10.0/24);主机 B 只有 eth1 网卡,IP 是 192.168.10.20/24,网关指向 192.168.10.1(也就是 A 的 eth1)。

步骤很简单。第一步,在 A 上开启 IP 转发,让它具备路由能力。第二步,配置 A 上 eth1 的 IP 为 192.168.10.1/24。第三步,在 A 上配置 NAT,让 B 访问外网时伪装成 A 的外网 IP。第四步,把 B 的默认网关改成 192.168.10.1。

全部完成后,在 B 上 ping 外网的一台机器。如果通了,恭喜你,你已经亲手完成了一次完整的跨网传输:B 发出 IP 包 → B 判断跨网 → 交给网关 A → A 查路由表 → A 做 NAT → 数据包出外网 → 外网回复 → A 根据 NAT 表还原 → 回给 B。

这个实验做完后,你再回看那些 NAT、路由、默认网关的概念,会发现全部串起来了。我当时做这个实验最大的收获是理解了“为什么 B 的网关必须填 A 的内网 IP,而不是外网 IP”——因为 B 只能直连到 192.168.10.1 这个网段,如果填错了,数据包根本送不到网关。

5. 把理论变成数据:iperf3、nc、rsync 的实测手法

5.1 iperf3 测吞吐:局域网到底能跑多快

说完了理论,来看看怎么用工具验证局域网和跨网传输的真实性能。第一个推荐的工具是 iperf3,它的作用很简单:专门用来测网络带宽,排除应用层干扰,直接测量 TCP/UDP 能跑多快。

用法非常直接。在一台机器上启动服务端:

iperf3 -s

默认监听 5201 端口。在另一台机器上启动客户端,注意这里填的是服务端的 IP:

iperf3 -c 192.168.1.10

默认测试 10 秒钟,输出结果里会包含传输的数据量、带宽(Mbits/sec)和重传次数。如果你想测试更接近真实场景,可以加参数:

iperf3 -c 192.168.1.10 -t 30 -P 4 -R

-t 30表示持续 30 秒,-P 4表示用 4 个并行流,-R表示测反向带宽(服务器向客户端发送)。并行流能更好地压榨出多核 CPU 和多队列网卡的潜力。

我第一次在实验室里用 iperf3 测两台机器,结果只有 300 Mbits/sec,但网卡明明是千兆。查了半天发现是网线只协商到百兆模式——ethtool eth0显示 Speed: 100Mb/s。换了一根六类网线后,立刻跑到 940 Mbits/sec。所以性能有问题时,先看物理层协商速率,别上来就怀疑 TCP 参数。

iperf3 还有一个容易被忽略的用法:测跨网传输。把服务端放在远程机器,客户端在本机运行,测出来的就是经过路由器 NAT、转发之后的实际可用带宽。这个数据比路由器标称的“最高速率”可靠得多,因为 NAT 转发本身也有 CPU 开销,尤其是小路由器上,NAT 吞吐往往远低于理论值。

5.2 nc 传文件:跨网传输最简单的一条命令

很多人一提到传文件,第一反应是 scp 或 sftp。但有些场景下(比如没有 SSH 服务的临时设备),nc(netcat)才是最快的选择。

nc 传文件的思路是:接收端监听一个端口,发送端把文件内容重定向到那个端口。假设接收端 IP 是 192.168.1.10,你想把本机的backup.tar.gz传过去。

接收端执行:

nc -l -p 1234 > backup.tar.gz

发送端执行:

nc 192.168.1.10 1234 < backup.tar.gz

文件传完后,接收端可以按 Ctrl+C 中断 nc。这个命令的本质是纯 TCP 流传输,没有加密,也没有文件完整性校验,所以适合在可信局域网里传临时文件,不适合传敏感数据。

用 nc 的时候有几个细节要注意。第一,数据流没有结束标志,所以接收端无法自动知道文件传完没有,需要手动中断,或者发送端传完文件后再发送一个额外信号,接收端根据信号判断。第二,如果文件比较大,建议加pv命令看实时进度:

nc -l -p 1234 | pv > backup.tar.gz

pv会显示当前传输速率和已传输大小。第三,nc 本身不校验文件是否完整,传完之后建议用md5sum对比两边文件的哈希值。这个习惯能帮你快速发现是传输损坏还是本身就是两台机器的文件不一致。

我经常用 nc 在嵌入式开发板和主机之间传固件包。开发板资源有限,没有 SSH 服务,但 busybox 里通常自带 nc,一条命令搞定。它能用上的前提依然是:两台设备在同一网络里,并且你知道对方的 IP 和端口。

5.3 rsync 增量同步:真实场景的跨网搬运

如果要在真实生产环境里跨网搬数据,rsync 是最靠谱的工具之一。它的核心价值不是“快”,而是“只传差异部分”。源目录里只有几个文件变了,rsync 扫描一遍后只传变化的文件,而不是整个目录重新搬一遍。

最常见的用法:

rsync -av --progress /data/ user@192.168.1.10:/backup/

-a表示归档模式,保留权限、时间戳等元信息;-v显示详细输出;--progress显示每个文件的传输进度。默认情况下 rsync 通过 SSH 传输,所以目标地址的格式是user@host:/path。

跨网传输时,rsync 还支持限速参数:

rsync -av --bwlimit=2000 /data/ user@192.168.1.10:/backup/

--bwlimit=2000表示限制带宽为 2000 KB/s。这个参数在有其他业务跑在链路上时非常实用,避免 rsync 把带宽抢光。我遇到过半夜做全量备份,第二天发现内网所有服务响应变慢的情况,罪魁祸首就是 rsync 不限速。

rsync 增量同步的原理,简单说就是比较文件大小、修改时间和可选的校验和,决定要不要传。带宽充裕时可以不加-c(checksum),靠时间和大小判断就够了;如果担心文件被改动但时间戳没变,可以加-c强制校验内容,代价是扫描时消耗更多 CPU。

还有一个常见的坑:rsync 同步目录时,源路径末尾的斜杠含义不同。rsync -av /data/ user@host:/backup/表示把 /data 目录里的内容同步到 /backup 目录下;而rsync -av /data user@host:/backup/表示在 /backup 下创建一个 data 目录,再把内容放进去。差一个斜杠,目录层级就完全不同,我在这上面栽过不止一次。

5.4 SSH 隧道:跨网访问服务的安全姿势

最后一个是 SSH 隧道,它解决的是另一个刚需:内网服务没有直接暴露到外网,但你又想在外面访问它。

SSH 隧道的基本命令格式是:

ssh -L 本地端口:目标地址:目标端口 跳板机用户@跳板机IP

举个例子。你在外面想访问家里内网一台机器的 Web 页面(192.168.1.100:80),但家里没有公网 IP,只有一个能 SSH 登录的跳板机(比如一台有公网 IP 的 VPS)。你能跳到跳板机,但跳板机访问不了你家里的内网。这时候光有 -L 不够,需要反向隧道,但那属于更复杂的组网话题。先看最常用的正向隧道:你在跳板机上,想通过跳板机访问它对端内网的服务,用 -L 就对了。

ssh -L 8080:192.168.1.100:80 user@192.168.1.1的意思是说:在本机(客户端)的 8080 端口上监听,所有请求通过 SSH 加密隧道转发到 192.168.1.1,然后由 192.168.1.1 访问内网目标 192.168.1.100 的 80 端口。本地浏览器访问http://localhost:8080,效果等同于访问内网 Web 服务。

这个方案的优点非常明显:隧道内容全程加密,中间任何环节都看不到明文数据;本地端口可以随意指定,不占用目标服务的端口。缺点是 SSH 连接断开隧道就没了,要长期保持得配合autossh这类的管理工具。

我在实际工作中用 SSH 隧道最多的场景是:远程维护一个内网数据库。数据库端口不对外暴露,只开 SSH,我本地用 MySQL 客户端连着本地转发的端口,安全又方便。安全上提醒一句:隧道只是帮你建立了可用的通路,访问控制、认证、授权这些事还是由目标服务自己负责,别以为套了 SSH 就万事大吉。

6. 常见问题与排查实录:用“分层思路”快速定位

6.1 能连 WiFi 但 ping 不通网关,先查这几步

先说一个高频现象:WiFi 显示已连接,但 ping 网关不通。按照分层思路,从下往上排查。

第一步,确认物理和链路层是否正常。iw dev wlan0 link可以看到无线网卡连接状态,包括 SSID、信号强度、速率。如果信号太差或处于“已关联但无流量”状态,直接重连。

第二步,确认 IP 配置。执行ip addr show wlan0,看有没有拿到 IP 地址,看 IP 和网关是不是同一个网段。很多“连上 WiFi 但没网”的问题,本质是 DHCP 失败,网卡拿到了一个 169.254.x.x 的 APIPA 地址(Windows 概念,Linux 上也会自动分配 link-local 地址),这会让你看起来“连上了”但没有可用的网络配置。解决方法是手动dhclient wlan0重新获取一次,或者检查路由器 DHCP 地址池是否够用。

第三步,确认网关 MAC 是否能学到。执行ip neigh show,看有没有网关 IP 的条目。如果一直是FAILED状态,说明 ARP 请求没有收到回复,问题很可能在无线链路或 AP 隔离上。这时可以把同一台机器插上网线,或者把两台设备都挪到有线网络,做对比实验,快速定位是无线还是路由问题。

第四步,检查防火墙。Linux 上默认防火墙(如 ufw)可能拦了 ICMP。你可以先用iptables -L -n看看有没有相关规则,或者暂时关闭防火墙测试。注意,关闭防火墙只是为了排查,确认原因后要恢复。

6.2 同网段能通、跨网段就断,大概率是路由问题

“局域网内互相 ping 通,但访问外网全断”是另一种经典问题。出现这个现象,说明二层通信正常,问题出在三层选路。

先执行ip route show,看默认路由有没有。没有default via条目,跨网包就没有出口。我见过有人配完静态 IP 后忘了填网关,同网段一切正常,外网永远不通,原因就这么简单。

再看默认网关填得对不对。网关必须是你直连网段内的 IP。如果你把网关填成了另一个网段的地址,本机根本没法把包送到网关,因为直连路由里没有匹配的网段。用ip route get 8.8.8.8可以看到实际选中的路由,如果是unreachable,那就是路由表有问题。

还有一种情况:多网卡机器的优先级错乱。比如机器既有 eth0(内网)又有 wlan0(外网),系统默认路由可能指向了错误的接口。调整办法是配置路由 metric。metric 越小优先级越高,比如让有线网卡的默认路由优先:

ip route add default via 192.168.1.1 dev eth0 metric 100

跨网段断还有一个隐蔽原因:DNS 配置。有时候你“ping 百度 IP”能通,但“ping baidu.com”不通,那不是网络问题,是 DNS 解析失败。检查/etc/resolv.conf,看 DNS 服务器是否可达。很多排障教程默认你分得清这些,但实际现场里,DNS 问题占“感觉网断了”的原因至少有三成。

6.3 数据传着传着变慢或卡死,如何分辨是线不行还是协议问题

跨网传输时遇到“一开始很快,后来越传越慢”或者干脆卡死,通常是这几个原因。

第一,TCP 重传。链路不稳定会产生丢包,TCP 检测到丢包会触发拥塞控制,主动降低发送速率。用iperf3 -c 目标IP看输出里的Retr(重传)列,如果数值很大,说明链路质量堪忧。再用mtr 目标IP看每一跳的丢包率,能定位是哪一段链路在丢包。

第二,路由器 NAT 性能瓶颈。小路由器同时处理大量连接时,CPU 会打满,导致吞吐骤降。这种情况在 P2P 下载、大文件并发传输时尤其明显。判断方法是:在局域网内先跑一次 iperf3,如果局域网内带宽正常,而跨网(经过路由器)带宽明显偏低,那瓶颈大概率在路由器转发性能上。

第三,MTU 问题。某些网络环境的 MTU 小于 1500,或者 PPPoE 拨号有额外的 8 字节开销,导致大包被分片或直接丢弃,表现为“小文件正常、大文件卡死”。用ping -M do -s 1400 目标IP测试,如果带不分片标志的大包不通,就是 MTU 问题。解决方法是调整网卡 MTU,比如常见的降为 1492。

第四,磁盘速度限制。这个最容易被忽略:网络传输的目标是写磁盘,如果磁盘写入速度比网络带宽慢,瓶颈就在磁盘。用dd if=/dev/zero of=/tmp/test bs=1M count=1024先测一下本地磁盘速度,再比较网络吞吐,别让网络背磁盘的锅。

6.4 一张速查表:遇到问题先看哪一层

把上面这些经验汇总成一张速查表,贴在旁边,比记一堆零散命令管用得多。

现象优先检查层常用命令常见根因
完全无法通信,WiFi 已连接链路层/网络接口层ip link、iw dev wlan0 link信号差、AP 隔离、网卡硬件故障
有 IP 但 ping 不通网关网络层ip addr、ip neigh、pingDHCP 失败、静态 IP 配置错误、防火墙拦 ICMP
同网段通,跨网段断网络层(路由)ip route show、ip route get缺少默认路由、网关填错、metric 优先级错乱
域名打不开但 IP 能通应用层(DNS)cat /etc/resolv.conf、digDNS 服务器不可达、配置错误
端口连不上传输层ss -tlnp、nc -vz IP 端口服务未监听、防火墙拦端口、端口被占用
传大文件慢/卡全链路iperf3、mtr、ethtool网线协商速率低、TCP 重传多、NAT 性能不足、磁盘瓶颈

实际操作中,我每次排查都会先用ping测三层连通性,再用ss -tnp看端口和状态,接着用ip route get确认选路,最后才轮到抓包。这个顺序执行完,绝大多数问题都能定位到具体某层,剩下极少情况用tcpdump抓包分析。

另外多说一句:排查网络问题时,改动前的备份非常重要。改配置文件之前先复制一份,比如cp /etc/netplan/01-network-config.yaml /etc/netplan/01-network-config.yaml.bak。我在生产服务器上犯过的最贵错误,就是改路由表没备份,结果回滚时记不清原始配置,花了一个多小时才恢复。网络配置这种“改错就断连”的操作,必须习惯先备份、再改动、后验证。

写在最后的小经验

如果你把这篇文章从头看到这里,再去动手做一遍那个“双网卡 Linux 当路由器”的实验,你对 TCP/IP 和跨网传输的理解绝对会超过一大半停留在“能连 WiFi”层面的使用者。

我自己这些年折腾网络最大的体会是:网络问题不可怕,可怕的是没有分层意识,遇到故障就瞎试。先想“这个现象发生在哪一层”,再用对应工具去验证,往往几分钟就能定位。另一个习惯是,任何配置改动前先备份,任何性能瓶颈先用 iperf3 和数据对比说话,别凭感觉判断。

最后分享一个小技巧:每次改完网络配置,先执行ip neigh flush all清掉 ARP 缓存,再用ip route get验证目标地址的路由走向。这两条命令花不了几秒钟,但能避免大量因缓存和旧路由导致的“幽灵故障”。网络的世界里,数据和理论最终都要落到命令行上验证,动手试一次,比读十篇文章都有用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询