NAT、代理服务与内网穿透详解

NAT、代理服务与内网穿透详解:从地址转换到公网访问内网服务

摘要:IPv4 地址数量有限,私有地址、NAT、代理服务和内网穿透都是围绕"不同网络之间如何通信"衍生出来的关键技术。本文从 NAT 和 NAPT 的转换过程讲起,对比正向代理、反向代理与 NAT 的差异,再解释为什么外网通常无法直接访问内网服务,以及内网穿透的基本思路。

前言

很多人在家里或公司写网络程序时,都会遇到一个现象:

text 复制代码
局域网内能访问,换到外网就访问不了。

这背后通常和私有 IP、NAT、路由器出口地址有关。NAT 让大量内网设备能够共享公网出口访问互联网,但它也带来了一个副作用:外部网络很难主动连接到内网机器。

代理服务和内网穿透又是在这个背景下经常出现的概念。它们看起来都像"中间转发",但工作层次、解决的问题和部署方式并不一样。

一、为什么需要 NAT

IPv4 地址是 32 位,地址总量有限。为了让更多设备接入网络,很多家庭、学校、公司内部都会使用私有 IP 地址,例如:

text 复制代码
10.0.0.10
192.168.1.100
172.16.1.20

私有 IP 只需要在当前局域网内不冲突,不要求全网唯一。公网 IP 则必须在互联网范围内唯一。

NAT 的核心作用是:让内网私有 IP 在对外通信时转换成公网 IP
#mermaid-svg-8N8KkJQYlyMjeNq0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8N8KkJQYlyMjeNq0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8N8KkJQYlyMjeNq0 .error-icon{fill:#552222;}#mermaid-svg-8N8KkJQYlyMjeNq0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8N8KkJQYlyMjeNq0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8N8KkJQYlyMjeNq0 .marker.cross{stroke:#333333;}#mermaid-svg-8N8KkJQYlyMjeNq0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8N8KkJQYlyMjeNq0 p{margin:0;}#mermaid-svg-8N8KkJQYlyMjeNq0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8N8KkJQYlyMjeNq0 .cluster-label text{fill:#333;}#mermaid-svg-8N8KkJQYlyMjeNq0 .cluster-label span{color:#333;}#mermaid-svg-8N8KkJQYlyMjeNq0 .cluster-label span p{background-color:transparent;}#mermaid-svg-8N8KkJQYlyMjeNq0 .label text,#mermaid-svg-8N8KkJQYlyMjeNq0 span{fill:#333;color:#333;}#mermaid-svg-8N8KkJQYlyMjeNq0 .node rect,#mermaid-svg-8N8KkJQYlyMjeNq0 .node circle,#mermaid-svg-8N8KkJQYlyMjeNq0 .node ellipse,#mermaid-svg-8N8KkJQYlyMjeNq0 .node polygon,#mermaid-svg-8N8KkJQYlyMjeNq0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8N8KkJQYlyMjeNq0 .rough-node .label text,#mermaid-svg-8N8KkJQYlyMjeNq0 .node .label text,#mermaid-svg-8N8KkJQYlyMjeNq0 .image-shape .label,#mermaid-svg-8N8KkJQYlyMjeNq0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-8N8KkJQYlyMjeNq0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8N8KkJQYlyMjeNq0 .rough-node .label,#mermaid-svg-8N8KkJQYlyMjeNq0 .node .label,#mermaid-svg-8N8KkJQYlyMjeNq0 .image-shape .label,#mermaid-svg-8N8KkJQYlyMjeNq0 .icon-shape .label{text-align:center;}#mermaid-svg-8N8KkJQYlyMjeNq0 .node.clickable{cursor:pointer;}#mermaid-svg-8N8KkJQYlyMjeNq0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8N8KkJQYlyMjeNq0 .arrowheadPath{fill:#333333;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8N8KkJQYlyMjeNq0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8N8KkJQYlyMjeNq0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8N8KkJQYlyMjeNq0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8N8KkJQYlyMjeNq0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8N8KkJQYlyMjeNq0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8N8KkJQYlyMjeNq0 .cluster text{fill:#333;}#mermaid-svg-8N8KkJQYlyMjeNq0 .cluster span{color:#333;}#mermaid-svg-8N8KkJQYlyMjeNq0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8N8KkJQYlyMjeNq0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8N8KkJQYlyMjeNq0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-8N8KkJQYlyMjeNq0 .icon-shape,#mermaid-svg-8N8KkJQYlyMjeNq0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8N8KkJQYlyMjeNq0 .icon-shape p,#mermaid-svg-8N8KkJQYlyMjeNq0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8N8KkJQYlyMjeNq0 .icon-shape .label rect,#mermaid-svg-8N8KkJQYlyMjeNq0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8N8KkJQYlyMjeNq0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8N8KkJQYlyMjeNq0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8N8KkJQYlyMjeNq0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 内网主机 10.0.0.10
NAT 路由器
公网服务器 163.221.120.9

