让我们聊聊如何让局域网内的应用被公网用户访问

一图胜千言

我先将我的架构图贴上来,稍后我在慢慢讲解。

原理

局域网IP(私有网络IP段)

我们都知道IPv4,很多人也知道局域网,但是很初入研发行列的人并不知道局域网IP(私有网络IP地址段)这件事情的存在。那么私有网路IP段是什么?一句话概括就是,你使用的IP地址是可以被重复的,你能访问公有网络IP地址段(IP地址不可重复),但是别人没办法访问你的IP地址。那么这些地址都是什么,可以看下面这个表

开始地址 结束地址 IP数量
A类,8位掩码,1个地址段 10.0.0.0  10.255.255.255 16777216
B类,12位掩码,16个地址段 172.16.0.0  172.31.255.255 1048576
C类,16位掩码,256个地址段 192.168.0.0 192.168.255.255  65536

NAT怎么工作的

NAT的工作原理是基于TCP状态机和IP:Port元组的对照关系表。我们假设我们的公有网络IP地址位202.96.199.13,我们使用的私有网络IP地址段位192.168.1.0/24。我们可以假设用户A的机器IP地址位192.168.1.10,网关地址是192.168.1.1。那么当用户A访问了一次Web,我们会在我们的网关(NAT路由器)上有什么呢?

内网IP 内网Port 外网IP 外网Port 目标IP 目标Port 协议类型
192.168.1.10 4859 202.96.199.13 8762 8.8.8.8 53 UDP
192.168.1.10 6736 202.96.199.13 3698 220.181.112.244 80 TCP
192.168.1.10 6737 202.96.199.13 3789 220.181.112.244 443 TCP

我们可以看到一个TCP的访问会出现内网IP和Port,外网IP和Port,还有目标IP和Port,以及协议类型。NAT路由器的工作就是将内网发出去的IP包的原IP和Port替换成外网的IP和Port,当收到数据包将目标IP和Port替换成内网IP和Port。如果内网IP开启了一个新TCP链接,这个表中没有,NAT路由器会创建一个新的条目。如果公网想访问内网该怎么办呢?,不是说绝对不可能,这个可以通过DNAT完成,但是有限制,这个限制限制了外网IP上的Port被永久映射到内网某个IP和Port上。也就是说,不能一个端口被任意使用,具体细节参看Linux iptables中的相关介绍。

这时候会有同学发出疑问,你不说NAT的工作原理是基于TCP嘛,为什么表上有UDP呢?因为NAT路由器在实现的时候考虑到UDP了,UDP虽然没有状态,但是可以通过统计是否有流量及设置超时的时间来决定是否关闭一条NAT规则。而TCP的关闭就会依照TCP的状态机和超时机制来决定何时关闭。

如何让公有IP访问私有IP的HTTP服务

从上面的讲解我们可以看到我们想让公有IP访问私有IP的HTTP服务,需要使用DNAT。但是如果不只一个人使用这个端口那就悲剧了。那么如果我们所有暴露的服务端口都是HTTP协议的,那么这个事情就非常好解决了,可以使用ngrok这个工具。那么其中的原理是什么呢?一个是泛域名技术,另一个是HTTP/1.1的header的host域。

通过使用泛域名技术,我们可以拥有很多类似usera.mbooks.me,userb.mbooks.me这种域名。另一方面,根据HTTP/1.1规范的规定,我们每个HTTP请求的host字段指定的是我们要访问的域名。这样我们就可以在一个IP:Port上使用多个域名了。

满足这两个条件之后,我们剩下的就是让RevProxy主动去连接AccessPoint了。当然AccessPoint后RouteMesh是有公网IP地址的,这样别人才能访问到。

系统如何工作的

用户需要做什么

我们假设有一个用户D,他的机器在NAT路由器后面。他所需要的是开启自己的Web服务器,并绑定一个IP:Port。接着启动RevProxy,并将刚才的IP:Port传入进去。然后用户只要访问RevProxy返回的域名就可以了。

RevProxy和AccessPoint怎么交互的

RevProxy接收到IP:Port后,主动连接到具有公网IP地址的AccessPoint,AccessPoint会随机生成一个域名给RevProxy,如我们可能会生成ae24.mbooks.me这种域名。然后AccessPoint将自己和生成的域名写入Redis。之后RevProxy和AccessPoint保持一个长链接。

RouteMesh和AccessPoint怎么交互的

RouteMesh解析请求的HTTP头,找出host字段。之后通过查询Redis找出相应的AccessPoint,并将请求转发给相应的AccessPoint。AcessPoint将请求转发给RevProxy。

RevProxy和用户怎么交互的

当RevProxy收到请求,将请求中的host替换成用户指定的IP,并转发给用户应用。

时间: 2024-12-11 04:34:49

