之前发在自己的博客上:https://blog.skyju.cc/post/nps-frp-over-v2ray/
经过一段时间的实践,已经证实差不多是可靠的,故发在这里让更多人有能力对抗信息办的权柄。
背景
由于山大内部服务器只有内网可以访问,一直以来使用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 协议。