《为什么公网访问不了内网?正向代理、内网穿透与 NAT 打洞一次说清》

正向代理服务器

类似学校的校园网中,内网到学校外的网络之间有一层学校的代理服务器,使用校园网的所有报文都会通过该代理服务器进行转发(即中间人),而该中间人可以获取报文内容,并对报文进行筛选,举一个更实际的例子,在公司内网中,公司为防止员工在上班期间娱乐,就会在对应公司的代理服务器中设置丢弃娱乐相关的报文,然后将筛选过滤后的报文发送至目标服务器-》替代客户端访问目标服务器的代理服务器即为正向代理服务器

注:正向代理服务器看似与路由器功能极其相似,都用于报文的转发,但实际上两者具备很大区别,首先,代理服务器(无论正向还是反向)本身是软件,常作用于应用层,而路由器是硬件,常作用于传输层和网络层;其次,代理服务器中不会建立NAPT表,而是常通过两条 TCP 长连接的形式实现路由器中唯一键值通信的需求,具体来说,类似客户端 <-> TCP连接A <-> 代理服务器 <-> TCP连接B <-> 目标服务器

正向代理示例:

反向代理服务器

在大多数情况下,服务端都是由多台主机组成的,且大致情况是一台主机A负责响应静态资源请求,并负责将动态请求负载均衡的分配给其他负责动态资源响应的主机BCD,在这种情况下,客户端访问的IP地址其实就是A的IP地址,而A就被称为反向代理服务器-》即代替服务端被客户端访问的代理服务器被称为反向代理服务器

注:负载均衡并非仅在反向代理服务器上进行,也可以在域名解析为IP地址时就进行,具体来说,存在一张域名解析表,可通过如轮询、就近解析等方式实现负载均衡

反向代理示例:

内网穿透

通过数据链路层博客的学习,已经得出"公网IP不能主动访问内网IP"的结论(因为没有建立好的NAPT表),但现实中确实会存在此种需求,比如,在家需要访问公司内网的IP时,家中IP与公司主机IP均为内网,此时,就需要使用内网穿透技术了,具体来说,通过一些软件可以让公司内网主机向一台公网主机A发送数据并实现图中节点路由器中NAPT表的维持,则此时,只需要将公网主机A作为中间人,就可以使用家中主机访问公司内网主机了,上述内网建立NAPT表并维持的技术就称为内网穿透-》结果是公网IP可以主动访问内网IP,但实际上仍旧是内网先主动建立NAPT表

内网穿透示例:

内网打洞(注:"内网穿透" 通常是个统称 / 大类------ 泛指 "让外网能访问到内网里的服务",因此这里介绍的内网打洞其实也可算作内网穿透的一种)

内网打洞技术可以实现减轻服务器负载,流量节省以及数据高效传输,具体来说,比如直播软件,直播者与观众两方都使用内网,正常情况下,需要将直播者主机的内容传输到APP的直播用公网服务器,然后该公网服务器将直播报文转发到观看直播的用户主机上,但显然,其实可以让直播者发送报文节点中的那个私网转公网的路由器A使用公网IP与观看直播的用户的报文传输过程中的私网转公网路由器B的公网IP直接通信,这样,就无需APP公网服务器这个中间人再进行报文转发了,而实现该技术的具体方案可以是:

  1. 直播者主机先向APP公网服务器通信,在途中路由器建立NAPT表,然后观众主机也进行同样操作
  2. APP公网服务器获取路由器A和B的公网IP,将A公网IP交给观众主机,将B公网IP交给直播者主机,这样,观众主机就可以通过自身路径的第一个公网IP与直播者主机路径的第一个公网IP直接通信了
  3. 需要注意的是,该工作完成后,A,B到APP公网服务器的连接可能不会断开,公网服务器后续会用于确保双方NAPT断开后的重新建立
  4. 内网穿透是将APP服务器当作中间人进行数据传输,而内网打洞虽也需要借助APP服务器,但其不负责数据传递,仅负责维持两端连接,由此内网打洞可以实现减轻服务器负载,流量节省(不需要A-》服务器-》B的中间流量了)以及数据高效传输(少了部分中间人,数据自然可以更高效传输)
  5. 由于节省流量以及安全性等原因,运营商可能会在节点路由器中设置禁止使用内网打洞技术
  6. 延伸出当今直播一种较新的技术方案:使用内网打洞,同时,APP服务器也伪造为观众,录取直播内容,直播结束后反馈给直播者,即可实现录播
  7. 小补充:在实践中,打洞要双方几乎同时发包才能打通,不过本文章旨在简单了解原理,而非实践指南
相关推荐
高磊20051 小时前
Kubernetes Pod 管理实战详解
linux·容器·kubernetes
喜欢吃燃面1 小时前
Linux网络编程深度解析:从Socket API到自定义协议设计
linux·网络·arm开发
xxy222411 小时前
Linux 网络编程入门(一):从 OSI 模型到 TCP Socket 编程
网络·tcp/ip·tcp
消失的旧时光-19431 小时前
(KMP-Net进阶)第一篇:AppResult<T>——网络层到底应该 throw,还是返回统一 Result?
网络·ktor·kmp
苹果嘉尔121382 小时前
Linux系统编程——网络(TCP)
linux·运维·服务器
网安蟹佬霸2 小时前
区块链与智能合约安全实战:从Solidity审计到DeFi漏洞深度剖析
运维·前端·网络·安全·自动化·区块链·智能合约
昌原的儿子LEO2 小时前
Linux进程知识点总结
linux·服务器·c语言·数据库
koi77u2 小时前
嵌入式学习---进程与线程(1)
linux·服务器·学习
椿.湫2 小时前
kubenetes pod管理
linux·运维·服务器