从公网服务器看,请求并不是来自 10.0.0.10,而是来自 NAT 路由器的公网地址。

二、NAT 的地址转换过程

假设内网主机 10.0.0.10 访问外网服务器 163.221.120.9,NAT 路由器的公网地址是 202.244.174.37

出站时:

text 复制代码
源 IP: 10.0.0.10       -> 202.244.174.37
目的 IP: 163.221.120.9 -> 163.221.120.9

入站响应回来时:

text 复制代码
源 IP: 163.221.120.9   -> 163.221.120.9
目的 IP: 202.244.174.37 -> 10.0.0.10

NAT 路由器内部会维护一张转换表。第一次从 10.0.0.10 发起对外通信时,路由器会记录这条映射关系;后续响应回来时,再根据映射把目标地址改回内网主机地址。

可以把它理解成:

阶段 NAT 做的事情
内网访问外网 把源私有 IP 改成公网出口 IP
外网响应回来 根据转换表把目的公网 IP 改回内网 IP
通信结束 删除对应转换关系

三、NAPT:为什么还要带端口

只有 IP 地址转换还不够。考虑一个更常见的情况:

text 复制代码
10.0.0.10 访问 163.221.120.9:80
10.0.0.11 也访问 163.221.120.9:80

外网服务器返回数据时,目的 IP 都是 NAT 路由器的公网 IP。路由器怎么知道应该转给 10.0.0.10,还是转给 10.0.0.11

这就需要 NAPT。NAPT 使用 IP + port 建立映射关系。

示例转换表:

内网连接 转换后的公网连接 目标服务
10.0.0.10:1025 202.244.174.37:1025 163.221.120.9:80
10.0.0.11:1025 202.244.174.37:1026 163.221.120.9:80

可以看到,即使两个内网主机使用了相同源端口,NAT 路由器也可以在公网侧改成不同端口,从而区分不同连接。

在 TCP 场景中,连接建立时会生成映射表项,连接断开后会删除表项。这些关系由 NAT 设备自动维护。

四、NAT 的限制

NAT 解决了 IPv4 地址不足问题,但它也带来一些限制。

限制 说明
外部难以主动访问内部服务 映射表通常由内网主动访问外网时生成
转换表有维护成本 表项创建、查询、销毁都需要开销
NAT 设备成为关键节点 设备异常可能导致已有连接全部中断
端到端连接语义被改变 原始源地址在出口处被替换

很多"内网服务无法被公网访问"的问题,本质上就来自第一条:没有映射关系时,外部请求到达 NAT 设备,NAT 不知道应该转给哪台内网主机。

五、代理服务是什么

代理服务器也位于客户端和目标服务器之间,也会转发请求和响应,所以它看起来和 NAT 有点像。

但二者关注点不同:

对比项 NAT 代理服务器
主要目标 缓解 IP 地址不足,完成地址转换 代表一方发起或接收应用请求
常见层次 网络层附近,改 IP/端口 更贴近应用层,理解具体协议
部署位置 路由器、防火墙等出口设备 独立服务器或软件服务
典型用途 内网共享公网出口 访问控制、缓存、负载均衡、安全隔离

NAT 更像网络基础能力,代理更像应用转发能力。

六、正向代理:代理客户端访问目标服务器

