github.com/moqsien/xraycore@v1.8.5/infra/conf/vless.go (about) 1 package conf 2 3 import ( 4 "encoding/json" 5 "runtime" 6 "strconv" 7 "syscall" 8 9 "github.com/moqsien/xraycore/common/net" 10 "github.com/moqsien/xraycore/common/protocol" 11 "github.com/moqsien/xraycore/common/serial" 12 "github.com/moqsien/xraycore/common/uuid" 13 "github.com/moqsien/xraycore/proxy/vless" 14 "github.com/moqsien/xraycore/proxy/vless/inbound" 15 "github.com/moqsien/xraycore/proxy/vless/outbound" 16 "google.golang.org/protobuf/proto" 17 ) 18 19 type VLessInboundFallback struct { 20 Name string `json:"name"` 21 Alpn string `json:"alpn"` 22 Path string `json:"path"` 23 Type string `json:"type"` 24 Dest json.RawMessage `json:"dest"` 25 Xver uint64 `json:"xver"` 26 } 27 28 type VLessInboundConfig struct { 29 Clients []json.RawMessage `json:"clients"` 30 Decryption string `json:"decryption"` 31 Fallback *VLessInboundFallback `json:"fallback"` 32 Fallbacks []*VLessInboundFallback `json:"fallbacks"` 33 } 34 35 // Build implements Buildable 36 func (c *VLessInboundConfig) Build() (proto.Message, error) { 37 config := new(inbound.Config) 38 config.Clients = make([]*protocol.User, len(c.Clients)) 39 for idx, rawUser := range c.Clients { 40 user := new(protocol.User) 41 if err := json.Unmarshal(rawUser, user); err != nil { 42 return nil, newError(`VLESS clients: invalid user`).Base(err) 43 } 44 account := new(vless.Account) 45 if err := json.Unmarshal(rawUser, account); err != nil { 46 return nil, newError(`VLESS clients: invalid user`).Base(err) 47 } 48 49 u, err := uuid.ParseString(account.Id) 50 if err != nil { 51 return nil, err 52 } 53 account.Id = u.String() 54 55 switch account.Flow { 56 case "", vless.XRV: 57 default: 58 return nil, newError(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`) 59 } 60 61 if account.Encryption != "" { 62 return nil, newError(`VLESS clients: "encryption" should not in inbound settings`) 63 } 64 65 user.Account = serial.ToTypedMessage(account) 66 config.Clients[idx] = user 67 } 68 69 if c.Decryption != "none" { 70 return nil, newError(`VLESS settings: please add/set "decryption":"none" to every settings`) 71 } 72 config.Decryption = c.Decryption 73 74 if c.Fallback != nil { 75 return nil, newError(`VLESS settings: please use "fallbacks":[{}] instead of "fallback":{}`) 76 } 77 for _, fb := range c.Fallbacks { 78 var i uint16 79 var s string 80 if err := json.Unmarshal(fb.Dest, &i); err == nil { 81 s = strconv.Itoa(int(i)) 82 } else { 83 _ = json.Unmarshal(fb.Dest, &s) 84 } 85 config.Fallbacks = append(config.Fallbacks, &inbound.Fallback{ 86 Name: fb.Name, 87 Alpn: fb.Alpn, 88 Path: fb.Path, 89 Type: fb.Type, 90 Dest: s, 91 Xver: fb.Xver, 92 }) 93 } 94 for _, fb := range config.Fallbacks { 95 /* 96 if fb.Alpn == "h2" && fb.Path != "" { 97 return nil, newError(`VLESS fallbacks: "alpn":"h2" doesn't support "path"`) 98 } 99 */ 100 if fb.Path != "" && fb.Path[0] != '/' { 101 return nil, newError(`VLESS fallbacks: "path" must be empty or start with "/"`) 102 } 103 if fb.Type == "" && fb.Dest != "" { 104 if fb.Dest == "serve-ws-none" { 105 fb.Type = "serve" 106 } else { 107 switch fb.Dest[0] { 108 case '@', '/': 109 fb.Type = "unix" 110 if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && (runtime.GOOS == "linux" || runtime.GOOS == "android") { 111 fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy 112 copy(fullAddr, fb.Dest[1:]) 113 fb.Dest = string(fullAddr) 114 } 115 default: 116 if _, err := strconv.Atoi(fb.Dest); err == nil { 117 fb.Dest = "127.0.0.1:" + fb.Dest 118 } 119 if _, _, err := net.SplitHostPort(fb.Dest); err == nil { 120 fb.Type = "tcp" 121 } 122 } 123 } 124 } 125 if fb.Type == "" { 126 return nil, newError(`VLESS fallbacks: please fill in a valid value for every "dest"`) 127 } 128 if fb.Xver > 2 { 129 return nil, newError(`VLESS fallbacks: invalid PROXY protocol version, "xver" only accepts 0, 1, 2`) 130 } 131 } 132 133 return config, nil 134 } 135 136 type VLessOutboundVnext struct { 137 Address *Address `json:"address"` 138 Port uint16 `json:"port"` 139 Users []json.RawMessage `json:"users"` 140 } 141 142 type VLessOutboundConfig struct { 143 Vnext []*VLessOutboundVnext `json:"vnext"` 144 } 145 146 // Build implements Buildable 147 func (c *VLessOutboundConfig) Build() (proto.Message, error) { 148 config := new(outbound.Config) 149 150 if len(c.Vnext) == 0 { 151 return nil, newError(`VLESS settings: "vnext" is empty`) 152 } 153 config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext)) 154 for idx, rec := range c.Vnext { 155 if rec.Address == nil { 156 return nil, newError(`VLESS vnext: "address" is not set`) 157 } 158 if len(rec.Users) == 0 { 159 return nil, newError(`VLESS vnext: "users" is empty`) 160 } 161 spec := &protocol.ServerEndpoint{ 162 Address: rec.Address.Build(), 163 Port: uint32(rec.Port), 164 User: make([]*protocol.User, len(rec.Users)), 165 } 166 for idx, rawUser := range rec.Users { 167 user := new(protocol.User) 168 if err := json.Unmarshal(rawUser, user); err != nil { 169 return nil, newError(`VLESS users: invalid user`).Base(err) 170 } 171 account := new(vless.Account) 172 if err := json.Unmarshal(rawUser, account); err != nil { 173 return nil, newError(`VLESS users: invalid user`).Base(err) 174 } 175 176 u, err := uuid.ParseString(account.Id) 177 if err != nil { 178 return nil, err 179 } 180 account.Id = u.String() 181 182 switch account.Flow { 183 case "", vless.XRV, vless.XRV + "-udp443": 184 default: 185 return nil, newError(`VLESS users: "flow" doesn't support "` + account.Flow + `" in this version`) 186 } 187 188 if account.Encryption != "none" { 189 return nil, newError(`VLESS users: please add/set "encryption":"none" for every user`) 190 } 191 192 user.Account = serial.ToTypedMessage(account) 193 spec.User[idx] = user 194 } 195 config.Vnext[idx] = spec 196 } 197 198 return config, nil 199 }