侧边栏壁纸
博主头像
分享你我博主等级

行动起来,活在当下

  • 累计撰写 108 篇文章
  • 累计创建 13 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

xray 前置实现复用443端口

管理员
2022-07-17 / 0 评论 / 0 点赞 / 4 阅读 / 20049 字

应用情景

由于 XTLS,Xray 需要监听 443 端口,这导致如果之前有网站运行在服务器上,那么此时网站无法运行或需要运行在其他端口上,这显然是不合理的。有以下三种方案可以解决这个问题:

  • Xray 监听其他常用端口(如 22、3389、8443)

    这个方案是最简单的,但不够完美。

  • Nginx 或 HAProxy 监听 443 端口,通过 SNI 分流做 L4 反向代理,实现端口复用

    这个方案比较复杂,需要对 Nginx 或 HAProxy 的使用有一定了解,此处不作过多解释。

  • Xray 监听 443 端口,通过 Fallbacks 功能 SNI 分流将网站流量回落到 Nginx 或 Caddy

    这个方案难度适中,也是此教程接下来想要演示的方案。


思路

Xray 回落流程

从 443 端口接收到流量后,Xray 会把 TLS 解密后首包长度 < 18、协议版本无效或身份认证失败的流量通过对 name、path、alpn 的匹配转发到 dest 指定的地址。

Xray 配置

{
  log: {
    loglevel: "warning",
  },
  inbounds: [
    {
      port: 443,
      protocol: "vless",
      settings: {
        clients: [
          {
            id: "UUID",
            flow: "xtls-rprx-direct",
          },
        ],
        decryption: "none",
        fallbacks: [
          {
            name: "example.com",
            path: "/vmessws",
            dest: 5000,
            xver: 1,
          },
          {
            dest: 5001,
            xver: 1,
          },
          {
            alpn: "h2",
            dest: 5002,
            xver: 1,
          },
          {
            name: "blog.example.com",
            dest: 5003,
            xver: 1,
          },
          {
            name: "blog.example.com",
            alpn: "h2",
            dest: 5004,
            xver: 1,
          },
        ],
      },
      streamSettings: {
        network: "tcp",
        security: "xtls",
        xtlsSettings: {
          alpn: ["h2", "http/1.1"],
          certificates: [
            {
              certificateFile: "/etc/ssl/xray/cert.pem",
              keyFile: "/etc/ssl/xray/privkey.key",
            },
          ],
        },
      },
    },
    {
      listen: "127.0.0.1",
      port: 5000,
      protocol: "vmess",
      settings: {
        clients: [
          {
            id: "UUID",
          },
        ],
      },
      streamSettings: {
        network: "ws",
        wsSettings: {
          acceptProxyProtocol: true,
          path: "/vmessws",
        },
      },
    },
  ],
  outbounds: [
    {
      protocol: "freedom",
    },
  ]
}

以上配置针对于 Nginx,以下是需要注意的一些细节。

  • 有关 Proxy Protocol

    Proxy Protocol 是 HaProxy 开发的一种旨在解决代理时容易丢失客户端信息问题的协议,常用于链式代理和反向代理。传统的处理方法往往较为复杂且有诸多限制,而 Proxy Protocol 非常简单地在传输数据时附带上原始连接四元组信息的数据包,解决了这个问题。

    凡事皆有利弊,Proxy Protocol 也是如此。

    在遇到异常时,请考虑配置是否符合上述条件。

    此处,我们使用 Proxy Protocol 让被回落到的目标获取到客户端的真实 IP。

    另外,当 Xray 的某个入站配置存在 "acceptProxyProtocol": true 时,ReadV 将失效。

    • 有发送必须有接收,反之亦然

    • 同一端口不能既兼容带 Proxy Protocol 数据的连接又兼容不带数据的连接(如:Nginx 同端口的不同虚拟主机(server),本质是上一条)[2][3]

  • 有关 HTTP/2

    首先,inbounds.streamSettings.xtlsSettings.alpn 有顺序,应将 h2 放前,http/1.1 放后,在优先使用 HTTP/2 的同时保证兼容性;反过来会导致 HTTP/2 在协商时变为 HTTP/1.1,成为无效配置。

    在上述配置中,每条回落到 Nginx 的配置都要分成两个。这是因为 h2 是强制 TLS 加密的 HTTP/2 连接,这有益于数据在互联网中传输的安全,但在服务器内部没有必要;而 h2c 是非加密的 HTTP/2 连接,适合该环境。然而,Nginx 不能在同一端口上同时监听 HTTP/1.1 和 h2c,为了解决这个问题,需要在回落中指定 alpn 项(是 fallbacks 而不是 xtlsSettings 里面的),以尝试匹配 TLS ALPN 协商结果。

    建议 alpn 项只按需用两种填法:[4]

    如果使用 Caddy 就大可不必如此繁杂了,因为它可以在同一端口上同时监听 HTTP/1.1 和 h2c,配置改动如下:

    • 省略

    • "h2"

"fallbacks": [
    {
        "name": "example.com",
        "path": "/vmessws",
        "dest": 5000,
        "xver": 1
    },
    {
        "dest": 5001,
        "xver": 1
    },
    {
        "name": "blog.example.com",
        "dest": 5002,
        "xver": 1
    }
 ]

Nginx 配置

set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
server {
    listen 127.0.0.1:5001 proxy_protocol default_server;
    listen 127.0.0.1:5002 proxy_protocol default_server http2;
    location / {
        root /srv/http/default;
    }
}
server {
    listen 127.0.0.1:5003 proxy_protocol;
    listen 127.0.0.1:5004 proxy_protocol http2;
    server_name blog.example.com;
    location / {
        root /srv/http/blog.example.com;
    }
}
server {
    listen 80;
    return 301 https://$host$request_uri;
}


0

评论区