☰
IP、DNS、TCP、NAT:一次外网访问故障背后的网络基础全解
2026/9/26 4:34:29 网站建设 项目流程

家里的NAS装了半个月,内网访问一直好好的,朋友说“用手机流量打不开”,我第一反应是“路由器端口映射没配好”,结果折腾了两天,最后发现不是映射的问题,而是我对“IP、网关、DNS、TCP”这些最基础的网络概念的理解,全都停在了“好像知道”的程度——知道IP是门牌号,但不知道子网掩码到底是干嘛的;知道DNS能把域名翻译成IP,但不知道本地DNS缓存和TTL能坑人到什么程度;知道TCP有三次握手,但从没想过“为什么是三次而不是两次”。

这篇文章我就把这次“补课”的过程完整整理出来,不按教科书顺序讲,而是按“一台新服务器从插上网线到被外网访问到”的链路来讲。每个概念都有对应的实操命令和真实故障场景,适合半路出家的开发者、自己折腾NAS或服务器的新手、以及面试前想把网络基础捋清楚的人。

1. 设备“入网”的三种身份凭证:IP地址、子网掩码与默认网关

新机器插上网线、连上Wi-Fi,你首先会发现它拿到了一个类似192.168.1.100的地址。很多人觉得“能拿到IP就能上网了”,其实这里藏着三个身份凭证:IP地址、子网掩码、默认网关,缺一个,设备就只是“在线”而不是“在网”。

1.1 IP地址和子网掩码:门牌号之外的“片区判定”

IP地址像门牌号,但只靠门牌号,你没法知道“对方在不在同一个小区”。IPv4地址是32位的,写成192.168.1.100这种点分十进制只是为了给人看。真正决定“这个地址属于哪个网络”的,是子网掩码。

拿最常见的192.168.1.100/24来说,/24表示前24位是网络号,后8位是主机号。换算成子网掩码就是255.255.255.0。网络号是192.168.1.0,主机号是100,广播地址是192.168.1.255。为什么一个网段里可用设备数是254而不是256?因为网络地址(末尾 .0)和广播地址(末尾 .255)都不能分配给设备。这个逻辑搞懂了,你看到/24就秒懂这个网段能放多少设备,不用死记。

Linux下查看这些信息用ip addr和ip route,Windows用ipconfig。我自己的开发机上跑ip addr,输出大致长这样:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0

这个192.168.1.100/24就同时告诉你IP和子网掩码。brd后面的地址就是广播地址。

1.2 默认网关:唯一一条“走出去”的路

有了IP和掩码,设备可以判断目标地址在不在同一网段。如果目标在网段内,直接通过ARP找到对方的MAC地址就能通信,不需要网关。但如果目标在别的网段,设备会把数据包交给默认网关——一条0.0.0.0/0的默认路由,意思是“除了直连网段之外的所有目标,都从这里走”。

我见过一个特别典型的故障:有人手动配置IP时把网关写错成192.168.1.254,但路由器实际是192.168.1.1,结果就是“能ping通同网段设备,但上不了网”。这时候执行ip route看一下默认路由指向哪里,立刻就能发现问题。网关不生效时,很多人的第一反应是换线、换路由器,其实只要把网关改对就行。

1.3 公网IP、私网IP与 DHCP 的坑

家用路由器里的设备基本都是私网IP,RFC1918规定了三个私有网段:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16。这些地址在公网上不可路由,必须经过NAT才能访问外网。

设备启动时,会通过DHCP自动向路由器申请IP。这里有个坑:如果DHCP失败,设备会给自己分配一个169.254.x.x的链路本地地址。在Windows上,看到IP是169.254开头,基本可以断定“没有拿到DHCP分配”,这时候检查网线、路由器DHCP服务,比重新配置IP地址更合理。我朋友那次打不开网站,后来发现路由器重启后DHCP分配了新的内网IP,而端口映射里写的还是旧IP,这就是典型的“身份凭证变了,规则还没跟上”。

2. 从域名到IP的翻译旅程:DNS解析链路与常见故障

配置好IP、网关,设备能上网了,但我们在浏览器里输入的是www.example.com这种域名,不是IP。把域名翻译成IP的体系就是DNS。这一步是“打不开网站”问题里藏得最深的一环,因为域名解析失败和服务器故障的表现可能完全一样。

