V2Ray+WebSocket+TSL+Nginx+CDN配置与学习
最近发现最近SSR越来越慢,而且我的博客有时打得开有时打不开,用端口测试工具之后发现,是GFW会间隔性的封杀我的服务器IP,原来的VPS在日本,然后开始了漫长的更换尝试。。。发现Vutrl的大部分45段和108段的IP基本都不能用了。最后换到了荷兰阿姆斯特丹可以用,然后开始着手准备换成新的工具。
V2Ray
V2Ray是Project V的核心工具,Project V 是一个工具集合,它可以帮助你打造专属的基础通信网络。V2Ray主要负责网络功能其网络协议和功能的实现。具体的可以去看它的官网,介绍的很详细,而且还有开发手册,让你知道它的整个设计以及架构。
V2Ray安装
V2Ray的安装方法官网介绍的很详细,Linux操作系统用官方的安装脚本即可顺利安装,不过目前自动运行脚本只支持带有 Systemd 的系统,以及 Debian / Ubuntu 全系列。而我的VPS系统是Centos6.9,所以无法顺利的用这个安装脚本。但是Google了一下解决办法也很简单。
# 执行安装脚本
curl -L -s https://install.direct/go.sh如果你也是像我一样是不支持Systemmd的系统,执行完会报错,直接无视就好了(更高级的版本应该可以直接安装完成)。然后我们需要在/etc/init.d目录下建立一个V2Ray的脚本,这样就可以用Service启动和关闭了。Centos7之后支持强大的Systemctl所以服务脚本放在不一样的目录下,所以安装脚本不支持没有Systemmd的系统。
现在先在/etc/init.d建立一个v2ray脚本(非centos6.x系统可以跳过这一步)
vim /etc/init.d/v2ray
#把以下脚本代码复制进去
#!/bin/sh
#
# v2ray Startup script for v2ray
#
# chkconfig: - 24 76
# processname: v2ray
# pidfile: /var/run/v2ray.pid
# description: V2Ray proxy services
#
### BEGIN INIT INFO
# Provides: v2ray
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: V2Ray proxy services
# Description: V2Ray proxy services
### END INIT INFO
DESC=v2ray
NAME=v2ray
DAEMON=/usr/bin/v2ray/v2ray
PIDFILE=/var/run/$NAME.pid
LOCKFILE=/var/lock/subsys/$NAME
SCRIPTNAME=/etc/init.d/$NAME
RETVAL=0
DAEMON_OPTS="-config /etc/v2ray/config.json"
# Exit if the package is not installed
[ -x $DAEMON ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Source function library.
. /etc/rc.d/init.d/functions
start() {
local pids=$(pgrep -f $DAEMON)
if [ -n "$pids" ]; then
echo "$NAME (pid $pids) is already running"
RETVAL=0
return 0
fi
echo -n $"Starting $NAME: "
mkdir -p /var/log/v2ray
$DAEMON $DAEMON_OPTS 1>/dev/null 2>&1 &
echo $! > $PIDFILE
sleep 2
pgrep -f $DAEMON >/dev/null 2>&1
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
success; echo
touch $LOCKFILE
else
failure; echo
fi
return $RETVAL
}
stop() {
local pids=$(pgrep -f $DAEMON)
if [ -z "$pids" ]; then
echo "$NAME is not running"
RETVAL=0
return 0
fi
echo -n $"Stopping $NAME: "
killproc -p ${PIDFILE} ${NAME}
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PIDFILE}
}
reload() {
echo -n $"Reloading $NAME: "
killproc -p ${PIDFILE} ${NAME} -HUP
RETVAL=$?
echo
}
rh_status() {
status -p ${PIDFILE} ${DAEMON}
}
# See how we were called.
case "$1" in
start)
rh_status >/dev/null 2>&1 && exit 0
start
;;
stop)
stop
;;
status)
rh_status
RETVAL=$?
;;
restart)
stop
start
;;
reload)
reload
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|reload|restart}" >&2
RETVAL=2
;;
esac
exit $RETVAL然后再执行
chmod a+x /etc/init.d/v2ray
chkconfig v2ray on
service v2ray start现在v2ray服务就启动了。
V2Ray配置
接着我们要开始在服务器上配置v2ray,v2ray的配置脚本在/etc/v2ray/config.json,配置脚本的每个字段的含义在官方文档里都有说明。
出站和入站协议
先看一下v2ray的架构(图片来自官方)
v2ray并没有分为客户端和服务端,每一个v2ray程序可以配置多个inbound和outbound,然后我们可以选择不同的Transport protocol作为载体将数据发送出去。而我们需要做的就是将服务器的inbound和客户端的outbound配置成能够互相收发数据。
v2ray支持多种inbound和outbound协议:例如Socks,HTTP,Shadowsocks,Vmess,所以如果之前VPS有跑SSR的话可以给服务器的inbound配置一个SSR就能够继续用SSR了。
HTTP,Socks大部分都很熟悉了,重点是这个Vmess,这个是v2ray的原创的一种加密传输协议。这一次我们要配置的是就是vmess+websocket+tls+cdn,先贴上我的服务器端的配置。
{
"inbounds": [
{
"port": 10000,
"listen": "127.0.0.1",
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "a2851a86-0352-49f7-9a82-bbb2a5fb407e",
"alterId": 64
}
]
},
"streamSettings": {
"network": "ws",
"wsSettings":{
"path": "/flutter"
}
}
}
],
"outbounds": [{
"protocol": "freedom",
"settings": {}
},{
"protocol": "blackhole",
"settings": {},
"tag": "blocked"
}],
"routing": {
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "blocked"
}
]
}
}id是UUID,它是一个 16 字节长的随机数,它的作用相当于一个令牌(Token)。 一个 ID 形如:a2851a86-0352-49f7-9a82-bbb2a5fb407e,几乎完全随机,可以使用任何的 UUID 生成器来生成,比如这个。这是作为客服端和服务器端认证连接的一个标志,所以客服端outbound和服务器端inbound需要配置成相同的id。配置中还有一个 alterId 参数,这个参数主要是为了加强防探测能力。理论上 alterId 越大越好,但越大就约占内存(只针对服务器,客户端不占内存),所以折中之下设一个中间值才是最好的,alterId 的大小要保证客户端的小于等于服务器的。
还有一点需要注意的是Vmess协议会检测两端的时间,时间差在90秒之内才能够通过校验,所以我们需要确保服务器的时间和客服端的时候同步。
底层传输的配置
当我们的inbound的配置Vmess协议之后,我们还需要配置底层的传输方式(协议),客户端的outbound和服务端的inbound需要使用相同的传输方式。可以选择TCP、mKCP、WebSocket等。我主要试过的是mKCP,和Websocket。
mKCP是v2ray的开发人员根据KCP协议改进的,KCPGitHub地址。KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。学过计算机网络的都知道,TCP/IP协议族里常用的传输协议是TCP和UDP,两者最大的区别就是一个是可靠的传输协议,一个是不可靠。因为TCP是需要两端经过三次握手建立起连接的,依靠可靠的自动选择重传算法,保证接受的一方能够有序的收到数据。而KCP只是作为一个快速的可靠重传协议,它主要是对选择重传做了优化。例如TCP丢包时会全部重传从丢的那个包开始以后的数据,KCP是选择性重传,只重传真正丢失的数据包。所以KCP提供了向上和向下的接口,向上我们可以把上层的协议装进KCP的数据部,向下我们可以选择UDP作为载体传输数据,这样即使是不可靠的UDP也能保证接受的一方能够有序的接受到数据,因为KCP会对每一个分片的数据包进行编号,就像TCP一样。
说了这么多,要配置底层的传输既可以全局配置就是每一个bound统一或者为单独的一个bound进行配置,在单独的bound里面有一个streamSettings就是单独的底层传输配置。
"streamSettings": {
"network": "mkcp",
"kcpSettings": {
"uplinkCapacity": 100,
"downlinkCapacity": 100,
"readBufferSize": 5,
"writeBufferSize": 5,
"congestion": false,
"header": {
"type": "wechat-video"
}
}
}这是一份KCP的配置,里面各个字段的详细解释官网都有,就不展开了。经过我的实测,kcp的延迟确实低很多,而且速度也特别快,但是最终我还是选择了Websocket作为常用的配置。
WebSocket
KCP的流量特征还是比较明显的,也有很多人说开了几个小时后VPS就被封掉了。所以我在VPS上配置的是现在很多人选择的配置V2Ray+WebSocket+TLS+CDN,当然,只要在inbounds配置两个inbound就能同时跑两个协议了,在看视频的时候切换mKCP就好了。所以我的整个配置文件是这样的
{
"inbounds": [
{
"port": 10000,
"listen": "127.0.0.1",
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "你的id",
"alterId": 50
}
]
},
"streamSettings": {
"network": "ws",
"wsSettings":{
"path": "/flutter"
}
}
},
{
"port": 8000,
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "你的id",
"alterId": 50
}
]
},
"streamSettings": {
"network": "mkcp",
"kcpSettings": {
"uplinkCapacity": 100,
"downlinkCapacity": 100,
"readBufferSize": 5,
"writeBufferSize": 5,
"congestion": false,
"header": {
"type": "wechat-video"
}
}
}
}
],
"outbounds": [{
"protocol": "freedom",
"settings": {}
},{
"protocol": "blackhole",
"settings": {},
"tag": "blocked"
}],
"routing": {
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "blocked"
}
]
}
}
配置WebSocket
服务器端的inbound的WebSocke的配置在上面已经贴出来了,当这样配置完成后,我们就可以通过ws://你的ip或者域名:10000这个url访问了。接下来我们需要进行一步的伪装。
一般Web服务的端口是80和443,两者的区别是一个是http一个是https(http+tls),关于这个我之前有写过博客。所以为了伪装访问普通网站的流量,我们可以配置一下tls然后让websocket服务走443端口。
ssl的证书申请可以参考我的这篇博客免费ssl证书申请。
接下来因为v2ray自身就支持tls协议,所以我们即可以使用文件来配置也可以使用web服务器配置tls然后代理WebSocket来实现。因为我的博客网站本身就配置在上面,而且我也配置好了tls,所以选择web服务器来配置会比较快。web服务器使用apache或者nginx都可以,但是我的apache是2.12版本要升级到2.14才支持WebSocket,所以我想了想停掉了apache全部都用nginx跑,接下来又是一顿折腾......
Nginx安装与配置
安装
直接去nginx官网看了一眼在Centos上安装
首先确保安装了yum-utils
sudo yum install yum-utils然后建立yum的库,在/etc/yum.repos.d这个目录建立nginx.repo这个文件
vim etc/yum.repos.d/nginx.repo
#文件内容如下
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true接着执行
sudo yum install nginx配置
接着开始配置,我配置的是完整的多虚拟主机以及支持PHP的nginx服务器
nginx的配置在/etc/nginx/conf.d/这个目录下,只要在这个目录下建立.conf文件就行了,因为在主配置文件里面已经引入了这个目录下所有.conf的文件。整个配置如下:
# /etc/nginx/conf.d/sagezhong.top.conf
#设定虚拟主机配置
server {
#侦听443端口,这个是ssl访问端口
listen 443 ssl;
#定义使用 访问域名
server_name sagezhong.top;
#定义服务器的默认网站根目录位置
root /var/www/html;
#设定本虚拟主机的访问日志
access_log /var/log/nginx/sagezhong.access.log main;
ssl_certificate /etc/ssl/sagezhong.top.crt;
ssl_certificate_key /etc/ssl/sagezhong.top.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #按照这个协议配置
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照这个套件配置
ssl_prefer_server_ciphers on;
#静态文件,nginx自己处理
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
#过期30天,静态文件不怎么更新,过期可以设大一点,
#如果频繁更新,则可以设置得小一点。
expires 30d;
}
location / {
root /var/www/html;
index index.php;
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-f $request_filename){
rewrite (.*) /index.php;
}
if ($request_uri = / ){
rewrite (.*) /index.php;
}
}
location = / {
rewrite (.*) /index.php;
}
location ~ \.php$ {
# 设置监听端口
fastcgi_pass 127.0.0.1:9000;
# 设置nginx的默认首页文件(上面已经设置过了,可以删除)
fastcgi_index index.php;
# 设置脚本文件请求的路径
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 引入fastcgi的配置文件
include fastcgi_params;
}
#禁止访问 .htxxx 文件
location ~ /.ht {
deny all;
}
}
server
{
# 80端口是http正常访问的接口
listen 80;
server_name sagezhong.top;
# 重定向到https
rewrite ^(.*) https://$host$1 permanent;
}
# /etc/nginx/conf.d/files.sagezhong.top.conf
#设定虚拟主机配置
server {
#侦听443端口,这个是ssl访问端口
listen 443 ssl;
#定义使用 访问域名
server_name files.sagezhong.top;
#定义服务器的默认网站根目录位置
root /var/www/html/files;
#设定本虚拟主机的访问日志
access_log /var/log/nginx/files.sagezhong.access.log main;
ssl_certificate /etc/ssl/sagezhong.top.crt;
ssl_certificate_key /etc/ssl/sagezhong.top.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #按照这个协议配置
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照这个套件配置
ssl_prefer_server_ciphers on;
#默认请求
#静态文件,nginx自己处理
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
#过期30天,静态文件不怎么更新,过期可以设大一点,
#如果频繁更新,则可以设置得小一点。
expires 30d;
}
location / {
root /var/www/html/files;
index index.php;
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-f $request_filename){
rewrite (.*) /index.php;
}
if ($request_uri = / ){
rewrite (.*) /index.php;
}
}
location = / {
rewrite (.*) /index.php;
}
location ~ \.php$ {
# 设置监听端口
fastcgi_pass 127.0.0.1:9000;
# 设置nginx的默认首页文件(上面已经设置过了,可以删除)
fastcgi_index index.php;
# 设置脚本文件请求的路径
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 引入fastcgi的配置文件
include fastcgi_params;
}
}
server
{
# 80端口是http正常访问的接口
listen 80;
server_name files.sagezhong.top;
rewrite ^(.*) https://$host$1 permanent;
}就是两个文件对应两个虚拟主机,通过不同的域名指向不同的文件目录。接下来这个配置比较重要,让nginx代理一下v2ray的WebSocket
# /etc/nginx/conf.d/ray.conf
server {
listen 443 ssl;
ssl_certificate /etc/ssl/sagezhong.top.crt;
ssl_certificate_key /etc/ssl/sagezhong.top.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
server_name flutter.sagezhong.top;
location /flutter { # 与 V2Ray 配置中的 path 保持一致
proxy_redirect off;
proxy_pass http://127.0.0.1:10000;#假设WebSocket监听在环回地址的10000端口上
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
# Show realip in v2ray access.log
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
配置到这里我们已经可以通过wss://flutter.sagezhong.top/flutter这个url来代理了,客户端的这样配置即可。
CDN
如果你的VPS的IP已经被封杀,那么可以用CDN绕开GFW,当然关键是你的CDN服务商也没有被封杀。免费的CDN服务商大家推荐的都是CloudFlare。不过它的节点大部分都是美国的,当然也有它现在也跟百度合作有国内的节点了,但是在国内用CDN服务的话首先需要保证的是你的域名已经备案了,因为我一直没有备案,所以就没有考虑用国内的节点了。最后我用的是阿里云的CDN,一般都是香港的节点。CDN的配置挺简单,像阿里云的话开通CDN后你只需要去你的域名服务商那里修改域名解析,将你的域名解析改为CNAME指向阿里云给你提供的域名就行了。
客户端下载
神一样的工具这个链接有所有常见客户端的下载,不过这个网站已经被墙掉了。



多语种文献的引用彰显学术包容性。
哈哈哈,写的太好了https://www.lawjida.com/
文章的确不错啊https://www.cscnn.com/
博主真是太厉害了!!!