UP | HOME

Websocket

Table of Contents

WebSocket 的配置其实很简单,就跟 mKCP 一样把 network 一改就行了

配置

服务器

{
    "inbounds": [
        {
            "port": 16823,
            "protocol": "vmess",
            "settings": {
                "clients": [
                    {
                        "id": "b831381d-6324-4d53-ad4f-8cda48b30811",
                        "alterId": 64
                    }
                ]
            },
            "streamSettings": {
                "network":"ws"
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "settings": {}
        }
    ]
}

客户端

{
    "inbounds": [
        {
            "port": 1080,
            "protocol": "socks",
            "sniffing": {
                "enabled": true,
                "destOverride": ["http", "tls"]
            },
            "settings": {
                "auth": "noauth"
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vmess",
            "settings": {
                "vnext": [
                    {
                        "address": "serveraddr.com",
                        "port": 16823,
                        "users": [
                            {
                                "id": "b831381d-6324-4d53-ad4f-8cda48b30811",
                                "alterId": 64
                            }
                        ]
                    }
                ]
            },
            "streamSettings":{
                "network":"ws"
            }
        }
    ]
}

WebSocket + TLS + Web

接下来搭配 Web 服务并同时实现 TLS 和 WebSocket

  • 使用 Nginx/Caddy/Apache 是因为 VPS 已经有 Nginx/Caddy/Apache 可以将 V2Ray 稍作隐藏
  • 使用 WebSocket 是因为搭配 Nginx/Caddy/Apache 只能用 WebSocket
  • 使用 TLS 是因为可以流量加密,看起来更像 HTTPS
也许 WebSocket + TLS + Web 的配置组合相对较好,但不意味着这样的配置适合任何人

注意: V2Ray 的 Websocket + TLS 配置组合并不依赖 Nginx/Caddy/Apache,只是能与其搭配使用而已,没有它们也可以正常使用

服务器

这次 TLS 的配置将写入 Web 配置中,由这些软件来监听 443 端口(443 比较常用,并非 443 不可),然后将流量转发到 V2Ray 的 WebSocket 所监听的内网端口(本例是 10000),V2Ray 服务器端不需要配置 TLS

V2ray

{
    "inbounds": [
        {
            "port": 10000,
            "listen":"127.0.0.1",//只监听 127.0.0.1,避免除本机外的机器探测到开放了 10000 端口
            "protocol": "vmess",
            "settings": {
                "clients": [
                    {
                        "id": "b831381d-6324-4d53-ad4f-8cda48b30811",
                        "alterId": 0
                    }
                ]
            },
            "streamSettings": {
                "network": "ws",
                "wsSettings": {
                    "path": "/ray"
                }
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "settings": {}
        }
    ]
}

证书

Nginx 配置和 Apache 配置中使用的是域名和证书使用 TLS 小节的举例,请替换成自己的

因为 Caddy 会自动申请证书并自动更新,所以使用 Caddy 不用指定证书、密钥

注意: 如果在 VPS 上有架设网页,请使用 webroot 模式生成证书而不是 TLS 小节中提到的 standalone 模式

证书生成
$ ~/.acme.sh/acme.sh --issue -d mydomain.me --webroot /path/to/webroot --keylength ec-256
安装证书和密钥
$ acme.sh --install-cert -d mydomain.com --ecc \
  --key-file       /etc/v2ray/v2ray.key \
  --fullchain-file /etc/v2ray/v2ray.crt \
  --reloadcmd     "service nginx force-reload"
Nginx 配置
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate       /etc/v2ray/v2ray.crt;
    ssl_certificate_key   /etc/v2ray/v2ray.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;

    ssl_protocols         TLSv1.2 TLSv1.3;
    ssl_ciphers           ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    server_name           mydomain.me;
    location /ray { # 与 V2Ray 配置中的 path 保持一致
        if ($http_upgrade != "websocket") { # WebSocket协商失败时返回404
               return 404;
           }
           proxy_redirect off;
           proxy_pass http://127.0.0.1:10000; # 假设WebSocket监听在环回地址的10000端口上
           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection "upgrade";
           proxy_set_header Host $host;
           # Show real IP in v2ray access.log
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

客户端

{
    "inbounds": [
        {
            "port": 1080,
            "listen": "127.0.0.1",
            "protocol": "socks",
            "sniffing": {
                "enabled": true,
                "destOverride": ["http", "tls"]
            },
            "settings": {
                "auth": "noauth",
                "udp": false
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vmess",
            "settings": {
                "vnext": [
                    {
                        "address": "mydomain.me",
                        "port": 443,
                        "users": [
                            {
                                "id": "b831381d-6324-4d53-ad4f-8cda48b30811",
                                "alterId": 64
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "ws",
                "security": "tls",
                "wsSettings": {
                    "path": "/ray"
                }
            }
        }
    ]
}

注意

  • V2Ray 自 4.18.1 后支持 TLS1.3,如果开启并强制 TLS1.3 请注意 v2ray 客户端版本
  • 较低版本的 nginx 的 location 需要写为 ray 才能正常工作
  • 如果在设置完成之后不能成功使用,可能是由于 SElinux 机制(如果你是 CentOS 7 的用户请特别留意 SElinux 这一机制)阻止了 Nginx 转发向内网的数据。如果是这样的话,在 V2Ray 的日志里不会有访问信息,在 Nginx 的日志里会出现大量的 "Permission Denied" 字段,要解决这一问题需要在终端下键入以下命令:

    setsebool -P httpd_can_network_connect 1
    
  • 请保持服务器和客户端的 wsSettings 严格一致,对于 V2Ray,/ray 和 ray 是不一样的
  • 较低版本的系统/浏览器可能无法完成握手. 如 Chrome 49/XP SP3, Safari 8/iOS 8.4, Safari 8/OS X 10.10 及更低的版本. 如果设备比较旧, 则可以通过在配置中添加较旧的 TLS 协议以完成握手
开启了 TLS 之后 path 参数是被加密的,GFW 看不到

主动探测一个 path 产生 Bad request 不能证明是 V2Ray

不安全的因素在于人,自己的问题就不要甩锅

使用 Header 分流并不比 path 安全, 不要迷信

WebSocket + BrowserForwarder

通过 WebSocket 的配置,服务端可以用一个真正的 HTTP 服务器接收 V2Ray 数据

而 V2Ray 4.37.0 加入的 浏览器转发 BrowserForwarder 模块,则可以让真正的网页浏览器发送 V2Ray 数据。如果说 HTTP 服务器隐藏了 V2Ray 服务器,那么使用浏览器转发,浏览器隐藏了 V2Ray 客户端。示意图如下:

[V2Ray client] --> [Browser] --> {Internet} --> [HTTP server] --> [V2Ray server] --> [github.com]

然而,最 tricky 的地方也正与浏览器有关。由于在日常使用中,浏览器往往是连上代理之后访问网络的。但是这里,浏览器成了 V2Ray 的代理服务器:

[Browser A] --> [V2Ray client] --> [Browser B] --> {Internet} --> [HTTP server] --> [V2Ray server] --> [github.com]
  • Browser A 是面向用户的浏览器
  • Browser B 则仅仅用于转发 V2Ray 流量

如果不想用两个浏览器的话,就需要注意配置路由规则,确保浏览器是直连科学服务器的。以下配置假定用户使用同一个浏览器上网以及转发。

配置

在实际应用场景中,浏览器转发模块一般用在客户端。不需要额外对服务器进行额外配置

任何使用 WebSocket 作为传输配置的客户端都可以配置为使用浏览器转发。不限于 WebSocket + TLS + Web 配置方式

客户端

在 WebSocket + TLS + Web 客户端配置的基础上进行修改

{
    "inbounds": [
        {
            "port": 1080,
            "protocol": "socks",
            "sniffing": {
                "enabled": true,
                "destOverride": ["http", "tls"]
            },
            "settings": {
                "auth": "noauth"
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "yourserver",
                        "port": 443,
                        "users": [
                            {
                                "id": "your-id",
                                "encryption": "none"
                            }
                        ]
                    }
                ]
            },
            "streamSettings":{
                "network": "ws",
                "wsSettings": {
                    "path": "/yourpath",
                    "useBrowserForwarding": true
                },
                "security": "tls",
                "tlsSettings": {
                    "serverName": "yourserver",
                    "allowInsecure": false
                }
            }
        },
        {
            "protocol": "freedom",
            "settings": {},
            "tag": "direct"
        }
    ],
    "routing": {
        "rules": [
            {
                "type": "field",
                "ip": ["127.0.0.1"],
                "outboundTag": "direct"
            },
            {
                "type": "field",
                "domain": ["yourserver"],
                "outboundTag": "direct"
            }
        ]
    },
    "browserForwarder": {
        "listenAddr": "127.0.0.1",
        "listenPort": 8080
    }
}
  • browserForwarderlistenPort 所指定的端口上(本例是 8080 )监听,稍后用于转发流量的浏览器需要访问此端口
  • ws 设置中的 "useBrowserForwarding": true 指示此 WebSocket 要由浏览器转发
  • 设置了 直连 127.0.0.1科学服务器 的路由规则

    如果不直连 127.0.0.1, V2Ray 无法与本机浏览器进行连接,流量将会一直在 V2Ray 和你的浏览器之间兜圈子,访问任何需要走 ws 的网站都会 timeout
    
    如果有别的分流手段可以实现上述目的,例如使用 Privoxy ,或者使用另一个不走代理的浏览器作为转发服务器,那么可以不需要此处的分流规则
    
  • 也可以使用 vmess 协议取代 vless 协议

为了使浏览器转发模块工作,还必须 下载 与当前 V2Ray 相同版本的 v2ray-extra.zip 。并将 browserforwarder 目录其解压到资源文件路径 中。为了简单起见,直接解压到 v2ray 所在目录,类似下面的列表:

.
├── browserforwarder
│   ├── index.html
│   └── index.js
├── v2ray.exe
└── wv2ray.exe

作为转发服务器的浏览器配置

打开一个现代网络浏览器,例如 Firefox 或是 Chromium ,访问 http://127.0.0.1:8080 ,使 V2Ray 连接上浏览器 。如连接成功, V2Ray 日志中应有类似输出:

2022/02/01 15:07:01 reflective server connected
Next: HTTP Previous: TLS Home:传输