背景

前段时间通过客服拿到了联通的公网 IP, 因此也申请了域名并做了解析, 也顺利应当地在路由器上做了端口映射, 从而可以在外网可以直接通过域名加端口的形式访问内网的服务. 但也有一个问题就是当处于内网环境时通过域名反而无法访问同一内网下的服务, 必须使用内网 IP 才行.

其实这个问题很明显, 就是网络报文在通过路由器时路由器将报文转发给了内网服务器, 但是内网服务器在回报文的时候直接按内网地址回包了. 这个问题由来已久, 也即 NAT 回环问题. 以下我们将通过脚本的形式在 RouterOS 上添加 NAT 规则来解决这个 NAT 回环问题.

具体环境为光猫配置了桥接后通过 MikroTik RB750Gr3 进行拨号, 同时 RB750Gr3 运行的 RouterOS 版本为 7.7, 并且内网网段为 192.168.2.0/24.

步骤

首先假设我们拥有公网 IP1.2.3.4, 现在新建一条 NAT 规则用于将内网服务暴露到外网:

/ip firewall nat add chain=dstnat dst-address-type=local protocol=tcp dst-port=18080 action=dst-nat to-addresses=192.168.2.123 to-ports=8080 comment="Vaultwarden"

这里新建规则意思是当访问 1.2.3.4:18080 上的服务时将其转发到内网的 192.168.2.123:8080 端口上. 在添加完这条规则后我们可以通过外网测试访问是否成功, 如无外网环境则可以通过蜂窝网络进行测试.

当确认以上端口转发规则没有问题后, 现在可以再新建一条用于解决 NAT 回环的规则, 在 MikroTik 官方文档中则被称为 Hairpin NAT:

/ip firewall nat add chain=srcnat src-address=192.168.2.0/24 dst-address=192.168.2.0/24 protocol=tcp out-interface-list=LAN action=masquerade comment="Hairpin-NAT"

这里我们新建的规则是当匹配到 SRCDST 地址都为 192.168.2.0/24 网段下时则进行 masquerade 地址伪装, 而网上不上针对 NAT 回环规则则匹配端口从而导致如果有多条端口转发规则时需要配置对应数量的 NAT 回环规则, 因此我们这里通过匹配 SRCDST 地址的形式来最大化复用该规则. 此时在内网环境下已经可以通过公网 IP 或域名的形式访问同一内网下的服务了, 从而实现内外网访问地址的统一, 避免了频繁切换地址的问题.