

局域网通过DDNS域名+端口访问自建服务的解决方案
source link: https://direct5dom.github.io/2024/02/19/%E5%B1%80%E5%9F%9F%E7%BD%91%E9%80%9A%E8%BF%87DDNS%E5%9F%9F%E5%90%8D-%E7%AB%AF%E5%8F%A3%E8%AE%BF%E9%97%AE%E8%87%AA%E5%BB%BA%E6%9C%8D%E5%8A%A1%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

局域网通过DDNS域名+端口访问自建服务的解决方案
2024-02-192024-02-20计算机网络
因为家里房屋翻新,整个网络拓扑结构得以升级,外加我个人有很多自建服务的需求,所以在这一年多的时间里折腾了不少东西,也遇到了不少问题。要说在所有问题里遇到的最棘手的问题,就是内外网难以通过同一种方式访问服务。
我路由器设置了DDNS域名:xxx.ddns.com
,并在主路由防火墙设置中将LAN
内软路由192.168.0.25
的8080
端口映射到了WAN
的8088
端口,于是乎我可以在学校宿舍通过xxx.ddns.com:8088
远程访问家里软路由的配置页面。
但是问题在于,如果我想通过LAN
来访问软路由的配置页面,我则只能通过192.168.0.25:8080
的方式访问,直接访问xxx.ddns.com:8088
会被拒绝连接。
如果服务比较少,或只在LAN
/WAN
使用的情况下还好说,大不了所有东西都上双栈(为LAN
和WAN
分别设置两套配置)。但是我现在用到的服务有几十个,而且经常在家里和外面跑,并且很多服务不支持/不能良好支持两套配置的协同,这就要求我必须找到一种方法让内外网都可以通过域名来访问对应的服务。
简化一下上面的案例:
- 通过DDNS域名+端口的方式访问某个服务(如:
xxx.ddns.com:8088
),在WAN
可以正常使用,在LAN
被拒绝连接。
这里的DDNS域名在内外网都可以被正常解析成对应的WAN
IP地址,所以问题可以进一步简化:
- 通过
WAN
IP+端口的方式访问某个服务(如:111.222.333.444:8088
),在WAN
可以正常使用,在LAN
被拒绝连接。
造成这一问题的主要原因是NAT本身,因为我使用的服务大多是基于TCP的,而TCP的三次握手会因为NAT的缘故失败。
依旧是举个例子:LAN
内的PC(192.168.0.10
)想要通过主路由(192.168.0.1
)的WAN
IP(111.222.333.444
)与LAN
内的服务器(192.168.0.254
)建立TCP链接。
对于PC(192.168.0.10
),数据包的发送路径是192.168.0.10 -> 111.222.333.444
,并期待111.222.333.444
的回复。数据包也正确通过主路由(192.168.0.1
),并转发给了服务器(192.168.0.254
)。
而问题出现在数据包的回复上,服务器(192.168.0.254
)向主路由(192.168.0.1
)回复数据包,而主路由发现目的地址是LAN
内的PC(192.168.0.10
),就直接将数据转发给了PC(192.168.0.10
),于是数据包的回复路径变成了192.168.0.254 -> 192.168.0.10
,而PC(192.168.0.10
)所期待的是111.222.333.444
的回复,来自服务器(192.168.0.254
)的“理应接收”的数据包被直接丢弃,进而造成了所我所遇到的问题。
一个题外话,TCP存在三次握手的设计,所以才会遇到问题,那么不需要握手确认的UDP是不是就没有这个问题呢?事实的确如此,因为UDP不需要“回复”来建立链接,所以基于UDP的数据包不受NAT影响,比如Wake on LAN的Magic Packet,但是问题在于至少我个人而言基于UDP的服务太少了。
其实这一问题是有“标准答案”的,即NAT环回(NAT Loopback)或者SNAT(Source Network Address Translation)。
NAT环回的本质就是SNAT,只是具体操作起来可能有所区别。工作原理是在路由器收到服务器转发的数据包时,手动对其做一些手脚,将其IP段改成自己的WAN
IP地址,再转发给PC,进而实现正常建立TCP连接。
但是这个“标准答案”有个问题,就是很难操作甚至无法操作。大多数人的家庭主路由都不是OpenWRT,这些家庭路由器的功能是严重缺失的,可能根本没有“NAT环回”这个选项,更别提“SNAT”这个需要手动操作iptables
的方法。
我的主路由是TPLink的商用级路由器TL-R479GP-AC 8.0,虽然它的端口映射(TPLink称“虚拟服务器”)是默认支持
LAN
的NAT回环的,并且也支持单独设置回环地址,但我个人尝试后发现不生效,网上提供的其他TPLink设置NAT回环方案也不适用于我的路由器。
因为我们最终还是通过DDNS域名来访问服务,而非直接使用IP,因此我们可以在域名 -> IP
这个过程使用一些手段,即:DNS劫持。
其原理就是在LAN
内直接将DDNS域名解析到具体的某个LAN
IP,这样通过DDNS访问某项服务,其本质和直接通过LAN
IP访问是一样的。
实现方案一(主路由DNS静态解析)
比如我们在主路由已经添加了DDNS域名xxx.ddns.com
,WAN
IP为111.222.333.444
,服务器LAN
IP为192.168.0.254
。
此时我们添加一条DNS静态解析:xxx.ddns.com -> 192.168.0.254
,可以实现效果:
WAN
访问:xxx.ddns.com -> 111.222.333.444 -> 192.168.0.254
;LAN
访问:xxx.ddns.com -> 192.168.0.254
。
直接在主路由上实现DNS静态解析的优点是连接至局域网即可完成域名解析的切换,不需要终端过多设置。而问题在于“DNS静态解析”这一功能在大多数家用路由器上也被阉割。
实现方案二(修改终端hosts
)
比如我们在主路由已经添加了DDNS域名xxx.ddns.com
,WAN
IP为111.222.333.444
,服务器LAN
IP为192.168.0.254
。
我们可以添加一条hosts
:192.168.0.254 xxx.ddns.com
,此时即可在LAN
中通过xxx.ddns.com
访问服务器。
但是这种方案的灵活度十分之低,复杂度又过高。每次离开LAN
都需要手动改回hosts
,等进入LAN
再改过来。这种方法麻烦至极,唯一优点在于要求极低,只要终端支持修改hosts
都可以(手机和平板寄了,但大多数PC都是支持修改hosts
的)。
实现方案三(内网设置DNS服务器)
如果你的主路由不支持方案一的DNS静态解析,也不想使用/无法使用方案二的修改hosts
,那么还有一个办法是自建一个DNS服务器。
如果你家里有其他支持DNS解析的设备(如:软路由、群晖、树莓派),那么你可以将方案一的做法应用于这些设备,建立起一个DNS服务器。然后你可以将路由器或终端设备的DNS指向DNS服务器,进而实现相同的效果。
这种做法的缺点在于你需要一个能稳定在线的单独设备做为DNS服务器存在,当然买一块Linux开发板的成本也不高(别买成单片机)。
DNS劫持虽然简单粗暴,但是不是所有问题都能解决。
比如DNS解析是域名 -> IP
,端口被忽视了。所以如果你的主路由映射了多台LAN
内设备的端口,那么你只能选择其中一个LAN
IP做域名映射,其他设备上的服务没办法通过同一个域名访问。
我个人的解决办法也很简单粗暴,多弄几个DDNS IP地址就好了(xxx.ddns.com
和yyy.ddns.com
分别映射到内网两台设备上,两台设备同时做DDNS使外网同样可用)
再一个问题是现代设备为了加快DNS解析速度,都会设置DNS缓存,所以你切换WAN
/LAN
环境时,DDNS域名可能没办法一下正确解析。
我个人的解决办法同样简单粗暴,直接清理DNS缓存。对于Windows系统可以通过cmd
命令ipconfig /flushdns
来清空,浏览器(这里只给Edge,其他浏览器的方案自行搜索)可以通过edge://net-internals/#dns
来清空。
Recommend
-
30
Nginx配置多端口多域名访问 Nov 18th, 2019 | Comments
-
4
Windows 10 局域网防火墙开放端口 2021-07-22 很少用 Windows 去配置服务,但偶尔是需要的,今天对外暴露一个服务的时候,发现局域网内设备无法访问,而我使用的 Fiddler 却可以在局域网内自由访问,对此表示很困惑,通过对比防火墙规则...
-
6
Nginx 禁止未绑定域名或 IP 访问 80 和 443 端口实践小结nginx 在决定请求由哪个 server 块执行时,主要关注的是 server 块中的 listen 和 server_name 两个字段,如果根据 listen 指令无法得到最佳匹配,将会开始解析 server_name 指令。nginx 会检查请求中的...
-
29
GXNAS 博客https://wp....
-
12
解决 nextcloud 通过不被信任的域名访问 问题 前置条件:本文讨论的是通过docker安装的nextcloud。如果是直接在宿主机上安装,那么改好配置文件不需要重启容器。 这个问题很好解决,进入到容器,
-
8
一开始不论怎么配置 /opt/etc/nginx/nginx.conf 总是不生效,在 /opt/etc/nginx/vhost/qbit.conf 下配置了 Hello World 的静态文件也不能访问。后来终于想到了 80 端口被其他服务占用的可能 这是在 openwrt 系统下,很多程序...
-
16
Nginx通过域名代理tcp端口 发表于...
-
3
V2EX › 问与答 内网主机通过域名访问路由器流量会过外网吗?
-
6
Linux服务器中配置tomcat的服务,并通过端口8888访问 精选 原创 Tomcat...
-
6
V2EX › NAS [教程] 随时随地通过域名远程访问 nas、openwrt、alist 等家庭内网设备
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK