Back
Featured image of post 解决内网电脑通过外网域名访问内网服务器时不通的网络问题

解决内网电脑通过外网域名访问内网服务器时不通的网络问题

前言

​ 网络环境:

  • 只有少量的公网地址
  • 内网用户数量较大
  • 内网用户上网需要防火墙进行NAT转换
  • 内网的服务器通过防火墙的NAT映射对外提供服务

​ 问题:

  • 内网用户无法通过公网地址 + 映射的端口访问到内网的服务器

​ 网络拓扑:

原因

参考资料:

可以直接看参考资料。也可以看我下面的快捷分析。

假设环境:

类型IP地址
公网IP1.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访问服务器

  1. 用户电脑打开端口9999,并等待1.1.1.1的80端口回包 —— 192.168.10.1:9999 => 1.1.1.1:80
  2. 通过NAT转换后 —— 192.168.10.1:9999 => 192.168.10.10:80
  3. 服务器收到包,发现地址与本机同一网段192.168.10.0/24,便直接转发包到用户电脑 —— 192.168.10.10:80 => 192.168.10.1:9999
  4. 但是用户电脑等待的是来自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占用率过高。

[USG系列不支持]配置方法 —— 华为官方文档

  • DNS 劫持

看具体设备,华为的好像都没有。。但是爱快就有。

image-20201201021333929

  • 静态路由 + 服务器挂载公网IP地址

这个才真正地解决了我的问题。。。因为我这边的出口设备就是华为的USG防火墙——不支持DNS Mapping,不支持DNS劫持。做多一层NAT,我也没有成功。(kao)

关键点:

  • 直接在核心路由做一条静态路由,让内网直接访问公网IP的流量都走过去服务器。
  • 服务器直接在lookback上面挂载公网地址

附上 Centos7的挂载文件 :

# /etc/sysconfig/network-scripts/ifcfg-lo

DEVICE=lo
IPADDR=127.0.0.1
NETMASK=255.0.0.0
NETWORK=127.0.0.0
# If you're having problems with gated making 127.0.0.0/8 a martian,
# you can change this to something else (255.255.255.255, for example)
BROADCAST=127.255.255.255

IPADDR1=你的第一个公网地址
NETMASK1=255.255.255.255
IPADDR2=你的第二个公网地址
NETMASK2=255.255.255.255

ONBOOT=yes
NAME=loopback

写完直接 systemctl restart network

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus