2020 年的第一篇博文竟然是讲虚拟砖混结构建筑物逾越技术的,感觉有点微妙。
年终总结啊,在写了在写了,明年就发。
因为嫌麻烦,我这几年基本用的都是现成的代理服务(俗称机场)。这样虽然不用担心自己机器 IP 被墙、速度方面基本有保障、节点也多,不过俗话说不要把鸡蛋放在一个篮子里,自建一个代理服务器备用还是很有必要的。
这几年翻墙技术似乎也发展了不少(是吗?),这次我选择的方法是 V2Ray + WebSocket + TLS + CloudFlare 中转:速度不重要,隐蔽性、抗干扰性第一。这么几层裹上去,除非真的掐网线搞大局域网,不然应该还是能撑个一段时间。
正文开始前先提个醒,本文不是小白教程,就是随手记录一下,所以我会假定你有一定的基础知识与操作经验。
1. 安装 V2Ray
除非你是真的小白零经验,或者「能用就好」主义的忠实信奉者,不然我是不推荐你一上来就直接使用网上那些「一键脚本」的。
就算一键脚本再怎么优秀再怎么便利,至少也应该亲自手动操作一次,了解一下大致的流程。如果我想要做某件事,应该进行哪些操作,脚本会替我完成哪些操作,这些自动化操作是不是符合自己的预期(尤其是脚本是其他人写好的情况下),最起码这些东西得心里有数。
脚本写出来就是帮我们自动完成一些繁琐的操作的,其存在当然有意义,不然每台机器上都手动操作一遍过去,不得累死?用肯定是要用,我所不赞成的只是在不了解这个脚本的情况下瞎用。
线上服务器搭建 LNMP 环境时我也经常用 OneinStack 这样的一键包,很方便。而且它的源码我也都看过,很清楚它能干嘛、会干嘛。也知道它自带的 vhost.sh
虚拟主机管理脚本虽然看起来挺友好,但其修改出来的东西经常惨不忍睹,所以服务器上 Nginx 的配置我从来不用它,都是自己管理的。
总的来说就是可以用傻瓜式脚本,但咱也不能真成傻瓜了,对吧。
好了不说废话,来安装 V2Ray。
安装方法有很多,这里就直接用官方提供的脚本:
bash <(curl -L -s https://install.direct/go.sh)
脚本会自动安装这些东西:
/usr/bin/v2ray/v2ray
V2Ray 程序/usr/bin/v2ray/v2ctl
V2Ray 工具/etc/v2ray/config.json
配置文件/usr/bin/v2ray/geoip.dat
IP 数据文件/usr/bin/v2ray/geosite.dat
域名数据文件/etc/systemd/system/v2ray.service
Systemd Service/etc/init.d/v2ray
SysV 启动脚本
2. 配置 V2Ray 服务端
虽然严格来说 V2Ray 并不分客户端和服务端……反正就是那个意思啦。
编辑配置文件 /etc/v2ray/config.json
:
{
"inbounds": [{
"port": 10086,
// 因为还要用 Nginx 反代,这里直接监听本地就行
"listen": "127.0.0.1",
"protocol": "vmess",
"settings": {
"clients": [
{
// 用户 UUID,自己随机弄一个
"id": "23ad6b10-8d1a-40f7-8ad0-e3e35cd38297",
"level": 1,
"alterId": 64
}
]
},
"streamSettings": {
// 指定底层传输方式为 WebSocket
"network": "ws",
"wsSettings": {
// 在哪个路径上提供 WS 服务,可自定义
"path": "/whatever"
}
}
}],
"outbounds": [{
"protocol": "freedom",
"settings": {}
},{
"protocol": "blackhole",
"settings": {},
"tag": "blocked"
}],
"routing": {
"rules": [
{
// 默认规则,禁止访问服务器内网
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "blocked"
}
]
}
}
上述配置是直接基于默认配置修改的,V2Ray 的配置很灵活,还有很多可以完善的地方。不过配置调优并不是本文的重点,所以这里按下不表,有兴趣可以自行阅读官方文档。
3. 运行 V2Ray
配置完了,运行一下:
systemctl start v2ray
如果你的服务器不用 Systemd:
service v2ray start
# 要么
/etc/init.d/v2ray start
# 或者手动运行
/usr/bin/v2ray/v2ray -config /etc/v2ray/config.json
测试一下有没有跑起来:
curl -i http://127.0.0.1:10086/whatever
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Sec-Websocket-Version: 13
X-Content-Type-Options: nosniff
Date: Sun, 12 Jan 2020 11:45:14 GMT
Content-Length: 12
Bad Request
注意 curl 访问的端口和路径要和上面 V2Ray 中配置的一致,出现 400 Bad Request 就对了。
4. 配置 Nginx
毕竟要隐蔽嘛,最好是选一个已经上线的正常网站,悄咪咪地把其中一个路径反代到我们的 V2Ray 上。
网上不少 V2Ray + WebSocket + TLS 的教程里,Web 服务器 + SSL 证书的配置都是重头戏。可如果你平时就有在捣鼓网站的话,这些实在是都不算啥……所以我这里也就一笔带过了。
以 Nginx 为例,找个合适的 server {}
块添加以下内容(这重定向语法够蛋疼的):
location /whatever {
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
set $is_v2ray 0;
if ($http_upgrade = "websocket") {
set $is_v2ray 1;
}
if ($is_v2ray = 1) {
# 仅当请求为 WebSocket 时才反代到 V2Ray
proxy_pass http://127.0.0.1:10086;
}
if ($is_v2ray = 0) {
# 否则显示正常网页
rewrite ^/(.*)$ /mask-page last;
}
}
注意 location
的路径要和上面 V2Ray 里配置的一样。
最后完整的 Nginx 配置大概类似这样:
server {
listen 443 ssl http2;
server_name example.com;
index index.html index.htm index.php;
root /data/wwwroot/example;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
location ~ [^/]\.php(/|$) {
fastcgi_pass unix:/dev/shm/php-cgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
location /whatever {
# ...
}
}
表面看上去像个正常 PHP 网站,/whatever
里才是大有乾坤。
再把路径和网站内容搞得唬人一点,我寻思隐蔽性方面应该是没问题的。
5. 配置 CloudFlare
呃,这个就不用讲什么了吧。还不说声多谢 CloudFlare 哥?
CDN 配置完了再用 curl 测试一下:
curl -i https://example.com/whatever
HTTP/2 400
date: Sun, 12 Jan 2020 08:44:07 GMT
content-type: text/plain; charset=utf-8
content-length: 12
sec-websocket-version: 13
x-content-type-options: nosniff
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" server: cloudflare
Bad Request
同样也是出现 400 Bad Request 就对了。
如果你像我上面一样在 Nginx 中配置了 $http_upgrade = "websocket"
的判断的话,这里返回的会是用于伪装的那个页面(而且 Nginx 的 $http_upgrade
变量不知道是按什么赋值的,直接 curl --header "Upgrade: websocket"
的话还不认,怪得很)。可以使用 wscat
来测试:
wscat -c wss://example.com/whatever
Connected (press CTRL+C to quit)
6. 配置 V2Ray 客户端
客户端配置文件大概改成这样:
{
"log": {
"loglevel": "warning"
},
"inbounds": [{
// 本地代理配置
"port": 1080,
"listen": "127.0.0.1",
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": false,
"ip": "127.0.0.1"
}
}],
"outbounds": [{
"protocol": "vmess",
"settings": {
"vnext": [
{
// 套过 CloudFlare 的网址
"address": "example.com",
"port": 443,
"users": [
{
// id 和 alterId 必须和服务端上配置的一样
"id": "23ad6b10-8d1a-40f7-8ad0-e3e35cd38297",
"alterId": 64
}
]
}
]
},
"streamSettings": {
// 传输协议为 WebSocket
"network": "ws",
// 底层传输安全为 TLS
"security": "tls",
"wsSettings": {
// 路径要和上面设置的一样
"path": "/whatever"
}
}
}],
"policy": {
"levels": {
"0": {"uplinkOnly": 0}
}
}
}
上述客户端配置同样也是简化的,路由、DNS 什么的都没设置。
当然,我估计桌面用户基本上用的都是各种图形客户端,不然可不是折腾自己嘛。以 Windows 上的 v2rayN 客户端为例,你可以这样添加服务器:
不出意外就可以正常使用了。
7. 后记
这一套配置下来,使用体验暂且不说,隐蔽性应该是拉满的。备用梯子嘛,能在大规模断网的时候依然坚挺就算不错了。
常言道有备无患,眼见着墙越来越高,给自己多留条路子总是好的。
参考链接: