暑假回中国了,虽然手机卡有漫游可以回去,但毕竟有流量限制,于是自然而然的需要一个梯子来方便回去。以前有在用 Trojan,不过好像最近 V2Ray 比较流行所以也来配一个玩玩好了。
在阅读本文之前,建议先阅读官方白话文指南以了解 V2Ray 的基本配置方法(或许阅读后你会发现没有必要看本文了(笑))。
那么我们就开始吧w
1. 事前准备
在配置 V2Ray 前,我想你需要先准备以下内容和知识
- 一台境外的 Linux 服务器
- 基本的服务器操作知识和相关软件
- 一个域名(如果你需要使用 TLS 的话)
2. V2Ray 的基本配置
让我们先配置一个最基本的 VMess 来熟悉一下 V2Ray 的配置方法。
到这里可能会有小伙伴有疑问了:说好的 V2Ray 怎么又变成 VMess 了呢?
你看这就是不读官方文档的坏处(敲打),人家文档上都已经写了:“VMess 协议是由 V2Ray 原创并使用于 V2Ray 的加密传输协议,如同 Shadowsocks 一样为了对抗墙的深度包检测 (opens new window)而研发的。在 V2Ray 上客户端与服务器的通信主要是通过 VMess 协议通信。”
那么就让我们来安装 V2Ray 并配置一个基本的 VMess 吧w
注意:VMess 协议的认证基于时间,一定要保证服务器和客户端的系统时间相差要在 90 秒以内。
# 安装一些需要的包
sudo apt install curl unzip vim
# 先提权
sudo -i
# 我们使用 https://github.com/v2fly/fhs-install-v2ray 的脚本进行安装
# 运行安装脚本
bash <(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)
# 安装完成后会询问是否要 remove 掉 curl 和 unzip, 个人觉得没必要
logout
sudo systemctl enable v2ray
安装完成后我们对服务器端的配置文件进行编辑,命令是 vim /usr/local/etc/v2ray/config.json
,修改完成后按 esc 并输入 :wq 保存并退出。如果你不习惯使用 vim 也可以本地编辑后再传上去。另外需注意使用双斜杠进行注释是 JSON5 的功能,别在其他不确定版本的 JSON 中尝试 = =。下面的配置中的 id 字段使用的是 Linux 的 UUID,建议使用此网站生成:Online UUID Generator Tool
{
"inbounds": [
{
"port": 10086, // 服务器监听端口,防火墙记得打开
"protocol": "vmess", // 主传入协议
"settings": {
"clients": [
{
"id": "c36581ab-7992-48c3-b25c-be6f9eec5242", // 用户 ID,客户端与服务器必须相同
"alterId": 0
}
]
}
}
],
"outbounds": [
{
"protocol": "freedom", // 主传出协议, 此处的 freedom 代表数据直接出去
"settings": {}
}
]
}
/usr/local/etc/v2ray/config.json编辑完成后检查一下格式对不对 sudo v2ray test -config /usr/local/etc/v2ray/config.json
,提示 Configuration OK.
代表配置正确,然后重启 v2ray。
sudo systemctl restart v2ray
客户端个人建议使用 Clash,文档可参考 Clash 官方文档。当然 Clash 也有很多(GUI)实现,我自己在用的是 ClashX 的 Pro 版本,Windows 用户可以使用 Clash for Windows,有开源洁癖(开玩笑)的可以使用 Clash.Meta。
Clash 的配置文件使用 YAML 格式,这是一种对缩进敏感的格式,并且字符串不需要包在引号之内,建议在本地编辑器(推荐使用 Visual Studio Code )进行编辑,否则大概率你的缩进会出问题导致无法使用
# 前面的内容省略, 会单独开一篇文章来讲 Clash 的配置
proxies:
# VMess
- name: "My v2ray"
type: vmess
server: your-server-domain/ip
port: 10086
uuid: c36581ab-7992-48c3-b25c-be6f9eec5242
alterId: 0
cipher: auto
# udp: true
# 后面的内容也省略
$HOME/.config/clash/myconfig.yaml如果可以正常连接的话代表配置成功,如果你并不想折腾 WebSocket + TLS + Web 的话到这里就可以了。
进阶教程:配置 WebSocket + TLS + Web
3. 创建服务账户(可选)
由于我们需要用 acme.sh 为 Nginx
生成证书,为了减小对系统的影响和风险,我们可以给 acme
创建一个没有 sudo
权限的账户
# 创建一个 certusers 用户组, 方便我们后面让 Nginx 使用证书文件
sudo groupadd certusers
# 创建 acme 用户并添加至 certusers 用户组
sudo useradd -r -m -G certusers acme
4. 安装依赖
# 安装 acme 所需要的依赖
sudo apt install socat cron openssl
# 启动crontab
sudo systemctl start cron
sudo systemctl enable cron
# 安装Nginx
sudo apt install nginx
5. 配置 Nginx
如果你在此前已经有配置 Nginx 虚拟主机,则需先将已有的虚拟主机文件备份并关闭已有的虚拟主机,后面的章节会讲如何与现有的虚拟主机集成
5.1. 关闭默认虚拟主机
Nginx 的虚拟主机配置文件在 /etc/nginx/sites-available/
文件夹中,如果要开启某一个虚拟主机,则可使用 mv 命令将配置文件移动至 /etc/nginx/sites-enabled/
文件夹并重启 Nginx 服务即可(当然你也可以使用软连接进行操作,但我觉得直接 mv 过去会更方便一些)。安装 Nginx 后会有一个默认的虚拟主机文件在 /etc/nginx/sites-enabled/
中,直接 rm 掉即可。然后我们创建一个 acme 申请证书用的虚拟主机文件。
# 删除默认虚拟主机文件
sudo rm /etc/nginx/sites-enabled/default
# 创建 acme 申请证书用的虚拟主机文件
#自己的虚拟主机文件, 注意 uuz_moe 改成你自己的域名, 此处的文件名仅用作方便识别
sudo vim /etc/nginx/sites-enabled/acme.conf
5.2. 编写 acme 用的虚拟主机文件
server {
listen 0.0.0.0:80;
listen [::]:80;
server_name _;
# 这个块接收所有 80 端口的流量并重定向到 443 端口
# 这样便开启了全站 https, 可防止恶意探测, 如果你不需要可以删去
location / {
return 301 https://$host$request_uri;
}
# 这个块是为 acme 申请证书准备的
location /.well-known/acme-challenge {
root /var/www/acme-challenge;
}
}
/etc/nginx/sites-enabled/acme.conf5.3. 测试并重启 Nginx
“启动之前测试一下总是好事”
# 启动之前测试一下总是好事, 没有报错就行
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx
# 查询 Nginx 服务的状态
sudo systemctl status nginx
6. 配置证书
使用 acme 从 Let’s Encrypt 获得证书时,Let’s Encrypt 会验证证书中域名的控制权。一般采用 HTTP-01 或 DNS-01 方式来验证,详情可参考官方文档的 challenge-types。本文使用 HTTP-01 方式验证,若需要使用 DNS-01 方式验证,请参考 acme.sh 官方文档的 How to use DNS API。
6.1. 创建证书文件夹
我们前面创建了 acme 用户来方便使用证书,下面就来创建证书文件夹并修改所有者吧。
# 创建证书文件夹
sudo mkdir -p /etc/mycerts
# 修改所有者为 acme, 使 acme 有权限写入文件
# 如果你没有为 acme 创建账户则需将 acme:acme 替换成你自己的用户名和用户组, 例如 uuz:uuz
sudo chown -R acme:acme /etc/mycerts
6.2. 创建 webroot 并修改所有者
本文使用 acme.sh 的 HTTP 方式申请证书,HTTP 方式需要在网站根目录下放置一个文件来验证域名所有权,故需要 acme.sh 和 Nginx 均对 webroot 目录有权限,故将运行 Nginx 的 worker 进程加入 certusers 组,下文再将 webroot 目录附加给 certusers 组即可。
在不同的 Linux 发新版本中,Nginx 可能使用不同的用户运行 worker process
,可能为 www-data
,nginx
,nobody
中的一个,可查看 /etc/nginx/nginx.conf 文件中 user 字段(千夏的是 user www-data;
,因此可知是用 www-data
运行的)或运行下述命令查找 nginx: worker process
所属用户。
# 查找 nginx worker process 的用户
ps -eo user,command|grep nginx
# 以下是千夏这边的返回结果, 在第二行可见 nginx: worker process 为 www-data
root nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data nginx: worker process
# 然后根据查找到的用户执行以下命令, 添加 nginx 用户至 certusers 用户组
# www-data 记得替换成你自己在上面查找到的
# 如果你没有在第三步中创建 certusers 用户组, 则将 certusers 替换成你所在的用户组
sudo usermod -aG certusers www-data
运行下面两条命令,新建文件夹用于存放 acme 的域名验证文件并更改所有者。
# 新建一个文件夹用于给 acme.sh 存放域名验证文件
sudo mkdir -p /var/www/acme-challenge
# 将文件夹所有者改为 acme, 使得用户 acme 有权写入文件并当验证时 Nginx 可以读取该文件
# 如果你没有在第三步中创建用户和用户组, 则将 acme:certusers 改成你自己的用户名和组
sudo chown -R acme:certusers /var/www/acme-challenge
6.3. 安装 acme.sh 并申请证书
下面我们来安装 acme.sh 并申请证书。
# 切换至用户 acme
# 如果你没有在第三步中创建账户则直接从第 4 行开始看
sudo su -l -s /bin/bash acme
# 安装 acme.sh, acme.sh 会安装到 ~/.acme.sh 目录下
curl https://get.acme.sh | sh
# 安装成功后执行以下命令以确保脚本所设置的命令别名生效
source ~/.bashrc
如果以上命令没有报错的话则恭喜你已经安装好 acme.sh 了,那么我们就来申请证书吧。
申请证书前需先确保有正确配置 Nginx 并配置好相关权限以使 acme 可以写入切 Nginx 可以读取相关文件。
# 先把默认 CA 修改为 letsencrypt
acme.sh --set-default-ca --server letsencrypt
# 使用以下命令申请证书, 注意替换 uuz.moe 为你自己要申请的域名
# --keylength 表示密钥长度, 带 ec 代表生成的是 ECC (ECDHE) 证书, 没有则是 RSA 证书
~/.acme.sh/acme.sh --issue -d uuz.moe -w /var/www/acme-challenge --keylength ec-256
# 以下输出则表示正确生成了证书
[Wed Aug 30 10:30:29 UTC 2023] Your cert is in /home/acme/.acme.sh/uuz.moe_ecc/uuz.moe.cer
[Wed Aug 30 10:30:29 UTC 2023] Your cert key is in /home/acme/.acme.sh/uuz.moe_ecc/uuz.moe.key
[Wed Aug 30 10:30:29 UTC 2023] The intermediate CA cert is in /home/acme/.acme.sh/uuz.moe_ecc/ca.cer
[Wed Aug 30 10:30:29 UTC 2023] And the full chain certs is there: /home/acme/.acme.sh/uuz.moe_ecc/fullchain.cer
# 如果申请失败则请检查 1.域名解析是否生效 2.文件夹权限是否有误 3.加上 --debug 和 --staging 再次执行看看问题在哪里
如果已经成功申请了证书,则可使用以下命令安装证书
# 将证书文件安装到 /etc/mycerts/ 文件夹, 注意文件名改成你自己的域名
~/.acme.sh/acme.sh --installcert -d uuz.moe --ecc \
--fullchain-file /etc/mycerts/uuz.moe.crt \
--key-file /etc/mycerts/uuz.moe.key
# 更新并设置自动更新
acme.sh --upgrade --auto-upgrade
# 由于 Let's Encrypt 的证书有效期只有 3 个月,因此需要 90 天至少要更新一次证书, acme.sh 脚本会每 60 天自动更新证书。也可以手动更新。
# 手动强制更新证书
~/.acme.sh/acme.sh --renew -d uuz.moe --force --ecc
安装完成后还需要修改一下权限
# 将证书文件夹所在用户组改为 certusers
chown -R acme:certusers /etc/mycerts
# 赋予证书文件夹组内用户读取权限, 这样 Nginx 就有权限读取证书了
chmod -R 750 /etc/mycerts
# 安装完成, 退出 acme 用户
exit
当 acme.sh 重新安装证书之后,Nginx 需要重新加载证书才行,执行 sudo crontab -u root -e
编辑 root 用户的 crontab 文件并加入以下内容保存
# 每月 1 日 4:00 重载 Nginx
00 04 01 * * systemctl reload nginx
crontab至于为何选用 ECC 证书?因为在安全性上 256 位的 ECC 证书等同于 3072 位的 RSA 证书, 且 256 位的 ECC 证书比 2048 位的 RSA 证书至少快 20 倍以上, 具体可以参考以下两篇文章:
短い暗号鍵長「ECC」でパフォーマンスとセキュリティの両立図るベリサイン — ITmedia
A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography — The Cloudflare Blog
# 以下为 rsa 和 ecdsa 的对比, 供参考
# MacBook Pro 13-inch, 2020, 2 GHz クアッドコアIntel Core i5 with 16 GB 3733 MHz LPDDR4X
# openssl speed rsa
Doing 2048 bits private rsa's for 10s: 14311 2048 bits private RSA's in 9.72s
# openssl speed ecdsa
Doing 256 bits sign ecdsa's for 10s: 384133 256 bits ECDSA signs in 9.71s
7. 服务器 V2Ray 配置
编辑 V2Ray 配置文件
sudo vim /usr/local/etc/v2ray/config.json
"listen":"127.0.0.1"
只监听 127.0.0.1,避免除本机外的机器探测到开放了 10080 端口
"id":
记得换成你自己生成的,切勿使用示例中的 id
"network": "ws"
表示使用 WebSocket
"path": "/v2ray"
表示路径为 /v2ray,建议换成只有你知道的
{
"inbounds": [
{
"port": 10080,
"listen":"127.0.0.1",
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "faf171ee-d211-4e25-a645-6ac087e48bfb",
"alterId": 0
}
]
},
"streamSettings": {
"network": "ws",
"wsSettings": {
"path": "/v2ray"
}
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {}
}
]
}
/usr/local/etc/v2ray/config.json8. 配置 Nginx 证书和反代
新建一个 Nginx 虚拟主机 sudo vim /etc/nginx/sites-enabled/uuz_moe.conf
,然后按照注释修改
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name uuz.moe; # 改成你自己的域名
# ssl 设置
ssl_certificate /etc/mycerts/uuz.moe.crt; #你自己的证书路径
ssl_certificate_key /etc/mycerts/uuz.moe.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
location /v2ray { # 与 V2Ray 配置中的 path 保持一致
if ($http_upgrade != "websocket") { # WebSocket协商失败时返回404
return 404;
}
proxy_redirect off;
proxy_pass http://127.0.0.1:10080; # 假设 V2Ray 的 WebSocket 监听在环回地址的10080端口上
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
# Show real IP in v2ray access.log if log on
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
/etc/nginx/sites-enabled/uuz_moe.conf9. Clash 配置
- name: uuz-ws
type: vmess
server: uuz.moe
port: 443
uuid: faf171ee-d211-4e25-a645-6ac087e48bfb
alterId: 0
cipher: auto
udp: true
tls: true
servername: uuz.moe
network: ws
ws-opts:
headers:
Host: uuz.moe
path: /v2ray
$HOME/.config/clash/myconfig.yaml10. 注意事项
以下内容摘自 新 V2Ray 白话文指南
- V2Ray 自 4.18.1 后支持 TLS1.3,如果开启并强制 TLS1.3 请注意 v2ray 客户端版本.
- 较低版本的 nginx 的 location 需要写为 /ray/ 才能正常工作
- 请保持服务器和客户端的 wsSettings (path) 严格一致,对于 V2Ray,
/ray
和/ray/
是不一样的 - 较低版本的系统/浏览器可能无法完成握手. 如 Chrome 49/XP SP3, Safari 8/iOS 8.4, Safari 8/OS X 10.10 及更低的版本. 如果你的设备比较旧, 则可以通过在配置中添加较旧的 TLS 协议以完成握手
- 如果在设置完成之后不能成功使用,可能是由于 SElinux 机制(如果你是 CentOS 7 的用户请特别留意 SElinux 这一机制)阻止了 Nginx 转发向内网的数据。如果是这样的话,在 V2Ray 的日志里不会有访问信息,在 Nginx 的日志里会出现大量的 “Permission Denied” 字段,要解决这一问题需要在终端下键入以下命令:
setsebool -P httpd_can_network_connect 1