# HTTP/2+TLS+WEB

V2RayClient --|-> Caddy -> V2RayServer -> Internet

流量经 Caddy 通过本地回环(lo)转发给 V2Ray ,如直接使用浏览器访问 V2Ray Path 将会返回 502 Bad Gateway,直接打开域名或访问其他路径与通过 HTTP/2 访问普通网站一般无二。每一个请求都是真实的 HTTP/2 PUT,正所谓真实是最完美的伪装。

CDN

H2 流量理论上跟 ws 一样可以被 CDN 转发。 但是遗憾的是, Cloudflare 只支持与源服务器进行 HTTP/1.x 通信。 Cloudflare only uses HTTP/1.x between the origin web server and Cloudflare. (opens new window)

# 缺陷

# 服务端配置

建议的部署顺序

先配置 Web 服务器,待 Web 服务器正常工作后部署 V2Ray。

本文之示例配置尚未使用 h2c,故 V2Ray 和 Caddy 均需要配置 SSL 证书。

需要自行修改的内容已使用 <CustomTag> 标注,部署时请注意修改。

TAG 说明
<Host> 服务器的域名
<Port> V2Ray 在本地回环(lo)中监听的端口。
<UUID> VMess 用户的主 ID。必须是一个合法的 UUID 。
<H2 Path> 以“/”开头的 HTTP 路径,客户端与服务端必须一致。
<Path to cert>
<Path to key>
指向证书/密钥的绝对路径
<Path to webroot> 指向 Web 页面根目录的绝对路径

# 前期准备

  • 注册域名并正确配置域名解析
  • 准备好 SSL 证书 (如果需要使用 Caddy 管理 SSL 证书,请自行修改 Caddyfile)
  • 完成 V2Ray 和 Web 服务器(例如 Caddy)的安装
  • 准备一些人畜无害的 HTML 页面用来挡刀

# Web 服务器

此处需要使用能转发 HTTP/2 流量的 Web 服务器。本文以 Caddy 1 的配置文件 Caddyfile 为例,其他 Web 服务器同理。

WARNING

NGINX 不能向后端转发 HTTP2 流量。1

下面的配置假定你已经拥有现成的 SSL 证书,如果需要使用 Caddy 管理 SSL 证书,请自行修改 tls 部分。

Caddyfile
http://<Host> {
    redir https://<Host>{url}
}

https://<Host> {
    log stdout
    errors stderr
    root <Path to webroot>
    tls <Path to cert> <Path to key>
    proxy <H2 Path> https://localhost:<Port> {
        insecure_skip_verify
        header_upstream Host {host}
        header_upstream X-Real-IP {remote}
        header_upstream X-Forwarded-For {remote}
        header_upstream X-Forwarded-Port {server_port}
        header_upstream X-Forwarded-Proto "https"
    }
}
Caddyfile (Caddy v2)
https://<Host> {
    root * <Path to webroot>
    file_server
    tls <Path to cert> <Path to key>
    proxy <H2 Path> https://localhost:<Port> {
        transport http {
            tls_insecure_skip_verify
        }
        header_up Host {host}
        header_up X-Real-IP {remote}
        header_up X-Forwarded-For {remote}
        header_up X-Forwarded-Port {server_port}
        header_up X-Forwarded-Proto "https"
    }
}
Caddyfile (Caddy v2 & H2C)
https://<Host> {
    root * <Path to webroot>
    file_server
    tls <Path to cert> <Path to key>
    proxy <H2 Path> https://localhost:<Port> {
        transport http {
            versions h2c
        }
    }
}

# V2Ray

下列配置不包含 log 部分。

V2Ray config.json
{
  "inbounds": [
    {
      "port": "<Port>",
      "listen": "127.0.0.1",
      "protocol": "vmess",
      "settings": {
        "clients": [
          {
            "id": "<UUID>",
            "alterId": 64
          }
        ]
      },
      "streamSettings": {
        "network": "h2",
        "security": "tls",
        "httpSettings": {
          "path": "<H2 Path>",
          "host": [
            "<Host>"
          ]
        },
        "tlsSettings": {
          "serverName": "<Host>",
          "certificates": [
            {
              "certificateFile": "<Path to cert>",
              "keyFile": "<Path to key>"
            }
          ]
        }
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "settings": {}
    }
  ]
}
V2Ray Server(H2C) config.json
{
  "inbounds": [
    {
      "port": "<Port>",
      "listen": "127.0.0.1",
      "protocol": "vmess",
      "settings": {
        "clients": [
          {
            "id": "<UUID>",
            "alterId": 64
          }
        ]
      },
      "streamSettings": {
        "network": "h2",
        "security": "none",
        # 此处改为"none"
        "httpSettings": {
          "path": "<H2 Path>",
          "host": [
            "<Host>"
          ]
        }
      }
      # "tlsSettings"字段删除
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "settings": {}
    }
  ]
}
V2Ray Client(H2C) config.json
  "outbounds":
    {
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "<Host>",
            "port": 443,
            "users": [
              {
                "id": "<UUID>",
                "alterId": 64
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "h2",
        "security": "tls",
        "tlsSettings": {
          "serverName": ""
          # 注意此处为空值
        },
        "httpSettings": {
          "path": "<H2 Path>",
          "host": [
            "<Host>"
          ]
        }
      }
    }

# 排错

  • 如果你后端的 V2Ray 挂了或配置不正确,访问 <H2 Path> 仍然会返回 502,因此不能通过 502 错误判断 V2Ray 正在运行。
  • 同时检查 V2Ray 和 Caddy 的日志,有助于确定问题出在哪一部分。

# 参考文献

1. v2ray-core #1063 (opens new window) https://github.com/veekxt/v2ray-template/tree/master/H2C%2Bvmess%2BCaddy2