自从今年 6 月 1 日开始的大规模封禁,我的 Shadowsocks 也受到了严重的影响,为了解决这一问题,我开始着手寻找一个更安全更稳定的翻墙方式,这便是 V2Ray。经历多次安装失败后,这里总结出一套完整的、不易出错的教程,内容基于 V2Ray 官方网站以及白话文教程

0 开篇

初识 V2Ray,很可能对它复杂的配置方式感到望而却步,但实际上大部分工作我们并不需要去做,大部分工作已经整合进 V2Ray 中或已有现成的脚本可以实现,大家大可不必担心自己会因专业知识不足而止步。

如果仅图个方便,那么只看前两部分就已经足够;如果希望翻墙的过程更安全(喜欢折腾),则可以参考之后的内容。

1 准备工作及服务器安装 V2Ray

1.1 校准时间

V2Ray 的使用最最最重要的一点是时间校准,一般要求服务器时间与本地时间相差不得超过 90 秒,否则可能出现验证失败的状况,因此我们第一步就是校准时间。

Linux 系统下使用 date -R 命令查看当前系统日期:

$ date -R
Sun, 30 Jun 2020 06:51:53 +0000

这里的 +0000 代表格林尼治时间,需要调换成自己设备对应的时区,调整方式如下:

$ dpkg-reconfigure tzdata 

// 选择时区
Current default time zone: 'Asia/Shanghai'
Local time is now:      Mon Mar  9 12:27:47 CST 2020.
Universal Time is now:  Mon Mar  9 04:27:47 UTC 2020.

1.2 安装 V2Ray

先安装必要的依赖:

$ apt update
$ apt upgrade
$ apt install curl zip

直接运行官方脚本:

$ bash <(curl -L -s https://install.direct/go.sh)

...

PORT:18362
UUID:5575a0ff-f9d4-4903-8b64-b49981e8cae0

...

这样 V2Ray 的基本安装就已经完成了,记住这里的 PORT 及 UUID 信息,最后启动V2Ray:

$ systemctl start v2ray.service

1.3 修改 V2Ray 配置

配置文件在 /etc/v2ray/config.json,以下为简单的配置模板:

{
  "inbounds": [
    {
      "port": 18362,  // 服务器监听端口
      "protocol": "vmess",  // 主传入协议
      "settings": {
        "clients": [
          {
            "id": "5575a0ff-f9d4-4903-8b64-b49981e8cae0",  // 用户 ID,客户端与服务器必须相同
            "alterId": 64
          }
        ]
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",  // 主传出协议
      "settings": {}
    }
  ]
}

注:其中 UUID 可以在 UUID 生成器中获取,或者输入 uuidgen 生成。

$ uuidgen
5575a0ff-f9d4-4903-8b64-b49981e8cae0

最后记得重新启动 V2Ray 让配置生效:

$ systemctl restart v2ray.service

2 客户端配置

{
  "inbounds": [
    {
      "port": 10808,  // 填写本地端口
      "protocol": "socks",
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      },
      "settings": {
        "auth": "noauth"
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "{ip_address}",
            "port": 18362,  // 必须与服务器端配置相同
            "users": [
              {
                "id": "5575a0ff-f9d4-4903-8b64-b49981e8cae0",  // 必须与服务器端配置相同
                "alterId": 64  // 必须与服务器端配置相同
              }
            ]
          }
        ]
      }
    }
  ]
}

3 V2Ray 进阶

这一节的内容可能会稍稍有一些繁琐,如若希望减少服务器被墙几率而且时间充裕则可以尝试尝试。

3.1 TLS

TLS 中文译名是传输层安全,可以使用户与服务器之间的通信不被窃听,详细内容可自行查询。

为了使用 TLS,可以去 Freenom 申请一个免费域名。然后设置将其解析到服务器,这里选择使用 Cloudflare 进行解析,但不要开启 CDN

以下内容假设注册的域名为 example.com。

3.1.1 安装证书

使用 TLS 还需要安装证书,选择免费证书 Let's Encrypt 即可,通过 certbot 脚本安装:

$ apt install certbot

然后开始安装,如果希望收到证书到期提醒邮件,可以删去 --register-unsafely-without-email