2.1 DNS解析的完整顺序

当你在浏览器输入一个域名时,查找顺序是:浏览器缓存 → 操作系统hosts文件 → 本地DNS缓存 → 向配置的DNS服务器发起查询。

其中hosts文件是一个容易被忽略的坑。Windows和Linux都有hosts文件,如果你曾经为了测试把某个域名写进去,之后忘了删,那DNS解析就会一直指向那个旧IP,而不是真实地址,并且任何DNS缓存刷新命令都管不到它。我自己就因为这个原因,把“域名解析问题”排查了半个小时,最后发现是hosts里躺着一行两年前写的映射。

真正向DNS服务器发起查询时,链路是这样的:你的设备问递归DNS服务器(比如你配置的223.5.5.5),递归DNS再依次去问根服务器、.com顶级域服务器、该域名的权威服务器,最终拿到A记录或AAAA记录,返回给你。这个过程用户无感知,但理解它有两个意义:一是知道为什么“刚改完DNS记录,浏览器却还在访问旧服务器”——因为中间每一级都可能缓存旧记录,生效时间由TTL(生存时间)决定;二是明白递归DNS服务器本身可能缓存了错误结果,换一个公共DNS往往能绕过这个缓存。

2.2 实操命令与DNS常见故障

Linux下查DNS用dig,Windows用nslookup。以dig example.com为例,你关心的是这段:

;; ANSWER SECTION: example.com. 3600 IN A 93.184.216.34

3600就是TTL,单位是秒,表示这个记录可以被缓存1小时。如果出现status: SERVFAIL,通常说明权威服务器出问题或递归服务器配置异常;如果返回IP和你预期不符,检查是不是本地缓存了旧记录,Windows执行ipconfig /flushdns清一下。

实践中还有一个很不显眼的坑:IPv6的AAAA记录查询超时。域名既有A记录也有AAAA记录时,有些操作系统会优先尝试IPv6连接,如果当前网络没有IPv6路由,就会一直等到超时才fallback回IPv4,表现为“网页转圈很久才打开,甚至报错”。这时候用dig AAAA example.com看一眼是否有AAAA记录,以及本地有没有拿到IPv6地址,就能定位。

公共DNS的选择方面,国内可用的223.5.5.5(阿里)、114.114.114.114(114DNS)、8.8.8.8(Google)各有特点。我的建议是首选前两个,解析延迟低。换DNS之后dig的结果如果不再异常,就说明问题出在之前配置的DNS服务器或它的缓存上。

3. TCP/IP分层不是用来背的:数据包在真实访问中的完整旅程

拿到服务器的IP之后,浏览器要发起HTTP请求,数据通过TCP/IP协议栈一层层封装,最终变成电信号或无线信号传到服务器。很多人背过OSI七层模型,但我建议先重点理解四层模型:应用层、传输层、网络层、链路层。这不是为了应付考试,而是为了“分层排查”——哪一层出问题,现象完全不同。

3.1 四层模型的职责划分

层级核心职责常见协议活生生的例子
应用层定义数据格式与语义HTTP/HTTPS、DNS、FTP浏览器拼一个GET请求
传输层端到端可靠传输、端口区分TCP/UDP给请求加上端口号、保证顺序
网络层寻址、路由选择IP、ICMP决定数据包从哪条路走
链路层物理传输、局域网寻址以太网、Wi-Fi在网线上发送二进制数据

用快递打比方:应用层是你写的收件内容;传输层是快递单号和服务等级(普通件/加急件);网络层是分拣中心根据城市名决定路线;链路层是快递员骑着车把你家门口的路跑完。如果你用curl -v访问一个HTTPS网站,看到的输出其实就对应层层协议在对话:先是DNS解析,然后是TCP连接,接着是TLS握手,最后才是HTTP请求和响应。每一层都像链条的一个环节,断在哪一环,后面的环节就不可能正常。

3.2 三次握手为什么是三次,以及端口与连接状态

