CentOS 7 V2ray TCP + TLS + Web 协议

在水群时无意间看到一个 TCP + TLS 的操作, 以为是玩什么梗, 结果真有这样的配置操作。于是决定尝试搭建一下。对于新手, 建议使用 TLS 分流器 方案 (划掉

目前, Vmess + WebSocket + TLS (以下简称 wss) 作为一种常见的方案, 由于其伪装能力极强, 像 HTTPS 流量一样, 可以隐藏 V2Ray 的路径。这种方式能够通过主动探测和伪装正常的 HTTP 网站响应来绕过审查, 广泛应用于隐匿流量。

然而, 这种强大的伪装能力需要付出性能代价, 特别是在 TLS 1.3 握手需要消耗 1 RTT (Round-trip time) 和 WebSocket 握手也需要消耗 1 RTT, 这会增加握手延迟。此外, V2Ray 引入了 mux 来减少握手的发生, 但实际使用中 mux 体验并不好, 很多用户选择关闭。

最近, 新的工具 Trojan, 它将类似 Socks 的协议直接通过 TLS 传输, 同时将认证失败的流量交由 Web 服务器处理, 从而减少了 WebSocket 握手的延迟, 同时保持了与 wss 相同的伪装能力。然而, Trojan 工具较为年轻, 没有路由功能, 各平台的图形化客户端也不完善, 因此仍有一定局限性。

基于此, 本篇尝试用 V2Ray 实现类似功能, 采用 Vmess + TCP + TLS, 并通过网站伪装省下 WebSocket 握手延迟。

工作原理

HAProxy 监听 443 端口, 处理完 TLS 流量后, 将 HTTP 请求交由 Web 服务器处理, 其他非 HTTP 流量则交由 V2Ray 按照 Vmess 协议处理

准备条件

本方案使用以下组件:

  • HAProxy: 作为 TLS 反向代理和流量分发器
  • Web 服务器: 如 Caddy 或 Nginx, 用于处理 HTTP 请求
  • V2Ray: 作为 Vmess 协议的处理器
  • 服务器系统: CentOS 7

实现步骤

本次方案使用 HAProxy, Caddy/Nginx (Web 服务器的使用不是本教程的重点, 可以用 httpd 等替代), V2Ray, 服务器系统为 CentOS 7。

  1. 安装 HAProxy

    为支持 TLS1.3, HAProxy 版本应大于 1.8.15, OpenSSL 版本应大于 1.1.1。如果你的系统自带的版本较低, 建议自行编译安装。

  2. 安装 Web 服务器

    可以选择 Nginx 或 Caddy 作为 Web 服务器。以 Nginx 为例, 添加官方软件仓库后, 使用以下命令安装

    yum install nginx
    
  3. 安装 V2Ray

    可以使用 V2Ray 官方的安装脚本进行安装

  4. 修改 V2Ray 配置文件

    编辑 V2Ray 配置文件, 以 Vmess 协议和 TCP 方式监听 40001 端口

    {
      "inbounds": [
        {
          "protocol": "vmess",
          "listen": "127.0.0.1",
          "port": 40001,
          "settings": {
            "clients": [
              {
                "id": "f2435e5c-9ad9-4367-836a-8341117d0a5f"
              }
            ]
          },
          "streamSettings": {
            "network": "tcp"
          }
        }
      ],
      "outbounds": [
        {
          "protocol": "freedom"
        }
      ]
    }
    
  5. 配置 Web 服务器

    配置 Web 服务器部署 HTTP 服务于 8080 端口, 以下为 Caddy 和 Nginx 的配置示例

    1. Caddy 配置

      http://example.com:8080 {
          root /var/www/html
      }
      
    2. Nginx 配置

      server {
        listen 8080;
        server_name example.com;
        root /var/www/html;
      }
      
  6. 配置 HAProxy

    修改 HAProxy 配置文件, 监听 443 端口并区分 HTTP 和非 HTTP 流量

    global
        log /dev/log local0
        log /dev/log local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
        stats timeout 30s
        user haproxy
        group haproxy
        daemon
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private
    
        # 仅使用支持 FS 和 AEAD 的加密套件
        ssl-default-bind-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-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
        # 禁用 TLS 1.2 之前的 TLS
        ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
    
        tune.ssl.default-dh-param 2048
    
    defaults
        log global
        # 我们需要使用 tcp 模式
        mode tcp
        option dontlognull
        timeout connect 5s
        # 空闲连接等待时间, 这里使用与 V2Ray 默认 connIdle 一致的 300s
        timeout client  300s
        timeout server  300s
    
    frontend tls-in
        # 监听 443 tls, tfo 根据自身情况决定是否开启, 证书放置于 /etc/ssl/private/example.com.pem
        bind *:443 tfo ssl crt /etc/ssl/private/example.com.pem
        tcp-request inspect-delay 5s
        tcp-request content accept if HTTP
        # 将 HTTP 流量发给 web 后端
        use_backend web if HTTP
        # 将其他流量发给 vmess 后端
        default_backend vmess
    
    backend web
        server server1 127.0.0.1:8080
    
    backend vmess
        server server1 127.0.0.1:40001
    

    注意: HAProxy 的证书和密钥需合并到一个文件中, 可以使用以下命令合成证书

    cat example.com.crt example.com.key > example.com.pem
    
  7. 重启服务

    重启 HAProxy、Web 服务器 (Caddy/Nginx) 和 V2Ray 服务

    systemctl restart haproxy
    systemctl restart caddy
    systemctl restart v2ray
    
  8. 客户端配置

    在客户端配置文件中, 客户端连接 example.com:443, 使用 Vmess 和 TLS 协议

    {
      "inbounds": [
        {
          "port": 1080,
          "listen": "127.0.0.1",
          "protocol": "socks"
        }
      ],
      "outbounds": [
        {
          "protocol": "vmess",
          "settings": {
            "vnext": [
              {
                "address": "example.com",
                "port": 443,
                "users": [
                  {
                    "id": "f2435e5c-9ad9-4367-836a-8341117d0a5f",
                    "security": "none"
                  }
                ]
              }
            ]
          },
          "streamSettings": {
            "network": "tcp",
            "security": "tls"
          }
        }
      ]
    }
    

性能测试

测试工具为 vmessping, 可见 Vmess + TCP + TLS (左) 延迟低于 Vmess + WSS (右)

但是我的实际测试效果没有明显改变

tQyKPD45fmAFl9x.jpg

总结

  1. 性能优化

    HAProxy、V2Ray 和 Nginx 都支持 Domain Socket, 如果流量较大或数据包较多, 使用 Socket 可以提高性能

  2. 隐蔽性

    与 wss 比较

    • 中间人监听时, 该方法在建立 TLS 连接后, 比 wss 少了一次握手。TLS 建立后直接发送请求并获得响应, 这符合正常 HTTPS 请求的行为
    • 主动探测时, 如 TLS 建立后发送 HTTP 请求, 将被转发到 Web 服务器进行处理。如果发送的是非 HTTP 请求, 则会被转发给 V2Ray 处理。如果 Vmess 认证失败, 连接会被关闭。发送非 HTTPS 请求给 HTTPS 服务器时, 连接也会被关闭, 这是正常的行为

原文

TCP + TLS + Web

最后更新于 2020-05-09
使用 Hugo 构建
主题 StackJimmy 设计