XRAY:SplitHTTP 配置参考

XRAY 内核在 1.8.16 及后续版本,支持新协议 SplitHTTP。其使用 HTTP GET 长连接传输下行流量,使用多个 HTTP POST 请求传输上行流量,可以通过不支持 WebSocket、gRPC 的 CDN。

笔者参照 Chika 提供的配置文件 GitHub ,进行了简单搭建测,此配置使用 SplitHTTP + NGINX + CloudFlare CDN,即使用 NGINX 作为反向代理服务器用于隐藏后端服务,通过 CDN 确保网络可用性,通过请求路径分流规则将特定流量引入 XRAY 。

bash

bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install

Debain 12 环境,安装相关库和软件,以源码编译 NGINX

bash

apt install gcc socat curl libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev wget automake autoconf libtool make vim -y

源码编译安装NGINX,默认安装NGINX目录为:/usr/local/nginx

bash

# 下载 NGINX 源码
wget https://nginx.org/download/nginx-1.26.1.tar.gz

# 解压
tar -zxvf nginx-1.26.1.tar.gz

# 将官方提供的 vim 配置复制到当前用户 vim 目录下,以实现使用 vim 编辑 nginx 配置文件时高亮显示
mkdir -p ~/.vim/
cd nginx-1.26.1/
cp -r contrib/vim/* ~/.vim/

# 设置编译参数
./configure --with-http_sub_module --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_v3_module

# 编译
make

# 安装
make install

添加 nginx.service,使得可以通过 systemctl 管理 NGINX

bash

vim /usr/lib/systemd/system/nginx.service

bash

[Unit]
Description=nginx
After=network.target
  
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
  
[Install]
WantedBy=multi-user.target

首先需要购买域名,应选择 Godaddy、NameSilo、NameCheap 等国外域名商,不要选择国内域名商。购买域名后,注册 CloudFlare 账号,在域名注册商处修改其 NS 记录以通过 CloudFlare 管理该域名,方便后续接入 CDN 操作。

为域名添加一个 A 记录,将其指向上述配置的的 VPS 地址。

安装 acme 脚本,申请证书

bash

# 下载 ACME 脚本
curl  https://get.acme.sh | sh -s email=my@your.domain【你的域名】

# 注册验证,生成公钥私钥
~/.acme.sh/acme.sh --issue -d your.domain【你的域名】 --standalone --keylength ec-256 --force
 
# 将证书及私钥放置到 NGINX 有权限的位置并重启 NGINX
~/.acme.sh/acme.sh --installcert -d your.domain【你的域名】 --ecc \
--fullchain-file /etc/ssl/private/fullchain.cer \
--key-file /etc/ssl/private/private.key \
--reloadcmd  "systemctl restart nginx"

# 创建NGINX日志文件
mkdir -p /var/log/nginx
touch /var/log/nginx/error.log

编辑 XRAY 配置文件: /usr/local/etc/xray/config.json ,填写如下内容,安全起见建议修改 22 行 ID 和 30 行路径.

json

{
    "log": {
        "loglevel": "warning"
    },
    "routing": {
        "rules": [
            {
                "port": "443",
                "network": "udp",
                "outboundTag": "block"
            }
        ]
    },
    "inbounds": [
        {
            "listen": "127.0.0.1",
            "port": 8001,
            "protocol": "vless",
            "settings": {
                "clients": [
                    {
                        "id": "5dfa2b4f-88a2-4a49-ad33-38e89008d19f" // 长度为 1-30 字节的任意字符串,或执行 xray uuid 生成
                    }
                ],
                "decryption": "none"
            },
            "streamSettings": {
                "network": "splithttp",
                "splithttpSettings": {
                    "path": "/lovelive"
                }
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls",
                    "quic"
                ]
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "tag": "direct"
        },
        {
            "protocol": "blackhole",
            "tag": "block"
        }
    ]
}

编辑 NGINX 配置文件: /usr/local/nginx/conf/nginx.conf ,填写如下内容,修改 73 行内容为自己的域名,安全起见建议修改 97 行路径

nginx

# NGINX 用户、根据CPU核心数自动设置工作线程数
# user nginx;
worker_processes auto;

# 错误日志与进程文件位置
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

# 事件模块:允许每个工作线程的最大连接数为1024
events {
    worker_connections 1024;
}

http {
	# 定义日志格式、访问日志存储位置
    log_format main '[$time_local] $remote_addr $request $status "$http_referer" "$http_user_agent"';
    access_log /var/log/nginx/access.log main;
	
	# 根据$http_upgrade头的值设置$connection_upgrade变量,如果$http_upgrade为空,则$connection_upgrade为close,否则为upgrade
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ""      close;
    }
	
	# 根据$remote_addr(客户端IP地址)的格式设置$proxy_forwarded_elem变量。IPv4地址格式为for=$remote_addr,IPv6地址格式为for="[$remote_addr]"。
    map $remote_addr $proxy_forwarded_elem {
        ~^[0-9.]+$        "for=$remote_addr";
        ~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\"";
        default           "for=unknown";
    }
	
	# 解析$http_forwarded头并在其后追加$proxy_forwarded_elem,形成$proxy_add_forwarded。
    map $http_forwarded $proxy_add_forwarded {
        "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
        default "$proxy_forwarded_elem";
    }
	
	# 80端口永久重定向到443端口
    server {
        listen 80;
        listen [::]:80;
        return 301 https://$host$request_uri;
    }
	
	# 默认443端口服务器配置(如果HTTP请求中没有匹配到主机头,则默认走该主机)
    server {
	
		# 监听IPv4、IPv6 443端口
        listen                  443 ssl default_server;
        listen                  [::]:443 ssl default_server;
		
		# 拒绝不支持的SSL握手
        ssl_reject_handshake    on;
		
		# 只允许TLSv1.2和TLSv1.3协议
        ssl_protocols           TLSv1.2 TLSv1.3;
		
		# SSL会话超时时间为1小时,共享SSL会话缓存,大小为10MB
        ssl_session_timeout     1h;
        ssl_session_cache       shared:SSL:10m;
    }
	
	# 主443端口服务器配置
    server {
		# 监听IPv4、IPv6 443端口
        listen                     443 ssl;
        listen                     [::]:443 ssl;
		# 启用HTTP/2
        http2                      on; # This directive appeared in version 1.25.1. Otherwise use it like this. "listen 443 ssl http2; listen [::]:443 ssl http2;"

		# 【填 SSL 证书中包含的域名,建议将域名指向服务端的 IP,多个域名以空格分隔】
		# 指定服务器的域名
        server_name                your.domain;
		
		# 指定 TLS 证书文件、私钥文件位置
        ssl_certificate            /etc/ssl/private/fullchain.cer;
        ssl_certificate_key        /etc/ssl/private/private.key;
		
		# 只允许TLSv1.2和TLSv1.3协议,指定允许的SSL密码套件,优先使用服务器指定的密码套件
        ssl_protocols              TLSv1.2 TLSv1.3;
        ssl_ciphers                TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
		ssl_prefer_server_ciphers  on;
		
		# 启用OCSP Stapling、验证OCSP响应
        ssl_stapling               on;
        ssl_stapling_verify        on;
		
		# 指定DNS解析器为1.1.1.1,有效期60秒、DNS解析超时时间为2秒
        resolver                   1.1.1.1 valid=60s;
        resolver_timeout           2s;

		# 客户端请求头缓冲区大小为8KB
        client_header_buffer_size  8k;

		# 【Nginx 配置中的 location /lovelive 需与 XRAY 服务端配置中的 "path": "/lovelive" 一致】
		# 匹配路径/lovelive,使用HTTP/1.1协议,将请求转发到http://127.0.0.1:8001,设置X-Forwarded-For头,禁用代理重定向
        location /lovelive {
            proxy_pass                          http://127.0.0.1:8001;
            proxy_http_version                  1.1;
            proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_redirect                      off;
        }

		# 反向代理配置由 https://www.digitalocean.com/community/tools/nginx 生成
		# 匹配根路径
        location / {
			# 替换响应内容中的$proxy_host为$host,关闭单次替换,允许多次替换
            sub_filter                            $proxy_host $host;
            sub_filter_once                       off;
			
			# 设置变量$website为www.lovelive-anime.jp,并将请求转发至该网站,使用1.1.1.1作为DNS解析器
            set $website                          www.lovelive-anime.jp;
            proxy_pass                            https://$website;
            resolver                              1.1.1.1;
			
			# 设置Host头为$proxy_host
            proxy_set_header Host                 $proxy_host;
			
			# 使用HTTP/1.1协议与服务器通信,升级请求不使用缓存
            proxy_http_version                    1.1;
            proxy_cache_bypass                    $http_upgrade;
			
			# 启用SNI(服务器名称指示)
            proxy_ssl_server_name                 on;
			
			# 设置Upgrade头为$http_upgrade,设置Connection头为$connection_upgrade
            proxy_set_header Upgrade              $http_upgrade;
            proxy_set_header Connection           $connection_upgrade;
			
			# 设置X-Real-IP头为客户端IP地址
            proxy_set_header X-Real-IP            $remote_addr;
			
			# 设置Forwarded头
            proxy_set_header Forwarded            $proxy_add_forwarded;
			# 设置X-Forwarded-For头(请求协议、主机名、服务器端口)
            proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto    $scheme;
            proxy_set_header X-Forwarded-Host     $host;
            proxy_set_header X-Forwarded-Port     $server_port;
			
			# 设置代理连接、发送、读取超时时间为60秒
            proxy_connect_timeout                 60s;
            proxy_send_timeout                    60s;
            proxy_read_timeout                    60s;
        }
    }
}

此时访问自己购买的域名(上述 NGINX 73 行配置),应该被重定向至 122 行配置的目标网站。

在 CloudFlare 控制面板中,网站 – 点击域名 – DNS – 找到上面添加的 A 记录 – 编辑 – 将“代理状态”打开(云朵由灰色变为橙色) – 保存。 然后在 CloudFlare 控制面板 – 网站 – 点击域名 – SSL/TLS – 将加密模式设置为完全(严格)。

配置后稍等 5 分钟左右,需要等 DNS 服务器完成更新。Windows 下可以使用 ipconfig /flushdns 刷新 DNS 缓存,此次再通过 ping 命令或者 在线 ping 等工具解析域名,会发现解析到的地址不再是之前添加的 A 记录的 VPS 地址,而是 CloudFlare 节点的地址。

无需变动任何配置,此时流量都是通过 CloudFlare 节点进入的 VPS ,不会向 GFW 暴露 VPS IP。可以通过查看 CloudFlare 面板流量信息,以及 VPS 中的请求日志确认。

与 xray.exe 同级目录下,新建 config.json,填写如下内容,注意修改 33 行和 48 行的域名,安全起见建议修改 37 行 ID 和 47 行路径

json

{
    "log": {
        "loglevel": "info"
    },
    "routing": {
        "rules": [
            {
                "ip": [
                    "geoip:private"
                ],
                "outboundTag": "direct"
            }
        ]
    },
    "inbounds": [
        {
            "listen": "0.0.0.0",
            "port": 7897,
            "protocol": "socks"
        },
        {
            "listen": "0.0.0.0",
            "port": 7898,
            "protocol": "http"
        }
    ],
    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "your.domain", // 此处需要填写你的域名
                        "port": 443,
                        "users": [
                            {
                                "id": "5dfa2b4f-88a2-4a49-ad33-38e89008d19f", // 与服务端一致
                                "encryption": "none"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "splithttp",
                "splithttpSettings": {
                    "path": "/lovelive", // 与服务端一致
                    "host": "your.domain" // 若 "address": "" 中填的是 VPS 的 IP,此处必须填 Nginx 配置中 server_name 的值,否则会因在 Nginx 配置中启用了 ssl_reject_handshake 而连接失败
                },
                "security": "tls",
                "tlsSettings": {
                    "serverName": "",
                    "fingerprint": "chrome"
                }
            },
            "tag": "proxy"
        },
        {
            "protocol": "freedom",
            "tag": "direct"
        }
    ]
}

此时进行连接测试,可以正常使用 XRAY 代理流量。