正向代理位于客户端和目标服务器之间,代表客户端向目标服务器发请求。
#mermaid-svg-vHr99gmZZZQ887m7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vHr99gmZZZQ887m7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vHr99gmZZZQ887m7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vHr99gmZZZQ887m7 .error-icon{fill:#552222;}#mermaid-svg-vHr99gmZZZQ887m7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vHr99gmZZZQ887m7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vHr99gmZZZQ887m7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vHr99gmZZZQ887m7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vHr99gmZZZQ887m7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vHr99gmZZZQ887m7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vHr99gmZZZQ887m7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vHr99gmZZZQ887m7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vHr99gmZZZQ887m7 .marker.cross{stroke:#333333;}#mermaid-svg-vHr99gmZZZQ887m7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vHr99gmZZZQ887m7 p{margin:0;}#mermaid-svg-vHr99gmZZZQ887m7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-vHr99gmZZZQ887m7 .cluster-label text{fill:#333;}#mermaid-svg-vHr99gmZZZQ887m7 .cluster-label span{color:#333;}#mermaid-svg-vHr99gmZZZQ887m7 .cluster-label span p{background-color:transparent;}#mermaid-svg-vHr99gmZZZQ887m7 .label text,#mermaid-svg-vHr99gmZZZQ887m7 span{fill:#333;color:#333;}#mermaid-svg-vHr99gmZZZQ887m7 .node rect,#mermaid-svg-vHr99gmZZZQ887m7 .node circle,#mermaid-svg-vHr99gmZZZQ887m7 .node ellipse,#mermaid-svg-vHr99gmZZZQ887m7 .node polygon,#mermaid-svg-vHr99gmZZZQ887m7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vHr99gmZZZQ887m7 .rough-node .label text,#mermaid-svg-vHr99gmZZZQ887m7 .node .label text,#mermaid-svg-vHr99gmZZZQ887m7 .image-shape .label,#mermaid-svg-vHr99gmZZZQ887m7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-vHr99gmZZZQ887m7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vHr99gmZZZQ887m7 .rough-node .label,#mermaid-svg-vHr99gmZZZQ887m7 .node .label,#mermaid-svg-vHr99gmZZZQ887m7 .image-shape .label,#mermaid-svg-vHr99gmZZZQ887m7 .icon-shape .label{text-align:center;}#mermaid-svg-vHr99gmZZZQ887m7 .node.clickable{cursor:pointer;}#mermaid-svg-vHr99gmZZZQ887m7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vHr99gmZZZQ887m7 .arrowheadPath{fill:#333333;}#mermaid-svg-vHr99gmZZZQ887m7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vHr99gmZZZQ887m7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vHr99gmZZZQ887m7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vHr99gmZZZQ887m7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vHr99gmZZZQ887m7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vHr99gmZZZQ887m7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vHr99gmZZZQ887m7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vHr99gmZZZQ887m7 .cluster text{fill:#333;}#mermaid-svg-vHr99gmZZZQ887m7 .cluster span{color:#333;}#mermaid-svg-vHr99gmZZZQ887m7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vHr99gmZZZQ887m7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vHr99gmZZZQ887m7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-vHr99gmZZZQ887m7 .icon-shape,#mermaid-svg-vHr99gmZZZQ887m7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vHr99gmZZZQ887m7 .icon-shape p,#mermaid-svg-vHr99gmZZZQ887m7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vHr99gmZZZQ887m7 .icon-shape .label rect,#mermaid-svg-vHr99gmZZZQ887m7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vHr99gmZZZQ887m7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vHr99gmZZZQ887m7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vHr99gmZZZQ887m7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
正向代理
目标服务器

工作流程:

  1. 客户端把请求发送给正向代理;
  2. 正向代理根据配置处理请求,例如缓存、过滤、访问控制;
  3. 正向代理把请求转发给目标服务器;
  4. 目标服务器把响应返回给正向代理;
  5. 正向代理再把响应返回给客户端。

常见能力:

能力 说明
缓存 常访问内容可以直接从代理返回
内容过滤 根据规则过滤请求或响应
访问控制 限制特定客户端访问特定网站
隐藏客户端身份 目标服务器看到的是代理地址
访问管理 企业或公共网络中控制出口访问

正向代理的核心视角是:服务器不知道真正的客户端是谁,客户端知道自己在使用代理

七、反向代理:代理后端服务器接收请求

