背景
上一篇文章介绍了手动安装并配置 X-ray 的 REALITY 协议,但是支持 REALITY 协议的 iOS 的客户端太少,所以打算同时安装一个 Hysteria 2 作为补充。目前来看 X-ray core 短期内不会支持 Hysteria 2,故考虑使用 nginx 同时反代 X-ray 和 Hysteria 2。
正如标题所言,这次我们上点强度,为了达到完美的效果,我们只使用一个 443 端口,实现 nginx 反代 X-ray(支持 REALITY&XHTTP)和 Hysteria 2,同时再反代一个 WEB 网站,网站支持 HTTP/2 和 HTTP/3。
流程如下:
┌─────────────┐ ┌────────────────┐ ┌───────────────────┐
│ WEB browser │ │ REALITY client │ │ Hysteria 2 client │
└──────┬──────┘ └───────┬────────┘ └─────────┬─────────┘
│ │ │
│ │ │
│ │ │
│ │ │
│ ┌────────▼────────┐ │
└──────────► example.com:443 ◄───────────────┘
└────────┬────────┘
│
│
┌───▼───┐
│ Nginx │
└───┬───┘
│
┌──────────────────┼────────────────────────┐
│ │ │
┌─────▼──────┐ ┌──────▼───────┐ ┌──────────▼────────┐
│ WEB server │ │ X-ray server │ │ Hysteria 2 server │
└────────────┘ └──────────────┘ └───────────────────┘
准备工作
- 一个域名,本文以 example.com 为例,注意自行替换下文所有配置文件中的域名为自己的域名
- 将 example.com 解析到自己主机,不要开启 CDN
- 和上一篇文章一样,本文所有操作均基于 root 用户
- 一些耐心
安装
安装 Nginx
编译安装最新版本 Nginx
wget https://nginx.org/download/nginx-1.26.2.tar.gz
tar -zxvf nginx-1.26.2.tar.gz
cd nginx-1.26.2
apt install gcc make -y
apt install libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev -y
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-stream --with-stream_ssl_module --with-http_realip_module --with-stream_ssl_preread_module
make && make install
设置 Nginx 开机启动,新建 /etc/systemd/system/nginx.service
,文件内容如下
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
After=xray.service
[Service]
Type=forking
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
启动 Nginx 服务并将 nginx 加入 PATH:
echo "PATH=$PATH:/usr/local/nginx/sbin" >> ~/.bashrc
systemctl enable nginx
systemctl start nginx
安装 acme 并申请 https 证书
安装 acme 并申请证书,注意更换为自己邮箱并提前设置域名解析:
curl https://get.acme.sh | sh -s email=[email protected]
source ~/.bashrc
acme.sh --issue -d example.com --nginx /usr/local/nginx/conf/nginx.conf
安装证书:
mkdir -p /usr/local/nginx/certs/example.com
acme.sh --install-cert -d example.com \
--key-file /usr/local/nginx/certs/example.com/cert.key \
--fullchain-file /usr/local/nginx/certs/example.com/fullchain.cer
安装 Hysteria 2
使用官方脚本一键安装并设置开机启动(注意需要设置 root 为启动用户):
HYSTERIA_USER=root bash <(curl -fsSL https://get.hy2.sh/)
systemctl enable hysteria-server
安装 X-ray
参考 上一篇文章 安装并设置自动更新 dat。
配置
端口规划:
端口 | 监听 | 协议 | 服务 | 作用 |
---|---|---|---|---|
80 | 0.0.0.0 | HTTP | Nginx | 强制重定向至 443 |
443 | 0.0.0.0 | TCP | Nginx | X-ray、HTTP/2 WEB 服务入口 |
443 | 0.0.0.0 | UDP | Nginx | Hysteria 2、HTTP/3 WEB 服务入口 |
2024 | 127.0.0.1 | gRPC | X-ray | X-ray REALITY 协议监听端口 |
3001 | 127.0.0.1 | HTTP | Any WEB service | WEB 服务监听端口,搭建自己的服务 |
1443 | 127.0.0.1 | TCP | X-ray | X-ray XHTTP 协议监听端口 |
2443 | 127.0.0.1 | UDP | Hysteria 2 | Hysteria 2监听端口 |
8443 | 127.0.0.1 | HTTP | Nginx | 反代 WEB 服务 |
配置 Nginx
懒得解释了,自行问 ChatGPT 吧 :D
worker_processes auto;
error_log logs/error.log notice;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
stream {
map $ssl_preread_server_name $backend_name {
example.com reality_backend;
default web_backend;
}
upstream reality_backend {
server 127.0.0.1:1443;
}
upstream web_backend {
server 127.0.0.1:8443;
}
upstream hysteria_backend {
server 127.0.0.1:2443;
}
server {
listen 443;
listen [::]:443;
ssl_preread on;
proxy_pass $backend_name;
proxy_protocol on;
}
server {
listen 443 udp reuseport;
listen [::]:443 udp reuseport;
proxy_pass hysteria_backend;
proxy_timeout 20s;
}
}
http {
server_tokens off;
include mime.types;
default_type application/octet-stream;
map $http_x_forwarded_for $clientRealIp {
"" $remote_addr;
"~*(?P<firstAddr>([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$" $firstAddr;
}
log_format main '$clientRealIp $remote_addr $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for '
'"$upstream_addr" "$upstream_status" "$upstream_response_time" "$request_time" ';
access_log logs/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
server {
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
server {
listen 127.0.0.1:8443 quic reuseport;
listen 127.0.0.1:8443 ssl proxy_protocol reuseport;
http2 on;
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
ssl_certificate /usr/local/nginx/certs/example.com/fullchain.cer;
ssl_certificate_key /usr/local/nginx/certs/example.com/cert.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305;
ssl_ecdh_curve secp521r1:secp384r1:secp256r1:x25519;
# 替换为自己 XHTTP 的路径,一般为随机字符串,对应下文中 X-ray 的配置
location /<replace-this> {
grpc_pass grpc://127.0.0.1:2024;
grpc_set_header Host $host;
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Alt-Svc 'h3=":443"; ma=86400';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
配置 X-ray
与上一篇文章一样,将配置文件中的所有 <replace-this>
替换为自己的配置,不同之处在于这次 reality 回落域名使用的是自己的域名,俗称“自己偷自己”。
{
"log": {
"loglevel": "warning",
"error": "/var/log/xray/error.log",
"access": "/var/log/xray/access.log"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"protocol": [
"bittorrent"
],
"outboundTag": "block"
},
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "block"
},
{
"type": "field",
"ip": [
"geoip:cn"
],
"outboundTag": "block"
},
{
"type": "field",
"domain": [
"geosite:category-ads-all"
],
"outboundTag": "block"
}
]
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 1443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "<replace-this>", // 可以使用 xray uuid 生成,注意保存
"flow": "xtls-rprx-vision"
}
],
"decryption": "none",
"fallbacks": [
{
"dest": 2024
}
]
},
"streamSettings": {
"network": "raw",
"security": "reality",
"realitySettings": {
"target": 8443,
"xver": 1,
"serverNames": [
"<replace-this>" // 设置客户端可用的 server name 列表,设置为你自己域名 example.com
],
"privateKey": "<replace-this>", // 可以使用 xray x25519 生成
"shortIds": [
""
]
},
"rawSettings": {
"acceptProxyProtocol": true
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
},
{
"listen": "127.0.0.1",
"port": 2024,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "<replace-this>", // 可以使用 xray uuid 生成,注意保存
}
],
"decryption": "none"
},
"streamSettings": {
"network": "xhttp",
"xhttpSettings": {
"path": "<replace-this>", // 随便输入一个路径,随机字符串即可,注意替换 Nginx 中的反代配置
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
]
}
配置 Hysteria 2
证书复用前文中使用 acme 申请到的证书,并将 Hysteria 2 的伪装(masquerade)设置为自己的网站 https://example.com/
,端口跳跃自行查阅官方文档开启。
这里多说一句,Hysteria 2 的伪装原理就是将自己伪装为成标准的 HTTP/3 流量,认证成功流量会通过 Hysteria 2,认证失败就会走伪装的网站。
listen: 127.0.0.1:2443
tls:
cert: /usr/local/nginx/certs/example.com/fullchain.cer
key: /usr/local/nginx/certs/example.com/cert.key
auth:
type: password
password: "<replace-this>", # 密码,可以使用 xray uuid 生成,注意保存
masquerade:
type: proxy
proxy:
url: https://example.com/
rewriteHost: true
配置成功后你会发现当启动 hysteria-server
后使用浏览器访问你的网站 https://example.com/
会显示协议为 h3,关闭 hysteria-server
后再访问网站协议就会变为 h2。
重启所有服务
完成配置后重启所有服务,并检查服务状态和日志是否正常。
systemctl restart nginx
systemctl restart hysteria-server
systemctl restart xray
以上,祝你成功。