Skip to content
EkkoG edited this page Mar 4, 2023 · 1 revision

使用NATMap在NAT-1私网IP宽带上部署 Trojan 服务,并通过其访问内网服务(回家)

通过NATMap在运营商的NAT-1上打洞,分配私网IPv4的宽带可以部署 Trojan 服务,并能像具有公网IP一样在其它外部主机上访问。

拓扑结构

                   Trojan Server                NATMap(on gateway)                Trojan Client

Internal:    (192.168.0.2:1243) <-----> (100.65.11.55:2133)
                                               ^
                                               |
                                               v
External:                              (112.24.0.23:6348) <------------>
  • Trojan Server: Trojan 服务端运行在内网主机,侦听在 192.168.0.2:1243 端口。
  • NATMap: NATMap运行在网关,侦听在 100.65.11.55:2133 端口,打洞使公网地址 112.24.0.23:6348 映射至 100.65.11.55:2133,同时又将100.65.11.55:2133映射至192.168.0.2:1243。从外部访问112.24.0.23:6348等同于访问192.168.0.2:1243。
  • Trojan Client: Trojan 客户端运行在外部主机上,通过 NATMap 打洞获得的公网地址 112.24.0.23:6348 访问 Trojan 服务。

域名访问

在具有动态公网IPv4的宽带上部署 Trojan 服务,只有公网IPv4因为重新拨号是在动态变化的,而端口则是固定的。利用动态DNS则可以通过固定的域名作为入口实时解析到动态变化的IP,进而访问到服务。

在NAT-1私网IPv4的宽带上,情况稍微有些不同,不仅打洞后获得的运营商侧公网IPv4是动态变化的,端口同样也是动态变化的。考虑到通常 Trojan 会配置代理客户端软件使用,而我们没有办法修改代理客户端的行为,所以只能配合它们。目前比较可行的方法是当端口变化时,读取新端口并根据新端口生成新的代理配置,并在代理客户端软件中及时更新配置。

安装部署

Trojan

任意方式安装 Trojan 服务端,无额外要求。

NATMap

安装

DDNS
Cloudflare

创建文件/usr/bin/ddns写入如下内容,并补充必要的变量值:

#!/bin/sh

ZONE=''
RECORD=''
EMAIL=''
AUTH=''
DOMAIN=''

IP=${1}

while true; do
    curl -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE}/dns_records/${RECORD}" \
        -H "X-Auth-Email: ${EMAIL}" \
        -H "Authorization: Bearer ${AUTH}" \
        -H "Content-Type:application/json" \
        --data "{\"type\":\"A\",\"name\":\"${DOMAIN}\",\"content\":\"${IP}\",\"ttl\":60,\"proxied\":false}" > /dev/null 2> /dev/null
    if [ $? -eq 0 ]; then
        break
    fi
done

再增加可执行权限:

chmod +x /usr/bin/ddns
OpenWrt 22.03 or later

从软件仓库安装natmap和luci-app-natmap软件包。

或命令行

opkg install natmap luci-app-natmap
其它系统

从项目发布页下载匹配的版本: https://github.com/heiher/natmap/releases

运行

OpenWrt 22.03 or later
1. 登录OpenWrt管理页面,进入「服务」->「NATMap」页面:

2. 点击「Add」按钮,输入如下配置:
  • Protocol: TCP
  • Interface: wan
  • STUN server: stunserver.stunprotocol.org
  • HTTP server: qq.com
  • Bind port: 2133
  • Forward mode: ☑
  • Forward target: 192.168.0.2
  • Forward target port: 1243
  • Notify script: /usr/bin/ddns

3. 保存后NATMap会显示出打洞后的外部公网IPv4地址和端口记录:

4. 防火墙放行TCP协议目的端口2133的入站:

其它系统

将如下内容写入 /etc/rc.local 开机自动启动,或创建其它服务管理配置:

natmap -d -i pppoe-wan -s stunserver.stunprotocol.org -h qq.com -b 2133 -t 192.168.0.2 -p 1243 -e /usr/bin/ddns

防火墙放行TCP协议目的端口2133的入站。

访问测试

域名解析结果

比如域名为: trojan.hev.cc

nslookup trojan.hev.cc

当配置正确且运行正常时,应当能够解析类似如下结果:

Server:		192.168.0.1
Address:	192.168.0.1#53

Non-authoritative answer:
Name:	trojan.hev.cc
Address: 113.1.98.1

规则生成

由于端口是动态变化的,所以需要在端口变化时重新生成规则,这里用 Surgio 作为例子。

在 /usr/bin/ddns 中不只要更新 IP 地址,还是更新端口,如果在 natmap 的运行环境中容易使用 Surgio 的话,将其和 natmap 的起跑即可。若不适合,则另想办法。

我这里是通过将新端口放在了 DNS 的 TXT 记录中,在另一台机跑一个计划任务,每分钟检查一次,若发现端口变化,则更新规则。

在 /usr/bin/ddns 中写入如下内容:

while true; do
    curl -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE}/dns_records/${RECORD}" \
        -H "X-Auth-Email: ${EMAIL}" \
        -H "X-Auth-Key: ${AUTH}" \
        -H "Content-Type:application/json" \
        --data "{\"type\":\"TXT\",\"name\":\"${DOMAIN}\",\"content\":\"trojan-port:${outter_port}\",\"ttl\":60,\"proxied\":false}"
    if [ $? -eq 0 ]; then
        break
    else
        sleep 3
    fi
done

在另一台机上跑如下脚本:

#!/bin/bash -e
date
cd $(dirname $0)
dig $DOMAIN txt @1.1.1.1
port_txt=$(dig $DOMAIN txt @1.1.1.1 +short)
if [ -z $port_txt ];then
        echo "empty record, exit."
        exit 0
fi
echo "DNS record $port_txt"
#"trojan-port:6589"
port=${port_txt:13}
port=${port%\"}
if [ -f ./.port.txt ]; then
    cache_port=$(cat ./.port.txt)
    if [ "$port" == "$cache_port" ]; then
        exit 0
    fi
fi
echo "new port $port"

git pull origin master

sed -i '/dynamic/ c\      port: '"$port"', //dynamic port' ./provider/home.js

git add .
git commit -m "update port"
git push origin master

echo $port > ./.port.txt

因为我的规则更新是由 git 提交触发的,所以这里也是用 git 来更新规则。如果你的不是,可以自行修改。

这样在配置更新后,就可以连回家里的代理的服务器了。