Hotaru's Notebook

v2ray - 比 Shadowsocks 更强大更复杂的替代品

V2ray icon

Preface

为了穿越防火墙,瓷国程序员可谓是想尽办法。

  1. VPN:带有非常明显的特征:IP上层的通信协议全是密文。
  2. Shadowsocks:基于SOCKS改良的通信协议,无握手 全程加密 无特征。不过换个思路想其实特征也很明显:TCP/UDP上层的包全是密文,这样就和VPN没啥区别了。

后来有人想出来个办法并付诸实践,于是 Shadowsocks-R 出现了,其中一个特性就是为原 Shadowsocks 协议的数据流前面加上HTTP头,让防火墙误认为是HTTP协议,于是防火墙就应用针对HTTP的规则,于是就骗过防火墙了。

但终究需要面对一个事实:防火墙心情不好,总想着丢点儿包来降低自己分析数据包的负担,由此会导致 TCP 窗口骤降 RTO(Retry Timeout)骤升,然后就龟速了。

然后有个人写了个纯算法的通信协议叫 KCP,然后又有个人用这个协议写了个软件叫 v2ray。v2ray在引入KCP的同时对其进行了一些改进,其中引起我关注的是:

  1. 使用UDP作为下层协议,避免TCP带来的窗口和RTO问题。
  2. 更小的协议头部以躲避特征检查。
  3. 在协议数据流前面增加伪装,比如伪装成BT下载。

安装部署v2ray

首先把v2ray从 v2ray-core Releases on GitHub 下载回来并解压,解压后主要关注下面这4个文件:

文件名 用途
v2ray 软件本体
vpoint_socks_vmess.json 客户端配置示例
vpoint_vmess_freedom.json 服务器配置示例
systemd/v2ray.service v2ray systemd 服务

下面分别贴出我修改后的配置文件内容,稍作修改即可部署: 注意:json本身不支持注释,请在应用下面的配置前去掉注释。

客户端配置示例:

{
  "log": {
    "access": "/var/log/v2ray/access.log",
    "error": "/var/log/v2ray/error.log",
    "loglevel": "info"
  },
  "inbound": {
    "protocol": "socks",
    "listen": "127.0.0.1", // SOCKS5监听地址,改成 "0.0.0.0" 则监听所有网卡.
    "port": 1080, // SOCKS5监听端口
    "settings": {
      "auth": "noauth",
      "udp": true,
      "timeout": 30
    }
  },
  "outbound": {
    "protocol": "vmess",
    "settings": {
      "vnext": [
        {
          "address": "8.8.8.8", // 远程服务器IP
          "port": 39225, // 远程服务器端口
          "users": [
            {
              "id": "00000000-0000-0000-0000-000000000000", // 使用 "uuidgen -r" 生成一个UUID 放在这里即可.
              "alterId": 64,
              "security": "aes-128-gcm" // security: 默认值 "aes-128-cfb",PC 上可以改用 "aes-128-gcm".
            }
          ]
        }
      ]
    },
    "streamSettings": {
      "network": "kcp"
    }
  },
  "inboundDetour": [
    {
      // 启用 HTTP入站 代理
      "protocol": "http",
      "listen": "0.0.0.0", // 监听IP
      "port": 8023, // 监听端口
      "allocate": {
        "strategy": "always" // 只监听指定的端口, 也就是上面写的 8023。
      },
      "settings": {
        "timeout": 30 // 从客户端读取数据的超时设置(秒),0 表示不限时。默认值为 0。
      },
      "streamSettings": {
        "network": "tcp",
        "security": "none",
        "tcpSettings": {
          "connectionReuse": false
        }
      }
    }
  ],
  "outboundDetour": [
    {
      "protocol": "freedom",
      "settings": {},
      "tag": "direct"
    }
  ],
  "dns": {
    "servers": [
      "8.8.8.8",
      "8.8.4.4"
    ]
  },
  "routing": {
    "strategy": "rules",
    "settings": {
      "domainStrategy": "IPIfNonMatch",
      "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": "direct"
        }
      ]
    }
  },
  "transport": {
    "kcpSettings": {
      "uplinkCapacity": 10, // uplinkCapacity 和 downlinkCapacity 请根据v2ray的文档自行调节.
      "downlinkCapacity": 10,
      "header": {
        "type": "utp" // 将kcp协议伪装成BT协议.
      }
    }
  }
}

