├── README.md
├── docs
├── HandlerService.md
├── LoggerService.md
└── StatsService.md
├── examples
├── addInbound.go
├── addInbound_test.go
├── alterInbound.go
├── alterInbound_test.go
├── getSystemStats.go
├── getSystemStats_test.go
├── init.go
├── queryTraffic.go
├── queryTraffic_test.go
├── removeInbound.go
├── removeInbound_test.go
├── restartLogger.go
├── restartLogger_test.go
└── structures.go
└── go.mod
/README.md:
--------------------------------------------------------------------------------
1 | # Xray-API-documents
2 | ## 写在开头
3 | 使用API是一个技术活, 请在编写相关程序前对 Xray 配置有所了解
4 | [点我了解](https://xtls.github.io/about/)
5 | 以及你至少会一门支持grpc的语言, 这里以 Golang 为例, ~~因为他比较方便~~.
6 |
7 | ## 文档
8 | 说明文档在 docs 目录下
9 | 相关示例在 example 目录下, 每一个方法都对应一个test文件演示完整的过程
10 |
11 | ## 其他说明
12 | - 请尽量不要并发执行, 经过测试,大约在第10个线程后,Xray内核会丢弃多余的请求
13 |
14 | 相关问题请提issue.
--------------------------------------------------------------------------------
/docs/HandlerService.md:
--------------------------------------------------------------------------------
1 | # HandlerService
2 | > 这部分控制由 HandlerServiceClient 承载
3 |
4 | 支持的接口方法
5 | ```shell
6 | AddInbound()
7 | RemoveInbound()
8 | AlterInbound()
9 | AddOutbound()
10 | RemoveOutbound()
11 | AlterOutbound()
12 | ```
13 |
14 | ## AddInbound
15 | 此方法使用 InboundHandlerConfig 配置增加一个入站。
16 |
17 | ## RemoveInbound
18 | 移除一个入站,使用 Tag 区分。
19 |
20 | ## AlterInbound
21 | 在一个入站代理中添加一个用户 (VMess, VLESS, Trojan, ShadowSocks)
22 |
23 | > Outbound 同理
--------------------------------------------------------------------------------
/docs/LoggerService.md:
--------------------------------------------------------------------------------
1 | # LoggerService
2 | > 这部分控制由 LoggerServiceClient 承载
3 |
4 | 支持的接口方法
5 | ```shell
6 | restartLogger()
7 | ```
8 | ## restartLogger
9 | 重启日志服务。
10 |
--------------------------------------------------------------------------------
/docs/StatsService.md:
--------------------------------------------------------------------------------
1 | # StatsService
2 | > 这部分控制由 StatsServiceClient 承载
3 |
4 | 支持接口的方法:
5 | ```shell
6 | QueryStats()
7 | GetSysStats()
8 | ```
9 |
10 | ## QueryStats
11 | 查询用户的上下行流量,与 Inbound 和 Outbound 上下行流量。
12 |
13 | ## GetSysStats
14 | 获取Xray运行数据。
15 |
--------------------------------------------------------------------------------
/examples/addInbound.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "context"
5 | "github.com/xtls/xray-core/app/proxyman"
6 | "github.com/xtls/xray-core/app/proxyman/command"
7 | "github.com/xtls/xray-core/common/net"
8 | protocol "github.com/xtls/xray-core/common/protocol"
9 | "github.com/xtls/xray-core/common/protocol/tls/cert"
10 | "github.com/xtls/xray-core/common/serial"
11 | "github.com/xtls/xray-core/core"
12 | _ "github.com/xtls/xray-core/infra/conf"
13 | "github.com/xtls/xray-core/proxy/vmess"
14 | //ssInbound "github.com/xtls/xray-core/proxy/shadowsocks"
15 | //trojanInbound "github.com/xtls/xray-core/proxy/trojan"
16 | vmessInbound "github.com/xtls/xray-core/proxy/vmess/inbound"
17 | "github.com/xtls/xray-core/transport/internet"
18 | _ "github.com/xtls/xray-core/transport/internet/tcp"
19 | "github.com/xtls/xray-core/transport/internet/tls"
20 | "github.com/xtls/xray-core/transport/internet/websocket"
21 | )
22 |
23 | func addInbound(client command.HandlerServiceClient) error {
24 |
25 | _, err := client.AddInbound(context.Background(), &command.AddInboundRequest{
26 | Inbound: &core.InboundHandlerConfig{
27 | Tag: "proxy0",
28 | ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
29 | // 监听端口 12345
30 | PortRange: net.SinglePortRange(net.Port(12360)),
31 | // 监听地址, 默认0.0.0.0
32 | Listen: net.NewIPOrDomain(net.AnyIP),
33 | // 流量探测
34 | SniffingSettings: &proxyman.SniffingConfig{
35 | Enabled: true,
36 | DestinationOverride: []string{"http", "tls"},
37 | },
38 | // 传输方式
39 | StreamSettings: &internet.StreamConfig{
40 | /*
41 | 传输方式名称
42 | 请自行在 github.com/xtls/xray-core/transport/internet/config.pb.go 中寻找支持的协议
43 | 截至 1.3.0 目前支持
44 | "TCP",
45 | "UDP",
46 | "MKCP",
47 | "WebSocket",
48 | "HTTP",
49 | "DomainSocket"
50 | 使用时请一律小写
51 |
52 | */
53 | ProtocolName: "websocket",
54 | TransportSettings: []*internet.TransportConfig{
55 | {
56 | ProtocolName: "websocket",
57 | /*
58 | 选定传输方式后,请去 github.com/xtls/xray-core/transport/internet 下你选定方式的文件夹中导入config结构
59 | 如选定WebSocket则需要使用 github.com/xtls/xray-core/transport/internet/websocket/config.pb.go 中的 Config struct
60 | 结构内容请自行翻看代码(Ctrl + 左键)
61 | */
62 | Settings: serial.ToTypedMessage(&websocket.Config{
63 | Path: "/web",
64 | Header: []*websocket.Header{
65 | {
66 | Key: "Host",
67 | Value: "www.xray.best",
68 | },
69 | },
70 | AcceptProxyProtocol: false,
71 | },
72 | ),
73 | },
74 | },
75 | /*
76 | 传输层加密
77 | 请在 github.com/xtls/xray-core/transport/internet/ 中选择合适的传输层加密方式
78 | 截至1.3.0 目前支持
79 | TLS
80 | XTLS
81 | 留空即为None
82 | */
83 | SecurityType: serial.GetMessageType(&tls.Config{}),
84 | SecuritySettings: []*serial.TypedMessage{
85 | serial.ToTypedMessage(&tls.Config{
86 | //Auto build
87 | Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
88 | }),
89 | },
90 | },
91 | }),
92 | /*
93 | 代理设置, 请到 github.com/xtls/xray-core/proxy/ 寻找你想要添加的入站代理类型
94 | 某些类型需要区分 Inbound 与 Outbound 的配置,
95 | 需要区分使用 github.com/xtls/xray-core/proxy/PROXYTYPE/inbound/config.pb.go 中的 Config 结构
96 | 无须区分的使用 github.com/xtls/xray-core/proxy/PROXYTYPE/config.pb.go 的 ServerConfig 结构
97 | */
98 | ProxySettings: serial.ToTypedMessage(&vmessInbound.Config{
99 | User: []*protocol.User{
100 | {
101 | Level: 0,
102 | Email: "love@xray.com",
103 | Account: serial.ToTypedMessage(&vmess.Account{
104 | Id: "10354ac4-9ec1-4864-ba3e-f5fd35869ef8",
105 | AlterId: 1,
106 | }),
107 | },
108 | },
109 | }),
110 | },
111 | })
112 |
113 | return err
114 | }
115 |
--------------------------------------------------------------------------------
/examples/addInbound_test.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import "testing"
4 |
5 | func TestAddInbound(t *testing.T) {
6 | // 先指定 API 端口和地址
7 | var (
8 | xrayCtl *XrayController
9 | cfg = &BaseConfig{
10 | APIAddress: "127.0.0.1",
11 | APIPort: 10085,
12 | }
13 | )
14 | // 初始化 Clients
15 | xrayCtl = new(XrayController)
16 | err := xrayCtl.Init(cfg)
17 | defer xrayCtl.CmdConn.Close()
18 | if err != nil {
19 | t.Errorf("Failed %s", err)
20 | }
21 | // 此处为执行命令部分
22 | err = addInbound(xrayCtl.HsClient)
23 | if err != nil {
24 | t.Errorf("Failed %s", err)
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/examples/alterInbound.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "context"
5 | "github.com/xtls/xray-core/app/proxyman/command"
6 | "github.com/xtls/xray-core/common/protocol"
7 | "github.com/xtls/xray-core/common/serial"
8 | "github.com/xtls/xray-core/proxy/shadowsocks"
9 | "github.com/xtls/xray-core/proxy/trojan"
10 | "github.com/xtls/xray-core/proxy/vmess"
11 | )
12 |
13 | // 这部分非常简单, 请先去 structure.go 下查看 UserInfo 结构信息
14 |
15 | func addVmessUser(client command.HandlerServiceClient, user *UserInfo) error {
16 | _, err := client.AlterInbound(context.Background(), &command.AlterInboundRequest{
17 | // 先确定哪个入站端口将要添加用户
18 | Tag: user.InTag,
19 | // 添加用户操作 github.com/xtls/xray-core/app/proxyman/command 中的 AddUserOperation
20 | Operation: serial.ToTypedMessage(&command.AddUserOperation{
21 | User: &protocol.User{
22 | // 用户信息(Level和Email为所有入站用户都需要的信息)
23 | Level: user.Level,
24 | Email: user.Email,
25 | /* 不同代理类型使用不同的用户信息结构
26 | 请在 github.com/xtls/xray-core/proxy/PROXYTYPE 下寻找 Account 结构体
27 | */
28 | Account: serial.ToTypedMessage(&vmess.Account{
29 | Id: user.Uuid,
30 | AlterId: user.AlertId,
31 | }),
32 | },
33 | }),
34 | })
35 | return err
36 | }
37 |
38 | func addSSUser(client command.HandlerServiceClient, user *UserInfo) error {
39 | var ssCipherType shadowsocks.CipherType
40 | switch user.CipherType {
41 | case "aes-128-gcm":
42 | ssCipherType = shadowsocks.CipherType_AES_128_GCM
43 | case "aes-256-gcm":
44 | ssCipherType = shadowsocks.CipherType_AES_256_GCM
45 | case "chacha20-ietf-poly1305":
46 | ssCipherType = shadowsocks.CipherType_CHACHA20_POLY1305
47 | }
48 |
49 | _, err := client.AlterInbound(context.Background(), &command.AlterInboundRequest{
50 | Tag: user.InTag,
51 | Operation: serial.ToTypedMessage(&command.AddUserOperation{
52 | User: &protocol.User{
53 | Level: user.Level,
54 | Email: user.Email,
55 | Account: serial.ToTypedMessage(&shadowsocks.Account{
56 | Password: user.Password,
57 | CipherType: ssCipherType,
58 | }),
59 | },
60 | }),
61 | })
62 | return err
63 | }
64 |
65 | func addTrojanUser(client command.HandlerServiceClient, user *UserInfo) error {
66 | _, err := client.AlterInbound(context.Background(), &command.AlterInboundRequest{
67 | Tag: user.InTag,
68 | Operation: serial.ToTypedMessage(&command.AddUserOperation{
69 | User: &protocol.User{
70 | Level: user.Level,
71 | Email: user.Email,
72 | Account: serial.ToTypedMessage(&trojan.Account{
73 | Password: user.Uuid,
74 | }),
75 | },
76 | }),
77 | })
78 | return err
79 | }
80 |
81 | // Email 为用户唯一标识符, 使用Email配合用户入站Tag来删除用户
82 |
83 | func removeUser(client command.HandlerServiceClient, user *UserInfo) error {
84 | _, err := client.AlterInbound(context.Background(), &command.AlterInboundRequest{
85 | Tag: user.InTag,
86 | Operation: serial.ToTypedMessage(&command.RemoveUserOperation{
87 | Email: user.Email,
88 | }),
89 | })
90 | return err
91 | }
92 |
--------------------------------------------------------------------------------
/examples/alterInbound_test.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import "testing"
4 |
5 | func TestAlertInbound(t *testing.T) {
6 | var (
7 | xrayCtl *XrayController
8 | cfg = &BaseConfig{
9 | APIAddress: "127.0.0.1",
10 | APIPort: 10085,
11 | }
12 | user = UserInfo{
13 | Uuid: "10354ac4-9ec1-4864-ba3e-f5fd35869ef8",
14 | AlertId: 0,
15 | Level: 0,
16 | InTag: "proxy0",
17 | Email: "love@xray.com",
18 | CipherType: "aes-256-gcm",
19 | Password: "xrayisthebest",
20 | }
21 | )
22 | xrayCtl = new(XrayController)
23 | err := xrayCtl.Init(cfg)
24 | defer xrayCtl.CmdConn.Close()
25 | if err != nil {
26 | t.Errorf("Failed %s", err)
27 | }
28 | err = addVmessUser(xrayCtl.HsClient, &user)
29 | if err != nil {
30 | t.Errorf("Failed %s", err)
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/examples/getSystemStats.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "context"
5 | statsService "github.com/xtls/xray-core/app/stats/command"
6 | )
7 |
8 | /*
9 | 获取运行数据, 如下
10 | NumGoroutine:17 NumGC:2 Alloc:1711192 TotalAlloc:2359880 Sys:14440840 Mallocs:19101 Frees:7242 LiveObjects:11859 PauseTotalNs:4983200 Uptime:31
11 | */
12 | func getSysStats(c statsService.StatsServiceClient) (stats *statsService.SysStatsResponse, err error) {
13 | stats, err = c.GetSysStats(context.Background(), &statsService.SysStatsRequest{})
14 |
15 | return
16 | }
17 |
--------------------------------------------------------------------------------
/examples/getSystemStats_test.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestGetSysStats(t *testing.T) {
9 | var (
10 | xrayCtl *XrayController
11 | cfg = &BaseConfig{
12 | APIAddress: "127.0.0.1",
13 | APIPort: 10085,
14 | }
15 | )
16 | xrayCtl = new(XrayController)
17 | err := xrayCtl.Init(cfg)
18 | defer xrayCtl.CmdConn.Close()
19 | if err != nil {
20 | t.Errorf("Failed %s", err)
21 | }
22 | SysStats, err := getSysStats(xrayCtl.SsClient)
23 | if err != nil {
24 | t.Errorf("Failed %s", err)
25 | }
26 | fmt.Println(SysStats)
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/examples/init.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "fmt"
5 | loggerService "github.com/xtls/xray-core/app/log/command"
6 | handlerService "github.com/xtls/xray-core/app/proxyman/command"
7 | routingService "github.com/xtls/xray-core/app/router/command"
8 | statsService "github.com/xtls/xray-core/app/stats/command"
9 | "google.golang.org/grpc"
10 | )
11 |
12 | // 取得API操作的Client
13 |
14 | func (xrayCtl *XrayController) Init(cfg *BaseConfig) (err error) {
15 | // 先取得ClientConn, 用完记得close
16 | xrayCtl.CmdConn, err = grpc.Dial(fmt.Sprintf("%s:%d", cfg.APIAddress, cfg.APIPort), grpc.WithInsecure())
17 | if err != nil {
18 | return err
19 | }
20 |
21 | // 依次获取API Client, 可根据需求删减
22 | xrayCtl.HsClient = handlerService.NewHandlerServiceClient(xrayCtl.CmdConn)
23 | xrayCtl.SsClient = statsService.NewStatsServiceClient(xrayCtl.CmdConn)
24 | xrayCtl.LsClient = loggerService.NewLoggerServiceClient(xrayCtl.CmdConn)
25 | //Not implement
26 | xrayCtl.RsClient = routingService.NewRoutingServiceClient(xrayCtl.CmdConn)
27 |
28 | return
29 | }
30 |
--------------------------------------------------------------------------------
/examples/queryTraffic.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "context"
5 | statsService "github.com/xtls/xray-core/app/stats/command"
6 | )
7 |
8 | /*
9 | 先按照 https://xtls.github.io/config/base/policy/ 打开入/出 站或用户流量统计
10 | 请参照 https://xtls.github.io/config/base/stats/ 来生成一条查询语句, 例如
11 | “user>>>love@xray.com>>>traffic>>>uplink” 查询 email 为 love@xray.com 的用户在所有的入站中的上行流量
12 | 可以选择在查询完之后重置流量信息。
13 |
14 | 目前支持 User, Inbound, Outbound 的上下行流量查询
15 | */
16 |
17 | func queryTraffic(c statsService.StatsServiceClient, ptn string, reset bool) (traffic int64, err error) {
18 | // 如果查无此用户或 bound 则返回-1, 默认值 -1
19 | traffic = -1
20 | resp, err := c.QueryStats(context.Background(), &statsService.QueryStatsRequest{
21 | // 这里是查询语句,例如 “user>>>love@xray.com>>>traffic>>>uplink” 表示查询用户 email 为 love@xray.com 在所有入站中的上行流量
22 | Pattern: ptn,
23 | // 是否重置流量信息(true, false),即完成查询后是否把流量统计归零
24 | Reset_: reset, // reset traffic data everytime
25 | })
26 | if err != nil {
27 | return
28 | }
29 | // Get traffic data
30 | stat := resp.GetStat()
31 | // 判断返回 是否成功
32 | // 返回样例,value 值是我们需要的: [name:"inbound>>>proxy0>>>traffic>>>downlink" value:348789]
33 | if len(stat) != 0 {
34 | // 返回流量数据 byte
35 | traffic = stat[0].Value
36 | }
37 |
38 | return
39 | }
40 |
--------------------------------------------------------------------------------
/examples/queryTraffic_test.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestQueryTraffic(t *testing.T) {
9 | var (
10 | xrayCtl *XrayController
11 | cfg = &BaseConfig{
12 | APIAddress: "127.0.0.1",
13 | APIPort: 10085,
14 | }
15 | )
16 | xrayCtl = new(XrayController)
17 | err := xrayCtl.Init(cfg)
18 | defer xrayCtl.CmdConn.Close()
19 | if err != nil {
20 | t.Errorf("Failed %s", err)
21 | }
22 | ptn := "inbound>>>proxy0>>>traffic>>>downlink"
23 | trafficData, err := queryTraffic(xrayCtl.SsClient, ptn, false)
24 | if err != nil {
25 | t.Errorf("Failed %s", err)
26 | }
27 | fmt.Println(trafficData)
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/examples/removeInbound.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "context"
5 | "github.com/xtls/xray-core/app/proxyman/command"
6 | )
7 |
8 | // 使用 Tag 操作,非常简单
9 | func removeInbound(client command.HandlerServiceClient, tag string) error {
10 | _, err := client.RemoveInbound(context.Background(), &command.RemoveInboundRequest{
11 | Tag: tag,
12 | })
13 | return err
14 | }
15 |
--------------------------------------------------------------------------------
/examples/removeInbound_test.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import "testing"
4 |
5 | func TestRemoveInbound(t *testing.T) {
6 | var (
7 | xrayCtl *XrayController
8 | cfg = &BaseConfig{
9 | APIAddress: "127.0.0.1",
10 | APIPort: 10085,
11 | }
12 | tag = "proxy0"
13 | )
14 | xrayCtl = new(XrayController)
15 | err := xrayCtl.Init(cfg)
16 | defer xrayCtl.CmdConn.Close()
17 | if err != nil {
18 | t.Errorf("Failed %s", err)
19 | }
20 | err = removeInbound(xrayCtl.HsClient, tag)
21 | if err != nil {
22 | t.Errorf("Failed %s", err)
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/examples/restartLogger.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "context"
5 | loggerService "github.com/xtls/xray-core/app/log/command"
6 | )
7 |
8 | func restartLogger(c loggerService.LoggerServiceClient) (err error) {
9 | _, err = c.RestartLogger(context.Background(), &loggerService.RestartLoggerRequest{})
10 |
11 | return
12 | }
13 |
--------------------------------------------------------------------------------
/examples/restartLogger_test.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestRestartLogger(t *testing.T) {
8 | var (
9 | xrayCtl *XrayController
10 | cfg = &BaseConfig{
11 | APIAddress: "127.0.0.1",
12 | APIPort: 10085,
13 | }
14 | )
15 | xrayCtl = new(XrayController)
16 | err := xrayCtl.Init(cfg)
17 | defer xrayCtl.CmdConn.Close()
18 | if err != nil {
19 | t.Errorf("Failed %s", err)
20 | }
21 | err = restartLogger(xrayCtl.LsClient)
22 | if err != nil {
23 | t.Errorf("Failed %s", err)
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/examples/structures.go:
--------------------------------------------------------------------------------
1 | package examples
2 |
3 | import (
4 | loggerService "github.com/xtls/xray-core/app/log/command"
5 | handlerService "github.com/xtls/xray-core/app/proxyman/command"
6 | routingService "github.com/xtls/xray-core/app/router/command"
7 | statsService "github.com/xtls/xray-core/app/stats/command"
8 | "google.golang.org/grpc"
9 | )
10 |
11 | // Xray API 监听地址及端口
12 | type BaseConfig struct {
13 | APIAddress string
14 | APIPort uint16
15 | }
16 |
17 | type UserInfo struct {
18 | // For VMess & Trojan
19 | Uuid string
20 | // For VMess
21 | AlertId uint32
22 | Level uint32
23 | // Which Inbound will add this user
24 | InTag string
25 | // User's Email, it's a unique identifier for users
26 | Email string
27 | // For ShadowSocks
28 | CipherType string
29 | // For ShadowSocks
30 | Password string
31 | }
32 |
33 | // Xray API 操作
34 | type XrayController struct {
35 | HsClient handlerService.HandlerServiceClient
36 | SsClient statsService.StatsServiceClient
37 | LsClient loggerService.LoggerServiceClient
38 | RsClient routingService.RoutingServiceClient
39 | CmdConn *grpc.ClientConn
40 | }
41 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/crossfw/Xray-API-documents
2 |
3 | go 1.15
4 |
5 | require (
6 | github.com/xtls/xray-core v1.3.0
7 | google.golang.org/grpc v1.35.0
8 | )
9 |
--------------------------------------------------------------------------------