diff --git a/api/v2raysocks/model.go b/api/v2raysocks/model.go index c46ef990..811de4ae 100644 --- a/api/v2raysocks/model.go +++ b/api/v2raysocks/model.go @@ -1,7 +1,7 @@ package v2raysocks type UserTraffic struct { - UID int `json:"user_id"` + UID int `json:"uid"` Upload int64 `json:"u"` Download int64 `json:"d"` } @@ -19,6 +19,10 @@ type NodeOnline struct { IP string `json:"ip"` } +type IllegalItem struct { + UID int `json:"uid"` +} + type REALITYConfig struct { Dest string `json:"dest,omitempty"` ProxyProtocolVer uint64 `json:"proxy_protocol_ver,omitempty"` diff --git a/api/v2raysocks/v2raysocks.go b/api/v2raysocks/v2raysocks.go index c91a5f05..dc7206e7 100644 --- a/api/v2raysocks/v2raysocks.go +++ b/api/v2raysocks/v2raysocks.go @@ -159,8 +159,8 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) { res, err := c.client.R(). SetHeader("If-None-Match", c.eTags["config"]). SetQueryParams(map[string]string{ - "act": "config", - "nodetype": nodeType, + "act": "config", + "node_type": nodeType, }). ForceContentType("application/json"). Get(c.APIHost) @@ -213,8 +213,8 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) { res, err := c.client.R(). SetHeader("If-None-Match", c.eTags["user"]). SetQueryParams(map[string]string{ - "act": "user", - "nodetype": nodeType, + "act": "user", + "node_type": nodeType, }). ForceContentType("application/json"). Get(c.APIHost) @@ -239,22 +239,21 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) { user.UID = response.Get("data").GetIndex(i).Get("id").MustInt() switch c.NodeType { case "Shadowsocks": - user.Email = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("secret").MustString() - user.Passwd = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("secret").MustString() - user.Method = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("cipher").MustString() - user.SpeedLimit = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("speed_limit").MustUint64() * 1000000 / 8 - user.DeviceLimit = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("device_limit").MustInt() + user.Email = response.Get("data").GetIndex(i).Get("secret").MustString() + user.Passwd = response.Get("data").GetIndex(i).Get("secret").MustString() + user.Method = response.Get("data").GetIndex(i).Get("cipher").MustString() + user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8 + user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt() case "Trojan": - user.UUID = response.Get("data").GetIndex(i).Get("trojan_user").Get("password").MustString() - user.Email = response.Get("data").GetIndex(i).Get("trojan_user").Get("password").MustString() - user.SpeedLimit = response.Get("data").GetIndex(i).Get("trojan_user").Get("speed_limit").MustUint64() * 1000000 / 8 - user.DeviceLimit = response.Get("data").GetIndex(i).Get("trojan_user").Get("device_limit").MustInt() + user.UUID = response.Get("data").GetIndex(i).Get("password").MustString() + user.Email = response.Get("data").GetIndex(i).Get("password").MustString() + user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8 + user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt() case "V2ray", "Vmess", "Vless": - user.UUID = response.Get("data").GetIndex(i).Get("v2ray_user").Get("uuid").MustString() - user.Email = response.Get("data").GetIndex(i).Get("v2ray_user").Get("email").MustString() - user.AlterID = uint16(response.Get("data").GetIndex(i).Get("v2ray_user").Get("alter_id").MustUint64()) - user.SpeedLimit = response.Get("data").GetIndex(i).Get("v2ray_user").Get("speed_limit").MustUint64() * 1000000 / 8 - user.DeviceLimit = response.Get("data").GetIndex(i).Get("v2ray_user").Get("device_limit").MustInt() + user.UUID = response.Get("data").GetIndex(i).Get("uuid").MustString() + user.Email = user.UUID + "@x.com" + user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8 + user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt() } if c.SpeedLimit > 0 { user.SpeedLimit = uint64((c.SpeedLimit * 1000000) / 8) @@ -283,8 +282,8 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error { res, err := c.client.R(). SetQueryParam("node_id", strconv.Itoa(c.NodeID)). SetQueryParams(map[string]string{ - "act": "submit", - "nodetype": strings.ToLower(c.NodeType), + "act": "submit", + "node_type": strings.ToLower(c.NodeType), }). SetBody(data). ForceContentType("application/json"). @@ -327,8 +326,8 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) { res, err := c.client.R(). SetQueryParam("node_id", strconv.Itoa(c.NodeID)). SetQueryParams(map[string]string{ - "act": "nodestatus", - "nodetype": strings.ToLower(c.NodeType), + "act": "nodestatus", + "node_type": strings.ToLower(c.NodeType), }). SetBody(systemload). ForceContentType("application/json"). @@ -350,8 +349,8 @@ func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) erro res, err := c.client.R(). SetQueryParam("node_id", strconv.Itoa(c.NodeID)). SetQueryParams(map[string]string{ - "act": "onlineusers", - "nodetype": strings.ToLower(c.NodeType), + "act": "onlineusers", + "node_type": strings.ToLower(c.NodeType), }). SetBody(data). ForceContentType("application/json"). @@ -365,6 +364,26 @@ func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) erro // ReportIllegal implements the API interface func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error { + data := make([]IllegalItem, len(*detectResultList)) + for i, r := range *detectResultList { + data[i] = IllegalItem{ + UID: r.UID, + } + } + + res, err := c.client.R(). + SetQueryParam("node_id", strconv.Itoa(c.NodeID)). + SetQueryParams(map[string]string{ + "act": "illegal", + "node_type": strings.ToLower(c.NodeType), + }). + SetBody(data). + ForceContentType("application/json"). + Post(c.APIHost) + _, err = c.parseResponse(res, "", err) + if err != nil { + return err + } return nil } @@ -423,7 +442,7 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (* var enableTLS bool var enableVless bool var enableReality bool - var alterID uint16 = 0 + var vlessFlow string tmpInboundInfo := nodeInfoResponse.Get("inbounds").MustArray() marshalByte, _ := json.Marshal(tmpInboundInfo[0].(map[string]interface{})) @@ -436,6 +455,12 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (* case "ws": path = inboundInfo.Get("streamSettings").Get("wsSettings").Get("path").MustString() host = inboundInfo.Get("streamSettings").Get("wsSettings").Get("headers").Get("Host").MustString() + case "httpupgrade": + host = inboundInfo.Get("streamSettings").Get("httpupgradeSettings").Get("Host").MustString() + path = inboundInfo.Get("streamSettings").Get("httpupgradeSettings").Get("path").MustString() + case "splithttp": + host = inboundInfo.Get("streamSettings").Get("splithttpSettings").Get("Host").MustString() + path = inboundInfo.Get("streamSettings").Get("splithttpSettings").Get("path").MustString() case "grpc": if data, ok := inboundInfo.Get("streamSettings").Get("grpcSettings").CheckGet("serviceName"); ok { serviceName = data.MustString() @@ -448,12 +473,11 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (* header = httpHeader } } - } enableTLS = inboundInfo.Get("streamSettings").Get("security").MustString() == "tls" - enableVless = inboundInfo.Get("streamSettings").Get("security").MustString() == "reality" - enableReality = enableVless + enableVless = inboundInfo.Get("protocol").MustString() == "vless" + enableReality = inboundInfo.Get("streamSettings").Get("security").MustString() == "reality" realityConfig := new(api.REALITYConfig) if enableVless { @@ -470,19 +494,26 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (* } } + // XTLS only supports TLS and REALITY directly for now + if transportProtocol == "tcp" && enableReality { + vlessFlow = "xtls-rprx-vision" + } else { + vlessFlow = c.VlessFlow + } + // Create GeneralNodeInfo // AlterID will be updated after next sync nodeInfo := &api.NodeInfo{ NodeType: c.NodeType, NodeID: c.NodeID, Port: port, - AlterID: alterID, + AlterID: 0, TransportProtocol: transportProtocol, EnableTLS: enableTLS, Path: path, Host: host, EnableVless: enableVless, - VlessFlow: c.VlessFlow, + VlessFlow: vlessFlow, ServiceName: serviceName, Header: header, EnableREALITY: enableReality,