调用 V2Ray 提供的 API 接口进行用户增删及流量统计查询操作

  • 一个叫 api 的顶级配置项
  • 一个 dokodemo-door inboundDetour
  • routing 里一个以 inboundTag 为匹配项的路由配置
{
"api": {
"services": [
"HandlerService"
],
"tag": "api"
},
"inbound": {
"port": 10086,
"protocol": "vmess",
"settings": {
"clients": [
{
"alterId": 32,
"id": "fcecbd2b-3a34-4201-bd3d-7c67d89c26ba",
"level": 0
}
]
},
"streamSettings": {
"network": "tcp"
},
"tag": "proxy"
},
"inboundDetour": [
{
"listen": "127.0.0.1",
"port": 10085,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api"
}
],
"log": {
"loglevel": "debug"
},
"outbound": {
"protocol": "freedom",
"settings": {}
},
"routing": {
"settings": {
"rules": [
{
"inboundTag": [
"api"
],
"outboundTag": "api",
"type": "field"
}
]
},
"strategy": "rules"
}
}
  • 当有顶级 api 配置项时,V2Ray 会自动创建一个以 api.tagtag 来标识的 outbound
  • 当有 API 请求发到 dokodemo-door 所监听的端口时,会理所当然地匹配到路由中配置的 api -> api 一项,所以 API 请求会从 dokodemo-door 被路由到上面所提到的 V2Ray 自动创建的 outbound 中,然后所有发送到这个 outbound 的请求都会被当作 gRPC API 请求处理。
  • 其中 dokodemo-doorsettings.address 可以随便填,因为在做路由时只用 inboundTag ,而不会用到这个地址(但必需要有一个合法地址值,不然会报错,这只是代码实现上的问题不用在意)
package mainimport (
"context"
"fmt"
"log"
"google.golang.org/grpc" "v2ray.com/core/app/proxyman/command"
"v2ray.com/core/common/protocol"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy/vmess"
)
const (
API_ADDRESS = "127.0.0.1"
API_PORT = 10085
INBOUND_TAG = "proxy" LEVEL = 0
EMAIL = "123@gmail.com"
UUID = "2601070b-ab53-4352-a290-1d44414581ee"
ALTERID = 32
)
func addUser(c command.HandlerServiceClient) {
resp, err := c.AlterInbound(context.Background(), &command.AlterInboundRequest{
Tag: INBOUND_TAG,
Operation: serial.ToTypedMessage(&command.AddUserOperation{
User: &protocol.User{
Level: LEVEL,
Email: EMAIL,
Account: serial.ToTypedMessage(&vmess.Account{
Id: UUID,
AlterId: ALTERID,
SecuritySettings: &protocol.SecurityConfig{Type: protocol.SecurityType_AUTO},
}),
},
}),
})
if err != nil {
log.Printf("failed to call grpc command: %v", err)
} else {
log.Printf("ok: %v", resp)
}
}
func removeUser(c command.HandlerServiceClient) {
resp, err := c.AlterInbound(context.Background(), &command.AlterInboundRequest{
Tag: INBOUND_TAG,
Operation: serial.ToTypedMessage(&command.RemoveUserOperation{
Email: EMAIL,
}),
})
if err != nil {
log.Printf("failed to call grpc command: %v", err)
} else {
log.Printf("ok: %v", resp)
}
}
func main() {
cmdConn, err := grpc.Dial(fmt.Sprintf("%s:%d", API_ADDRESS, API_PORT), grpc.WithInsecure())
if err != nil {
panic(err)
}
hsClient := command.NewHandlerServiceClient(cmdConn)
addUser(hsClient)
// removeUser(hsClient)
}
  • 代码中可以看到,要操作的是 tagproxyinbound ,也就是说增加的用户会被配置到这个 inbound
  • 需要用 email 字段来区别用户
  • 删除用户后,并不会“立刻生效”,需要等几分钟;现在 Core 的代码实现中,删除用户操作仅仅是把用户从用户列表中移除,但没有把对应的 auth session 移除,这样的话就需要等这些 session 超时后,这个用户才会无法认证
V2RAY_RAY_BUFFER_SIZE=1 v2ray -config cfg.json

2018.5 update(流量统计信息查询):

流量统计信息查询跟增删用户的配置方法非常相似,具体可以参考这个完整配置文件:https://gist.github.com/eycorsican/aa8cdc1d39c3fa355c499f89a15b9753

v2ctl api --server=127.0.0.1:10085 StatsService.GetStats 'name: "user>>>123@gmail.com>>>traffic>>>downlink" reset: false'
  • reset 表示是否在获取此用户的统计信息后把统计值重置为 0
  • 请注意在查询流量前要先使对应的用户产生一些流量,否则返回为空值。

--

--

eric.y.corsican@gmail.com https://twitter.com/TachyonDevel

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store