xray 与 nginx 多网站共存(443端口复用方案)
443 端口只能一个程序进行监听,所以方案有两个,一个是用 nginx 的负载均衡分流给 xray ,另一个是使用 xray 的回落功能分流给 nginx
当然把其中一个修改为非 443 端口也行,但这样既不专业也不安全。加点难度(笑
本篇文章使用的方案是利用 xray 的回落,分流给 nginx
注:我的 nginx 环境是宝塔面板自带的
1. 加回落
首先,把正常的网站也加到回落的配置中,记得加上 name
假设我们有一个伪装站,两个正常网站,以下是操作
原版:
json
"fallbacks": [
{
"dest": 8080 // 默认回落到防探测的代理
}
]
改之后:
json
"fallbacks": [
{
"name": "这里是伪装站的域名", // 回落域名,不填表示任意域名
"dest": 8080 // 默认回落到防探测的代理
},
{
"name": "正常站定域名1",
"xver": 1, // 用于传递请求的真实来源 IP 和端口, 1 为开启
"dest": 回落端口1
},
{
"name": "正常站定域名2",
"xver": 1, // 用于传递请求的真实来源 IP 和端口, 1 为开启
"dest": 回落端口2
}
]
2. 配置SSL证书
接下来是配置正常站点的域名证书
申请证书教程:
shell
# 测试能不能申请(网络问题、路径问题等)
acme.sh --issue --server letsencrypt --test -d 域名 -w /网站文件的根路径 --keylength ec-256
# 设置设置默认的 CA 为 Let's Encrypt
acme.sh --set-default-ca --server letsencrypt
# 申请(有多少个域名,就加多少个-d,会变成多域名证书)
acme.sh --issue -d 域名 -d www.域名 -w /网站文件的根路径 --keylength ec-256 --force
# 安装(每次手动运行会刷新参数,之后acme.sh会在域名快过期时自动运行同样的命令)
# 安装时以申请证书的第一个域名作为参数即可(也可以全写上)
acme.sh --install-cert -d 域名 \
--key-file /root/xray_cert/域名/privkey.key \
--fullchain-file /root/xray_cert/域名/fullchain.crt --ecc \
--reloadcmd "systemctl restart xray"
# 如果方案为nginx分流,重启nginx为下面这个命令,使用force-reload才能刷新证书
# --reloadcmd "service nginx force-reload"
之后把正常站点域名证书路径加到 certificates 列表中
json
"certificates": [
{
"certificateFile": "/root/xray_cert/xray.crt",
"keyFile": "/root/xray_cert/xray.key"
},
// 下面这个是正常域名证书
{
"certificateFile": "/root/xray_cert/域名/fullchain.crt",
"keyFile": "/root/xray_cert/域名/privkey.key"
}
]
3. 配置Nginx
为了使正常网站能获取到用户请求的真实 ip,得给 nginx 加配置
修改 nginx 的 default.conf, 宝塔面板的 nginx 配置文件位置为/www/server/panel/vhost/nginx/0.default.conf
:
注:一般正常安装的 nginx 配置文件位置为/etc/nginx/conf.d/default.conf
shell
vim /www/server/panel/vhost/nginx/0.default.conf
在文件顶上加上以下两行
nginx
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
最后给对应的网站在 nginx 中配置对应的端口监听,并且添加 proxy_protocol
例如,配置的正常网站的回落端口为回落端口1
,则在对应网站的配置文件的 server 块中添加下面这行即可
nginx
listen 回落端口1 proxy_protocol;
注:由于 nginx 配置中 http1 和 http2 协议的端口不能为同一个,所以 xray 配置中如果有 h2 协议,则 xray 回落端口的 http/1.1 和 h2 得分开写,同样的,nginx 也得添加监听 http2 的端口。
nginx
# xray中为:
{
"name": "域名1",
"xver": 1, // 用于传递请求的真实来源 IP 和端口, 1 为开启
"alpn": "h2",
"dest": 回落端口1
},
{
"name": "域名1",
"xver": 1, // 用于传递请求的真实来源 IP 和端口, 1 为开启
"alpn": "http/1.1",
"dest": 回落端口2
}
# 此时,nginx也得添加 http2 协议的端口
listen 回落端口2 http2 proxy_protocol;
4. 重启服务
之后重启 xray 和 nginx 即可
bash
# 重启
systemctl restart xray
# 查看状态
systemctl status xray
重启并查看 nginx 状态
bash
# 重启
service nginx restart
# 查看状态
service nginx status
参考链接
SNI 回落 | Project X (xtls.github.io)
Xray 与多个 HTTPS 站点(Nginx)共存,两种 443 端口复用方案 - revery.cc
Xray 与现有网站共存-宝塔篇 - 折腾的 2HA (oooutman.github.io)
Xray(https)回落到 nginx(http)报 400 的问题 · 议题 #308 · XTLS/Xray-core · GitHub
共用 443 端口方案 | 程小白 (chengxiaobai.com)
由于URL中带有一些屏蔽词汇例如 v2r*y等,在CSDN等平台无法发布,所以使用的URL编码的方式。既能保证链接可以正确解析,又可以规避这种欲加之罪。
以下是JavaScript代码(用JS是因为有浏览器控制台就能用)
javascript
function toHex(str) {
return str.split('').map(function(char) {
return '%' + char.charCodeAt(0).toString(16).toUpperCase();
}).join('');
}
let keyword = ""; // 替换为你的关键词
let encodedKeyword = toHex(keyword);
console.log(encodedKeyword);
其他记录
推荐:http 跳转 https 端口的方案很多,一个是在 server 块的 server_name 下面添加:
nginx
if ($server_port = 80) { return 301 https://$http_host$request_uri; }
此时 nginx 只需要监听该域名的 80 和回落的端口即可
另一个方案是网站本身只监听回落端口,然后加上另一个 server 块即可:
nginx
server {
listen 80;
server_name 域名;
return 301 https://$http_host$request_uri;
}
原理类似
还有一个比较省心的办法,如果当前服务器下的所有网站都希望是 https,则可以在监听 80 端口的 server 块上添加重定向代码:
这个方法没试过,估计会有点问题,这里只是提出一个设想
这里的server_name _
是一个通配符,表示匹配所有未被其他 server_name 指令明确匹配到的请求
nginx
server {
listen 80;
server_name _;
return 301 https://$http_host$request_uri;
}