反向代理通常部署在 Web 服务前面。客户端访问的是反向代理,反向代理再根据规则把请求转发给后端服务器。
#mermaid-svg-hZahhe38xEGp3V9r{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hZahhe38xEGp3V9r .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hZahhe38xEGp3V9r .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hZahhe38xEGp3V9r .error-icon{fill:#552222;}#mermaid-svg-hZahhe38xEGp3V9r .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hZahhe38xEGp3V9r .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hZahhe38xEGp3V9r .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hZahhe38xEGp3V9r .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hZahhe38xEGp3V9r .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hZahhe38xEGp3V9r .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hZahhe38xEGp3V9r .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hZahhe38xEGp3V9r .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hZahhe38xEGp3V9r .marker.cross{stroke:#333333;}#mermaid-svg-hZahhe38xEGp3V9r svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hZahhe38xEGp3V9r p{margin:0;}#mermaid-svg-hZahhe38xEGp3V9r .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hZahhe38xEGp3V9r .cluster-label text{fill:#333;}#mermaid-svg-hZahhe38xEGp3V9r .cluster-label span{color:#333;}#mermaid-svg-hZahhe38xEGp3V9r .cluster-label span p{background-color:transparent;}#mermaid-svg-hZahhe38xEGp3V9r .label text,#mermaid-svg-hZahhe38xEGp3V9r span{fill:#333;color:#333;}#mermaid-svg-hZahhe38xEGp3V9r .node rect,#mermaid-svg-hZahhe38xEGp3V9r .node circle,#mermaid-svg-hZahhe38xEGp3V9r .node ellipse,#mermaid-svg-hZahhe38xEGp3V9r .node polygon,#mermaid-svg-hZahhe38xEGp3V9r .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hZahhe38xEGp3V9r .rough-node .label text,#mermaid-svg-hZahhe38xEGp3V9r .node .label text,#mermaid-svg-hZahhe38xEGp3V9r .image-shape .label,#mermaid-svg-hZahhe38xEGp3V9r .icon-shape .label{text-anchor:middle;}#mermaid-svg-hZahhe38xEGp3V9r .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hZahhe38xEGp3V9r .rough-node .label,#mermaid-svg-hZahhe38xEGp3V9r .node .label,#mermaid-svg-hZahhe38xEGp3V9r .image-shape .label,#mermaid-svg-hZahhe38xEGp3V9r .icon-shape .label{text-align:center;}#mermaid-svg-hZahhe38xEGp3V9r .node.clickable{cursor:pointer;}#mermaid-svg-hZahhe38xEGp3V9r .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hZahhe38xEGp3V9r .arrowheadPath{fill:#333333;}#mermaid-svg-hZahhe38xEGp3V9r .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hZahhe38xEGp3V9r .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hZahhe38xEGp3V9r .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hZahhe38xEGp3V9r .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hZahhe38xEGp3V9r .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hZahhe38xEGp3V9r .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hZahhe38xEGp3V9r .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hZahhe38xEGp3V9r .cluster text{fill:#333;}#mermaid-svg-hZahhe38xEGp3V9r .cluster span{color:#333;}#mermaid-svg-hZahhe38xEGp3V9r div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hZahhe38xEGp3V9r .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hZahhe38xEGp3V9r rect.text{fill:none;stroke-width:0;}#mermaid-svg-hZahhe38xEGp3V9r .icon-shape,#mermaid-svg-hZahhe38xEGp3V9r .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hZahhe38xEGp3V9r .icon-shape p,#mermaid-svg-hZahhe38xEGp3V9r .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hZahhe38xEGp3V9r .icon-shape .label rect,#mermaid-svg-hZahhe38xEGp3V9r .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hZahhe38xEGp3V9r .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hZahhe38xEGp3V9r .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hZahhe38xEGp3V9r :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
反向代理
后端服务器 A
后端服务器 B
后端服务器 C

在这个过程中,客户端只知道反向代理地址,并不知道后端真实服务器是谁。

反向代理常见用途:

用途 说明
负载均衡 把请求分发到多个后端服务器
安全保护 隐藏后端真实地址,统一做安全策略
缓存加速 重复内容可以直接从代理返回
内容过滤和重写 修改请求头、路径或响应内容
动静分离 静态资源直接由代理层返回
CDN 内容分发网络常采用反向代理思想

反向代理的核心视角是:客户端不知道真正的后端是谁,后端服务知道前面有代理层

八、正向代理和反向代理怎么区分

很多初学者容易把二者混在一起。可以用一句话区分:

text 复制代码
正向代理代理客户端,反向代理代理服务器。
对比项 正向代理 反向代理
代理对象 客户端 服务端
客户端是否感知代理 通常知道 通常只访问代理入口
目标服务器看到谁 看到代理 看到反向代理转来的请求
常见用途 访问控制、缓存、隐藏客户端 负载均衡、安全隔离、缓存、动静分离

更通俗地说:

正向代理像"我不方便直接去买东西,让别人替我去买"。商家看到的是代买的人。

反向代理像"店家把货提前放到一个统一窗口,顾客只找窗口拿货"。顾客不需要知道后面有几个仓库。

九、内网穿透解决什么问题

NAT 的一个典型限制是:外网无法直接访问内网服务。

比如你在家里的机器上启动了一个 Web 服务:

text 复制代码
192.168.1.20:8080

局域网内其他设备能访问,但公网用户无法直接访问这个私有地址。内网穿透要解决的就是:

text 复制代码
让公网用户可以访问内网中的某个服务。

常见思路是引入一个公网中转节点:
#mermaid-svg-EMZBPLtX2EQIFg6d{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EMZBPLtX2EQIFg6d .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EMZBPLtX2EQIFg6d .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EMZBPLtX2EQIFg6d .error-icon{fill:#552222;}#mermaid-svg-EMZBPLtX2EQIFg6d .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EMZBPLtX2EQIFg6d .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EMZBPLtX2EQIFg6d .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EMZBPLtX2EQIFg6d .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EMZBPLtX2EQIFg6d .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EMZBPLtX2EQIFg6d .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EMZBPLtX2EQIFg6d .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EMZBPLtX2EQIFg6d .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EMZBPLtX2EQIFg6d .marker.cross{stroke:#333333;}#mermaid-svg-EMZBPLtX2EQIFg6d svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EMZBPLtX2EQIFg6d p{margin:0;}#mermaid-svg-EMZBPLtX2EQIFg6d .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-EMZBPLtX2EQIFg6d .cluster-label text{fill:#333;}#mermaid-svg-EMZBPLtX2EQIFg6d .cluster-label span{color:#333;}#mermaid-svg-EMZBPLtX2EQIFg6d .cluster-label span p{background-color:transparent;}#mermaid-svg-EMZBPLtX2EQIFg6d .label text,#mermaid-svg-EMZBPLtX2EQIFg6d span{fill:#333;color:#333;}#mermaid-svg-EMZBPLtX2EQIFg6d .node rect,#mermaid-svg-EMZBPLtX2EQIFg6d .node circle,#mermaid-svg-EMZBPLtX2EQIFg6d .node ellipse,#mermaid-svg-EMZBPLtX2EQIFg6d .node polygon,#mermaid-svg-EMZBPLtX2EQIFg6d .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EMZBPLtX2EQIFg6d .rough-node .label text,#mermaid-svg-EMZBPLtX2EQIFg6d .node .label text,#mermaid-svg-EMZBPLtX2EQIFg6d .image-shape .label,#mermaid-svg-EMZBPLtX2EQIFg6d .icon-shape .label{text-anchor:middle;}#mermaid-svg-EMZBPLtX2EQIFg6d .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EMZBPLtX2EQIFg6d .rough-node .label,#mermaid-svg-EMZBPLtX2EQIFg6d .node .label,#mermaid-svg-EMZBPLtX2EQIFg6d .image-shape .label,#mermaid-svg-EMZBPLtX2EQIFg6d .icon-shape .label{text-align:center;}#mermaid-svg-EMZBPLtX2EQIFg6d .node.clickable{cursor:pointer;}#mermaid-svg-EMZBPLtX2EQIFg6d .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EMZBPLtX2EQIFg6d .arrowheadPath{fill:#333333;}#mermaid-svg-EMZBPLtX2EQIFg6d .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EMZBPLtX2EQIFg6d .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EMZBPLtX2EQIFg6d .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EMZBPLtX2EQIFg6d .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EMZBPLtX2EQIFg6d .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EMZBPLtX2EQIFg6d .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EMZBPLtX2EQIFg6d .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EMZBPLtX2EQIFg6d .cluster text{fill:#333;}#mermaid-svg-EMZBPLtX2EQIFg6d .cluster span{color:#333;}#mermaid-svg-EMZBPLtX2EQIFg6d div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EMZBPLtX2EQIFg6d .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EMZBPLtX2EQIFg6d rect.text{fill:none;stroke-width:0;}#mermaid-svg-EMZBPLtX2EQIFg6d .icon-shape,#mermaid-svg-EMZBPLtX2EQIFg6d .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EMZBPLtX2EQIFg6d .icon-shape p,#mermaid-svg-EMZBPLtX2EQIFg6d .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EMZBPLtX2EQIFg6d .icon-shape .label rect,#mermaid-svg-EMZBPLtX2EQIFg6d .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EMZBPLtX2EQIFg6d .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EMZBPLtX2EQIFg6d .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EMZBPLtX2EQIFg6d :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 公网用户
公网中转节点
内网穿透客户端
内网服务 192.168.1.20:8080

