diff --git a/api/panel/node.go b/api/panel/node.go index d69a533..4d7dac1 100644 --- a/api/panel/node.go +++ b/api/panel/node.go @@ -2,6 +2,7 @@ package panel import ( "fmt" + "github.com/Yuzuki616/V2bX/conf" "github.com/goccy/go-json" "reflect" "regexp" @@ -54,6 +55,7 @@ type NodeInfo struct { Host string Port int Network string + ExtraConfig V2rayExtraConfig NetworkSettings json.RawMessage Tls bool ServerName string @@ -66,13 +68,23 @@ type NodeInfo struct { PullInterval time.Duration } +type V2rayExtraConfig struct { + EnableVless bool `json:"EnableVless"` + VlessFlow string `json:"VlessFlow"` + EnableReality bool `json:"EnableReality"` + RealityConfig conf.RealityConfig `json:"RealityConfig"` +} + func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { const path = "/api/v1/server/UniProxy/config" - r, err := c.client.R().Get(path) + r, err := c.client. + R(). + SetHeader("If-None-Match", c.etag). + Get(path) if err = c.checkResponse(r, path, err); err != nil { return } - if c.etag == r.Header().Get("ETag") { // node info not changed + if r.StatusCode() == 304 { return nil, nil } // parse common params @@ -85,17 +97,30 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { if err != nil { return nil, fmt.Errorf("decode common params error: %s", err) } + var extra []byte for i := range common.Routes { // parse rules from routes - if common.Routes[i].Action == "block" { - var matchs []string - if _, ok := common.Routes[i].Match.(string); ok { - matchs = strings.Split(common.Routes[i].Match.(string), ",") - } else { - matchs = common.Routes[i].Match.([]string) + var matchs []string + if _, ok := common.Routes[i].Match.(string); ok { + matchs = strings.Split(common.Routes[i].Match.(string), ",") + } else if _, ok = common.Routes[i].Match.([]string); ok { + matchs = common.Routes[i].Match.([]string) + } else { + temp := common.Routes[i].Match.([]interface{}) + matchs = make([]string, len(temp)) + for i := range temp { + matchs[i] = temp[i].(string) } + } + switch common.Routes[i].Action { + case "block": for _, v := range matchs { node.Rules = append(node.Rules, regexp.MustCompile(v)) } + case "dns": + if matchs[0] != "extra" { + break + } + extra = []byte(strings.Join(matchs[1:], "")) } } node.ServerName = common.ServerName @@ -117,6 +142,12 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { if rsp.Tls == 1 { node.Tls = true } + if len(extra) != 0 { + err = json.Unmarshal(extra, &node.ExtraConfig) + if err != nil { + return nil, fmt.Errorf("decode v2ray extra error: %s", err) + } + } case "shadowsocks": rsp := ShadowsocksNodeRsp{} err = json.Unmarshal(r.Body(), &rsp) diff --git a/api/panel/node_test.go b/api/panel/node_test.go index dea16e8..570182f 100644 --- a/api/panel/node_test.go +++ b/api/panel/node_test.go @@ -23,6 +23,7 @@ func init() { func TestClient_GetNodeInfo(t *testing.T) { log.Println(client.GetNodeInfo()) + log.Println(client.GetNodeInfo()) } func TestClient_ReportUserTraffic(t *testing.T) { diff --git a/api/panel/utils.go b/api/panel/utils.go index 938bec9..74ef5b3 100644 --- a/api/panel/utils.go +++ b/api/panel/utils.go @@ -18,7 +18,7 @@ func (c *Client) checkResponse(res *resty.Response, path string, err error) erro if err != nil { return fmt.Errorf("request %s failed: %s", c.assembleURL(path), err) } - if res.StatusCode() != 200 { + if res.StatusCode() >= 400 { body := res.Body() return fmt.Errorf("request %s failed: %s", c.assembleURL(path), string(body)) } diff --git a/common/builder/inbound.go b/common/builder/inbound.go index ad2b357..e8a6d8f 100644 --- a/common/builder/inbound.go +++ b/common/builder/inbound.go @@ -102,6 +102,25 @@ func BuildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag s } } } + // use remote reality replace local config + if nodeInfo.ExtraConfig.EnableReality { + rc := nodeInfo.ExtraConfig.RealityConfig + in.StreamSetting.Security = "reality" + d, err := json.Marshal(rc.Dest) + if err != nil { + return nil, fmt.Errorf("marshal reality dest error: %s", err) + } + in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{ + Dest: d, + Xver: rc.Xver, + ServerNames: rc.ServerNames, + PrivateKey: rc.PrivateKey, + MinClientVer: rc.MinClientVer, + MaxClientVer: rc.MaxClientVer, + MaxTimeDiff: rc.MaxTimeDiff, + ShortIds: rc.ShortIds, + } + } // Support ProxyProtocol for any transport protocol if *in.StreamSetting.Network != "tcp" && *in.StreamSetting.Network != "ws" && @@ -117,7 +136,8 @@ func BuildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag s } func buildV2ray(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error { - if config.XrayOptions.EnableVless { + if config.XrayOptions.EnableVless || + nodeInfo.ExtraConfig.EnableVless { //Set vless inbound.Protocol = "vless" if config.XrayOptions.EnableFallback { diff --git a/common/builder/user.go b/common/builder/user.go index 4239626..bde1c86 100644 --- a/common/builder/user.go +++ b/common/builder/user.go @@ -14,8 +14,6 @@ import ( "strings" ) -const xtlsFLow = "xtls-rprx-vision" - func BuildVmessUsers(tag string, userInfo []panel.UserInfo) (users []*protocol.User) { users = make([]*protocol.User, len(userInfo)) for i, user := range userInfo { @@ -37,21 +35,19 @@ func BuildVmessUser(tag string, userInfo *panel.UserInfo) (user *protocol.User) } } -func BuildVlessUsers(tag string, userInfo []panel.UserInfo, xtls bool) (users []*protocol.User) { +func BuildVlessUsers(tag string, userInfo []panel.UserInfo, flow string) (users []*protocol.User) { users = make([]*protocol.User, len(userInfo)) for i := range userInfo { - users[i] = BuildVlessUser(tag, &(userInfo)[i], xtls) + users[i] = BuildVlessUser(tag, &(userInfo)[i], flow) } return users } -func BuildVlessUser(tag string, userInfo *panel.UserInfo, xtls bool) (user *protocol.User) { +func BuildVlessUser(tag string, userInfo *panel.UserInfo, flow string) (user *protocol.User) { vlessAccount := &vless.Account{ Id: userInfo.Uuid, } - if xtls { - vlessAccount.Flow = xtlsFLow - } + vlessAccount.Flow = flow return &protocol.User{ Level: 0, Email: BuildUserTag(tag, userInfo.Uuid), diff --git a/conf/node.go b/conf/node.go index 074f738..f8b38c9 100644 --- a/conf/node.go +++ b/conf/node.go @@ -28,7 +28,7 @@ type XrayOptions struct { EnableDNS bool `yaml:"EnableDNS"` DNSType string `yaml:"DNSType"` EnableVless bool `yaml:"EnableVless"` - EnableXtls bool `yaml:"EnableXtls"` + VlessFlow string `json:"VlessFlow"` EnableUot bool `yaml:"EnableUot"` EnableTFO bool `yaml:"EnableTFO"` DisableIVCheck bool `yaml:"DisableIVCheck"` @@ -103,12 +103,12 @@ type CertConfig struct { } type RealityConfig struct { - Dest interface{} `yaml:"Dest"` - Xver uint64 `yaml:"Xver"` - ServerNames []string `yaml:"ServerNames"` - PrivateKey string `yaml:"PrivateKey"` - MinClientVer string `yaml:"MinClientVer"` - MaxClientVer string `yaml:"MaxClientVer"` - MaxTimeDiff uint64 `yaml:"MaxTimeDiff"` - ShortIds []string `yaml:"ShortIds"` + Dest interface{} `yaml:"Dest" json:"Dest"` + Xver uint64 `yaml:"Xver" json:"Xver"` + ServerNames []string `yaml:"ServerNames" json:"ServerNames"` + PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"` + MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"` + MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"` + MaxTimeDiff uint64 `yaml:"MaxTimeDiff" json:"MaxTimeDiff"` + ShortIds []string `yaml:"ShortIds" json:"ShortIds"` } diff --git a/core/hy/server_test.go b/core/hy/server_test.go index 95c8f9a..db16d4f 100644 --- a/core/hy/server_test.go +++ b/core/hy/server_test.go @@ -1,17 +1,23 @@ package hy import ( + "encoding/base64" "github.com/Yuzuki616/V2bX/api/panel" "github.com/Yuzuki616/V2bX/conf" + "github.com/Yuzuki616/V2bX/limiter" "github.com/sirupsen/logrus" + "log" "testing" + "time" ) func TestServer(t *testing.T) { logrus.SetLevel(logrus.DebugLevel) - s := NewServer("test") + limiter.Init() + l := limiter.AddLimiter("test", &conf.LimitConfig{}, nil) + s := NewServer("test", l) t.Log(s.runServer(&panel.NodeInfo{ - Port: 11415, + Port: 1145, UpMbps: 100, DownMbps: 100, HyObfs: "atresssdaaaadd", @@ -24,5 +30,13 @@ func TestServer(t *testing.T) { }, })) s.users.Store("test1111", struct{}{}) + go func() { + for { + time.Sleep(10 * time.Second) + auth := base64.StdEncoding.EncodeToString([]byte("test1111")) + log.Println(auth) + log.Println(s.counter.getCounters(auth).UpCounter.Load()) + } + }() select {} } diff --git a/core/xray/user.go b/core/xray/user.go index cea922b..b5cc330 100644 --- a/core/xray/user.go +++ b/core/xray/user.go @@ -73,11 +73,24 @@ func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) { users := make([]*protocol.User, 0, len(p.UserInfo)) switch p.NodeInfo.Type { case "v2ray": - if p.Config.XrayOptions.EnableXtls { - users = builder.BuildVlessUsers(p.Tag, p.UserInfo, true) + + if p.Config.XrayOptions.EnableVless || + p.NodeInfo.ExtraConfig.EnableVless { + + if p.Config.XrayOptions.VlessFlow != "" { + if p.Config.XrayOptions.VlessFlow == p.NodeInfo.ExtraConfig.VlessFlow { + users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.Config.XrayOptions.VlessFlow) + } else { + users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) + } + + } else { + users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) + } } else { users = builder.BuildVmessUsers(p.Tag, p.UserInfo) } + case "trojan": users = builder.BuildTrojanUsers(p.Tag, p.UserInfo) case "shadowsocks": diff --git a/example/config.yml.example b/example/config.yml.example index 58f0141..697ca57 100644 --- a/example/config.yml.example +++ b/example/config.yml.example @@ -31,7 +31,7 @@ Nodes: DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy EnableTFO: false # Enable TCP Fast Open EnableVless: false # Enable Vless for V2ray Type - EnableXtls: false # Enable xtls-rprx-vision, only vless + VlessFlow: "xtls-rprx-vision" # flow for vless, "xtls-rprx-vision" or "none" or "" EnableProxyProtocol: false # Only works for WebSocket and TCP EnableFallback: false # Only support for Trojan and Vless FallBackConfigs: # Support multiple fallbacks