之前小白写过一篇nps的入门教程:超详细openwrt内网穿透-nps小白教程,反应还不错,恰巧昨天看到一篇大佬的技术博文,原来还有更高级的玩法,现将全文转载如下:
在受审查的网络下,常规内网穿透工具由于特征较明显容易被封锁。本文介绍一种思路,通过v2ray https+websocket作为底层传输方式保护nps通道,从而规避防火墙审查。
背景
由于组织内部服务器只有内网可以访问,一直以来使用nps连到自己在国内的一台小鸡上做内网穿透,转发ssh、web等服务。但近期由于组织内防火墙的缘故,大量frp、nps的反代遭到封杀,服务器被以判断IP并直接丢包的方式封锁。nps采用web图形化界面,增删改查主机和穿透隧道十分便捷,在客户端上也只需要一句命令就能直接运行,但恐怕特征明显,组织内部的小防火墙也能轻松识别。
于是尝试使用v2ray作为媒介,vmess+https+websocket的配置作为底层传输方式代理nps流量。能轻松应对GFW的协议,想必应对野鸡防火墙完全手到擒来。
鉴于使用v2ray可能产生的断线问题,本文末尾介绍了另一个基于hysteria代理穿透隧道的方案。
nps内网穿透工具:https://github.com/ehang-io/nps
服务端配置
服务端正常搭建v2ray即可,不需要额外配置。这里使用x-ui面板配置vmess+http+websocket服务端,并使用nginx反代支持https。
nginx配置代码片段:
location /example_ws_path { # websocket子路径建议在nginx处配 proxy_redirect off; proxy_pass http://127.0.0.1:20000/; # 上面的vmess端口号 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
关于v2ray服务端的具体配置非本文重点,请参考网络上其他文章或v2ray官方文档。
x-ui面板:https://github.com/vaxilu/x-ui
v2ray官方指南:https://guide.v2fly.org
服务端正常启动nps,客户端连接端口为默认的8024:
客户端配置
内网机器,也就是客户端配置如下:
{ "logs": { "loglevel": "debug" }, "inbounds": [ { "listen": "0.0.0.0", "port": 8024, "protocol": "dokodemo-door", "settings": { "address": "server.example.com", "port": 8024, "network": "tcp,udp", "timeout": 0, "followRedirect": false, "userLevel": 0 } } ], "outbounds": [ { "protocol": "vmess", "settings": { "vnext": [ { "address": "server.example.com", "port": 443, "users": [ { "id": "d9b1afa4-2f40-4b3c-ad98-7b47ab9e4386", "alterId": 0, "security": "none" } ] } ] }, "streamSettings": { "network": "ws", "security": "tls", "wsSettings": { "path": "/example_ws_path", "headers": { "Host": "server.example.com" } } } } ] }
假设服务器地址为server.example.com
。
其中outbounds
处即连接到v2ray服务端上的常规配置,没有什么特别的。
在inbounds
处配置了一个dokodemo-door
协议,该协议可用于端口转发。配置指向服务器的8024端口,也就是nps的客户端连接端口,并将timeout调整为0(不限制超时时间),以便保证后续nps连接不断。并在本地同样开启8024端口,作为后续nps客户端实际连接的端口。注意本地监听端口可以和服务器端口不一样,仅仅作为一个转发的目的。
在未配置路由的情况下,v2ray默认会使用outbounds
中的第一个配置项作为所有inbounds
的出口,故上面配置的dokodemo-door
先走vmess连到服务器,再连到服务器自己上的8024端口。
本地开启v2ray后,便可以进行nps客户端的连接了。
nps客户端连接
nps的服务端版本就叫nps,客户端版本叫npc,两者分离,因此先下载npc。
在web面板上添加一个客户端,展开客户端命令,如图所示:
在内网机器上运行命令:
npc -server=127.0.0.1:8024 -vkey=xxxxxxxxxxx -type=tcp
把web面板展示的server IP和端口换成本地IP和刚刚在v2ray客户端上配置的dokodemo-door
监听端口号即可。
最后按照常规方式添加隧道即可建立穿透。
解决连接中断问题
按上面配置完之后,发现每隔一分钟左右连接会断一次,然后又重新连接。
由于客户端到服务器的v2ray连接经过nginx反代,于是猜想到是nginx配置的问题。
首先从Stack Overflow上某个问题了解到是配置反代时没有设置好超时时间,导致连接断开,504 Gateway Timeout。
于是修改方才的nginx反代配置:
location /example_ws_path { # websocket子路径建议在nginx处配 proxy_redirect off; proxy_pass http://127.0.0.1:20000/; # 上面的vmess端口号 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 加入下面的超时时间设置 proxy_connect_timeout 300d; proxy_send_timeout 300d; proxy_read_timeout 300d; send_timeout 300d; }
300d
代表300天(若后面不加单位则表示“秒”),这下怎么也不会超时了。
另一个地方的timeout可能也与此有关:
ssl_session_timeout 10m;
将10m调大,比如改成100d。
讨论
直接使用socks5代理
输入npc -h
可以查看npc的帮助,其中有一个指令:
-proxy string proxy socks5 url(eg:socks5://111:[email protected]:9007)
因此npc自身也支持经由代理连接,那么也可以不配置dokodemo-door
,仅配置本地socks5代理。然后使用如下格式的连接语句:
npc -server=server.example.com:8024 -vkey=xxxxxxxxxxx -type=tcp -proxy socks5://127.0.0.1:10808
其中假设本地socks5代理端口为10808。
nps始终频繁断线
测试发现在特定环境下即使按照如上方式配置超时时间,nps仍然频繁断线。直接使用tcp的vmess协议,避免通过nginx反代可能可以解决问题。
推荐改用udp协议的代理。例如v2ray的kcp代理(慎用)、quic代理等。udp是无状态协议,不存在断线问题。
另外再介绍一个近期热门的代理工具:
Hysteria:https://github.com/HyNetwork/hysteria
Hysteria 是一个功能丰富的,专为恶劣网络环境进行优化的网络工具(双边加速),比如卫星网络、拥挤的公共 Wi-Fi、在中国连接国外服务器等。 基于修改版的 QUIC 协议。
测试表明使用hysteria在一定程度上大大增加了链接的稳定性,几乎不产生断线。若所使用的运营商未对udp协议进行QoS,建议作为首选方案。