在AWS EC2上搭建V2ray+Caddy代理

Page content

狭义的VPN虛拟私人网络(Virtual Private Network,缩写:VPN)是一种常用于连接中、大型企业或团体与团体间的私人网络的通讯方法。 广义的VPN是广大网民突破GFW,连接外国网络的方法。这里我们聊一聊怎样在服务器上搭建自己的VPN。

在VPS搭建VPN服务主要有4种比较便捷的方式:

  • L2TP/IPSec VPN (不建议,较容易被墙)
  • Shadowsocks (不建议,较容易被墙)
  • V2Ray (推荐 Nginx+WS+TLS or Caddy+WS+TLS)
  • Torjan (推荐)

如果你想不被针对,原则上应该选大型云计算商的机器

这个指的是如AWS/Azure/Google Cloud/IBM等被大量公司采用的服务,由于跑在上面的正常业务很多,被GFW按IP段整个屏蔽的可能性较小。 现在说较小也就是相对了,真的屏蔽了也不很奇怪。 AWS支持弹性IP,即使IP被封了,后台重新申请一个公网IP绑定到对应的实例,可以很方便的更换IP。但AWS流量相对其他机场价格略贵。

反面案例是Linode/Vultr/DigitalOcean这种实际规模不大,却在翻墙圈“大名鼎鼎”的“飞机场”,这几家显然已经进入了黑名单, 最近一段时间经常被间歇性整段IP屏蔽。

前提条件

本文假设读者已经具备以下条件:

  • 一台境外的vps。
  • 一个域名,无备案要求。先设置dns将域名解析到vps的ip。
  • 为域名申请一个证书,可以从Let’s Encrypt获取免费证书;本文用到caddy能自动申请。
  • 有基本linux技巧,能使用vim/nano等编辑器。

自建V2Ray服务器首先要购买VPS(虚拟主机),为避免广告嫌疑,正文中不推荐VPS。 一般而言,自建服务的成本远远低于机场,大多数VPS每个月花费20-30元左右,流量1TB/月,有些外资VPS价格低到10-20元,甚至每月不到10元。 如果愿意折腾,还可以用免费的谷歌云。此外,自建服务没有客户端数量限制,如果多人分摊成本,价格就更便宜了。

理论上来说,证书不是必须的。 但没有tls加持或不做加密,防火墙直接能看出来流量真实意图从而进行干扰,这也是为什么不建议伪装http流量的原因。 本文给出的方法采用合法机构签发的证书对流量进行加密,不是做特征混淆得到的TLS流量,从而更难被检测和干扰。

关于伪装技术的选择,V2ray web+websocket+tls 和 V2ray web+http2+tls 常用来做对比。 理论上http2省去了upgrade的请求,性能更好。但实际使用中两者没有明显区别,本文使用的是websocket方式。

本文用到系统环境及软件版本如下:

  • 系统: ubuntu 18.04
  • Caddy: 2.x
  • V2ray: 4.x

V2ay服务端

校准时区

VMess 协议的认证基于时间,一定要保证服务器和客户端的系统时间相差要在 90 秒以内。

这里我们把时区设成上海

> timedatectl list-timezones | grep Shanghai
Asia/Shanghai

> sudo timedatectl set-timezone Asia/Shanghai

> date -R
Sat, 26 Jun 2021 18:03:36 +0800

服务端安装

curl -O https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh
# 目前ubuntu上稳定版本为v4.34.0
sudo bash install-release.sh --version v4.34.0
# /etc/systemd/system/v2ray.service.d/10-donot_touch_single_conf.conf
# In case you have a good reason to do so, duplicate this file in the same directory and make your customizes there.
# Or all changes you made will be lost!  # Refer: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
[Service]
ExecStart=
ExecStart=/usr/local/bin/v2ray -config /usr/local/etc/v2ray/config.json

installed: /usr/local/bin/v2ray
installed: /usr/local/bin/v2ctl
installed: /usr/local/share/v2ray/geoip.dat
installed: /usr/local/share/v2ray/geosite.dat
installed: /usr/local/etc/v2ray/config.json
installed: /var/log/v2ray/
installed: /var/log/v2ray/access.log
installed: /var/log/v2ray/error.log
installed: /etc/systemd/system/v2ray.service
installed: /etc/systemd/system/[email protected]

此脚本会自动安装文件:

  • /usr/local/bin/v2ray:V2Ray 程序;
  • /usr/local/bin/v2ctl:V2Ray 工具;
  • /usr/local/etc/v2ray/config.json:配置文件;
  • /usr/local/share/v2ray/geoip.dat:IP 数据文件
  • /usr/local/share/v2ray/geosite.dat:域名数据文件 此脚本会配置自动运行脚本
  • /etc/systemd/system/v2ray.service:将V2Ray配置成 systemctl 服务
  • /etc/systemd/system/[email protected]

修改配置

编辑 /usr/local/etc/v2ray/config.json 文件来配置你需要的代理方式。

vim /usr/local/etc/v2ray/config.json

启动V2ray

sudo systemctl enable v2ray
sudo systemctl start v2ray
  • 之后可以使用 sudo systemctl start|stop|status|reload|restart|reload-or-restart 控制 V2Ray 的运行

服务端配置

将服务器 /etc/v2ray/config.json 文件修改成下面的内容。 这里是一个最基本的服务端配置,我们尽量保持简单,太复杂的东西总是难以维护,最后就放弃了。

修改完成后要运行systemctl restart v2ray重启 V2Ray,使修改的配置生效。

启动后,V2ray会以 Vmess + WS 方式监听 8888 端口。

{
    "inbound": {
        "port": 8888,
        "listen": "127.0.0.1",
        "protocol": "vmess",
        "settings": {
            "clients": [
                {
                    "id": "26f616e6-d668-11eb-baaf-acde48001122", 
                    "alterId": 64
                }
            ]
        },
        "streamSettings": {
            "network": "ws",
            "wsSettings": {
                "path": "/ray"
            }
        }
    },
    "outbound": {
        "protocol": "freedom",
        "settings": {}
    }
}

说明:

  • ws - WebSocket 方式
  • 8888 服务器监听端口
  • 127.0.0.1代表本机, 只监听 127.0.0.1,避免除本机外的机器探测到开放了8888端口
  • id 为 UUID 格式,请使用软件生成,不要尝试自己造一个,否则很大程度上造出一个错误的格式来。
  • freedom - 主传出协议 这里是直接转发所有流量

V2Ray客户端

客户端配置

将客户端的 config.json 文件修改成下面的内容,修改完成后要重启客户端 V2Ray 才会使修改的配置生效。 (#及后面的文字为注释,json文件中不需要包含)

{
  "inbounds": [
    {
      "port": 1080, # 本地监听端口
      "protocol": "socks", # 入口协议为 SOCKS 5
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      },
      "settings": {
        "auth": "noauth"  #socks的认证设置,noauth 代表不认证,由于 socks 通常在客户端使用,所以这里不认证
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "vmess", # 出口协议
      "settings": {
        "vnext": [
          {
            "address": "your_server_ip", # 服务器地址,请修改为你自己的服务器IP
            "port": 8888,  # 服务器监听的端口
            "users": [
              {
                "id": "26f616e6-d668-11eb-baaf-acde48001122",  # 用户 ID,必须与服务器端配置相同
                "alterId": 64 # 此处的值也应当与服务器相同
              }
            ]
          }
        ],
        "streamSettings": {
          "network": "ws",
          "wsSettings": {
            "path": "/ray"
          }
        }
      }
    }
  ]
}

客户端运行

  • 在 Windows 和 macOS 中,配置文件通常是 V2Ray 同目录下的 config.json 文件。直接运行 v2ray 或 v2ray.exe 即可。
  • 在 Linux 中,配置文件通常位于 /etc/v2ray/config.json 文件。运行 v2ray –config=/etc/v2ray/config.json,或使用 systemd 等工具把 V2Ray 作为服务在后台运行。

Caddy安装与配置

为啥选Caddy

完成V2Ray + Websocket 模式的配置后,V2ray就基本可以正常使用了,但依然不够安全,存在被封的风险。 WALL不知道你做了什么,但知道你使用加密协议在访问外网。

V2ray伪装便是将穿墙流量以常见的HTTPS/TLS包装,大大降低vps被墙或被干扰的可能性,在敏感时期提供稳如狗的上外网体验。 通常的做法是将V2ray放在Nginx或Caddy或Apache代理的后面,伪装成普通http服务。

目前比较流行的是 Vmess + WebSocket + TLS (以下简称 wss)方式, WSS三件套的思路其实就是,本地v2ray客户端出口(outBound)访问代理服务器,然后通过代理服务器将请求转发到服务端的v2ray入口(inBound)。 由于使用TLS协议加密,且整个过程看起来就是普通的https请求,降低被WALL的几率。

  • 使用 Nginx/Caddy/Apache 是因为 VPS 已经有 Nginx/Caddy/Apache 可以将 V2Ray 稍作隐藏
  • 使用 WebSocket 是因为搭配 Nginx/Caddy/Apache 只能用 WebSocket
  • 使用 TLS 是因为可以流量加密,看起来更像 HTTPS
  • 使用域名是因为 TLS 需要使用域名和证书,域名需要添加A记录,将域名解析到Caddy所在的服务器

Nginx需要手动生成一个SSL证书,添加到配置里。 Caddy 会自动申请证书并自动更新,所以使用 Caddy 不用指定证书、密钥。这里选择更简单的 Caddy。

安装Caddy

sudo apt update
sudo apt install caddy

如果遇到这个错误

E: Unable to locate package caddy

可以运行

sudo apt install curl
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

# 确认caddy版本 
caddy version
v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=

更新配置Caddy

打开Caddyfile,添加如下内容:

your_domain.com:443 {
    log {
        output file /home/vpn/caddy/access.log
    }
    root * /home/vpn/caddy/html
    file_server
    tls {
        protocols tls1.2 tls1.3
        ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
        curves x25519
    }
    @v2ray_websocket {
        path /ray
        header Connection *Upgrade*
        header Upgrade websocket
    }
    reverse_proxy @v2ray_websocket localhost:8888
}
  • Caddy v1.x 和 v2.x 的配置文件是不兼容的,这里我们采用的是最新的v2
  • Caddy监听 443 端口(可以是其他端口)
  • Caddy处理 TLS 之后,将流量转发到 V2Ray 的 WebSocket 所监听的内网端口,本例是8888
  • V2Ray收到请求后依然 按 Vmess 处理,V2ray服务器端不需要配置 TLS

重新加载Caddy配置

sudo caddy reload

检查证书

直接用浏览器访问这个地址,这里示例域名: yourdomain.com

https://crt.sh/?q=yourdomain.com

V2Ray客户端

更新客户端配置

{
  "inbounds": [
    {
      "port": 1080, # 监听端口
      "protocol": "socks", # 入口协议为 SOCKS 5
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls"
        ]
      },
      "settings": {
        "auth": "noauth" #socks的认证设置,noauth 代表不认证,由于 socks 通常在客户端使用,所以这里不认证
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "vmess", # 出口协议
      "settings": {
        "vnext": [
          {
            "address": "yourdomain.com", # 服务器地址,请修改为你自己的服务器域名
            "port": 443, # 服务器端口 443是https使用的端口
            "users": [
              {
                "id": "26f616e6-d668-11eb-baaf-acde48001122", # 用户 ID,必须与服务器端配置相同
                "alterId": 64 # 此处的值也应当与服务器相同
              }
            ]
          }
        ],
        "streamSettings": {
          "network": "ws",
          "security": "tls", # 客户端的 security 要设置为 tls
          "wsSettings": {
            "path": "/ray" # 注意:对于 V2Ray,/ray 和 /ray/ 是不一样的
          }
        }
      }
    }
  ]
}

新的配置修改了3个地方:(#及后面的文字为注释,json文件中不需要包含)

  • address:ip -> your_domain,把ip修改为你的域名,tls需要使用域名
  • port:8888 -> 443,443是https使用的端口,也是Caddy监听的端口
  • streamSettings添加 "security": "tls";服务端不用配,是因为tls交给Caddy处理了

注意:

  • 我们的客户端现在对接的是Caddy了,端口啥的都要和Caddy配置文件对应
  • 开启了 TLS 之后 path 参数是被加密的,WALL看不到
  • 主动探测一个 path 产生 Bad request 不能证明是 V2Ray
  • 使用 Header 分流并不比 path 安全,不要迷信 (不懂,反正教程里这么说的)

然后重启V2Ray客户端,这样访问代理的流量就跟访问普通网站一样,https/tls会加密路径信息,仅靠中间环节捕捉到的流量包极难区分是正常请求还是夹带私货的流量。 这也显示了v2ray的强大之处:通过配置不同的协议和载体,就能对进出的流量做定制。 从流量伪装、反向代理的功能上看,v2ray毫无疑问的是一个强大的网络框架/工具,科学上网功能只是其一个成功应用。