2020-11-25 13:01:53 +02:00
|
|
|
package conf
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/golang/protobuf/proto"
|
2020-12-04 03:36:16 +02:00
|
|
|
"github.com/xtls/xray-core/common/protocol"
|
|
|
|
"github.com/xtls/xray-core/common/serial"
|
2021-01-12 13:31:02 +02:00
|
|
|
"github.com/xtls/xray-core/common/uuid"
|
2020-12-04 03:36:16 +02:00
|
|
|
"github.com/xtls/xray-core/proxy/vmess"
|
|
|
|
"github.com/xtls/xray-core/proxy/vmess/inbound"
|
|
|
|
"github.com/xtls/xray-core/proxy/vmess/outbound"
|
2020-11-25 13:01:53 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type VMessAccount struct {
|
2021-04-29 01:29:42 +03:00
|
|
|
ID string `json:"id"`
|
|
|
|
AlterIds uint16 `json:"alterId"`
|
|
|
|
Security string `json:"security"`
|
|
|
|
Experiments string `json:"experiments"`
|
2020-11-25 13:01:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Build implements Buildable
|
|
|
|
func (a *VMessAccount) Build() *vmess.Account {
|
|
|
|
var st protocol.SecurityType
|
|
|
|
switch strings.ToLower(a.Security) {
|
|
|
|
case "aes-128-gcm":
|
|
|
|
st = protocol.SecurityType_AES128_GCM
|
|
|
|
case "chacha20-poly1305":
|
|
|
|
st = protocol.SecurityType_CHACHA20_POLY1305
|
|
|
|
case "auto":
|
|
|
|
st = protocol.SecurityType_AUTO
|
|
|
|
case "none":
|
|
|
|
st = protocol.SecurityType_NONE
|
2021-03-05 10:41:18 +02:00
|
|
|
case "zero":
|
|
|
|
st = protocol.SecurityType_ZERO
|
2020-11-25 13:01:53 +02:00
|
|
|
default:
|
|
|
|
st = protocol.SecurityType_AUTO
|
|
|
|
}
|
|
|
|
return &vmess.Account{
|
|
|
|
Id: a.ID,
|
|
|
|
AlterId: uint32(a.AlterIds),
|
|
|
|
SecuritySettings: &protocol.SecurityConfig{
|
|
|
|
Type: st,
|
|
|
|
},
|
2021-04-29 01:29:42 +03:00
|
|
|
TestsEnabled: a.Experiments,
|
2020-11-25 13:01:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type VMessDetourConfig struct {
|
|
|
|
ToTag string `json:"to"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build implements Buildable
|
|
|
|
func (c *VMessDetourConfig) Build() *inbound.DetourConfig {
|
|
|
|
return &inbound.DetourConfig{
|
|
|
|
To: c.ToTag,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type FeaturesConfig struct {
|
|
|
|
Detour *VMessDetourConfig `json:"detour"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type VMessDefaultConfig struct {
|
|
|
|
AlterIDs uint16 `json:"alterId"`
|
|
|
|
Level byte `json:"level"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build implements Buildable
|
|
|
|
func (c *VMessDefaultConfig) Build() *inbound.DefaultConfig {
|
|
|
|
config := new(inbound.DefaultConfig)
|
|
|
|
config.AlterId = uint32(c.AlterIDs)
|
|
|
|
config.Level = uint32(c.Level)
|
|
|
|
return config
|
|
|
|
}
|
|
|
|
|
|
|
|
type VMessInboundConfig struct {
|
|
|
|
Users []json.RawMessage `json:"clients"`
|
|
|
|
Features *FeaturesConfig `json:"features"`
|
|
|
|
Defaults *VMessDefaultConfig `json:"default"`
|
|
|
|
DetourConfig *VMessDetourConfig `json:"detour"`
|
|
|
|
SecureOnly bool `json:"disableInsecureEncryption"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build implements Buildable
|
|
|
|
func (c *VMessInboundConfig) Build() (proto.Message, error) {
|
|
|
|
config := &inbound.Config{
|
|
|
|
SecureEncryptionOnly: c.SecureOnly,
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Defaults != nil {
|
|
|
|
config.Default = c.Defaults.Build()
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.DetourConfig != nil {
|
|
|
|
config.Detour = c.DetourConfig.Build()
|
|
|
|
} else if c.Features != nil && c.Features.Detour != nil {
|
|
|
|
config.Detour = c.Features.Detour.Build()
|
|
|
|
}
|
|
|
|
|
|
|
|
config.User = make([]*protocol.User, len(c.Users))
|
|
|
|
for idx, rawData := range c.Users {
|
|
|
|
user := new(protocol.User)
|
|
|
|
if err := json.Unmarshal(rawData, user); err != nil {
|
|
|
|
return nil, newError("invalid VMess user").Base(err)
|
|
|
|
}
|
|
|
|
account := new(VMessAccount)
|
|
|
|
if err := json.Unmarshal(rawData, account); err != nil {
|
|
|
|
return nil, newError("invalid VMess user").Base(err)
|
|
|
|
}
|
2021-01-12 13:31:02 +02:00
|
|
|
|
|
|
|
u, err := uuid.ParseString(account.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
account.ID = u.String()
|
|
|
|
|
2020-11-25 13:01:53 +02:00
|
|
|
user.Account = serial.ToTypedMessage(account.Build())
|
|
|
|
config.User[idx] = user
|
|
|
|
}
|
|
|
|
|
|
|
|
return config, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type VMessOutboundTarget struct {
|
|
|
|
Address *Address `json:"address"`
|
|
|
|
Port uint16 `json:"port"`
|
|
|
|
Users []json.RawMessage `json:"users"`
|
|
|
|
}
|
2021-10-19 19:57:14 +03:00
|
|
|
|
2020-11-25 13:01:53 +02:00
|
|
|
type VMessOutboundConfig struct {
|
|
|
|
Receivers []*VMessOutboundTarget `json:"vnext"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build implements Buildable
|
|
|
|
func (c *VMessOutboundConfig) Build() (proto.Message, error) {
|
|
|
|
config := new(outbound.Config)
|
|
|
|
|
|
|
|
if len(c.Receivers) == 0 {
|
|
|
|
return nil, newError("0 VMess receiver configured")
|
|
|
|
}
|
|
|
|
serverSpecs := make([]*protocol.ServerEndpoint, len(c.Receivers))
|
|
|
|
for idx, rec := range c.Receivers {
|
|
|
|
if len(rec.Users) == 0 {
|
|
|
|
return nil, newError("0 user configured for VMess outbound")
|
|
|
|
}
|
|
|
|
if rec.Address == nil {
|
|
|
|
return nil, newError("address is not set in VMess outbound config")
|
|
|
|
}
|
|
|
|
spec := &protocol.ServerEndpoint{
|
|
|
|
Address: rec.Address.Build(),
|
|
|
|
Port: uint32(rec.Port),
|
|
|
|
}
|
|
|
|
for _, rawUser := range rec.Users {
|
|
|
|
user := new(protocol.User)
|
|
|
|
if err := json.Unmarshal(rawUser, user); err != nil {
|
|
|
|
return nil, newError("invalid VMess user").Base(err)
|
|
|
|
}
|
|
|
|
account := new(VMessAccount)
|
|
|
|
if err := json.Unmarshal(rawUser, account); err != nil {
|
|
|
|
return nil, newError("invalid VMess user").Base(err)
|
|
|
|
}
|
2021-01-12 13:31:02 +02:00
|
|
|
|
|
|
|
u, err := uuid.ParseString(account.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
account.ID = u.String()
|
|
|
|
|
2020-11-25 13:01:53 +02:00
|
|
|
user.Account = serial.ToTypedMessage(account.Build())
|
|
|
|
spec.User = append(spec.User, user)
|
|
|
|
}
|
|
|
|
serverSpecs[idx] = spec
|
|
|
|
}
|
|
|
|
config.Receiver = serverSpecs
|
|
|
|
return config, nil
|
|
|
|
}
|