V2Ray 自带的负载均衡策略只有随机选择,对于不稳定的网络而言,显然是不够的
ShadowSocks 可以使用 HAProxy 进行负载均衡,但是 V2Ray 具有多种协议,显然是不可行的
我们可以利用 Docker 的特性完成一个使用 HAProxy 进行负载均衡且可以自动维护可用节点列表(利用 HAProxy 健康检查功能 与 V2Ray 任意门)的网络
NOTE:这篇文章所有代码几乎全部复制即可用,但是我还是强烈建议仔细阅读注释
Table of Contents
负载均衡网络概述

HAProxy 可以处理 TCP 数据流,最近也添加了对 Socks 的支持(尽管我不知道怎么配置)
所以,我们可以在出口处创建多个独立的 V2Ray Docker 容器用来把 V2Ray 的其他协议都转换为 TCP 协议(或者直接使用 HTTP 代理),然后在使用 HAProxy 对其进行负载均衡。
集群配置
代码中有大量注释(几乎包含每一行参数),请仔细阅读
Docker 集群配置
这里为了方便。我们使用 Docker Compose 进行配置
/home/$USER/.config/v2ray/docker/docker-compose.yml
version: "3"
services:
v2ray: # 入口代理,也就是为用户直接提供 HTTP、Socks 等代理协议的客户端
image: v2ray/official # 使用 V2Ray 稳定版镜像
container_name: v2ray # 为容器命名为 V2Ray
restart: unless-stopped # 开机自启
depends_on:
- haproxy # 待 HAProxy 启动后再启动
ports:
- "127.0.0.1:1080:1080" # 为 Docker 容器打开 1080 本地端口的 TCP 协议访问
- "127.0.0.1:1080:1080/udp" # 1080本地端口的 UDP 协议访问
- "8118:8080" # 为局域网打开 8118 端口的 TCP 访问
- "8118:8080/udp" # 为局域网打开 8118 端口的 UDP 访问
volumes:
- /home/$USER/.config/v2ray/docker/v2ray/config.json:/etc/v2ray/config.json # 将宿主机上相对应的配置文件映射到 Docker 容器中
networks:
- app-network # 使用名为app-network 的自定义 Docker 网络
# 解释过的参数请对照理解
haproxy:
image: haproxy
container_name: haproxy
restart: unless-stopped
expose:
- "8388" # 允许在 app-network 网络中发起的 8338 端口访问 https://docs.docker.com/compose/compose-file/#expose
ports:
- "127.0.0.1:8080:8080" # 为网络管理页面做 8080 端口映射
volumes:
- /home/$USER/.config/v2ray/docker/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
networks:
- app-network
v2ray_out_0_tcp: # 处理出口流量,也就是把负载均衡过的 TCP 流量用其他协议发给对应的服务器
image: v2ray/official
container_name: v2ray_out_0_tcp
restart: unless-stopped
expose:
- "80"
- "1080"
volumes:
- /home/$UAER/.config/v2ray/docker/v2ray/config_0_tcp.json:/etc/v2ray/config.json
networks:
- app-network
v2ray_out_0_quic:
image: v2ray/official
container_name: v2ray_out_0_quic
restart: unless-stopped
expose:
- "80"
- "1080"
volumes:
- /home/$USER/.config/v2ray/docker/v2ray/config_0_quic.json:/etc/v2ray/config.json
networks:
- app-network
v2ray_out_1_tcp:
image: v2ray/official
container_name: v2ray_out_1_tcp
restart: unless-stopped
expose:
- "80"
- "1080"
volumes:
- /home/$USER/.config/v2ray/docker/v2ray/config_out_1_tcp.json:/etc/v2ray/config.json
networks:
- app-network
v2ray_out_2_tcp:
image: v2ray/official
container_name: v2ray_out_2_tcp
restart: unless-stopped
expose:
- "80"
- "1080"
volumes:
- /home/$USER/.config/v2ray/docker/v2ray/config_2_tcp.json:/etc/v2ray/config.json
networks:
- app-network
networks:
app-network: # 自定义一个 Docker 网络
driver: bridge # 网桥网络
driver_opts:
com.docker.network.bridge.name: v2ray_bridge # 为网桥自定义一个名字(不设置就是一个随机的字符串),方便主机防火墙管理
V2Ray 入口配置
这一部分可以部分参考Docker 部署 V2Ray
我们使用 V2Ray 的 TCP 协议作为中间协议(方便 HAProxy 负载均衡)
/home/$USER/.config/v2ray/docker/v2ray/config.json
{
"inbounds": [
{
"port": 1080,
"listen": "0.0.0.0",
"protocol": "socks",
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
},
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"listen": "0.0.0.0",
"port": 8080,
"protocol": "http",
"settings": {
"timeout": 0,
"allowTransparent": false,
"userLevel": 0
}
}
],
"outbounds": [
{
"protocol": "vmess",
"tag": "proxy",
"settings": {
"vnext": [
{
"address": "haproxy",
"//": "Docker 内部的路由会把 haproxy 解析为正确的 IP 地址",
"port": 8388,
"//": "这里的演示用 HAProxy 配置文件用的是 8388 端口",
"users": [
{
"alterId": 64,
"id": "2279f418-5be1-48db-92e8-c80eae89ee28",
"//": "用于容器集群内部的网络通讯,注释记得删了",
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "tcp"
},
"mux": {
"enabled": false,
"concurrency": 32,
"//": " 在这里开 mux 没有用,但是单主机 mux 可以明显提高速度,这种情况下应该在出口端配置 mux"
}
},
{
"protocol": "freedom",
"tag": "direct",
"settings": {}
}
],
"routing": {
"//": "路由就按照自己平常的习惯配置,比如全局代理还是绕过大陆网址什么的"
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"outboundTag": "proxy",
"domain": ["google.cn"]
},
{
"type": "field",
"outboundTag": "direct",
"domain": [
"geosite:cn",
"baidupan.com",
"lanzous.com"
]
},
{
"type": "field",
"outboundTag": "direct",
"ip": ["geoip:private", "geoip:cn", "192.168.0.0/24"]
}
]
}
}
HAProxy 负载均衡配置
这一部分配置可以参考用 HAProxy 为 ShadowSocks 加速
HAProxy 健康检查参考资料:HAProxy 进阶使用技巧,官方文档
/home/$USER/.config/v2ray/docker/haproxy/haproxy.cfg
defaults
mode tcp
option dontlognull
timeout connect 10s
timeout client 1m
timeout server 1m
#---------------------------------------------------------------------
frontend v2ray-in
bind 0.0.0.0:8388
default_backend v2ray-out
#---------------------------------------------------------------------
backend v2ray-out
balance leastconn
option httpchk GET http://google.com/generate_204 HTTP/1.1\r\nHost:\ google.com\r\n
server server1_name v2ray_out_0_tcp:1080 check port 80
# 这里的 v2ray_out_0_tcp,Docker 会自动解析为正确的 IP
# check 表示启用监控,port 80 表示使用 80 端口进行可用性监控
server server2_name v2ray_out_0_quic:1080 check port 80
server server3_name v2ray_out_1_tcp:1080 check port 80
server server4_name v2ray_out_2_tcp:1080 check port 80
#---------------------------------------------------------------------
listen admin_stats # 网页管理页面
bind 0.0.0.0:8080 # 如果在前面你是跟我相同配置的端口映射,启动容器后访问 http://127.0.0.1:8080/haproxy
mode http
log 127.0.0.1 local0 err
stats refresh 10s
stats uri /haproxy
stats realm welcome login\ Haproxy
stats hide-version
stats admin if TRUE
V2Ray 出口配置
配置大同小异,以 v2ray_out_0_tcp 为例
/home/$UAER/.config/v2ray/docker/v2ray/config_0_tcp.json
{
"inbounds": [
{
"port": 1080,
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "2279f418-5be1-48db-92e8-c80eae89ee28",
"//": "这里填你自己的 Docker 网络内部的中间 V2Ray TCP 协议用的 UUID",
"alterId": 64,
"security": "none",
"level": 0
}
]
}
},
{
"protocol": "dokodemo-door",
"//": "这里利用任意门将 204 流量转发到 google 实现对节点可用性的监控"
"port": 80,
"settings": {
"address": "google.com",
"port": 80,
"network": "tcp,udp",
"timeout": 300
}
}
],
"outbounds": [
{
"protocol": "vmess",
"tag": "proxy",
"settings": {
"vnext": [
{
"address": "example.com",
"port": 1080,
"//": "这里填你自己的服务器的 IP 和端口",
"users": [
{
"alterId": 64,
"id": "8a21a0a7-6392-4f96-a6f4-22a792bd1baf",
"//": "这里填你自己访问服务器用的 UUID"
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "tcp"
},
"mux": {
"//": "我们可以在出口处聚合一下 TCP 连接,实测在低速网络下效果非常显著,代理网络能够更加稳定 https://guide.v2fly.org/advanced/mux.html"
"enabled": true,
"concurrency": 64
}
},
{
"protocol": "freedom",
"tag": "direct",
"settings": {}
}
],
"routing": {
"//": "我们已经在 V2Ray 入口配置里配置了路由,这里的路由可以不设置,以提高效率,就好象服务端一样,我这里有只是为了放注释 2333"
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"outboundTag": "direct",
"ip": ["geoip:private"]
}
]
}
}
运行集群
以下命令必须要在 docker-compose.yml 文件相对应的目录下才能正常执行
docker-compose up -d # 运行集群,“-d”是后台运行。如果要调试代码,不加“-d”即可
docker-compose stop # 停止集群
结语
Docker 配置灵活方便,是不错的应用容器。
这里主要需要注意两点:
- Docker Compose 配置里的 expose 参数
- Docker Compose 以服务名作为路由,例如 docker-compose.yml 配置文件开头的 “services”(找不到可以搜索一下该网页)
发表回复