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

0 开篇

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

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

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

1.1 校准时间

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

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

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

dpkg-reconfigure tzdata 

再次使用 date -R 确认时间已经正确修改即可。

1.2 安装 V2Ray

直接运行官方脚本:

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

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

systemctl start v2ray

1.3 修改 V2Ray 配置

配置文件通过 vim /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 生成器 中获取,或者在 Linux 系统中输入 uuidgen 生成。

2 客户端配置

{
  "inbounds": [
    {
      "port": 1080,  // 填写本地端口
      "protocol": "socks",
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      },
      "settings": {
        "auth": "noauth"
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "服务器ip",
            "port": 18362, // PORT,必须与服务器端配置相同
            "users": [
              {
                "id": "5575a0ff-f9d4-4903-8b64-b49981e8cae0",  // 用户 ID,必须与服务器端配置相同
                "alterId": 64 // 此处的值也应当与服务器相同
              }
            ]
          }
        ]
      }
    }
  ]
}

3 V2Ray 进阶

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

3.1 TLS

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

为了使用 TLS,我们需要一个域名,可以选择付费域名,申请方式见我之前的文章,或者也可以去 https://www.freenom.com 申请一个免费域名(终身免费,需每年手动续期)。然后设置将其解析到服务器,这里选择使用 Cloudflare 进行解析,参考 -> https://cyh.me/tutorials/build-a-website/#toc-head-8,但注意:不要开启 CDN 加速,否则之后无法正常设置。

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

3.1.1 安装证书

使用 TLS 还需要安装证书,证书也有免费和付费之分,我们这里直接选择免费证书,证书认证机构为 Let's Encrypt,通过 acme.sh 脚本安装:

apt install socat
curl  https://get.acme.sh | sh
~/.acme.sh/acme.sh --issue -d example.com --standalone -k ec-256

由于 Let's Encrypt 的证书有效期只有 3 个月,因此需要 90 天至少要更新一次证书,acme.sh 脚本会每 60 天自动更新证书。也可以手动更新,如需手动更新请执行:

~/.acme.sh/acme.sh --renew -d example.com --force --ecc

为了更好的管理,我们可以将证书与 V2Ray 安装在一起(非必需):

~/.acme.sh/acme.sh --installcert -d example.com --fullchainpath /etc/v2ray/v2ray.crt --keypath /etc/v2ray/v2ray.key --ecc

安装完成后可以前往 Qualys SSL Labs's SSL Server Test 测试证书是否安装妥当:

如图则说明安装正确,可以继续安装,否则请重新操作(建议直接重装系统)。

3.1.2 修改配置文件

服务器端配置:

{
  "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/v2ray/v2ray.crt", // 证书地址
              "keyFile": "/etc/v2ray/v2ray.key" // 密钥地址
            }
          ]
        }
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "settings": {}
    }
  ]
}

客户端配置:

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

3.2 TLS + Websocket + Web

在上一节的基础上,我们搭建一个真正的网站出来,这样从外部看我们是在正常访问一个网站,而实际上请求的内容在服务器内部进行转发,再通过服务器去请求我们需要的内容,然后返回客户端。由于这种方式是真实地去访问网站而非某种混淆,因此使用这种方式的安全系数最高,可最大程度降低被 Ban 的可能性。

3.2.1 制作一个简易网站

可以选择不同的方式搭建,一般分为 Nginx / Caddy / Apache 三种,以下逐一介绍,大家任选一种即可。

注意:Nginx 和 Apache 都需要先在上一节中安装证书,但 Caddy 不需要,它会自动申请并安装证书。

3.2.1.1 Nginx

安装 Nginx 并新建配置:

apt install nginx
vim /etc/nginx/conf.d/example.com.conf  # 文件以.conf结尾即可

写入以下配置:

server {
  listen                  443 ssl http2;
  listen                  [::]:443 ssl http2;
  ssl_certificate         /etc/v2ray/v2ray.crt; # 证书地址
  ssl_certificate_key     /etc/v2ray/v2ray.key; # 密钥地址
  ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers             HIGH:!aNULL:!MD5;
  server_name             example.com; # 改成注册的域名

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

安装 Caddy:

curl https://getcaddy.com | bash -s personal

配置基础文件并设置开机自启:

chown root:root /usr/local/bin/caddy
chmod 755 /usr/local/bin/caddy

setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy

groupadd -g 33 www-data
useradd -g www-data --no-user-group --home-dir /var/www --no-create-home --shell /usr/sbin/nologin --system --uid 33 www-data

mkdir /etc/caddy
chown -R root:root /etc/caddy
mkdir /etc/ssl/caddy
chown -R root:www-data /etc/ssl/caddy
chmod 0770 /etc/ssl/caddy

mkdir /etc/caddy
touch /etc/caddy/Caddyfile
chown root:root /etc/caddy/Caddyfile
chmod 644 /etc/caddy/Caddyfile

mkdir /var/www
chown www-data:www-data /var/www
chmod 555 /var/www

mkdir /var/www/example.com  # 替换成自己的域名
chown -R www-data:www-data /var/www/example.com
chmod -R 555 /var/www/example.com

# 如果不需要开机自启则不用执行以下代码
wget https://raw.githubusercontent.com/mholt/caddy/master/dist/init/linux-systemd/caddy.service
cp caddy.service /etc/systemd/system/
chown root:root /etc/systemd/system/caddy.service
chmod 644 /etc/systemd/system/caddy.service
systemctl daemon-reload

systemctl enable caddy.service  # 开机自启

输入 vim /etc/caddy/Caddyfile 进行配置(建议删除注释)

example.com {
  proxy /v2ray localhost:18362 {  # 路径和端口请自行更改
  websocket
  header_upstream -Origin
  }
}

最后输入 systemctl start caddy.service 启动。

3.2.1.3 Apache
apt install apache2

# 开启以下module
a2enmod ssl
a2enmod proxy
a2enmod proxy_wstunnel
a2enmod proxy_http
a2enmod rewrite
a2enmod headers

输入 vim /etc/apache2/sites-available/yourdomain.com.conf 配置 Apache:

<VirtualHost *:443>
  ServerName example.com.
  ServerAlias example.com.
  SSLEngine On
  SSLCertificateFile /etc/v2ray/v2ray.crt
  SSLCertificateKeyFile /etc/v2ray/v2ray.key

  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket [NC]
  RewriteRule /(.*)           ws://localhost:18362/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket [NC]
  RewriteRule /(.*)           http://localhost:18362/$1 [P,L]

  SSLProxyEngine On
  Proxypass /v2ray http://127.0.0.1:18362
  ProxyPassReverse /v2ray http://127.0.0.1:18362
</VirtualHost>

开启 Apache:

a2ensite example.com
systemctl restart apache2

3.2.2 修改配置文件

服务器端配置:

{
  "inbounds": [
    {
      "port": 10086,
      "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": 1080,
      "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"
        }
      }
    }
  ]
}

一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。