Set up V2Ray with Caddy 2 (TLS+WS+Web) on Ubuntu 20.04

This guide covers how to install and config V2Ray for Caddy 2, with TLS automatically enabled by the Caddy 2 web server, plus WebSocket for data encryption and extra protection 😁

Background

V2Ray is the core of Project V, which is a set of tools to build your own privacy network over Internet. V2Ray supports multiple inbound/outbound proxies with customization routing. It also supports obfuscation, reverse proxy and multiple protocols, such as Socks, Shadowsocks, VMess, etc. It is deemed by most as the best tool (at least for now) to circumvent Internet censorship. The intent of this guide is to demo its capability and for knowledge sharing purpose only.

There are many ways to configure V2Ray to satisfy various needs with varying degrees of complexities. Currently, the most secure and reliable configuration involves encrypting the internet traffic with the V2Ray’s built-in VMESS protocol, then wrapping it inside HTTPS/TLS so the actual data cannot be decrypted even when the data was intercepted by GFW or ISVs. The traffic itself will look like normal HTTPS traffic going back-and-forth between your overseas web servers and your local devices.

Caddy is a powerful, enterprise-ready, open source web server with automatic HTTPS. It provides an easy way to set up a full-fledged web sever with HTTPS automatically enabled and is much easier to set up than NGINX or Apache for a HTTPS website, as it can obtain and renew TLS certificates for your sites automatically with great performance.

The encrypted traffic wrapped inside TLS from V2Ray will be picked up by the web server, then redirected to the Web Socket that V2Ray is listening on through the reverse proxy capability provided by Caddy. With Caddy, you could also set up your own website at the web server IP address to provide additional camouflage if desired.

1. Install V2Ray on the server

The V2Ray binaries can be used at both the server and the client side. You’ll only need to modify the config.json to set up the “data flow” with data inbound and outbound rules. To install V2Ray on an Ubuntu server, running 20.04:

$ wget https://install.direct/go.sh
$ sudo bash go.sh
$ sudo systemctl start v2ray

Later, you can use the go.sh script to update V2Ray. This can be quite handy as the v2-ray project is constantly being updated for bugs fixes and new feature additions.

2. Install Caddy 2 web server with TLS

Installing Caddy 2 web server and setting it up is covered in a previous blog post, which you can find in this step-by-step guide. Note you do not need to use the simple Caddyfile provided by the above guide. Instead, you will use a modified version of the Caddyfile tailored work with V2Ray, as shown in Section 4. After Caddy 2 installation and a proper Caddyfile configured, the server should automatically have HTTPS / TLS enabled, to secure the data transmitted with V2Ray.

Don’t forget to open the TLS port 443 through the local/cloud firewall to allow the HTTPS traffic to go through.

3. Install V2-UI to manage V2Ray (optional)

V2-UI is a web panel that helps provide easy management of multi-user, multi-protocol v2ray configuration on the v2ray server. It also provides networking bandwidth tracking on a per user basis (SSID).

To install v2-ui, run the following:

$ wget https://github.com/sprov065/v2-ui/releases/download/5.1.2/v2-ui-linux.tar.gz
$ tar zxvf v2-ui-linux.tar.gz
$ rm v2-ui-linux.tar.gz -f
$ cd v2-ui
$ chmod +x v2-ui
$ sudo cp -f v2-ui.service /etc/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl enable v2-ui
$ sudo systemctl restart v2-ui 
$ sudo curl -o /usr/bin/v2-ui -Ls https://raw.githubusercontent.com/sprov065/v2-ui/master/v2-ui.sh
$ sudo chmod +x /usr/bin/v2-ui

Then you can start v2-ui by running $ sudo v2-ui. If the v2-ui service is not running, you can update v2-ui through the CLI tool.

After confirming the portal is running, you can access the web portal via https://yourdomain.com:65432 (make sure the port is open through local/cloud firewall, with admin as the username and password). You can change the login credential in the web portal via Panel Settings.

4. Configure Caddyfile for V2Ray and Caddy 2

Caddy can be configured by using the Caddyfile. There are some changes in Caddy v2 so some of the Caddyfile provided by other online tutorials would likely not work. You can use the following Caddyfile to set up the reverse proxy to redirect traffic to V2Ray’s Web Socket.

yourdomain.com {
    log {
        output file /var/log/caddy/site-access.log 
    }

    encode zstd gzip
    root * /var/www/

    # v2-ui config
    redir /v2-ui /v2-ui/ 
    @v2-ui {
       path /v2-ui/*
    }
    reverse_proxy @v2-ui localhost:65432

    # ws config for a single user
    @v2ray {
        path /ray
        header Connection Upgrade
        header Upgrade websocket
    }
    reverse_proxy @v2ray localhost:12345

    # Enable the static file server.
    file_server 
}

5. Server side V2Ray Config through V2-UI

The V2Ray on the Server side can be configured by modifying the config.json located inside the /etc/v2ray/ folder or by using v2-ui through the web portal. Modifying the configuration through v2-ui web portal will overwrite the existing V2Ray config.json.

To configure V2Ray using V2-UI, log on to V2-UI by accessing https://yourdomain.com/v2-ui.

Under “Panel Settings”, make sure the “Web root path” matches what is configured in Caddy via reverse_proxy. Then you can change the “Listening IP” to 127.0.0.1 so that the outside world cannot access the panel directly, by only by using the reverse_proxy enabled by Caddy.

Under “Accounts”, click the plus sign to add a user and use the following config.

V2-UI configuration to add an account with TLS + WS

Note that the port, and web socket (ws) path should match what is configured in the Caddyfile (refer to Section 4). You should also note the id (in SSID form) as it will be used to configure V2Ray on the client side. There is not need to enable the “tls” option, as the web server should already be protected by TLS provided automatically by Caddy 2.

6. Set up V2Ray on the client side

Depending on the client device’s architecture and OS platform, you could download V2Ray client from the V2Ray’s official release. For Windows, you could download the v2ray-windows-32.zip for 32-bit Windows or v2ray-windows-64.zip for 64-bit Windows.

After the archive is extracted, you should see a config.json inside the folder. For starters, you’ll only need to change the outbounds section of the file. The full config.json is provided below.

// Config file of V2Ray. This file follows standard JSON format, with comments support.
// Uncomment entries below to satisfy your needs. Also read our manual for more detail at
// https://www.v2ray.com/
{
  "log": {
    // By default, V2Ray writes access log to stdout.
    // "access": "/path/to/access/log/file",

    // By default, V2Ray write error log to stdout.
    // "error": "/path/to/error/log/file",

    // Log level, one of "debug", "info", "warning", "error", "none"
    "loglevel": "warning"
  },
  // List of inbound proxy configurations.
  "inbounds": [{
    // Port to listen on. You may need root access if the value is less than 1024.
    "port": 1080,

    // IP address to listen on. Change to "0.0.0.0" to listen on all network interfaces.
    "listen": "127.0.0.1",

    // Tag of the inbound proxy. May be used for routing.
    "tag": "socks-inbound",

    // Protocol name of inbound proxy.
    "protocol": "socks",

    // Settings of the protocol. Varies based on protocol.
    "settings": {
      "auth": "noauth",
      "udp": false,
      "ip": "127.0.0.1"
    },

    // Enable sniffing on TCP connection.
    "sniffing": {
      "enabled": true,
      // Target domain will be overriden to the one carried by the connection, if the connection is HTTP or HTTPS.
      "destOverride": ["http", "tls"]
    }
  }],

  // List of outbound proxy configurations.
  "outbounds": [{
    // Protocol name of the outbound proxy.
    //"protocol": "freedom",
    "protocol": "vmess",
    "mux": {"enabled": true}, 
    // Settings of the protocol. Varies based on protocol.
    //"settings": {},
    "settings": {
        "vnext": [{
            "address": "yourdomain.com", // modify this to yourdomain.com
            "port": 443,  // TLS port 
            "users": [{
                "id": "your_SSID",  // Change this to the "id" from v2-UI, which should follow SSID format
                "alterId": 64 // This value should be the same with the server
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",  // Hinting we are using WebSocket
        "security": "tls", // Hinting we have TLS
        "wsSettings": {
          "path": "/ray" // This should match what's configured in V2-UI and Caddyfile's reverse_proxy
        }
      }
  },{
    "protocol": "freedom",
    "tag": "direct",
    "settings": {}
  },{
    "protocol": "blackhole",
    "settings": {},
    "tag": "blocked"
  }],

  // Transport is for global transport settings. If you have multiple transports with same settings
  // (say mKCP), you may put it here, instead of in each individual inbound/outbounds.
  //"transport": {},

  // Routing controls how traffic from inbounds are sent to outbounds.
  "routing": {
    "domainStrategy": "IPOnDemand",
    "rules":[{
        // Blocks access to private IPs. Remove this if you want to access your router.
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        // Blocks major ads.
        "type": "field",
        "domain": ["geosite:category-ads"],
        "outboundTag": "blocked"
      }
    ]
  },

  // Dns settings for domain resolution.
  "dns": {
    // Static hosts, similar to hosts file.
    "hosts": {
      // Match v2ray.com to another domain on CloudFlare. This domain will be used when querying IPs for v2ray.com.
      "domain:v2ray.com": "www.vicemc.net",

      // The following settings help to eliminate DNS poisoning in mainland China.
      // It is safe to comment these out if this is not the case for you.
      "domain:github.io": "pages.github.com",
      "domain:wikipedia.org": "www.wikimedia.org",
      "domain:shadowsocks.org": "electronicsrealm.com"
    },
    "servers": [
      "1.1.1.1",
      {
        "address": "114.114.114.114",
        "port": 53,
        // List of domains that use this DNS first.
        "domains": [
          "geosite:cn"
        ]
      },
      "8.8.8.8",
      "localhost"
    ]
  },

  // Policy controls some internal behavior of how V2Ray handles connections.
  // It may be on connection level by user levels in 'levels', or global settings in 'system.'
  "policy": {
    // Connection policys by user levels
    "levels": {
      "0": {
        "uplinkOnly": 0,
        "downlinkOnly": 0
      }
    },
    "system": {
      "statsInboundUplink": false,
      "statsInboundDownlink": false
    }
  },

  // Stats enables internal stats counter.
  // This setting can be used together with Policy and Api. 
  //"stats":{},

  // Api enables gRPC APIs for external programs to communicate with V2Ray instance.
  //"api": {
    //"tag": "api",
    //"services": [
    //  "HandlerService",
    //  "LoggerService",
    //  "StatsService"
    //]
  //},

  // You may add other entries to the configuration, but they will not be recognized by V2Ray.
  "other": {}
}

Congratulations!

You could simply run v2ray.exe and change your proxy settings to SOCKS 5 @ 127.0.0.1:1080 to enjoy the freedom of Internet. There are many tutorials about how to configure a SOCKS 5 proxy on Windows, so I won’t cover the details here. As you can see, the setup of V2Ray using Caddy 2 with automatic TLS is quite simple compared to other web server stacks such as NGINX and Apache.

One final note – please be responsible and considerate for your actions and behaviors as always, even if those are online.

Any questions? Feel free to leave a comment below.

Leave a Reply