免责声明:本文及所提供资源仅用于技术探讨或学习,严禁用于非法用途!
本文适用于熟悉Linux基本操作,熟悉Nginx建站、熟悉docker操作或爱折腾的老哥!
关联文章:
【富强系列-一键脚本】nginx + websocket + tls一键脚本
【富强系列-面板】nginx + websocket + tls + cname 控制面板
原理与架构
原理为nginx + websocket + tls,在此基础之上新增加CNAME域名用于平衡/切换服务器流量(负载均衡),玩法更加灵活。一图胜千言:
- CNAME域名:别名域名,指向最终服务器的域名
- A域名:IPV4域名,指向服务器IPV4,A域名指向谁就是谁在提供服务
- path:path指的是A域名后面的访问路径,如https://taobao.xyz/123,则path为123
- 正常path:访问站点的正常路径,包括根路径如访问https://taobao.xyz或者https://taobao.xyz/login跳转到正常页面,即伪站定义的页面,别的不存在的path即为404 NOT FOUND
- 代理path:可自定义复杂字符串,如用代理工具访问https://taobao.xyz/QtKmDvemB^%0sddU则转发给代理工具
- 下图流量来回全程走https,没人知道你的path以及流量内容是什么。
- 该架构适用于多服务器/多用户
...(A域名集群)
---->> A域名3
---->> A域名2 -->> 其他path -->> 404/403(自定义)
| |
| |
你的流量 -->> CNAME域名 -->> -->> 正常path -->> 网站(伪站)
| |
| |
---->> A域名1 -->> Nginx -->>
|
| 代理path1 (rewrite)
-->>代理path2 --------->> 代理根path -->> 代理工具 --->> 和谐站点
代理path3 (rewrite)
....
既然玩这么复杂,那必定有它的好处:
- 有一天服务器1挂了/没流量了/老板跑路等等,此时将CNAME域名指向服务器2(A域名2)即可无疼切换!客户端并不需要改任何配置!(此处有个注意事项:要实现此操作必须CNAME域名在服务器1和服务器2上同时有该CNAME域名的tls证书文件!)
- 有一天有个哥们儿想和你一起用,但是你并不想把代理根path暴露给他,此时你只需要添加一条代理path重写到代理根path即可,该哥们儿可以愉快的用该代理path而不是dialing根path上网,如果哪天你和他闹矛盾,删除该代理path即可,不影响代理根path,简而言之,实现多用户的管理!
nginx + websocket + tls实现思路
该架构适用于单服务器/单用户
这部分可简化为下图(考虑最简单情况,一个主机一个域名):
-->> 其他path -->> 404/403(自定义)
|
|
你的流量 -->> A域名 -->> Nginx -->> -->> 正常path -->> 网站(伪站)
|
| 代理path1 (rewrite)
-->>代理path2 --------->> 代理根path -->> 代理工具 --->> 和谐站点
代理path3 (rewrite)
....
iptables关闭服务器所有端口(ssh端口除外),Nginx绑定在80和443端口以模拟真实站点,下面重点来了:
假设条件:
- 域名为domain.com,且已经获得HTTPS证书
- 代理根路径为(切记设置成复杂字符串,uuid那种也可以):dailiPath
Nginx配置文件如下:(这只是样例,说明原理,切勿简单套用)
server {
server_name domain.com;
# 正常path,伪站设定
location / {
root /usr/share/nginx/html; # 伪站放置位置
index index.html index.htm;
}
# 代理根path设定
location /dailiPath {
proxy_redirect off;
# proxy_pass http://代理工具IP:代理工具端口;
proxy_pass http://127.0.0.1:51234;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # 此段必须要,让https请求升级为websocket
proxy_set_header Connection "upgrade"; # 此段必须要,让https请求升级为websocket
proxy_set_header Host $http_host;
}
# 监听443
listen 443 ssl;
ssl_certificate /你的证书路径/fullchain.pem;
ssl_certificate_key /你的证书路径/privkey.pem;
ssl_dhparam /你的证书路径/ssl-dhparams.pem;
}
# 80 端口跳转443
server {
if ($host = domain.com) {
return 301 https://$host$request_uri;
}
listen 80;
server_name domain.com;
return 404; # 其他访问跳转404/403 随你定义
}
细心的你已经看出来了,上面只是配置了代理根路径的反向代理设置而已,那谁来接收这些流量呢?当然是代理工具,此处用酸酸+v兔锐插件实现,酸酸配置文件如下
{
"server":["::1", "127.0.0.1"], # 酸酸IP,即为上面Nginx配置中的代理工具IP
"mode":"tcp_and_udp",
"server_port":51234, # 酸酸监听端口,即为上面Nginx配置中的代理工具端口
"local_port":1080,
"password":"pwd", # 密码
"timeout":60,
"method":"chacha20-ietf-poly1305", # 加密方式
"plugin":"v2ray-plugin", # 加载v2ray插件
"plugin_opts":"server;path=/dailiPath;loglevel=none" # v2ray插件配置,注意path要和上面的代理根path一致
}
此处就已经实现了ws + tls流量传递给代理工具的服务端设置
添加代理path,避免暴露代理根path
如果新加代理path呢?注意代理根path是不需要暴露出去的,添加代理path实现思路是将要添加的代理path重写到代理根path,Nginx配置如下:
server {
...
# 代理path添加
location /your-new-proxy-path$ {
rewrite /your-new-proxy-path$ /dailiPath;
}
...
}
重加载下配置文件nginx -s reload
,此时访问your-new-proxy-path和访问dailiPath效果相同,你甚至可以这样玩:
server {
...
# 包含该文件夹下面所有.path结尾的文件
include /etc/nginx/proxy_conf/*.path;
...
}
这样添加路径
cat > /etc/nginx/proxy_conf/your-new-proxy-path.path <<EOF
rewrite /your-new-proxy-path$ /dailiPath;
EOF
添加完成后重新加载配置文件nginx -s reload
就可以,这样的好处是可以用脚本很方便的添加路径!
CNAME负载均衡实现思路
此部分主要实现原理中的CNAME域名用于平衡/切换服务器流量(负载均衡)的部分。
此部分实现相对简单,主要是在域名控制台进行操作,假设你的域名为domain.com,你可以这样规划:
---->> A域名:1.domain.com(服务器1)
|
|
你的流量 ----->> CNAME域名:service.domain.com -->>--->> A域名:2.domain.com(服务器2)
|
|
---->> A域名:3.domain.com(服务器3)
需要注意的是CNAME域名在每个服务器上都要有HTTPS证书,这样才能实现切换,否则网络连不通,也就是说service.domain.com
这个域名需要在服务器1、服务器2、服务器3上都有HTTPS证书且Nginx已经配置好,服务器1配置1.domain.com
的HTTPS证书就可以,以此类推,服务器2有2.domain.com
的证书,服务器3有3.domain.com
的证书。
这样比如说1.domain.com
这台机器没有流量了,service.domain.com
切换到2.domain.com
,那么service.domain.com
就可以继续使用,客户端无需配置任何东西,只需要在域名控制台更改CNAME指向就可以。
当然在实际使用中一般一个CNAME域名对应一个A域名,所有CNAME域名全部提供出去,这样更加灵活配置,相当于将客户端配置与服务器解耦。
如果是用cloudflare之类可以进行代理的CDN,甚至可以用他们提供的代理隐藏IP,这样相当于你的流量-->>CNAME域名-->>cloudflare-->>A域名(服务器)-->>代理工具-->>和谐站点
,这样多了一层,虽然更加安全,但是速度相对较慢,救急也许可以考虑一下,更多玩法请按参考具体环境。
实现
上面说的都是原理架构以及配置样例,能说这么多那肯定是已经实现这套流程了,否则就是光说不练假把式唬人而已,所涉及操作这边全部封装成了docker镜像/一键脚本(其中还包括添加用户,删除用户,流量统计,限速等功能,甚至还包含了一个控制面板,这些后面专门开文章说),从0到1简化步骤如下:
- 需要至少一台服务器(这不废话么),KVM(支持docker)虚拟化的VPS(有独立公网ip,有80/443端口),假设系统为CentOS7,其他系统不保证能成功!
- 需要至少一个域名(这不废话么)
- 域名控制台添加A记录指向服务器ip,假设为a.domain.com
- ssh到服务器执行:(根据提示输入即可,提示中的请输入v兔瑞路径即为代理根路径,不输入则随机生成!这个记着后面有用)
bash <(curl https://raw.githubusercontent.com/scriptwang/SSoverTLS/master/sh/SSoverTLS_Adv.sh) -i
上面四个步骤已经实现了nginx + websocket + tls,打开对应平台客户端导入即可:
- 安卓:小飞机加v兔瑞插件
- PC:小飞机加v兔瑞插件(将v兔瑞-plugin.exe下载改名为v兔瑞.exe放到酸酸文件夹里,谐音请自动转换)
- IOS:版本在2.1.37及以上的小火箭(收费版本此处不予分享)
- MAC:小飞机加v兔瑞插件(有人编译了插件,有需要自行谷歌吧)
下面是实现CNAME负载均衡
- 在域名控制台添加A记录将service.domain.com指向服务器
- ssh到服务器执行:(1:域名填写service.domain.com 2:路径填写代理根路径,写错了不生效!)
bash <(curl https://raw.githubusercontent.com/scriptwang/SSoverTLS/master/sh/AddDomain.sh)
- 到域名控制台删除A记录service.domain.com,添加CNAME记录service.domain.com指向a.domain.com
此时,你就可以通过service.domain.com来上网了,如果你还有b.domain.com,到域名控制台将service.domain.com切换到b.domain.com即可无痛切换服务器。