mirror of
https://github.com/wyx2685/V2bX.git
synced 2025-01-22 18:08:14 -05:00
refactor NodeInfo
This commit is contained in:
parent
42e86bf94c
commit
42407d5c62
@ -3,21 +3,45 @@ package panel
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/InazumaV/V2bX/common/crypt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/InazumaV/V2bX/common/crypt"
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommonNodeRsp struct {
|
// Security type
|
||||||
|
const (
|
||||||
|
None = 0
|
||||||
|
Tls = 1
|
||||||
|
Reality = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type NodeInfo struct {
|
||||||
|
Id int
|
||||||
|
Type string
|
||||||
|
Security int
|
||||||
|
PushInterval time.Duration
|
||||||
|
PullInterval time.Duration
|
||||||
|
RawDNS RawDNS
|
||||||
|
Rules Rules
|
||||||
|
|
||||||
|
// origin
|
||||||
|
VAllss *VAllssNode
|
||||||
|
Shadowsocks *ShadowsocksNode
|
||||||
|
Trojan *TrojanNode
|
||||||
|
Hysteria *HysteriaNode
|
||||||
|
Common *CommonNode
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommonNode struct {
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
ServerPort int `json:"server_port"`
|
ServerPort int `json:"server_port"`
|
||||||
ServerName string `json:"server_name"`
|
ServerName string `json:"server_name"`
|
||||||
Routes []Route `json:"routes"`
|
Routes []Route `json:"routes"`
|
||||||
BaseConfig BaseConfig `json:"base_config"`
|
BaseConfig *BaseConfig `json:"base_config"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Route struct {
|
type Route struct {
|
||||||
@ -31,45 +55,50 @@ type BaseConfig struct {
|
|||||||
PullInterval any `json:"pull_interval"`
|
PullInterval any `json:"pull_interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type V2rayNodeRsp struct {
|
// VAllssNode is vmess and vless node info
|
||||||
|
type VAllssNode struct {
|
||||||
|
CommonNode
|
||||||
Tls int `json:"tls"`
|
Tls int `json:"tls"`
|
||||||
|
TlsSettings TlsSettings `json:"tls_settings"`
|
||||||
Network string `json:"network"`
|
Network string `json:"network"`
|
||||||
NetworkSettings json.RawMessage `json:"networkSettings"`
|
NetworkSettings json.RawMessage `json:"networkSettings"`
|
||||||
ServerName string `json:"server_name"`
|
ServerName string `json:"server_name"`
|
||||||
|
|
||||||
|
// vless only
|
||||||
|
Flow string `json:"flow"`
|
||||||
|
RealityConfig RealityConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShadowsocksNodeRsp struct {
|
type TlsSettings struct {
|
||||||
|
ServerName []string `json:"sever_name"`
|
||||||
|
ServerPort string `json:"server_port"`
|
||||||
|
ShortIds []string `json:"short_ids"`
|
||||||
|
PrivateKey string `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RealityConfig struct {
|
||||||
|
Dest string `json:"Dest"`
|
||||||
|
Xver uint64 `json:"Xver"`
|
||||||
|
MinClientVer string `json:"MinClientVer"`
|
||||||
|
MaxClientVer string `json:"MaxClientVer"`
|
||||||
|
MaxTimeDiff uint64 `json:"MaxTimeDiff"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShadowsocksNode struct {
|
||||||
|
CommonNode
|
||||||
Cipher string `json:"cipher"`
|
Cipher string `json:"cipher"`
|
||||||
ServerKey string `json:"server_key"`
|
ServerKey string `json:"server_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HysteriaNodeRsp struct {
|
type TrojanNode CommonNode
|
||||||
|
|
||||||
|
type HysteriaNode struct {
|
||||||
|
CommonNode
|
||||||
UpMbps int `json:"up_mbps"`
|
UpMbps int `json:"up_mbps"`
|
||||||
DownMbps int `json:"down_mbps"`
|
DownMbps int `json:"down_mbps"`
|
||||||
Obfs string `json:"obfs"`
|
Obfs string `json:"obfs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeInfo struct {
|
|
||||||
Id int
|
|
||||||
Type string
|
|
||||||
Rules Rules
|
|
||||||
Host string
|
|
||||||
Port int
|
|
||||||
Network string
|
|
||||||
RawDNS RawDNS
|
|
||||||
ExtraConfig V2rayExtraConfig
|
|
||||||
NetworkSettings json.RawMessage
|
|
||||||
Tls bool
|
|
||||||
ServerName string
|
|
||||||
UpMbps int
|
|
||||||
DownMbps int
|
|
||||||
ServerKey string
|
|
||||||
Cipher string
|
|
||||||
HyObfs string
|
|
||||||
PushInterval time.Duration
|
|
||||||
PullInterval time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
type RawDNS struct {
|
type RawDNS struct {
|
||||||
DNSMap map[string]map[string]interface{}
|
DNSMap map[string]map[string]interface{}
|
||||||
DNSJson []byte
|
DNSJson []byte
|
||||||
@ -80,24 +109,6 @@ type Rules struct {
|
|||||||
Protocol []string
|
Protocol []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type V2rayExtraConfig struct {
|
|
||||||
EnableVless string `json:"EnableVless"`
|
|
||||||
VlessFlow string `json:"VlessFlow"`
|
|
||||||
EnableReality string `json:"EnableReality"`
|
|
||||||
RealityConfig *RealityConfig `json:"RealityConfig"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RealityConfig struct {
|
|
||||||
Dest string `yaml:"Dest" json:"Dest"`
|
|
||||||
Xver string `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 string `yaml:"MaxTimeDiff" json:"MaxTimeDiff"`
|
|
||||||
ShortIds []string `yaml:"ShortIds" json:"ShortIds"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
|
func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
|
||||||
const path = "/api/v1/server/UniProxy/config"
|
const path = "/api/v1/server/UniProxy/config"
|
||||||
r, err := c.client.
|
r, err := c.client.
|
||||||
@ -110,7 +121,6 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
|
|||||||
if r.StatusCode() == 304 {
|
if r.StatusCode() == 304 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
// parse common params
|
|
||||||
node = &NodeInfo{
|
node = &NodeInfo{
|
||||||
Id: c.NodeId,
|
Id: c.NodeId,
|
||||||
Type: c.NodeType,
|
Type: c.NodeType,
|
||||||
@ -119,26 +129,72 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
|
|||||||
DNSJson: []byte(""),
|
DNSJson: []byte(""),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
common := CommonNodeRsp{}
|
// parse protocol params
|
||||||
err = json.Unmarshal(r.Body(), &common)
|
var cm *CommonNode
|
||||||
|
switch c.NodeType {
|
||||||
|
case "vmess", "vless":
|
||||||
|
rsp := &VAllssNode{}
|
||||||
|
err = json.Unmarshal(r.Body(), rsp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("decode common params error: %s", err)
|
return nil, fmt.Errorf("decode v2ray params error: %s", err)
|
||||||
|
}
|
||||||
|
cm = &rsp.CommonNode
|
||||||
|
node.VAllss = rsp
|
||||||
|
node.Security = node.VAllss.Tls
|
||||||
|
if len(rsp.NetworkSettings) > 0 {
|
||||||
|
/*err = json.Unmarshal(rsp.NetworkSettings, &rsp.RealityConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode reality config error: %s", err)
|
||||||
|
}*/
|
||||||
|
if node.Security == Reality {
|
||||||
|
key := crypt.GenX25519Private([]byte(strconv.Itoa(c.NodeId) + c.NodeType + c.Token))
|
||||||
|
rsp.TlsSettings.PrivateKey = base64.RawURLEncoding.EncodeToString(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "shadowsocks":
|
||||||
|
rsp := &ShadowsocksNode{}
|
||||||
|
err = json.Unmarshal(r.Body(), rsp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode v2ray params error: %s", err)
|
||||||
|
}
|
||||||
|
cm = &rsp.CommonNode
|
||||||
|
node.Shadowsocks = rsp
|
||||||
|
node.Security = None
|
||||||
|
case "trojan":
|
||||||
|
rsp := &TrojanNode{}
|
||||||
|
err = json.Unmarshal(r.Body(), rsp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode v2ray params error: %s", err)
|
||||||
|
}
|
||||||
|
cm = (*CommonNode)(rsp)
|
||||||
|
node.Trojan = rsp
|
||||||
|
node.Security = Tls
|
||||||
|
case "hysteria":
|
||||||
|
rsp := &HysteriaNode{}
|
||||||
|
err = json.Unmarshal(r.Body(), rsp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode v2ray params error: %s", err)
|
||||||
|
}
|
||||||
|
cm = &rsp.CommonNode
|
||||||
|
node.Hysteria = rsp
|
||||||
|
node.Security = Tls
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range common.Routes {
|
// parse rules and dns
|
||||||
|
for i := range cm.Routes {
|
||||||
var matchs []string
|
var matchs []string
|
||||||
if _, ok := common.Routes[i].Match.(string); ok {
|
if _, ok := cm.Routes[i].Match.(string); ok {
|
||||||
matchs = strings.Split(common.Routes[i].Match.(string), ",")
|
matchs = strings.Split(cm.Routes[i].Match.(string), ",")
|
||||||
} else if _, ok = common.Routes[i].Match.([]string); ok {
|
} else if _, ok = cm.Routes[i].Match.([]string); ok {
|
||||||
matchs = common.Routes[i].Match.([]string)
|
matchs = cm.Routes[i].Match.([]string)
|
||||||
} else {
|
} else {
|
||||||
temp := common.Routes[i].Match.([]interface{})
|
temp := cm.Routes[i].Match.([]interface{})
|
||||||
matchs = make([]string, len(temp))
|
matchs = make([]string, len(temp))
|
||||||
for i := range temp {
|
for i := range temp {
|
||||||
matchs[i] = temp[i].(string)
|
matchs[i] = temp[i].(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch common.Routes[i].Action {
|
switch cm.Routes[i].Action {
|
||||||
case "block":
|
case "block":
|
||||||
for _, v := range matchs {
|
for _, v := range matchs {
|
||||||
if strings.HasPrefix(v, "protocol:") {
|
if strings.HasPrefix(v, "protocol:") {
|
||||||
@ -156,7 +212,7 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
|
|||||||
}
|
}
|
||||||
if matchs[0] != "main" {
|
if matchs[0] != "main" {
|
||||||
node.RawDNS.DNSMap[strconv.Itoa(i)] = map[string]interface{}{
|
node.RawDNS.DNSMap[strconv.Itoa(i)] = map[string]interface{}{
|
||||||
"address": common.Routes[i].ActionValue,
|
"address": cm.Routes[i].ActionValue,
|
||||||
"domains": domains,
|
"domains": domains,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -166,57 +222,16 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.ServerName = common.ServerName
|
|
||||||
node.Host = common.Host
|
// set interval
|
||||||
node.Port = common.ServerPort
|
node.PushInterval = intervalToTime(cm.BaseConfig.PushInterval)
|
||||||
node.PullInterval = intervalToTime(common.BaseConfig.PullInterval)
|
node.PullInterval = intervalToTime(cm.BaseConfig.PullInterval)
|
||||||
node.PushInterval = intervalToTime(common.BaseConfig.PushInterval)
|
|
||||||
// parse protocol params
|
node.Common = cm
|
||||||
switch c.NodeType {
|
// clear
|
||||||
case "v2ray":
|
cm.Routes = nil
|
||||||
rsp := V2rayNodeRsp{}
|
cm.BaseConfig = nil
|
||||||
err = json.Unmarshal(r.Body(), &rsp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("decode v2ray params error: %s", err)
|
|
||||||
}
|
|
||||||
node.Network = rsp.Network
|
|
||||||
node.NetworkSettings = rsp.NetworkSettings
|
|
||||||
node.ServerName = rsp.ServerName
|
|
||||||
if rsp.Tls == 1 {
|
|
||||||
node.Tls = true
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(rsp.NetworkSettings, &node.ExtraConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("decode v2ray extra error: %s", err)
|
|
||||||
}
|
|
||||||
if node.ExtraConfig.EnableReality == "true" {
|
|
||||||
if node.ExtraConfig.RealityConfig == nil {
|
|
||||||
node.ExtraConfig.EnableReality = "false"
|
|
||||||
} else {
|
|
||||||
key := crypt.GenX25519Private([]byte(strconv.Itoa(c.NodeId) + c.NodeType + c.Token))
|
|
||||||
node.ExtraConfig.RealityConfig.PrivateKey = base64.RawURLEncoding.EncodeToString(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "shadowsocks":
|
|
||||||
rsp := ShadowsocksNodeRsp{}
|
|
||||||
err = json.Unmarshal(r.Body(), &rsp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("decode v2ray params error: %s", err)
|
|
||||||
}
|
|
||||||
node.ServerKey = rsp.ServerKey
|
|
||||||
node.Cipher = rsp.Cipher
|
|
||||||
case "trojan":
|
|
||||||
node.Tls = true
|
|
||||||
case "hysteria":
|
|
||||||
rsp := HysteriaNodeRsp{}
|
|
||||||
err = json.Unmarshal(r.Body(), &rsp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("decode v2ray params error: %s", err)
|
|
||||||
}
|
|
||||||
node.DownMbps = rsp.DownMbps
|
|
||||||
node.UpMbps = rsp.UpMbps
|
|
||||||
node.HyObfs = rsp.Obfs
|
|
||||||
}
|
|
||||||
c.nodeEtag = r.Header().Get("ETag")
|
c.nodeEtag = r.Header().Get("ETag")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,14 @@ func New(c *conf.ApiConfig) (*Client, error) {
|
|||||||
// Check node type
|
// Check node type
|
||||||
c.NodeType = strings.ToLower(c.NodeType)
|
c.NodeType = strings.ToLower(c.NodeType)
|
||||||
switch c.NodeType {
|
switch c.NodeType {
|
||||||
case "v2ray", "trojan", "shadowsocks", "hysteria":
|
case "v2ray":
|
||||||
|
c.NodeType = "vmess"
|
||||||
|
case
|
||||||
|
"vmess",
|
||||||
|
"trojan",
|
||||||
|
"shadowsocks",
|
||||||
|
"hysteria",
|
||||||
|
"vless":
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
|
||||||
}
|
}
|
||||||
|
12
conf/cert.go
12
conf/cert.go
@ -9,16 +9,4 @@ type CertConfig struct {
|
|||||||
Provider string `yaml:"Provider"` // alidns, cloudflare, gandi, godaddy....
|
Provider string `yaml:"Provider"` // alidns, cloudflare, gandi, godaddy....
|
||||||
Email string `yaml:"Email"`
|
Email string `yaml:"Email"`
|
||||||
DNSEnv map[string]string `yaml:"DNSEnv"`
|
DNSEnv map[string]string `yaml:"DNSEnv"`
|
||||||
RealityConfig *RealityConfig `yaml:"RealityConfig"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RealityConfig struct {
|
|
||||||
Dest string `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"`
|
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
type AddUsersParams struct {
|
type AddUsersParams struct {
|
||||||
Tag string
|
Tag string
|
||||||
Config *conf.Options
|
Users []panel.UserInfo
|
||||||
UserInfo []panel.UserInfo
|
*panel.NodeInfo
|
||||||
NodeInfo *panel.NodeInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Core interface {
|
type Core interface {
|
||||||
Start() error
|
Start() error
|
||||||
Close() error
|
Close() error
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/uuid"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -33,7 +32,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
|||||||
}
|
}
|
||||||
listen := option.ListenOptions{
|
listen := option.ListenOptions{
|
||||||
Listen: (*option.ListenAddress)(&addr),
|
Listen: (*option.ListenAddress)(&addr),
|
||||||
ListenPort: uint16(info.Port),
|
ListenPort: uint16(info.Common.ServerPort),
|
||||||
ProxyProtocol: c.SingOptions.EnableProxyProtocol,
|
ProxyProtocol: c.SingOptions.EnableProxyProtocol,
|
||||||
TCPFastOpen: c.SingOptions.TCPFastOpen,
|
TCPFastOpen: c.SingOptions.TCPFastOpen,
|
||||||
InboundOptions: option.InboundOptions{
|
InboundOptions: option.InboundOptions{
|
||||||
@ -42,83 +41,56 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
var tls option.InboundTLSOptions
|
var tls option.InboundTLSOptions
|
||||||
if info.Tls || info.Type == "hysteria" {
|
switch info.Security {
|
||||||
|
case panel.Tls:
|
||||||
if c.CertConfig == nil {
|
if c.CertConfig == nil {
|
||||||
return option.Inbound{}, fmt.Errorf("the CertConfig is not vail")
|
return option.Inbound{}, fmt.Errorf("the CertConfig is not vail")
|
||||||
}
|
}
|
||||||
tls.Enabled = true
|
|
||||||
tls.Insecure = true
|
|
||||||
tls.ServerName = info.ServerName
|
|
||||||
switch c.CertConfig.CertMode {
|
switch c.CertConfig.CertMode {
|
||||||
case "none", "":
|
case "none", "":
|
||||||
break // disable
|
break // disable
|
||||||
case "reality":
|
|
||||||
if c.CertConfig.RealityConfig == nil {
|
|
||||||
return option.Inbound{}, fmt.Errorf("RealityConfig is not valid")
|
|
||||||
}
|
|
||||||
rc := c.CertConfig.RealityConfig
|
|
||||||
tls.ServerName = rc.ServerNames[0]
|
|
||||||
if len(rc.ShortIds) == 0 {
|
|
||||||
rc.ShortIds = []string{""}
|
|
||||||
}
|
|
||||||
dest, _ := strconv.Atoi(rc.Dest)
|
|
||||||
mtd, _ := strconv.Atoi(strconv.FormatUint(rc.MaxTimeDiff, 10))
|
|
||||||
tls.Reality = &option.InboundRealityOptions{
|
|
||||||
Enabled: true,
|
|
||||||
ShortID: rc.ShortIds,
|
|
||||||
PrivateKey: rc.PrivateKey,
|
|
||||||
MaxTimeDifference: option.Duration(time.Duration(mtd) * time.Second),
|
|
||||||
Handshake: option.InboundRealityHandshakeOptions{
|
|
||||||
ServerOptions: option.ServerOptions{
|
|
||||||
Server: rc.ServerNames[0],
|
|
||||||
ServerPort: uint16(dest),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
case "remote":
|
|
||||||
if info.ExtraConfig.EnableReality == "true" {
|
|
||||||
if c.CertConfig.RealityConfig == nil {
|
|
||||||
return option.Inbound{}, fmt.Errorf("RealityConfig is not valid")
|
|
||||||
}
|
|
||||||
rc := info.ExtraConfig.RealityConfig
|
|
||||||
if len(rc.ShortIds) == 0 {
|
|
||||||
rc.ShortIds = []string{""}
|
|
||||||
}
|
|
||||||
dest, _ := strconv.Atoi(rc.Dest)
|
|
||||||
mtd, _ := strconv.Atoi(rc.MaxTimeDiff)
|
|
||||||
tls.Reality = &option.InboundRealityOptions{
|
|
||||||
Enabled: true,
|
|
||||||
ShortID: rc.ShortIds,
|
|
||||||
PrivateKey: rc.PrivateKey,
|
|
||||||
MaxTimeDifference: option.Duration(time.Duration(mtd) * time.Second),
|
|
||||||
Handshake: option.InboundRealityHandshakeOptions{
|
|
||||||
ServerOptions: option.ServerOptions{
|
|
||||||
Server: rc.ServerNames[0],
|
|
||||||
ServerPort: uint16(dest),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
|
tls.Enabled = true
|
||||||
tls.CertificatePath = c.CertConfig.CertFile
|
tls.CertificatePath = c.CertConfig.CertFile
|
||||||
tls.KeyPath = c.CertConfig.KeyFile
|
tls.KeyPath = c.CertConfig.KeyFile
|
||||||
}
|
}
|
||||||
|
case panel.Reality:
|
||||||
|
tls.Enabled = true
|
||||||
|
v := info.VAllss
|
||||||
|
tls.ServerName = v.TlsSettings.PrivateKey
|
||||||
|
if len(v.TlsSettings.ShortIds) == 0 {
|
||||||
|
v.TlsSettings.ShortIds = []string{""}
|
||||||
|
}
|
||||||
|
dest, _ := strconv.Atoi(v.TlsSettings.ServerPort)
|
||||||
|
mtd, _ := strconv.Atoi(strconv.FormatUint(v.RealityConfig.MaxTimeDiff, 10))
|
||||||
|
tls.Reality = &option.InboundRealityOptions{
|
||||||
|
Enabled: true,
|
||||||
|
ShortID: v.TlsSettings.ShortIds,
|
||||||
|
PrivateKey: v.TlsSettings.PrivateKey,
|
||||||
|
MaxTimeDifference: option.Duration(time.Duration(mtd) * time.Second),
|
||||||
|
Handshake: option.InboundRealityHandshakeOptions{
|
||||||
|
ServerOptions: option.ServerOptions{
|
||||||
|
Server: v.TlsSettings.ServerName[0],
|
||||||
|
ServerPort: uint16(dest),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
in := option.Inbound{
|
in := option.Inbound{
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
}
|
}
|
||||||
switch info.Type {
|
switch info.Type {
|
||||||
case "v2ray":
|
case "vmess", "vless":
|
||||||
|
n := info.VAllss
|
||||||
t := option.V2RayTransportOptions{
|
t := option.V2RayTransportOptions{
|
||||||
Type: info.Network,
|
Type: n.Network,
|
||||||
}
|
}
|
||||||
switch info.Network {
|
switch n.Network {
|
||||||
case "tcp":
|
case "tcp":
|
||||||
t.Type = ""
|
t.Type = ""
|
||||||
case "ws":
|
case "ws":
|
||||||
network := WsNetworkConfig{}
|
network := WsNetworkConfig{}
|
||||||
err := json.Unmarshal(info.NetworkSettings, &network)
|
err := json.Unmarshal(n.NetworkSettings, &network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
|
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
|
||||||
}
|
}
|
||||||
@ -141,12 +113,13 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
|||||||
Headers: h,
|
Headers: h,
|
||||||
}
|
}
|
||||||
case "grpc":
|
case "grpc":
|
||||||
err := json.Unmarshal(info.NetworkSettings, &t.GRPCOptions)
|
err := json.Unmarshal(n.NetworkSettings, &t.GRPCOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
|
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if info.ExtraConfig.EnableVless == "true" {
|
tls.ServerName = n.ServerName
|
||||||
|
if info.Type == "vless" {
|
||||||
in.Type = "vless"
|
in.Type = "vless"
|
||||||
in.VLESSOptions = option.VLESSInboundOptions{
|
in.VLESSOptions = option.VLESSInboundOptions{
|
||||||
ListenOptions: listen,
|
ListenOptions: listen,
|
||||||
@ -163,8 +136,9 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
|||||||
}
|
}
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
in.Type = "shadowsocks"
|
in.Type = "shadowsocks"
|
||||||
|
n := info.Shadowsocks
|
||||||
var keyLength int
|
var keyLength int
|
||||||
switch info.Cipher {
|
switch n.Cipher {
|
||||||
case "2022-blake3-aes-128-gcm":
|
case "2022-blake3-aes-128-gcm":
|
||||||
keyLength = 16
|
keyLength = 16
|
||||||
case "2022-blake3-aes-256-gcm":
|
case "2022-blake3-aes-256-gcm":
|
||||||
@ -174,13 +148,13 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
|||||||
}
|
}
|
||||||
in.ShadowsocksOptions = option.ShadowsocksInboundOptions{
|
in.ShadowsocksOptions = option.ShadowsocksInboundOptions{
|
||||||
ListenOptions: listen,
|
ListenOptions: listen,
|
||||||
Method: info.Cipher,
|
Method: n.Cipher,
|
||||||
}
|
}
|
||||||
p := make([]byte, keyLength)
|
p := make([]byte, keyLength)
|
||||||
_, _ = rand.Read(p)
|
_, _ = rand.Read(p)
|
||||||
randomPasswd := string(p)
|
randomPasswd := string(p)
|
||||||
if strings.Contains(info.Cipher, "2022") {
|
if strings.Contains(n.Cipher, "2022") {
|
||||||
in.ShadowsocksOptions.Password = info.ServerKey
|
in.ShadowsocksOptions.Password = n.ServerKey
|
||||||
randomPasswd = base64.StdEncoding.EncodeToString([]byte(randomPasswd))
|
randomPasswd = base64.StdEncoding.EncodeToString([]byte(randomPasswd))
|
||||||
}
|
}
|
||||||
in.ShadowsocksOptions.Users = []option.ShadowsocksUser{{
|
in.ShadowsocksOptions.Users = []option.ShadowsocksUser{{
|
||||||
@ -188,27 +162,9 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
|||||||
}}
|
}}
|
||||||
case "trojan":
|
case "trojan":
|
||||||
in.Type = "trojan"
|
in.Type = "trojan"
|
||||||
t := option.V2RayTransportOptions{
|
|
||||||
Type: info.Network,
|
|
||||||
}
|
|
||||||
switch info.Network {
|
|
||||||
case "tcp":
|
|
||||||
t.Type = ""
|
|
||||||
case "grpc":
|
|
||||||
err := json.Unmarshal(info.NetworkSettings, &t.GRPCOptions)
|
|
||||||
if err != nil {
|
|
||||||
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
randomPasswd := uuid.New().String()
|
|
||||||
in.TrojanOptions = option.TrojanInboundOptions{
|
in.TrojanOptions = option.TrojanInboundOptions{
|
||||||
ListenOptions: listen,
|
ListenOptions: listen,
|
||||||
Users: []option.TrojanUser{{
|
|
||||||
Name: randomPasswd,
|
|
||||||
Password: randomPasswd,
|
|
||||||
}},
|
|
||||||
TLS: &tls,
|
TLS: &tls,
|
||||||
Transport: &t,
|
|
||||||
}
|
}
|
||||||
if c.SingOptions.FallBackConfigs != nil {
|
if c.SingOptions.FallBackConfigs != nil {
|
||||||
// fallback handling
|
// fallback handling
|
||||||
@ -230,9 +186,9 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
|||||||
in.Type = "hysteria"
|
in.Type = "hysteria"
|
||||||
in.HysteriaOptions = option.HysteriaInboundOptions{
|
in.HysteriaOptions = option.HysteriaInboundOptions{
|
||||||
ListenOptions: listen,
|
ListenOptions: listen,
|
||||||
UpMbps: info.UpMbps,
|
UpMbps: info.Hysteria.UpMbps,
|
||||||
DownMbps: info.DownMbps,
|
DownMbps: info.Hysteria.DownMbps,
|
||||||
Obfs: info.HyObfs,
|
Obfs: info.Hysteria.Obfs,
|
||||||
TLS: &tls,
|
TLS: &tls,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,8 @@ func (b *Box) Router() adapter.Router {
|
|||||||
|
|
||||||
func (b *Box) Protocols() []string {
|
func (b *Box) Protocols() []string {
|
||||||
return []string{
|
return []string{
|
||||||
"v2ray",
|
"vmess",
|
||||||
|
"vless",
|
||||||
"shadowsocks",
|
"shadowsocks",
|
||||||
"trojan",
|
"trojan",
|
||||||
"hysteria",
|
"hysteria",
|
||||||
|
@ -13,58 +13,58 @@ import (
|
|||||||
|
|
||||||
func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
||||||
switch p.NodeInfo.Type {
|
switch p.NodeInfo.Type {
|
||||||
case "v2ray":
|
case "vmess", "vless":
|
||||||
if p.NodeInfo.ExtraConfig.EnableVless == "true" {
|
if p.NodeInfo.Type == "vless" {
|
||||||
us := make([]option.VLESSUser, len(p.UserInfo))
|
us := make([]option.VLESSUser, len(p.Users))
|
||||||
for i := range p.UserInfo {
|
for i := range p.Users {
|
||||||
us[i] = option.VLESSUser{
|
us[i] = option.VLESSUser{
|
||||||
Name: p.UserInfo[i].Uuid,
|
Name: p.Users[i].Uuid,
|
||||||
Flow: p.NodeInfo.ExtraConfig.VlessFlow,
|
Flow: p.VAllss.Flow,
|
||||||
UUID: p.UserInfo[i].Uuid,
|
UUID: p.Users[i].Uuid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = b.inbounds[p.Tag].(*inbound.VLESS).AddUsers(us)
|
err = b.inbounds[p.Tag].(*inbound.VLESS).AddUsers(us)
|
||||||
} else {
|
} else {
|
||||||
us := make([]option.VMessUser, len(p.UserInfo))
|
us := make([]option.VMessUser, len(p.Users))
|
||||||
for i := range p.UserInfo {
|
for i := range p.Users {
|
||||||
us[i] = option.VMessUser{
|
us[i] = option.VMessUser{
|
||||||
Name: p.UserInfo[i].Uuid,
|
Name: p.Users[i].Uuid,
|
||||||
UUID: p.UserInfo[i].Uuid,
|
UUID: p.Users[i].Uuid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = b.inbounds[p.Tag].(*inbound.VMess).AddUsers(us)
|
err = b.inbounds[p.Tag].(*inbound.VMess).AddUsers(us)
|
||||||
}
|
}
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
us := make([]option.ShadowsocksUser, len(p.UserInfo))
|
us := make([]option.ShadowsocksUser, len(p.Users))
|
||||||
for i := range p.UserInfo {
|
for i := range p.Users {
|
||||||
var password = p.UserInfo[i].Uuid
|
var password = p.Users[i].Uuid
|
||||||
switch p.NodeInfo.Cipher {
|
switch p.Shadowsocks.Cipher {
|
||||||
case "2022-blake3-aes-128-gcm":
|
case "2022-blake3-aes-128-gcm":
|
||||||
password = base64.StdEncoding.EncodeToString([]byte(password[:16]))
|
password = base64.StdEncoding.EncodeToString([]byte(password[:16]))
|
||||||
case "2022-blake3-aes-256-gcm":
|
case "2022-blake3-aes-256-gcm":
|
||||||
password = base64.StdEncoding.EncodeToString([]byte(password[:32]))
|
password = base64.StdEncoding.EncodeToString([]byte(password[:32]))
|
||||||
}
|
}
|
||||||
us[i] = option.ShadowsocksUser{
|
us[i] = option.ShadowsocksUser{
|
||||||
Name: p.UserInfo[i].Uuid,
|
Name: p.Users[i].Uuid,
|
||||||
Password: password,
|
Password: password,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = b.inbounds[p.Tag].(*inbound.ShadowsocksMulti).AddUsers(us)
|
err = b.inbounds[p.Tag].(*inbound.ShadowsocksMulti).AddUsers(us)
|
||||||
case "trojan":
|
case "trojan":
|
||||||
us := make([]option.TrojanUser, len(p.UserInfo))
|
us := make([]option.TrojanUser, len(p.Users))
|
||||||
for i := range p.UserInfo {
|
for i := range p.Users {
|
||||||
us[i] = option.TrojanUser{
|
us[i] = option.TrojanUser{
|
||||||
Name: p.UserInfo[i].Uuid,
|
Name: p.Users[i].Uuid,
|
||||||
Password: p.UserInfo[i].Uuid,
|
Password: p.Users[i].Uuid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = b.inbounds[p.Tag].(*inbound.Trojan).AddUsers(us)
|
err = b.inbounds[p.Tag].(*inbound.Trojan).AddUsers(us)
|
||||||
case "hysteria":
|
case "hysteria":
|
||||||
us := make([]option.HysteriaUser, len(p.UserInfo))
|
us := make([]option.HysteriaUser, len(p.Users))
|
||||||
for i := range p.UserInfo {
|
for i := range p.Users {
|
||||||
us[i] = option.HysteriaUser{
|
us[i] = option.HysteriaUser{
|
||||||
Name: p.UserInfo[i].Uuid,
|
Name: p.Users[i].Uuid,
|
||||||
AuthString: p.UserInfo[i].Uuid,
|
AuthString: p.Users[i].Uuid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = b.inbounds[p.Tag].(*inbound.Hysteria).AddUsers(us)
|
err = b.inbounds[p.Tag].(*inbound.Hysteria).AddUsers(us)
|
||||||
@ -72,7 +72,7 @@ func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return len(p.UserInfo), err
|
return len(p.Users), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Box) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
func (b *Box) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
||||||
|
@ -6,8 +6,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/InazumaV/V2bX/api/panel"
|
"github.com/InazumaV/V2bX/api/panel"
|
||||||
"github.com/InazumaV/V2bX/conf"
|
"github.com/InazumaV/V2bX/conf"
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
@ -17,141 +15,121 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// BuildInbound build Inbound config for different protocol
|
// BuildInbound build Inbound config for different protocol
|
||||||
func buildInbound(config *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*core.InboundHandlerConfig, error) {
|
func buildInbound(option *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*core.InboundHandlerConfig, error) {
|
||||||
in := &coreConf.InboundDetourConfig{}
|
in := &coreConf.InboundDetourConfig{}
|
||||||
// Set network protocol
|
|
||||||
t := coreConf.TransportProtocol(nodeInfo.Network)
|
|
||||||
in.StreamSetting = &coreConf.StreamConfig{Network: &t}
|
|
||||||
var err error
|
var err error
|
||||||
|
var network string
|
||||||
switch nodeInfo.Type {
|
switch nodeInfo.Type {
|
||||||
case "v2ray":
|
case "v2ray":
|
||||||
err = buildV2ray(config, nodeInfo, in)
|
err = buildV2ray(option, nodeInfo, in)
|
||||||
|
network = nodeInfo.VAllss.Network
|
||||||
case "trojan":
|
case "trojan":
|
||||||
err = buildTrojan(config, in)
|
err = buildTrojan(option, in)
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
err = buildShadowsocks(config, nodeInfo, in)
|
err = buildShadowsocks(option, nodeInfo, in)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks", nodeInfo.Type)
|
return nil, fmt.Errorf("unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks", nodeInfo.Type)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Set network protocol
|
||||||
|
t := coreConf.TransportProtocol(network)
|
||||||
|
in.StreamSetting = &coreConf.StreamConfig{Network: &t}
|
||||||
// Set server port
|
// Set server port
|
||||||
in.PortList = &coreConf.PortList{
|
in.PortList = &coreConf.PortList{
|
||||||
Range: []coreConf.PortRange{{From: uint32(nodeInfo.Port), To: uint32(nodeInfo.Port)}},
|
Range: []coreConf.PortRange{
|
||||||
|
{
|
||||||
|
From: uint32(nodeInfo.Common.ServerPort),
|
||||||
|
To: uint32(nodeInfo.Common.ServerPort),
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
// Set Listen IP address
|
// Set Listen IP address
|
||||||
ipAddress := net.ParseAddress(config.ListenIP)
|
ipAddress := net.ParseAddress(option.ListenIP)
|
||||||
in.ListenOn = &coreConf.Address{Address: ipAddress}
|
in.ListenOn = &coreConf.Address{Address: ipAddress}
|
||||||
// Set SniffingConfig
|
// Set SniffingConfig
|
||||||
sniffingConfig := &coreConf.SniffingConfig{
|
sniffingConfig := &coreConf.SniffingConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
DestOverride: &coreConf.StringList{"http", "tls"},
|
DestOverride: &coreConf.StringList{"http", "tls"},
|
||||||
}
|
}
|
||||||
if config.XrayOptions.DisableSniffing {
|
if option.XrayOptions.DisableSniffing {
|
||||||
sniffingConfig.Enabled = false
|
sniffingConfig.Enabled = false
|
||||||
}
|
}
|
||||||
in.SniffingConfig = sniffingConfig
|
in.SniffingConfig = sniffingConfig
|
||||||
if *in.StreamSetting.Network == "tcp" {
|
switch network {
|
||||||
|
case "tcp":
|
||||||
if in.StreamSetting.TCPSettings != nil {
|
if in.StreamSetting.TCPSettings != nil {
|
||||||
in.StreamSetting.TCPSettings.AcceptProxyProtocol = config.XrayOptions.EnableProxyProtocol
|
in.StreamSetting.TCPSettings.AcceptProxyProtocol = option.XrayOptions.EnableProxyProtocol
|
||||||
} else {
|
} else {
|
||||||
tcpSetting := &coreConf.TCPConfig{
|
tcpSetting := &coreConf.TCPConfig{
|
||||||
AcceptProxyProtocol: config.XrayOptions.EnableProxyProtocol,
|
AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol,
|
||||||
} //Enable proxy protocol
|
} //Enable proxy protocol
|
||||||
in.StreamSetting.TCPSettings = tcpSetting
|
in.StreamSetting.TCPSettings = tcpSetting
|
||||||
}
|
}
|
||||||
} else if *in.StreamSetting.Network == "ws" {
|
case "ws":
|
||||||
in.StreamSetting.WSSettings = &coreConf.WebSocketConfig{
|
in.StreamSetting.WSSettings = &coreConf.WebSocketConfig{
|
||||||
AcceptProxyProtocol: config.XrayOptions.EnableProxyProtocol} //Enable proxy protocol
|
AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol} //Enable proxy protocol
|
||||||
|
default:
|
||||||
|
socketConfig := &coreConf.SocketConfig{
|
||||||
|
AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol,
|
||||||
|
TFO: option.XrayOptions.EnableTFO,
|
||||||
|
} //Enable proxy protocol
|
||||||
|
in.StreamSetting.SocketSettings = socketConfig
|
||||||
}
|
}
|
||||||
// Set TLS or Reality settings
|
// Set TLS or Reality settings
|
||||||
if nodeInfo.Tls {
|
switch nodeInfo.Security {
|
||||||
if config.CertConfig == nil {
|
case panel.Tls:
|
||||||
|
// Normal tls
|
||||||
|
if option.CertConfig == nil {
|
||||||
return nil, errors.New("the CertConfig is not vail")
|
return nil, errors.New("the CertConfig is not vail")
|
||||||
}
|
}
|
||||||
switch config.CertConfig.CertMode {
|
switch option.CertConfig.CertMode {
|
||||||
case "none", "":
|
case "none", "":
|
||||||
break // disable
|
break // disable
|
||||||
case "reality":
|
|
||||||
// Reality
|
|
||||||
in.StreamSetting.Security = "reality"
|
|
||||||
d, err := json.Marshal(config.CertConfig.RealityConfig.Dest)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("marshal reality dest error: %s", err)
|
|
||||||
}
|
|
||||||
if len(config.CertConfig.RealityConfig.ShortIds) == 0 {
|
|
||||||
config.CertConfig.RealityConfig.ShortIds = []string{""}
|
|
||||||
}
|
|
||||||
in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{
|
|
||||||
Dest: d,
|
|
||||||
Xver: config.CertConfig.RealityConfig.Xver,
|
|
||||||
ServerNames: config.CertConfig.RealityConfig.ServerNames,
|
|
||||||
PrivateKey: config.CertConfig.RealityConfig.PrivateKey,
|
|
||||||
MinClientVer: config.CertConfig.RealityConfig.MinClientVer,
|
|
||||||
MaxClientVer: config.CertConfig.RealityConfig.MaxClientVer,
|
|
||||||
MaxTimeDiff: config.CertConfig.RealityConfig.MaxTimeDiff,
|
|
||||||
ShortIds: config.CertConfig.RealityConfig.ShortIds,
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "remote":
|
|
||||||
if nodeInfo.ExtraConfig.EnableReality == "true" {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
if len(rc.ShortIds) == 0 {
|
|
||||||
rc.ShortIds = []string{""}
|
|
||||||
}
|
|
||||||
Xver, _ := strconv.ParseUint(rc.Xver, 10, 64)
|
|
||||||
MaxTimeDiff, _ := strconv.ParseUint(rc.Xver, 10, 64)
|
|
||||||
in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{
|
|
||||||
Dest: d,
|
|
||||||
Xver: Xver,
|
|
||||||
ServerNames: rc.ServerNames,
|
|
||||||
PrivateKey: rc.PrivateKey,
|
|
||||||
MinClientVer: rc.MinClientVer,
|
|
||||||
MaxClientVer: rc.MaxClientVer,
|
|
||||||
MaxTimeDiff: MaxTimeDiff,
|
|
||||||
ShortIds: rc.ShortIds,
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
{
|
|
||||||
// Normal tls
|
|
||||||
in.StreamSetting.Security = "tls"
|
in.StreamSetting.Security = "tls"
|
||||||
in.StreamSetting.TLSSettings = &coreConf.TLSConfig{
|
in.StreamSetting.TLSSettings = &coreConf.TLSConfig{
|
||||||
Certs: []*coreConf.TLSCertConfig{
|
Certs: []*coreConf.TLSCertConfig{
|
||||||
{
|
{
|
||||||
CertFile: config.CertConfig.CertFile,
|
CertFile: option.CertConfig.CertFile,
|
||||||
KeyFile: config.CertConfig.KeyFile,
|
KeyFile: option.CertConfig.KeyFile,
|
||||||
OcspStapling: 3600,
|
OcspStapling: 3600,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
RejectUnknownSNI: config.CertConfig.RejectUnknownSni,
|
RejectUnknownSNI: option.CertConfig.RejectUnknownSni,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case panel.Reality:
|
||||||
|
// Reality
|
||||||
|
in.StreamSetting.Security = "reality"
|
||||||
|
v := nodeInfo.VAllss
|
||||||
|
d, err := json.Marshal(v.RealityConfig.Dest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("marshal reality dest error: %s", err)
|
||||||
}
|
}
|
||||||
|
short := nodeInfo.VAllss.TlsSettings.ShortIds
|
||||||
|
if len(short) == 0 {
|
||||||
|
short = []string{""}
|
||||||
}
|
}
|
||||||
// Support ProxyProtocol for any transport protocol
|
in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{
|
||||||
if *in.StreamSetting.Network != "tcp" &&
|
Dest: d,
|
||||||
*in.StreamSetting.Network != "ws" &&
|
Xver: v.RealityConfig.Xver,
|
||||||
config.XrayOptions.EnableProxyProtocol {
|
ServerNames: v.TlsSettings.ServerName,
|
||||||
socketConfig := &coreConf.SocketConfig{
|
PrivateKey: v.TlsSettings.PrivateKey,
|
||||||
AcceptProxyProtocol: config.XrayOptions.EnableProxyProtocol,
|
MinClientVer: v.RealityConfig.MinClientVer,
|
||||||
TFO: config.XrayOptions.EnableTFO,
|
MaxClientVer: v.RealityConfig.MaxClientVer,
|
||||||
} //Enable proxy protocol
|
MaxTimeDiff: v.RealityConfig.MaxTimeDiff,
|
||||||
in.StreamSetting.SocketSettings = socketConfig
|
ShortIds: short,
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
in.Tag = tag
|
in.Tag = tag
|
||||||
return in.Build()
|
return in.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
|
func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
|
||||||
if nodeInfo.ExtraConfig.EnableVless == "true" {
|
v := nodeInfo.VAllss
|
||||||
|
if nodeInfo.Type == "vless" {
|
||||||
//Set vless
|
//Set vless
|
||||||
inbound.Protocol = "vless"
|
inbound.Protocol = "vless"
|
||||||
if config.XrayOptions.EnableFallback {
|
if config.XrayOptions.EnableFallback {
|
||||||
@ -188,22 +166,22 @@ func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreCon
|
|||||||
}
|
}
|
||||||
inbound.Settings = (*json.RawMessage)(&s)
|
inbound.Settings = (*json.RawMessage)(&s)
|
||||||
}
|
}
|
||||||
if len(nodeInfo.NetworkSettings) == 0 {
|
if len(v.NetworkSettings) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch nodeInfo.Network {
|
switch v.Network {
|
||||||
case "tcp":
|
case "tcp":
|
||||||
err := json.Unmarshal(nodeInfo.NetworkSettings, &inbound.StreamSetting.TCPSettings)
|
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.TCPSettings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unmarshal tcp settings error: %s", err)
|
return fmt.Errorf("unmarshal tcp settings error: %s", err)
|
||||||
}
|
}
|
||||||
case "ws":
|
case "ws":
|
||||||
err := json.Unmarshal(nodeInfo.NetworkSettings, &inbound.StreamSetting.WSSettings)
|
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.WSSettings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unmarshal ws settings error: %s", err)
|
return fmt.Errorf("unmarshal ws settings error: %s", err)
|
||||||
}
|
}
|
||||||
case "grpc":
|
case "grpc":
|
||||||
err := json.Unmarshal(nodeInfo.NetworkSettings, &inbound.StreamSetting.GRPCConfig)
|
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.GRPCConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unmarshal grpc settings error: %s", err)
|
return fmt.Errorf("unmarshal grpc settings error: %s", err)
|
||||||
}
|
}
|
||||||
@ -239,8 +217,9 @@ func buildTrojan(config *conf.Options, inbound *coreConf.InboundDetourConfig) er
|
|||||||
|
|
||||||
func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
|
func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
|
||||||
inbound.Protocol = "shadowsocks"
|
inbound.Protocol = "shadowsocks"
|
||||||
|
s := nodeInfo.Shadowsocks
|
||||||
settings := &coreConf.ShadowsocksServerConfig{
|
settings := &coreConf.ShadowsocksServerConfig{
|
||||||
Cipher: nodeInfo.Cipher,
|
Cipher: s.Cipher,
|
||||||
}
|
}
|
||||||
p := make([]byte, 32)
|
p := make([]byte, 32)
|
||||||
_, err := rand.Read(p)
|
_, err := rand.Read(p)
|
||||||
@ -248,9 +227,9 @@ func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *c
|
|||||||
return fmt.Errorf("generate random password error: %s", err)
|
return fmt.Errorf("generate random password error: %s", err)
|
||||||
}
|
}
|
||||||
randomPasswd := hex.EncodeToString(p)
|
randomPasswd := hex.EncodeToString(p)
|
||||||
cipher := nodeInfo.Cipher
|
cipher := s.Cipher
|
||||||
if nodeInfo.ServerKey != "" {
|
if s.ServerKey != "" {
|
||||||
settings.Password = nodeInfo.ServerKey
|
settings.Password = s.ServerKey
|
||||||
randomPasswd = base64.StdEncoding.EncodeToString([]byte(randomPasswd))
|
randomPasswd = base64.StdEncoding.EncodeToString([]byte(randomPasswd))
|
||||||
cipher = ""
|
cipher = ""
|
||||||
}
|
}
|
||||||
@ -266,8 +245,8 @@ func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *c
|
|||||||
}
|
}
|
||||||
t := coreConf.TransportProtocol("tcp")
|
t := coreConf.TransportProtocol("tcp")
|
||||||
inbound.StreamSetting = &coreConf.StreamConfig{Network: &t}
|
inbound.StreamSetting = &coreConf.StreamConfig{Network: &t}
|
||||||
s, err := json.Marshal(settings)
|
sets, err := json.Marshal(settings)
|
||||||
inbound.Settings = (*json.RawMessage)(&s)
|
inbound.Settings = (*json.RawMessage)(&sets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("marshal shadowsocks settings error: %s", err)
|
return fmt.Errorf("marshal shadowsocks settings error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -71,21 +71,19 @@ func (c *Core) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int6
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
|
func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
|
||||||
users := make([]*protocol.User, 0, len(p.UserInfo))
|
users := make([]*protocol.User, 0, len(p.Users))
|
||||||
switch p.NodeInfo.Type {
|
switch p.NodeInfo.Type {
|
||||||
case "v2ray":
|
case "vmess":
|
||||||
if p.NodeInfo.ExtraConfig.EnableVless == "true" {
|
users = buildVmessUsers(p.Tag, p.Users)
|
||||||
users = buildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow)
|
case "vless":
|
||||||
} else {
|
users = buildVlessUsers(p.Tag, p.Users, p.VAllss.Flow)
|
||||||
users = buildVmessUsers(p.Tag, p.UserInfo)
|
|
||||||
}
|
|
||||||
case "trojan":
|
case "trojan":
|
||||||
users = buildTrojanUsers(p.Tag, p.UserInfo)
|
users = buildTrojanUsers(p.Tag, p.Users)
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
users = buildSSUsers(p.Tag,
|
users = buildSSUsers(p.Tag,
|
||||||
p.UserInfo,
|
p.Users,
|
||||||
p.NodeInfo.Cipher,
|
p.Shadowsocks.Cipher,
|
||||||
p.NodeInfo.ServerKey)
|
p.Shadowsocks.ServerKey)
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("unsupported node type: %s", p.NodeInfo.Type)
|
return 0, fmt.Errorf("unsupported node type: %s", p.NodeInfo.Type)
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,8 @@ func (c *Core) Close() error {
|
|||||||
|
|
||||||
func (c *Core) Protocols() []string {
|
func (c *Core) Protocols() []string {
|
||||||
return []string{
|
return []string{
|
||||||
"v2ray",
|
"vmess",
|
||||||
|
"vless",
|
||||||
"shadowsocks",
|
"shadowsocks",
|
||||||
"trojan",
|
"trojan",
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ func (c *Controller) renewCertTask() error {
|
|||||||
|
|
||||||
func (c *Controller) requestCert() error {
|
func (c *Controller) requestCert() error {
|
||||||
switch c.CertConfig.CertMode {
|
switch c.CertConfig.CertMode {
|
||||||
case "reality", "none", "":
|
case "none", "":
|
||||||
case "file":
|
case "file":
|
||||||
if c.CertConfig.CertFile == "" || c.CertConfig.KeyFile == "" {
|
if c.CertConfig.CertFile == "" || c.CertConfig.KeyFile == "" {
|
||||||
return fmt.Errorf("cert file path or key file path not exist")
|
return fmt.Errorf("cert file path or key file path not exist")
|
||||||
|
@ -65,7 +65,7 @@ func (c *Controller) Start() error {
|
|||||||
return fmt.Errorf("update rule error: %s", err)
|
return fmt.Errorf("update rule error: %s", err)
|
||||||
}
|
}
|
||||||
c.limiter = l
|
c.limiter = l
|
||||||
if node.Tls || node.Type == "hysteria" {
|
if node.Security == panel.Tls {
|
||||||
err = c.requestCert()
|
err = c.requestCert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("request cert error: %s", err)
|
return fmt.Errorf("request cert error: %s", err)
|
||||||
@ -78,8 +78,7 @@ func (c *Controller) Start() error {
|
|||||||
}
|
}
|
||||||
added, err := c.server.AddUsers(&vCore.AddUsersParams{
|
added, err := c.server.AddUsers(&vCore.AddUsersParams{
|
||||||
Tag: c.tag,
|
Tag: c.tag,
|
||||||
Config: c.Options,
|
Users: c.userList,
|
||||||
UserInfo: c.userList,
|
|
||||||
NodeInfo: node,
|
NodeInfo: node,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
50
node/task.go
50
node/task.go
@ -26,9 +26,9 @@ func (c *Controller) startTasks(node *panel.NodeInfo) {
|
|||||||
_ = c.nodeInfoMonitorPeriodic.Start(false)
|
_ = c.nodeInfoMonitorPeriodic.Start(false)
|
||||||
log.WithField("tag", c.tag).Info("Start report node status")
|
log.WithField("tag", c.tag).Info("Start report node status")
|
||||||
_ = c.userReportPeriodic.Start(false)
|
_ = c.userReportPeriodic.Start(false)
|
||||||
if node.Tls {
|
if node.Security == panel.Tls {
|
||||||
switch c.CertConfig.CertMode {
|
switch c.CertConfig.CertMode {
|
||||||
case "reality", "none", "", "file":
|
case "none", "", "file", "self":
|
||||||
default:
|
default:
|
||||||
c.renewCertPeriodic = &task.Task{
|
c.renewCertPeriodic = &task.Task{
|
||||||
Interval: time.Hour * 24,
|
Interval: time.Hour * 24,
|
||||||
@ -51,7 +51,7 @@ func (c *Controller) startTasks(node *panel.NodeInfo) {
|
|||||||
|
|
||||||
func (c *Controller) nodeInfoMonitor() (err error) {
|
func (c *Controller) nodeInfoMonitor() (err error) {
|
||||||
// get node info
|
// get node info
|
||||||
newNodeInfo, err := c.apiClient.GetNodeInfo()
|
newN, err := c.apiClient.GetNodeInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"tag": c.tag,
|
"tag": c.tag,
|
||||||
@ -60,7 +60,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// get user info
|
// get user info
|
||||||
newUserInfo, err := c.apiClient.GetUserList()
|
newU, err := c.apiClient.GetUserList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"tag": c.tag,
|
"tag": c.tag,
|
||||||
@ -68,11 +68,11 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}).Error("Get user list failed")
|
}).Error("Get user list failed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if newNodeInfo != nil {
|
if newN != nil {
|
||||||
c.info = newNodeInfo
|
c.info = newN
|
||||||
// nodeInfo changed
|
// nodeInfo changed
|
||||||
if newUserInfo != nil {
|
if newU != nil {
|
||||||
c.userList = newUserInfo
|
c.userList = newU
|
||||||
}
|
}
|
||||||
c.traffic = make(map[string]int64)
|
c.traffic = make(map[string]int64)
|
||||||
// Remove old tag
|
// Remove old tag
|
||||||
@ -88,10 +88,10 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
// Remove Old limiter
|
// Remove Old limiter
|
||||||
limiter.DeleteLimiter(c.tag)
|
limiter.DeleteLimiter(c.tag)
|
||||||
// Add new Limiter
|
// Add new Limiter
|
||||||
c.tag = c.buildNodeTag(newNodeInfo)
|
c.tag = c.buildNodeTag(newN)
|
||||||
l := limiter.AddLimiter(c.tag, &c.LimitConfig, c.userList)
|
l := limiter.AddLimiter(c.tag, &c.LimitConfig, c.userList)
|
||||||
// check cert
|
// check cert
|
||||||
if newNodeInfo.Tls || newNodeInfo.Type == "hysteria" {
|
if newN.Security == panel.Tls {
|
||||||
err = c.requestCert()
|
err = c.requestCert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@ -102,7 +102,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add new node
|
// add new node
|
||||||
err = c.server.AddNode(c.tag, newNodeInfo, c.Options)
|
err = c.server.AddNode(c.tag, newN, c.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"tag": c.tag,
|
"tag": c.tag,
|
||||||
@ -112,9 +112,8 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
_, err = c.server.AddUsers(&vCore.AddUsersParams{
|
_, err = c.server.AddUsers(&vCore.AddUsersParams{
|
||||||
Tag: c.tag,
|
Tag: c.tag,
|
||||||
Config: c.Options,
|
Users: c.userList,
|
||||||
UserInfo: c.userList,
|
NodeInfo: newN,
|
||||||
NodeInfo: newNodeInfo,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@ -123,7 +122,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}).Error("Add users failed")
|
}).Error("Add users failed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err = l.UpdateRule(&newNodeInfo.Rules)
|
err = l.UpdateRule(&newN.Rules)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"tag": c.tag,
|
"tag": c.tag,
|
||||||
@ -133,15 +132,15 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
c.limiter = l
|
c.limiter = l
|
||||||
// Check interval
|
// Check interval
|
||||||
if c.nodeInfoMonitorPeriodic.Interval != newNodeInfo.PullInterval &&
|
if c.nodeInfoMonitorPeriodic.Interval != newN.PullInterval &&
|
||||||
newNodeInfo.PullInterval != 0 {
|
newN.PullInterval != 0 {
|
||||||
c.nodeInfoMonitorPeriodic.Interval = newNodeInfo.PullInterval
|
c.nodeInfoMonitorPeriodic.Interval = newN.PullInterval
|
||||||
c.nodeInfoMonitorPeriodic.Close()
|
c.nodeInfoMonitorPeriodic.Close()
|
||||||
_ = c.nodeInfoMonitorPeriodic.Start(false)
|
_ = c.nodeInfoMonitorPeriodic.Start(false)
|
||||||
}
|
}
|
||||||
if c.userReportPeriodic.Interval != newNodeInfo.PushInterval &&
|
if c.userReportPeriodic.Interval != newN.PushInterval &&
|
||||||
newNodeInfo.PushInterval != 0 {
|
newN.PushInterval != 0 {
|
||||||
c.userReportPeriodic.Interval = newNodeInfo.PullInterval
|
c.userReportPeriodic.Interval = newN.PullInterval
|
||||||
c.userReportPeriodic.Close()
|
c.userReportPeriodic.Close()
|
||||||
_ = c.userReportPeriodic.Start(false)
|
_ = c.userReportPeriodic.Start(false)
|
||||||
}
|
}
|
||||||
@ -151,10 +150,10 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// node no changed, check users
|
// node no changed, check users
|
||||||
if len(newUserInfo) == 0 {
|
if len(newU) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
deleted, added := compareUserList(c.userList, newUserInfo)
|
deleted, added := compareUserList(c.userList, newU)
|
||||||
if len(deleted) > 0 {
|
if len(deleted) > 0 {
|
||||||
// have deleted users
|
// have deleted users
|
||||||
err = c.server.DelUsers(deleted, c.tag)
|
err = c.server.DelUsers(deleted, c.tag)
|
||||||
@ -170,9 +169,8 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
// have added users
|
// have added users
|
||||||
_, err = c.server.AddUsers(&vCore.AddUsersParams{
|
_, err = c.server.AddUsers(&vCore.AddUsersParams{
|
||||||
Tag: c.tag,
|
Tag: c.tag,
|
||||||
Config: c.Options,
|
|
||||||
NodeInfo: c.info,
|
NodeInfo: c.info,
|
||||||
UserInfo: added,
|
Users: added,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@ -199,7 +197,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.userList = newUserInfo
|
c.userList = newU
|
||||||
if len(added)+len(deleted) != 0 {
|
if len(added)+len(deleted) != 0 {
|
||||||
log.WithField("tag", c.tag).
|
log.WithField("tag", c.tag).
|
||||||
Infof("%d user deleted, %d user added", len(deleted), len(added))
|
Infof("%d user deleted, %d user added", len(deleted), len(added))
|
||||||
|
Loading…
Reference in New Issue
Block a user