ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

别只懂连WiFi:Linux网络排查、TCP/IP协议栈与跨网传输实战

别只懂连WiFi:Linux网络排查、TCP/IP协议栈与跨网传输实战 很多朋友第一次在笔记本上装 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 是 6UDP 是 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/24B 的 IP 是 192.168.1.20/24。24 表示子网掩码是 255.255.255.0前 24 位是网络位。把 192.168.1.10 和 255.255.255.0 按位与得到 192.168.1.0B 也算出来是 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. 跨网传输硬核逻辑网关、路由与 NAT4.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 机器作为路由器内网接口是 eth1192.168.1.1外网接口是 eth0假设是公网 IP需要开启 IP 转发echo 1 /proc/sys/net/ipv4/ip_forward然后配置 NATiptables -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/24eth1 连着内网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 端口。在另一台机器上启动客户端注意这里填的是服务端的 IPiperf3 -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 服务的临时设备ncnetcat才是最快的选择。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文件传完后接收端可以按 CtrlC 中断 nc。这个命令的本质是纯 TCP 流传输没有加密也没有文件完整性校验所以适合在可信局域网里传临时文件不适合传敏感数据。用 nc 的时候有几个细节要注意。第一数据流没有结束标志所以接收端无法自动知道文件传完没有需要手动中断或者发送端传完文件后再发送一个额外信号接收端根据信号判断。第二如果文件比较大建议加pv命令看实时进度nc -l -p 1234 | pv backup.tar.gzpv会显示当前传输速率和已传输大小。第三nc 本身不校验文件是否完整传完之后建议用md5sum对比两边文件的哈希值。这个习惯能帮你快速发现是传输损坏还是本身就是两台机器的文件不一致。我经常用 nc 在嵌入式开发板和主机之间传固件包。开发板资源有限没有 SSH 服务但 busybox 里通常自带 nc一条命令搞定。它能用上的前提依然是两台设备在同一网络里并且你知道对方的 IP 和端口。5.3 rsync 增量同步真实场景的跨网搬运如果要在真实生产环境里跨网搬数据rsync 是最靠谱的工具之一。它的核心价值不是“快”而是“只传差异部分”。源目录里只有几个文件变了rsync 扫描一遍后只传变化的文件而不是整个目录重新搬一遍。最常见的用法rsync -av --progress /data/ user192.168.1.10:/backup/-a表示归档模式保留权限、时间戳等元信息-v显示详细输出--progress显示每个文件的传输进度。默认情况下 rsync 通过 SSH 传输所以目标地址的格式是userhost:/path。跨网传输时rsync 还支持限速参数rsync -av --bwlimit2000 /data/ user192.168.1.10:/backup/--bwlimit2000表示限制带宽为 2000 KB/s。这个参数在有其他业务跑在链路上时非常实用避免 rsync 把带宽抢光。我遇到过半夜做全量备份第二天发现内网所有服务响应变慢的情况罪魁祸首就是 rsync 不限速。rsync 增量同步的原理简单说就是比较文件大小、修改时间和可选的校验和决定要不要传。带宽充裕时可以不加-cchecksum靠时间和大小判断就够了如果担心文件被改动但时间戳没变可以加-c强制校验内容代价是扫描时消耗更多 CPU。还有一个常见的坑rsync 同步目录时源路径末尾的斜杠含义不同。rsync -av /data/ userhost:/backup/表示把 /data 目录里的内容同步到 /backup 目录下而rsync -av /data userhost:/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 user192.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 bs1M count1024先测一下本地磁盘速度再比较网络吞吐别让网络背磁盘的锅。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 能通应用层DNScat /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验证目标地址的路由走向。这两条命令花不了几秒钟但能避免大量因缓存和旧路由导致的“幽灵故障”。网络的世界里数据和理论最终都要落到命令行上验证动手试一次比读十篇文章都有用。
返回列表