Tech 4 min read

V2Ray (WebSocket+TLS) server setup notes

IkesanContents

In the previous article, ShadowSocks server setup notes, I mentioned that V2Ray was the successor protocol. I actually ran that too, and I found my old notes, so I am putting them here.

What V2Ray is

V2Ray is a proxy tool developed as a successor to ShadowSocks. It supports multiple protocols and can disguise traffic as HTTPS using WebSocket or gRPC.

Compared with ShadowSocks:

  • ShadowSocks: simple and lightweight, with easy setup
  • V2Ray: more feature-rich and flexible. WebSocket+TLS makes censorship evasion stronger, but the configuration is more complex

Architecture

The setup is:

Client -> Cloudflare (CDN) -> Caddy (reverse proxy) -> V2Ray (WebSocket)

Putting Cloudflare in the middle gives you:

  • Hides the server’s real IP
  • Automatic SSL/TLS certificate management
  • Faster delivery through CDN caching

Server setup

These steps are for CentOS 7.

Preparation

yum update -y && yum install curl -y

Cloudflare setup

  1. Add a subdomain in Cloudflare, for example v2ray.example.com
  2. Create an A record pointing to the server IP
  3. Enable the proxy setting (orange cloud)
  4. Wait for DNS propagation

Install V2Ray

Use the 233blog script:

bash <(curl -s -L https://git.io/v2ray.sh)

Installer choices:

  1. Select 1 for V2Ray
  2. Select 4 for WebSocket+TLS
  3. Port number: press Enter for the default, or use 443
  4. Enter the subdomain, for example v2ray.example.com
  5. Then mostly proceed with Y or N
    • Auto config: Y
    • Enable ad blocking: N (optional)
    • ShadowSocks: N

Note: If Cloudflare DNS has not propagated yet, the installer will stop midway. Make sure nslookup v2ray.example.com resolves first.

Verify the install

v2ray status

If both V2Ray and Caddy are active (running), you are good.

Caddy configuration

Edit /etc/caddy/Caddyfile:

v2ray.example.com {
  root /var/www/html
  tls your-email@example.com
  log ./access.log
  timeouts none
  proxy / 127.0.0.1:54878 {
    websocket
    header_upstream -Origin
  }
}
import sites/*

Key points:

  • Replace the email address in tls with your own
  • Make sure the proxy port, 54878, matches the V2Ray config

Disable the firewall

systemctl stop firewalld
systemctl disable firewalld

Or just open the ports you need, such as 443.

Tune kernel parameters

Use the same settings as ShadowSocks. See the previous article for details.

/etc/security/limits.conf:

root soft nofile 51200
root hard nofile 51200

Set /etc/sysctl.conf to the same values as in the previous article, then run sysctl -p.

Enable BBR

v2ray bbr

Select 1 to enable BBR. A reboot is required:

reboot

Set the timezone

timedatectl set-timezone Asia/Tokyo
date  # check

Configuration files

There are two V2Ray config files:

  • /etc/v2ray/config.json - main config
  • /etc/v2ray/233blog_v2ray_config.json - config used by the 233blog script

Important: you need to set the UUID in both files or it will fail. Back them up before editing:

cp /etc/v2ray/config.json /etc/v2ray/config.json.bak
cp /etc/v2ray/233blog_v2ray_config.json /etc/v2ray/233blog_v2ray_config.json.bak

config.json structure

{
  "log": {
    "access": "/var/log/v2ray/access.log",
    "error": "/var/log/v2ray/error.log",
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "port": 54878,
      "protocol": "vmess",
      "settings": {
        "clients": [
          {
            "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "level": 1,
            "alterId": 233
          }
        ]
      },
      "streamSettings": {
        "network": "ws"
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "settings": {}
    },
    {
      "protocol": "blackhole",
      "settings": {},
      "tag": "blocked"
    }
  ],
  "dns": {
    "server": ["1.1.1.1", "1.0.0.1", "8.8.8.8", "8.8.4.4", "localhost"]
  },
  "routing": {
    "domainStrategy": "IPOnDemand",
    "rules": [
      {
        "type": "field",
        "ip": [
          "0.0.0.0/8",
          "10.0.0.0/8",
          "127.0.0.0/8",
          "192.168.0.0/16"
        ],
        "outboundTag": "blocked"
      }
    ]
  },
  "transport": {
    "kcpSettings": {
      "uplinkCapacity": 100,
      "downlinkCapacity": 100,
      "congestion": true
    },
    "sockopt": {
      "tcpFastOpen": true
    }
  }
}

Key points:

  • inbounds.port must match the port used in Caddy’s proxy
  • clients.id must be the same UUID on the client side
  • routing.rules blocks access to private IP ranges

Multiple users

Add more users to the clients array:

"clients": [
  {
    "id": "uuid-for-user1",
    "level": 1,
    "alterId": 233
  },
  {
    "id": "uuid-for-user2",
    "level": 1,
    "alterId": 233
  }
]

Unlike ShadowSocks, users are distinguished by UUID rather than by port.

Restart after changes

v2ray restart
v2ray status