服务器配置示例:

{
  "log": {
    // 日志文件地址和日志等级
    "access": "/var/log/v2ray/access.log",
    "error": "/var/log/v2ray/error.log",
    "loglevel": "warning"
  },
  "inbound": {
    "listen": "8.8.8.8", // 服务器入站监听地址
    "port": 1234, // 服务器入站监听端口
    "protocol": "vmess",
    "settings": {
      "clients": [
        {
          "id": "00000000-0000-0000-0000-000000000000", // 这里的UUID需与上面客户端配置的UUID一致.
          "level": 1,
          "alterId": 64
        }
      ]
    },
    "streamSettings": {
      "network": "kcp"
    }
  },
  "outbound": {
    "protocol": "freedom",
    "settings": {
      "timeout": 30
    }
  },
  "outboundDetour": [
    {
      "protocol": "blackhole",
      "settings": {},
      "tag": "blocked"
    }
  ],
  "routing": {
    "strategy": "rules",
    "settings": {
      "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"
        }
      ]
    }
  },
  "transport": {
    "kcpSettings": {
      "uplinkCapacity": 20, // 这里同样请参照v2ray文档来配置.
      "downlinkCapacity": 20,
      "header": {
        "type": "utp" // 同客户端配置.
      }
    }
  }
}

测试并运行

使用命令 v2ray -config=<配置文件名> -test 来测试配置文件是否有语法错误,使用 v2ray -config=<配置文件名> 来运行v2ray客户端/服务端。

注: 在配置文件中有关日志的设置,因为使用了 /var/log/ 这样的路径,在非root用户下运行v2ray很可能会出错并结束进程。建议配置systemd来运行v2ray。如果非要手动运行的话,请修改日志文件路径到 运行这个程序的用户可以访问的路径下。

使用systemd将v2ray置为系统服务

使用systemd来运行v2ray而不是手动运行,出于以下目的:

  1. 不用手动敲命令行参数了
  2. 可以开机自动启动
  3. 重启v2ray也更简单了

添加/配置 v2ray 用户 日志文件夹 配置文件

root权限下执行下面命令

# 创建用户/用户组
useradd -M --user-group --shell /usr/sbin/nologin v2ray # 添加一个用户叫 v2ray,-M: 不创建对应的home目录.
# 创建日志文件夹
mkdir --parents /var/log/v2ray/
cd /var/log/v2ray/
touch ./access.log ./error.log
chown -R v2ray:v2ray ./
chmod 750 ./ # rwxr-x---
chmod 640 ./* # rw-r-----
# 创建配置文件
mkdir --parent /etc/v2ray/
cd /etc/v2ray/
touch config.json
chown -R v2ray:v2ray ./
chmod 750 ./ # rwxr-x---
chmod 640 ./config.json # rw-r-----

然后将前面的配置文件示例写入 config.json 并按照自己的需求进行修改。

安装 v2ray 可执行文件

# 创建v2ray的可执行文件目录
mkdir --parents /usr/bin/v2ray/
cd /usr/bin/v2ray/
cp /somewhere/v2ray ./ # 从其他地方把v2ray可执行文件复制到此目录下
chown -R v2ray:v2ray ./
chmod 750 ./ # rwxr-x---
chmod 540 ./v2ray # r-xr-----

配置 v2ray 的 systemd 服务

创建文件 /etc/systemd/system/v2ray.servicechown v2ray:v2ray chmod 640,文件内容如下:

[Unit]
Description=V2Ray Service
After=network.target
Wants=network.target

[Service]
Type=simple
PIDFile=/var/run/v2ray.pid
ExecStart=/usr/bin/v2ray/v2ray -config /etc/v2ray/config.json
Restart=on-failure
User=v2ray
Group=v2ray

[Install]
WantedBy=multi-user.target

启动v2ray.service服务

systemctl daemon-reload # 载入新添加的 v2ray.service
systemctl start v2ray # 启动v2ray服务

更新历史

26 Nov 2016:首次发布 17 Jan 2017:

11 Apr 2017:

References

  1. v2ray 官方文档
  2. v2ray on GitHub
  3. KCP - A Fast and Reliable ARQ Protocol on GitHub
  4. 配置 uplinkCapacity 和 downlinkCapacity - 传输配置 · V2Ray 官方网站

#v2ray #shadowsocks #kcp