$ certbot certonly --register-unsafely-without-email
Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Plugins selected: Authenticator standalone, Installer None
Registering without email!

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): example.com

...

 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem

...

注意证书和密钥的安装位置:

  • 证书:/etc/letsencrypt/live/example.com/fullchain.pem
  • 密钥:/etc/letsencrypt/live/example.com/privkey.pem

3.1.2 修改 V2Ray 配置

服务器端配置:

{
  "inbounds": [
    {
      "port": 443,  // 建议使用 443 端口
      "protocol": "vmess",    
      "settings": {
        "clients": [
          {
            "id": "5575a0ff-f9d4-4903-8b64-b49981e8cae0",
            "alterId": 64
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",  // security 要设置为 tls 才会启用 TLS
        "tlsSettings": {
          "certificates": [
            {
              "certificateFile": "/etc/letsencrypt/live/example.com/fullchain.pem",  // 证书地址
              "keyFile": "/etc/letsencrypt/live/example.com/privkey.pem"  // 密钥地址
            }
          ]
        }
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "settings": {}
    }
  ]
}

客户端配置:

{
  "inbounds": [
    {
      "port": 10808,
      "protocol": "socks",
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      },
      "settings": {
        "auth": "noauth"
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "example.com",  // 填写域名
            "port": 443,
            "users": [
              {
                "id": "5575a0ff-f9d4-4903-8b64-b49981e8cae0",
                "alterId": 64
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls"  // 客户端的 security 也要设置为 tls
      }
    }
  ]
}

3.2 TLS + Websocket + Web

在上一节的基础上,我们使用真正的网站请求,这样从外部看我们是在正常访问一个网站,而实际上请求的内容在服务器内部进行转发,再通过服务器去获得我们需要的内容,然后返回客户端。这是目前最为安全且稳定的使用方式。

3.2.1 Nginx 配置

安装 Nginx,并新建一个 Nginx 配置文件,注意以 .conf 结尾

$ apt install nginx
$ vim /etc/nginx/conf.d/example.com.conf

写入以下配置:

server {
    server_name             example.com;  # 改成注册的域名
    listen                  80;

    location /v2ray {  # 可随意设置location路径,待会需要用到
        proxy_redirect off;
        proxy_pass http://127.0.0.1:18362;  # 记住端口号
        proxy_http_version 1.1;
	    proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
    }
}

3.2.2 安装证书

安装 certbot 和它的 Nginx 插件:

$ apt install certbot python3-certbot-nginx

安装证书,如果希望收到证书到期提醒邮件,可以删去 --register-unsafely-without-email

$ certbot --nginx --register-unsafely-without-email
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Registering without email!

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1

...

Deploying Certificate to VirtualHost /etc/nginx/conf.d/example.com.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/example.com.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://example.com

...

此时再查看 Nginx 的配置文件会发现发生了一些变化:

server {
    server_name             example.com;

    location /v2ray {
        proxy_redirect off;
        proxy_pass http://127.0.0.1:18362;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    server_name             example.com;
    listen                  80;
    return 404; # managed by Certbot


}

这时 Nginx 和证书的配置就完成了,接下来修改 V2Ray 的配置

3.2.2 修改 V2Ray 配置

服务器端配置:

{
  "inbounds": [
    {
      "port": 18362,  // 与上一小节的端口号一致
      "listen":"127.0.0.1",
      "protocol": "vmess",
      "settings": {
        "clients": [
          {
            "id": "5575a0ff-f9d4-4903-8b64-b49981e8cae0",  // 请自行修改
            "alterId": 64
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "wsSettings": {
        "path": "/v2ray"  // 与上一小节的路径一致
        }
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "settings": {}
    }
  ]
}

客户端配置:

{
  "inbounds": [
    {
      "port": 10808,
      "listen": "127.0.0.1",
      "protocol": "socks",
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      },
      "settings": {
        "auth": "noauth",
        "udp": false
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "example.com",
            "port": 443,
            "users": [
              {
                "id": "5575a0ff-f9d4-4903-8b64-b49981e8cae0",
                "alterId": 64
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "wsSettings": {
          "path": "/v2ray"
        }
      }
    }
  ]
}