让我们聊聊如何让局域网内的应用被公网用户访问的相关文章

解决为什么内网不能用公网地址访问内网服务器

NAT地址池和服务器地址要与出口IP不同网段,NAT地址池可以和服务器地址在同一网段,也可在不同网段. 对于下文中推论的回答:我认为不会成环,ping NAT地址池的没用到的地址,得不到回应,就没有回去的数据包,怎么会成环呢..... 以下参考下面这个文章,附上本文留存,原文引用链接为: http://www.2cto.com/net/201202/119693.html NAT网络回流现象解释,内网使用服务器的外网IP登陆 hi大家好,今天我们来讨论一个很多人都找不到答案得问题:究竟为什么内网

ROS Dst-Nat 后内网不能通过公网IP访问内网服务器解决方法

通常企业内部会有很多服务器需要互联网用户访问,这时就需要做Dst-Nat. 但是我们配置完后会 发现内网用户不能通过公网IP访问对应的服务器.其实这时我们再添加一条策略即可搞定. 实例说明: 内网服务器:172.16.0.101 路由器LAN口: 172.16.254.2 公网IP: 106.37.xxx.xxx 外网访问IP假设为 1.1.1.1    内网访问的PC 假设IP为172.16.3.100 配置NAT: 配置完后,外网可以正常访问了.但是内网通过公网IP不可访问. 究其原因: 外

vue-cli3.0启动项目,在局域网内其他电脑通过自己ip访问

最近一直在使用vue-cli3.0做项目, package.json中配置后,自启动项目,也就没留意过小黑窗, "scripts": { "serve": "vue-cli-service serve --open", // 自启动浏览器 "build": "vue-cli-service build" }, 启动后发现,如下,不仅有Local,还有 Network App running at: - Lo

Socket Android手机客户端与PC服务端局域网内联测试

Socket Android手机客户端与PC服务端局域网内联测试,笔者采用的是 PC服务器,Android平板客户端 ,PC模拟器客户端, 前段时间为了加深对Socket通信的印象和知识的深度掌握,我模仿了QQ的一些元素,也借鉴了其他牛人的一些源码思想,写了 一个 叫 IQ 的 Android 聊天软件,该软件大致由 Android客户端.JAVA pc服务端.mysql数据库组成,客户端和服务端都 比较多的用到了读写的IO流,SCOKET,线程等,这篇博客主要给大家介绍测试环境,不讲源码实现方

如何统计局域网内的邮件收发次数和流量?

使用WFilter上网行为管理软件,您可以很直观的监控到局域网内的邮件收发,并且对其进行统计. 本文,我们将简单介绍WFilter的邮件统计功能. 如果需要了解邮件监控,审计,收发限制的其他方案,请参考:WFilter邮件监控方案 1. 在"分类统计"中,选择需要查看的邮件统计报表. 支持"邮件次数统计","邮件大小统计",和"邮件类型统计" 每个报表都可以选择不同的统计字段 设置不同的日期范围 可以设置饼图.柱状图.折线图.

tomcat局域网内发布html

1. 保证tomcat装好,启动 验证:浏览器输入:localhost:8080,看到下面页面表示成功 2. 把html文件或包含html的目录拷到Apach安装目录的Root目录下 (例如:C:\Program Files\Apache Software Foundation\Tomcat 8.0\webapps\ROOT) 3. 访问 浏览器中输入:localhost:8080/youdir/index.html 其中youdir是存放待发布html文件的目录:可以通过命令行ipconfig

ping命令扫描局域网内的主机

linux: 禁ping vim /proc/sys/net/ipv4/icmp_echo_ignore_all 0 代表允许 1代表禁止 ping.sh #!/bin/bash for i in {2..5}; do   host=122.152.172.$i  ping -c2  $host  >/dev/null  if [ $? = 0 ]  then      echo "122.152.172.$i is connected"  else  echo "12

局域网内一键唤醒所有的支持网卡启动的机器的shell脚本

先编写一个create_wake.sh脚本,用于生成唤醒脚本IP=$(hostname -I|awk '{print $1}') SUBNET=$(hostname -I|awk '{print $1}' | awk -F. '{print $1"."$2"."$3".*"}') nmap -sP -n $SUBNET | egrep -v "^Nmap done:|^Starting Nmap|$IP"| awk '/^Nm

局域网内使用IntelliJ IDEA无法下载Gradle插件的问题

团队要使用IntelliJ IDEA和Gradle进行开发. 因为在局域网内,必须通过代理访问外网,而IntelliJ IDEA全局配置代理后仍无法下载Gradle插件: Error:Connection timed out: connect. If you are behind an HTTP proxy, please configure the proxy settings either in IDE or Gradle. 提示超时. 后来想到直接把本机的 C:\Users\weiwei\