折腾NAS的小伙伴大都申请了公网IP了吧,也都配置了DDNS,可以非常方便的在外访问家里的服务。但是此时会出现一个奇怪的问题,内网使用DDNS域名访问你的服务,很大概率是会失败的,还是需要用我们内网的IP来访问,使得我们在内网的体验反而不如外网,有什么办法解决吗?答案是有的。

一、NAT Loopback/Harpin

NAT即网络地址转换,它的存在有效地解决了IP地址不够用的问题,主要通过将内部的私有IP地址转换成可以在公网使用的公网IP地址。有兴趣的小伙伴可以自行深入学习。

!> 对于家庭路由器来说,其实不应该叫做路由器,而是应该叫做NAT网关,可以让你的所有设备通过路由的WAN口IP上网。

所谓NAT Loopback就是NAT回流,我们先来理清三个问题。

  1. 内网用户访问内网服务器

    毫无疑问是可以的,同属一个局域网,通过交换机进行通讯。

  2. 外网用户访问内网服务器

    不可以,需要通过NAT才能访问。常见的方式有DMZ主机、端口映射。

  3. 内网用户访问公网IP的内网服务器(配置好DMZ或者端口映射)

    不可以,需要配置NAT回流才可以访问。

说下原因,小白略过这段:内网用户通过出口IP访问内网服务器,数据包到出口设备时,因为我们设置的NAT的存在,目的地址会被修改成内网服务器地址;内网服务器收到数据包后进行回复,源地址和目的地址对调,数据包直接通过交换机返回给内网用户,内网用户收到数据包后进行解封,由于地址不匹配,数据包被丢弃,造成访问失败。

接下来以ROS系统为例配置,我不是很想截图,所以给命令叭。

使用ROS进行PPPoE拨号,并且获取了公网IP,DDNS解析到这个公网IP,域名为ddns.example.com。

使用WinBox、SSH或telnet等连接上ROS终端。

我们先配置群辉的端口映射,比如5000和5001端口,多个端口可以用逗号隔开,不写默认映射全部端口,也就是DMZ主机效果了。这里省略了一个参数to-ports,不写默认和dst-port保持一致,如果想外部端口和内部端口不一样,可以改写,需要注意一一对应关系。

# pppoe-out1是用来拨号的接口, 192.168.88.5是内网群辉的地址
# 配置TCP
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=192.168.88.5 protocol=tcp in-interface=pppoe-out1 dst-port=5000,5001 comment="DSM TCP"
# 配置UDP
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=192.168.88.5 protocol=udp in-interface=pppoe-out1 dst-port=5000,5001 comment="DSM UDP"

接下来配置NAT回流。

# ether2是我的lan口, 110.1.1.1为公网IP
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=192.168.88.5 dst-address=110.1.1.1 in-interface=ether2 comment="NAT Loopback"

已经完成了,你可以测试下能否使用域名ddns.example.com:5000访问内网的群辉了。

上面的配置还遗留了一个问题,配置NAT回流的时候,目的地址需要填写公网IP,对于家庭来说一般是动态公网IP,如果因为IP变化而手动更改配置是不现实的,所以我们还需要通过脚本来实现自动更改配置。

建议使用Winbox创建脚本,命令不是很方便,在System->Scripts中添加一个脚本,Name自定义,在下面的Source中粘贴下面的脚本。只需要改注释的两个变量即可。

# 拨号端口
:local iwan "pppoe-out01"
# 之前配置的回流规则的注释
:local natrule "NAT Loopback"
:local newip
:local oldip
:if [/interface get [/interface find  name=$iwan] running] do={
    :set newip [/ip address get [/ip address find interface=$iwan] address]
    :set newip [:pick $newip 0 ([:len $newip] -3)]
    :set oldip [/ip firewall nat get [find comment=$natrule] dst-address]
    :if (!($newip=$oldip)) do={
        /ip firewall nat set [/ip firewall nat find comment=$natrule] dst-address=$newip
    }
}

接着在System->Scheduler中添加一个计划,Name自定义,Start DateStart Time设置为早于今天的任意时间,Interval为执行周期,例如1d 00:00:00表示每天执行一次,00:05:00表示每5分钟执行一次,不超过一天的时候,可以省略天数,On Event中填写上一步添加的脚本Name即可。

然后,你可以将NAT中的回流配置地址改为任意值,过5分钟看看是否会被自动更新。

二、DNS劫持

这种方法就比较简单了,但是局限性比较高,首先你需要使用自己的DNS,比如ROS或者OpenWrt,然后在ROS或者OpenWrt配置静态域名解析,解析ddns.example.com到内网IP,这样当你在内网使用域名访问的时候,实际上获取到的解析就是内网服务器地址,在外网访问时,获取到的解析就是公网地址。

最后修改:2022 年 05 月 31 日
如果觉得我的文章对你有用,请随意赞赏