TCP三次握手是SYN、SYN-ACK、ACK三步。为什么不是两次?核心原因是防止“历史迷路的连接请求”把连接建立起来。假设客户端发出了一个SYN,因为网络拥塞超时,客户端以为丢了,重发SYN。然后第一个迟到的SYN又到了服务端,如果只靠两次握手,服务端收到这个迟到的SYN就会返回SYN-ACK并建立连接,但客户端其实已经发起新连接了,两边状态就不一致。三次握手让客户端在收到服务端的SYN-ACK时能判断“这个确认对应的是我哪一次SYN”,如果是旧的就发RST把连接拆掉。所以第二次握手不仅是确认,更是给客户端一个“确认你是哪次连接”的机会。

握手完成后,TCP连接才真正开始传数据。这里有一个非常实用的查看命令:ss -tlnp(Linux)或netstat -an(Windows/Linux)可以看到本机监听的端口。端口的概念很简单:IP是楼地址,端口是房间号。HTTP默认80,HTTPS默认443,SSH默认22,DNS是53。你用ss -tlnp | grep 443看到有监听,说明服务进程在跑;看到TIME_WAIT状态堆积,通常是短连接频繁关闭导致的,和对端服务是否正常没有直接关系。

抓包看握手是最直观的。一条命令就可以:

sudo tcpdump -i any tcp port 443 -c 20

然后用另一个终端执行curl https://example.com,你会在抓包里看到清晰的SYN、SYN-ACK、ACK序列,以及后续TLS的ClientHello、ServerHello。我建议每个想弄懂TCP的人都实际抓一次包,因为“看过”和“见过”完全是两种理解深度。

到了HTTPS这一步,传输层之上还有TLS握手:客户端发ClientHello,服务端回ServerHello和证书,双方协商出会话密钥,之后所有HTTP内容都加密传输。这也是为什么HTTPS默认走443端口,因为TLS会话是在TCP连接建立之后、HTTP请求发送之前完成的。

4. 数据包如何“走出家门”:路由、端口映射与NAT

前面的链路已经把数据包封装好、准备发出去了,但一个关键问题还没解决:从你家里发出的数据包,怎么知道经路由器的哪个口出去、到达公网之后又怎么回来?这就涉及路由和NAT。

4.1 路由表与最长前缀匹配

每个设备、路由器都有一张路由表,决定“目标IP的数据包往哪个接口发”。家用路由器的核心路由规则通常是:

default via 192.168.1.1 dev eth0

这一行default就是默认路由,对应0.0.0.0/0。收到目的IP为8.8.8.8的数据包时,路由表里没有更具体的匹配项,就会匹配这条默认路由,发给网关。

多路由条目场景下的选择原则是“最长前缀匹配”——谁的掩码更长、匹配的位数更多,就选谁。比如路由器可以做策略路由,让某个网段走特定出口。理解了最长前缀匹配,你就不会惊讶“为什么同时有两条路由时,某些流量走A、某些流量走B”。

用traceroute(Linux)或tracert(Windows)可以直观看到数据包逐跳经过的路径。原理是利用IP头里的TTL字段:每经过一个路由器TTL减1,减到0时路由器丢弃包并返回ICMP超时。测试时从TTL=1开始递增,就会逐个记录每一跳的地址。我拿它排查过“访问某服务器特别慢”的问题,发现慢的不是服务器,而是中间某个运营商节点丢包严重。

4.2 NAT、端口映射与安全组

家用路由器拿到的公网IP通常只有一个,但家里可能有手机、电脑、NAS好几台设备同时上网。路由器靠NAT(网络地址转换)解决这个矛盾,更准确的说是NAPT,它不仅改IP,还改端口。

举个例子:你电脑192.168.1.50:52340访问公网服务器1.2.3.4:443,数据包经过家用路由器时,源IP被改写为路由器的公网IP202.x.x.x,源端口也被改成一个随机端口54321。路由器在内存里记一条映射:192.168.1.50:52340 ↔ 202.x.x.x:54321。服务器回包时,目的地址是202.x.x.x:54321,路由器查映射表,把目的改写回192.168.1.50:52340,数据包才能回到你电脑。

理解了NAT这张映射表,再回头看“外网访问内网服务器”就顺了:外网用户访问你家的公网IP的某个端口,路由器根本不知道这个端口对应哪台内网设备。所以需要在路由器上配置端口映射(也叫端口转发/DNAT),比如把公网IP的8080端口转发到内网192.168.1.100的80端口。这样外网访问http://公网IP:8080时,路由器改写目的IP和端口,把请求交给你家里的Nginx。

云服务器场景下的“安全组”和家用路由器不太一样。安全组是云平台在虚拟网络层做的一层过滤规则,你买了一台ECS,公网端口默认全闭,必须在安全组规则里放行443或8080,否则就算服务器内启动服务也访问不到。家用场景则要检查路由器端口映射和设备防火墙。我见过有人在云服务器上配好了Nginx,端口也监听了,就是忘了加安全组规则,结果外网“连接被拒绝”,这个顺序初学者特别容易踩。

NAT这里还有一个更深层的坑:它只对TCP/UDP这类有端口的协议友好。如果你以后做P2P联机或自建游戏服务器,会碰到“为什么服务器明明开着,对方就是连不上”的问题,那是因为NAT阻碍了直接入站连接,必须借助STUN/TURN这类NAT穿透方案。做项目时提前知道这个限制,会少走很多弯路。

5. 一次真实的断网排查:用分层思维逐层定位根因

概念讲了一堆,最终都要落实到排障。这里复盘一次我帮朋友排查“网站突然打不开”的完整过程,你会看到上面所有概念是怎么被串起来的。

5.1 排查命令链:每一层失败代表什么

故障现象是:外网用户访问https://xxx.example.com报超时,朋友在内网用同一域名访问正常。我的排查顺序是:

  1. 本机协议栈是否正常:ping 127.0.0.1。如果这一步都不通,说明本机TCP/IP协议栈有问题,但这概率极低。
  2. 本机到网关是否通:ping 192.168.1.1。失败说明链路层或DHCP有问题,比如网线没插好、Wi-Fi信号差、网卡被禁用。
  3. 本机到公网是否通:ping 223.5.5.5。失败说明默认网关或路由/NAT有问题,也可能是运营商线路断了。
  4. 域名解析是否正确:dig xxx.example.com。看到返回的公网IP和预期一致,说明DNS正常;如果不一致,查hosts、查本地DNS缓存、查TTL。
  5. 端口是否可达:nc -vz xxx.example.com 443(或telnet xxx.example.com 443)。这一步测试的是TCP连接能不能建立,也就是路由+NAT+端口映射+安全组+服务进程是否都通畅。如果是Connection timed out,多半是路由路径上丢包或防火墙丢弃;如果是Connection refused,说明目标主机上服务没监听或防火墙主动拒绝。
排查命令验证目标典型失败含义
ping 127.0.0.1本机协议栈网卡/协议栈异常
ping 192.168.1.1到网关的链路网线/Wi-Fi/DHCP问题
ping 223.5.5.5出公网路由与NAT默认网关/运营商线路问题
dig或nslookupDNS解析hosts、DNS缓存、TTL问题
nc -vz 域名 443端到端连通性NAT/端口映射/安全组/服务进程

5.2 这次断网的根因:动态IP与端口映射的“失配”

按上面的链路排查,最后发现:ping外网IP通了,dig解析出的IP也正确,但nc测试443端口超时。问题出在端口映射这一层。

原来朋友家路由器重启过一次,重启后动态公网IP变了,而他在路由器上配的“端口转发”规则写的是旧的公网IP地址映射(有些路由器在拨号IP变化后会保留DDNS更新,但端口转发规则可能依赖旧的接口绑定),再加上DDNS的缓存还没更新到最新公网IP,外网用户访问的其实还是旧IP。修复方法也很直接:重新检查路由器WAN口获取的当前公网IP,确认DDNS记录用的是域名→最新公网IP,然后把端口转发规则里的“内网目标IP”改成DHCP为服务器分配的当前内网地址。

这个案例最值得反思的点是:问题根源其实非常基础——IP会变、DHCP分配会变、DNS记录有TTL、NAT规则必须和IP匹配。任何一个环节失配,表现都是“网站打不开”,但用分层排查法,20分钟内就能定位到具体是哪一层。

整套走完,我自己最大的体会是:网络基础概念一定不要孤立地背,它是一条“数据走哪个门、怎么找路、怎么翻译、怎么映射”的完整链路。建议你手头找一台闲置的电脑或树莓派,配一个Nginx,然后故意做几个破坏动作——改错网关、改错DNS、关掉安全组端口、停掉Nginx——再按上面这套命令逐层排查。折腾完这四五个故障,你对网络的理解会比看十遍教程都深刻。

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

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

立即咨询