关键点在于:内网机器主动连接公网中转节点。因为这个连接是从内网主动发起的,所以可以穿过 NAT 建立出去。之后公网用户访问中转节点,中转节点再通过已经建立的连接把请求转发回内网服务。

十、内网打洞的基本理解

内网打洞可以理解为让通信双方借助公网节点交换必要信息,尝试建立可用的通信路径。

它通常需要解决几个问题:

  1. 内网主机没有公网地址;
  2. NAT 会维护映射表;
  3. 外部请求如果没有对应映射,通常无法直接进入;
  4. 需要借助公网节点让内网侧先建立可用通道。

在实际使用中,内网穿透可能采用中转模式,也可能尝试打洞直连。能不能直连,取决于 NAT 类型、网络环境和具体实现。对开发者来说,最重要的是先理解:公网访问内网服务,本质上需要一条公网可达的入口,以及一条能回到内网服务的转发通道

十一、NAT、代理和内网穿透的关系

这三个概念都涉及"中间节点",但目的不同。

技术 主要解决的问题 典型位置
NAT/NAPT 多台内网主机共享公网出口 路由器、防火墙
正向代理 客户端借代理访问目标服务器 客户端侧或出口侧
反向代理 后端服务通过统一入口对外提供能力 服务端入口
内网穿透 让公网访问内网服务 公网中转节点 + 内网客户端

如果用一句话串起来:

text 复制代码
NAT 让内网访问外网更容易;代理让请求转发更可控;内网穿透让外网访问内网成为可能。

十二、常见问题与易错点

1. 认为 NAT 只改 IP 不改端口

普通地址转换只解释了一部分场景。多个内网主机共享同一个公网地址时,通常还需要端口参与映射,这就是 NAPT。

2. 认为有 NAT 就能从公网访问内网服务

默认情况下,NAT 映射多由内网主动连接生成。外部主动访问内网服务时,如果没有端口映射、穿透通道或其他配置,通常无法成功。

3. 把 NAT 和代理服务器混为一谈

NAT 主要工作在网络转发层面,改地址和端口;代理服务器更接近应用层,理解请求内容,能做缓存、过滤、负载均衡等动作。

4. 分不清正向代理和反向代理

看代理的是谁:代理客户端,就是正向代理;代理服务端,就是反向代理。

5. 以为内网穿透一定是直连

内网穿透不一定意味着双方直接通信。很多实现会通过公网节点中转,是否能打洞直连取决于网络环境。

总结

NAT 是 IPv4 地址不足背景下的重要技术,它通过地址转换让大量私有地址设备共享公网出口。NAPT 进一步使用 IP 和端口建立映射,解决多台内网主机同时访问同一外部服务的问题。

代理服务和 NAT 都有"中转"味道,但代理更贴近应用层。正向代理代表客户端访问目标服务器,反向代理代表后端服务器接收客户端请求。内网穿透则是在 NAT 限制下,为公网访问内网服务建立可用入口和转发通道。

相关推荐
云栖梦泽在1 小时前
Claude Code / Codex 使用卡顿怎么办?AI 编程 Agent 连接失败与网络排查思路
网络·人工智能·网络协议·chatgpt·性能优化
灯厂码农2 小时前
C语言内存管理——内存对齐与共用体union
linux·服务器·c语言
GV191rLvq2 小时前
基于Socket实现的最简单的Web服务器【ASP.NET原理分析】
服务器·前端·asp.net
深盾科技_Virbox2 小时前
加密狗授权能力选型:从授权模型到全生命周期管理
java·网络·数据库
charlie1145141912 小时前
Cinux: 加载第一个内核:从 bootloader 跳进 C++
linux·开发语言·c++·嵌入式
运维管理2 小时前
H3C SecPath W2000-G[AK]系列Web应用防火墙 典型配置举例(E6711 E6712 E6713)-6W108-H3C 官方配置
服务器·网络·php
C+-C资深大佬3 小时前
python while循环
服务器·开发语言·python
Tian_Hang3 小时前
eclipse ditto 学习笔记
运维·服务器·开发语言·javascript·3d
tuddy7894643 小时前
Privazer 源码级避坑指南:从编译到部署的深度解析
网络·copilot