近日有感于一些网站无法访问的无奈,就动了科学爱国的念头。以前我都是买个 VPN 完事,但是因为一次偶尔看到了一种新型工具 – V2Ray 的介绍,心里就有点蠢蠢欲动,开始了折腾。没想到这个软件的可玩性相当高,一玩就是一个星期,期间还使用了两种 web 内容提供软件 – caddy 和 nginx ,并分别用两个软件搭建了自己的第一个 https 加密网站,感觉学到了很多,所以在这里记录一下。
目前我试验了 V2Ray 的 vmess+kcp、shadowsocks+kcp、vmess+http2+tls+web 和 shadowsocks+websockets+tls+web 这四种配置,并最终停留在最后一种。网上的测评基本上是 V2Ray 的 vmess 协议要比 shadowsocks 协议快一些,当然我买的 vps 的 ping 值很高,速度也不快,这点差距就无视了,还有就是用 V2Ray 配置 shadowsocks 协议更加有趣。同时我还体验了 caddy 和 nginx 搭建网站的步骤,就目前的个人体会而言,caddy 的配置文件要远比 nginx 的简洁明了,尤其是在配置 https 加密的时候,caddy 自带免费证书申请续签,比 nginx 不知简单了多少,当然据说 nginx 的性能要好一些,毕竟 caddy 是 go 语言写的,不过如果是初配置的话还是用 caddy 吧,另外 nginx 不支持 http2 反向代理,所以如果使用 vmess+http2+tls+web 的组合的话也只有用 caddy 了,有人好像用 apache 搭建过,有兴趣的可以尝试一下。我这里只是把相关的配置文件做一个整理,具体的搭建过程可以看V2Ray的官方教程 和 白话文教程 。
1、vmess+kcp¶
kcp是一种传输协议,提供了一些加速和数据伪装等一些功能,在一些延迟比较高的vps中,可以使用这种技术来实现网络加速,同时这个协议可以通过修改数据头实现流量伪装,比如伪装成微信视频、bt 下载等。vmess 是 V2Ray 团队实现的一种新型加密传输协议,按照 白话文教程 的说法,比 shadowsocks 协议更安全、速度更快。我查了一下才发现 kcp 协议好像是国内的 skywind 团队实现的,知乎上有其帐号 韦易笑 ,虽然我不是很喜欢这个人,但是东西做的不错还是值得点赞的。服务器端与客户端的配置文件如下,如果你要使用可以把 example.org 改成你的 vps 的 ip 地址或者网址,id 也改成你的 uid,当然要注意格式。Sphinx 不支持 json 语法高亮,凑合着看吧。
服务器端:
{
"log": {
"error": "/var/log/v2ray/error.log",
"loglevel": "warning"
},
"inbound": {
"protocol": "vmess",
"port": 10086,
"settings": {
"clients": [
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"alterId": 64,
"level": 1
}
]
},
"streamSettings": {
"network": "mkcp",
"kcpSettings": {
"uplinkCapacity": 5,
"downlinkCapacity": 100,
"congestion": true,
"header": {
"type": "utp"
}
}
}
},
"outbounds": [
{
"protocol": "freedom",
"tag": "direct",
"settings": {}
},
{
"protocol": "blackhole",
"tag": "blocked",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"::1/128",
"fc00::/7",
"fe80::/10"
],
"outboundTag": "blocked"
}
]
}
}
客户端:
{
"log": {
"error": "C:\\Users\\Sky\\Downloads\\PortableApps\\v2ray\\error.log",
"loglevel": "warning"
},
"inbounds": [
{
"protocol": "socks",
"port": 1080,
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
},
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "example.org",
"port": 10086,
"users": [
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"alterId": 64,
"security": "aes-128-gcm",
"level": 1
}
]
}
]
},
"streamSettings": {
"network": "mkcp",
"kcpSettings": {
"uplinkCapacity": 5,
"downlinkCapacity": 100,
"congestion": true,
"header": {
"type": "utp"
}
}
}
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
},
{
"tag":"blocked",
"protocol":"blackhole",
"settings":{}
}
],
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"port": "54-79",
"outboundTag": "direct"
},
{
"type": "field",
"port": "81-442",
"outboundTag": "direct"
},
{
"type": "field",
"port": "444-65535",
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"gc.kis.scr.kaspersky-labs.com"
],
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:cn",
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "chinasites",
"outboundTag": "direct"
},
{
"type": "chinaip",
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"::1/128",
"fc00::/7",
"fe80::/10"
],
"outboundTag": "direct"
}
]
}
}
2、shadowsocks+kcp¶
shadowsocks 大家都很熟悉了吧,很知名的加密传输协议,当然作者被请喝茶了(笑)。V2Ray 也集成了 shadowsocks 的功能,同时相比原版的 shadowsocks 程序实现了诸如 kcp 等配置功能,据说速度也比原版速度更快。用 V2Ray 配置 shadowsocks 可以说是一种邪道用法,如果没有啥特殊原因不建议使用,相比 vmess 没什么优势。如果你要使用可以把 address 和 password 改一下,email 可填可不填。
服务器端:
{
"log": {
"error": "/var/log/v2ray/error.log",
"loglevel": "warning"
},
"inbound": {
"protocol": "shadowsocks",
"port": 10086,
"settings": {
"method": "aes-128-gcm",
"password": "xxxxxxxxxxxxxxxx",
"level": 1
},
"streamSettings": {
"network": "mkcp",
"kcpSettings": {
"uplinkCapacity": 5,
"downlinkCapacity": 100,
"congestion": true,
"header": {
"type": "utp"
}
}
}
},
"outbounds": [
{
"protocol": "freedom",
"tag": "direct",
"settings": {}
},
{
"protocol": "blackhole",
"tag": "blocked",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"::1/128",
"fc00::/7",
"fe80::/10"
],
"outboundTag": "blocked"
}
]
}
}
客户端:
{
"log": {
"error": "C:\\Users\\Sky\\Downloads\\PortableApps\\v2ray\\error.log",
"loglevel": "warning"
},
"inbounds": [
{
"protocol": "socks",
"port": 1080,
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
},
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"protocol": "shadowsocks",
"settings": {
"servers": [
{
"email":"[email protected]",
"address": "example.org",
"port": 10086,
"method": "aes-128-gcm",
"password": "xxxxxxxxxxxxxxxx",
"level": 1
}
]
},
"streamSettings": {
"network": "mkcp",
"kcpSettings": {
"uplinkCapacity": 5,
"downlinkCapacity": 100,
"congestion": true,
"header": {
"type": "utp"
}
}
}
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
},
{
"tag":"blocked",
"protocol":"blackhole",
"settings":{}
}
],
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"port": "54-79",
"outboundTag": "direct"
},
{
"type": "field",
"port": "81-442",
"outboundTag": "direct"
},
{
"type": "field",
"port": "444-65535",
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"gc.kis.scr.kaspersky-labs.com"
],
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:cn",
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "chinasites",
"outboundTag": "direct"
},
{
"type": "chinaip",
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"::1/128",
"fc00::/7",
"fe80::/10"
],
"outboundTag": "direct"
}
]
}
}
3、vmess+http2+tls+web¶
http2 是 http1 协议的升级版,为啥要用 http2 协议我也不清楚。当然重点是 tls+web 的配置可以让流量完全伪装为正常的 https 网站,同时对数据进行加密,防止 GFW 检测到你的数据和你的 vps 的真实 ip 地址。这个配置还可以搭配 cdn 中转,实现高速过墙,即使主机 ip 被墙了也不影响。不过免费的 cdn 提供商 cloudflare 太慢了,我试了一下感觉不太好,如果有钱可以考虑一些收费的 cdn 提供商。总之这个配置的优点是隐秘性较高,不容易被封 ip,但是 websockets 的速度不如 tcp,所以可能速度上会慢一些。用的是 caddy,具体的安装很简单,网上有教程的。xxxx@example.com 是你的邮箱地址,path 可以随便填一个。
服务器端:
{
"log": {
"error": "/var/log/v2ray/error.log",
"loglevel": "warning"
},
"inbound": {
"protocol": "vmess",
"listen": "127.0.0.1",
"port": 10086,
"settings": {
"clients": [
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx",
"alterId": 64,
"level": 1
}
]
},
"streamSettings": {
"network": "h2",
"security": "tls",
"httpSettings": {
"path": "/path",
"host": ["example.org"]
},
"tlsSettings": {
"serverName": "example.org",
"certificates": [
{
"certificateFile": "/etc/v2ray/v2ray.crt",
"keyFile": "/etc/v2ray/v2ray.key"
}
]
}
}
},
"outbounds": [
{
"protocol": "freedom",
"tag": "direct",
"settings": {}
},
{
"protocol": "blackhole",
"tag": "blocked",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"::1/128",
"fc00::/7",
"fe80::/10"
],
"outboundTag": "blocked"
}
]
}
}
客户端:
{
"log": {
"error": "C:\\Users\\Sky\\Downloads\\PortableApps\\v2ray\\error.log",
"loglevel": "warning"
},
"inbounds": [
{
"protocol": "socks",
"port": 1080,
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
},
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "example.org",
"port": 443,
"users": [
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"alterId": 64,
"security": "aes-128-gcm",
"level": 1
}
]
}
]
},
"mux": {
"enabled": true,
"concurrency": 8
},
"streamSettings": {
"network": "h2",
"security": "tls",
"tlsSettings": {
"serverName": "example.org"
},
"httpSettings": {
"host": [
"example.org"
],
"path": "/path"
}
}
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
},
{
"tag":"blocked",
"protocol":"blackhole",
"settings":{}
}
],
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"port": "54-79",
"outboundTag": "direct"
},
{
"type": "field",
"port": "81-442",
"outboundTag": "direct"
},
{
"type": "field",
"port": "444-65535",
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"gc.kis.scr.kaspersky-labs.com"
],
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:cn",
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "chinasites",
"outboundTag": "direct"
},
{
"type": "chinaip",
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"::1/128",
"fc00::/7",
"fe80::/10"
],
"outboundTag": "direct"
}
]
}
}
Caddy 配置文件 Caddyfile:
:80 {
root /var/www
gzip {
ext .html .htm .php
level 6
}
}
http://example.org {
redir https://example.org{url}
}
https://example.org {
root /var/www/
tls xxxx@examaple.com {
ciphers ECDHE-ECDSA-WITH-CHACHA20-POLY1305 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-CBC-SHA
curves p384
key_type p384
}
proxy /path https://localhost:10086 {
insecure_skip_verify
header_upstream X-Forwarded-Proto "https"
header_upstream Host "example.org"
}
header / {
Strict-Transport-Security "max-age=31536000;"
X-XSS-Protection "1; mode=block"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
}
}
4、shadowsocks+websockets+tls+web¶
这个是我最后使用的配置,一般来说常用的配置是 vmess+websockets+tls+web,这种配置安全性比较高,因此很多人在搭建 V2Ray 时会选择这种方案。其中 https 加密也可以用 caddy 实现,而且比 nginx 更简单,当然我这里用的是 nginx+acme.sh 的组合实现的,其中 nginx 提供 web 页面内容,acme.sh 提供免费证书和自动续签。不过我在使用 nginx 的时候发现网上的很多教程是无法使用的,acme.sh 根本无法获取证书,原因就在于没有配置 80 端口的访问权限,这个问题困扰了我好几天,直到在一个 issue 上找到了解决办法,就是在 acme.sh 的读取路径配置添加 allow all。这里贴一下我的配置,如果有遇到问题可以参考一下。另外这个配置里我把一些没必要的配置给删除了,配置文件看起来更简洁,上面的方案应该也可以简化一下的。
服务器端:
{
"log": {
"error": "/var/log/v2ray/error.log",
"loglevel": "warning"
},
"inbound": {
"protocol": "shadowsocks",
"listen": "127.0.0.1",
"port": 10086,
"settings": {
"method": "aes-128-gcm",
"password": "xxxxxxxxxxxxxxxx",
"level": 1
},
"streamSettings": {
"network": "ws",
"wsSettings": {
"path": "/path"
}
}
},
"outbounds": [
{
"protocol": "freedom",
"tag": "direct",
"settings": {}
},
{
"protocol": "blackhole",
"tag": "blocked",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"::1/128",
"fc00::/7",
"fe80::/10"
],
"outboundTag": "blocked"
}
]
}
}
客户端:
{
"log": {
"error": "C:\\Users\\Sky\\Downloads\\PortableApps\\v2ray\\error.log",
"loglevel": "warning"
},
"inbounds": [
{
"protocol": "socks",
"port": 1080,
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
},
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"protocol": "shadowsocks",
"settings": {
"servers": [
{
"address": "example.org",
"port": 443,
"method": "aes-128-gcm",
"password": "xxxxxxxxxxxxxxxx",
"level": 1
}
]
},
"mux": {
"enabled": true,
"concurrency": 8
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "example.org"
},
"wsSettings": {
"host": [
"example.org"
],
"path": "/path"
}
}
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
},
{
"tag":"blocked",
"protocol":"blackhole",
"settings":{}
}
],
"routing": {
"domainStrategy": "IPOnDemand",
"rules": [
{
"type": "field",
"port": "54-79",
"outboundTag": "direct"
},
{
"type": "field",
"port": "81-442",
"outboundTag": "direct"
},
{
"type": "field",
"port": "444-65535",
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"gc.kis.scr.kaspersky-labs.com"
],
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:cn",
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "chinasites",
"outboundTag": "direct"
},
{
"type": "chinaip",
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"::1/128",
"fc00::/7",
"fe80::/10"
],
"outboundTag": "direct"
}
]
}
}
Nginx 80 端口配置文件 default:
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/html;
allow all;
}
location = /.well-known/acme-challenge/ {
try_files $uri =404;
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}
Nginx 443 端口配置文件 example.org:
server {
listen 443 ssl http2 fastopen=128 reuseport;
listen [::]:443 ssl http2 fastopen=128 reuseport;
server_name example.org;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_certificate /etc/nginx/ssl/example.org.cer;
ssl_certificate_key /etc/nginx/ssl/example.org.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES25$
add_header Strict-Transport-Security max-age=15768000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
server_tokens off;
ssl_stapling on;
ssl_stapling_verify on;
location / {
try_files $uri $uri/ =404;
}
location /path {
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_intercept_errors on;
# Show realip in v2ray access.log
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if ($http_upgrade = "websocket" ){
proxy_pass http://127.0.0.1:10086;
}
}
}