前言
网络环境:
- 只有少量的公网地址
- 内网用户数量较大
- 内网用户上网需要防火墙进行NAT转换
- 内网的服务器通过防火墙的NAT映射对外提供服务
问题:
- 内网用户无法通过
公网地址 + 映射的端口
访问到内网
的服务器
网络拓扑:
原因
参考资料:
可以直接看参考资料。也可以看我下面的快捷分析。
假设环境:
类型 | IP地址 |
---|---|
公网IP | 1.1.1.1 |
内网电脑 | 192.168.10.1 |
内网Web服务器 | 192.168.10.10 |
Web服务器 服务端口 | 80 |
场景一: 内网用户上网冲浪(NAPT)
内网电脑通过NAT将内网IP转换成公网IP,即
192.168.10.1:9999 => 1.1.1.1:8888
场景二: 外部用户访问内网Web服务器(NAT映射)
1.1.1.1:80 => 192.168.10.10:80
场景三: 内网用户访问内网Web服务器(单纯同网段/内部路由转发)
192.168.10.1:9999 => 192.168.10.10:80
以上三种场景,大家都不会有什么疑问。
场景四: 内网用户通过公网IP访问服务器
- 用户电脑打开端口9999,并等待1.1.1.1的80端口回包 ——
192.168.10.1:9999 => 1.1.1.1:80
- 通过NAT转换后 ——
192.168.10.1:9999 => 192.168.10.10:80
- 服务器收到包,发现地址与本机同一网段
192.168.10.0/24
,便直接转发包到用户电脑 ——192.168.10.10:80 => 192.168.10.1:9999
- 但是用户电脑等待的是来自
1.1.1.1
的包,而不是来自于192.168.10.10:80
的包。
这样子就导致了用户电脑一直等不到包的回复,造成连不上服务器。
解决方法
- 部署内网DNS
内网电脑直接使用自定义的DNS服务器,当访问内部域名的时候直接指向内部服务器的内网地址。全程的流量都不经过出口的防火墙/路由器。
- 多层NAT
将内网的IP地址再做一层转换,转换为内部网络没有的地址。让默认路由再丢包给出口设备,让出口设备再次查询NAT会话,从而让包返回给内网用户。
- DNS Mapping
DNS mapping通过配置“域名-公网地址-公网端口-协议类型”的映射表,建立内部服务器域名与内部服务器公网信息的对应关系。
在配置了NAT的接口上,设备检查接收到的DNS响应报文,根据报文中的域名查找用户配置的DNS mapping映射表,并根据表项内的“公网地址-公网端口-协议类型”查找内部服务器,然后用内部服务器的私网地址替换DNS查询结果中的公网地址。
这样私网用户收到的DNS响应报文中就包含了要访问的私网内部服务器的私网地址,就可以使用内部服务器域名访问同一私网内的内部服务器。
但是域名数量配置过多或者DNS查询流量过大都会导致CPU占用率过高。
- DNS 劫持
看具体设备,华为的好像都没有。。但是爱快就有。
- 静态路由 + 服务器挂载公网IP地址
这个才真正地解决了我的问题。。。因为我这边的出口设备就是华为的USG防火墙——不支持DNS Mapping,不支持DNS劫持。做多一层NAT,我也没有成功。(kao)
关键点:
- 直接在核心路由做一条静态路由,让内网直接访问公网IP的流量都走过去服务器。
- 服务器直接在lookback上面挂载公网地址
附上 Centos7的挂载文件 :
1# /etc/sysconfig/network-scripts/ifcfg-lo
2
3DEVICE=lo
4IPADDR=127.0.0.1
5NETMASK=255.0.0.0
6NETWORK=127.0.0.0
7# If you're having problems with gated making 127.0.0.0/8 a martian,
8# you can change this to something else (255.255.255.255, for example)
9BROADCAST=127.255.255.255
10
11IPADDR1=你的第一个公网地址
12NETMASK1=255.255.255.255
13IPADDR2=你的第二个公网地址
14NETMASK2=255.255.255.255
15
16ONBOOT=yes
17NAME=loopback
写完直接 systemctl restart network