Featured image of post 受审查网络下的内网穿透:通过v2ray代理nps/frp通道

受审查网络下的内网穿透:通过v2ray代理nps/frp通道

在受审查的网络下,常规内网穿透工具由于特征较明显容易被封锁。本文介绍一种思路,通过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配置代码片段:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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:

客户端配置

内网机器,也就是客户端配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{
    "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面板上添加一个客户端,展开客户端命令,如图所示:

在内网机器上运行命令:

1
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反代配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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可能也与此有关:

1
ssl_session_timeout 10m;

将10m调大,比如改成100d。

讨论

直接使用socks5代理

输入npc -h可以查看npc的帮助,其中有一个指令:

1
2
-proxy string
        proxy socks5 url(eg:socks5://111:[email protected]:9007)

因此npc自身也支持经由代理连接,那么也可以不配置dokodemo-door,仅配置本地socks5代理。然后使用如下格式的连接语句:

1
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,建议作为首选方案。

Licensed under CC BY-NC-SA 4.0
-1