vless.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. package conf
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "path/filepath"
  6. "runtime"
  7. "strconv"
  8. "strings"
  9. "syscall"
  10. "github.com/xtls/xray-core/common/errors"
  11. "github.com/xtls/xray-core/common/net"
  12. "github.com/xtls/xray-core/common/protocol"
  13. "github.com/xtls/xray-core/common/serial"
  14. "github.com/xtls/xray-core/common/uuid"
  15. "github.com/xtls/xray-core/proxy/vless"
  16. "github.com/xtls/xray-core/proxy/vless/inbound"
  17. "github.com/xtls/xray-core/proxy/vless/outbound"
  18. "google.golang.org/protobuf/proto"
  19. )
  20. type VLessInboundFallback struct {
  21. Name string `json:"name"`
  22. Alpn string `json:"alpn"`
  23. Path string `json:"path"`
  24. Type string `json:"type"`
  25. Dest json.RawMessage `json:"dest"`
  26. Xver uint64 `json:"xver"`
  27. }
  28. type VLessInboundConfig struct {
  29. Clients []json.RawMessage `json:"clients"`
  30. Decryption string `json:"decryption"`
  31. Fallbacks []*VLessInboundFallback `json:"fallbacks"`
  32. Flow string `json:"flow"`
  33. }
  34. // Build implements Buildable
  35. func (c *VLessInboundConfig) Build() (proto.Message, error) {
  36. config := new(inbound.Config)
  37. config.Clients = make([]*protocol.User, len(c.Clients))
  38. switch c.Flow {
  39. case vless.None:
  40. c.Flow = ""
  41. case "", vless.XRV:
  42. default:
  43. return nil, errors.New(`VLESS "settings.flow" doesn't support "` + c.Flow + `" in this version`)
  44. }
  45. for idx, rawUser := range c.Clients {
  46. user := new(protocol.User)
  47. if err := json.Unmarshal(rawUser, user); err != nil {
  48. return nil, errors.New(`VLESS clients: invalid user`).Base(err)
  49. }
  50. account := new(vless.Account)
  51. if err := json.Unmarshal(rawUser, account); err != nil {
  52. return nil, errors.New(`VLESS clients: invalid user`).Base(err)
  53. }
  54. u, err := uuid.ParseString(account.Id)
  55. if err != nil {
  56. return nil, err
  57. }
  58. account.Id = u.String()
  59. switch account.Flow {
  60. case "":
  61. account.Flow = c.Flow
  62. case vless.None:
  63. account.Flow = ""
  64. case vless.XRV:
  65. default:
  66. return nil, errors.New(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`)
  67. }
  68. if account.Encryption != "" {
  69. return nil, errors.New(`VLESS clients: "encryption" should not be in inbound settings`)
  70. }
  71. if account.Reverse != nil && account.Reverse.Tag == "" {
  72. return nil, errors.New(`VLESS clients: "tag" can't be empty for "reverse"`)
  73. }
  74. user.Account = serial.ToTypedMessage(account)
  75. config.Clients[idx] = user
  76. }
  77. config.Decryption = c.Decryption
  78. if !func() bool {
  79. s := strings.Split(config.Decryption, ".")
  80. if len(s) < 4 || s[0] != "mlkem768x25519plus" {
  81. return false
  82. }
  83. switch s[1] {
  84. case "native":
  85. case "xorpub":
  86. config.XorMode = 1
  87. case "random":
  88. config.XorMode = 2
  89. default:
  90. return false
  91. }
  92. t := strings.SplitN(strings.TrimSuffix(s[2], "s"), "-", 2)
  93. i, err := strconv.Atoi(t[0])
  94. if err != nil {
  95. return false
  96. }
  97. config.SecondsFrom = int64(i)
  98. if len(t) == 2 {
  99. i, err := strconv.Atoi(t[1])
  100. if err != nil {
  101. return false
  102. }
  103. config.SecondsTo = int64(i)
  104. }
  105. padding := 0
  106. for _, r := range s[3:] {
  107. if len(r) < 20 {
  108. padding += len(r) + 1
  109. continue
  110. }
  111. if b, _ := base64.RawURLEncoding.DecodeString(r); len(b) != 32 && len(b) != 64 {
  112. return false
  113. }
  114. }
  115. config.Decryption = config.Decryption[27+len(s[2]):]
  116. if padding > 0 {
  117. config.Padding = config.Decryption[:padding-1]
  118. config.Decryption = config.Decryption[padding:]
  119. }
  120. return true
  121. }() && config.Decryption != "none" {
  122. if config.Decryption == "" {
  123. return nil, errors.New(`VLESS settings: please add/set "decryption":"none" to every settings`)
  124. }
  125. return nil, errors.New(`VLESS settings: unsupported "decryption": ` + config.Decryption)
  126. }
  127. if config.Decryption != "none" && c.Fallbacks != nil {
  128. return nil, errors.New(`VLESS settings: "fallbacks" can not be used together with "decryption"`)
  129. }
  130. for _, fb := range c.Fallbacks {
  131. var i uint16
  132. var s string
  133. if err := json.Unmarshal(fb.Dest, &i); err == nil {
  134. s = strconv.Itoa(int(i))
  135. } else {
  136. _ = json.Unmarshal(fb.Dest, &s)
  137. }
  138. config.Fallbacks = append(config.Fallbacks, &inbound.Fallback{
  139. Name: fb.Name,
  140. Alpn: fb.Alpn,
  141. Path: fb.Path,
  142. Type: fb.Type,
  143. Dest: s,
  144. Xver: fb.Xver,
  145. })
  146. }
  147. for _, fb := range config.Fallbacks {
  148. /*
  149. if fb.Alpn == "h2" && fb.Path != "" {
  150. return nil, errors.New(`VLESS fallbacks: "alpn":"h2" doesn't support "path"`)
  151. }
  152. */
  153. if fb.Path != "" && fb.Path[0] != '/' {
  154. return nil, errors.New(`VLESS fallbacks: "path" must be empty or start with "/"`)
  155. }
  156. if fb.Type == "" && fb.Dest != "" {
  157. if fb.Dest == "serve-ws-none" {
  158. fb.Type = "serve"
  159. } else if filepath.IsAbs(fb.Dest) || fb.Dest[0] == '@' {
  160. fb.Type = "unix"
  161. if strings.HasPrefix(fb.Dest, "@@") && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
  162. fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
  163. copy(fullAddr, fb.Dest[1:])
  164. fb.Dest = string(fullAddr)
  165. }
  166. } else {
  167. if _, err := strconv.Atoi(fb.Dest); err == nil {
  168. fb.Dest = "localhost:" + fb.Dest
  169. }
  170. if _, _, err := net.SplitHostPort(fb.Dest); err == nil {
  171. fb.Type = "tcp"
  172. }
  173. }
  174. }
  175. if fb.Type == "" {
  176. return nil, errors.New(`VLESS fallbacks: please fill in a valid value for every "dest"`)
  177. }
  178. if fb.Xver > 2 {
  179. return nil, errors.New(`VLESS fallbacks: invalid PROXY protocol version, "xver" only accepts 0, 1, 2`)
  180. }
  181. }
  182. return config, nil
  183. }
  184. type VLessOutboundVnext struct {
  185. Address *Address `json:"address"`
  186. Port uint16 `json:"port"`
  187. Users []json.RawMessage `json:"users"`
  188. }
  189. type VLessOutboundConfig struct {
  190. Address *Address `json:"address"`
  191. Port uint16 `json:"port"`
  192. Level uint32 `json:"level"`
  193. Email string `json:"email"`
  194. Id string `json:"id"`
  195. Flow string `json:"flow"`
  196. Seed string `json:"seed"`
  197. Encryption string `json:"encryption"`
  198. Reverse *vless.Reverse `json:"reverse"`
  199. Vnext []*VLessOutboundVnext `json:"vnext"`
  200. }
  201. // Build implements Buildable
  202. func (c *VLessOutboundConfig) Build() (proto.Message, error) {
  203. config := new(outbound.Config)
  204. if c.Address != nil {
  205. c.Vnext = []*VLessOutboundVnext{
  206. {
  207. Address: c.Address,
  208. Port: c.Port,
  209. Users: []json.RawMessage{{}},
  210. },
  211. }
  212. }
  213. if len(c.Vnext) != 1 {
  214. return nil, errors.New(`VLESS settings: "vnext" should have one and only one member. Multiple endpoints in "vnext" should use multiple VLESS outbounds and routing balancer instead`)
  215. }
  216. for _, rec := range c.Vnext {
  217. if rec.Address == nil {
  218. return nil, errors.New(`VLESS vnext: "address" is not set`)
  219. }
  220. if len(rec.Users) != 1 {
  221. return nil, errors.New(`VLESS vnext: "users" should have one and only one member. Multiple members in "users" should use multiple VLESS outbounds and routing balancer instead`)
  222. }
  223. spec := &protocol.ServerEndpoint{
  224. Address: rec.Address.Build(),
  225. Port: uint32(rec.Port),
  226. }
  227. for _, rawUser := range rec.Users {
  228. user := new(protocol.User)
  229. if c.Address != nil {
  230. user.Level = c.Level
  231. user.Email = c.Email
  232. } else {
  233. if err := json.Unmarshal(rawUser, user); err != nil {
  234. return nil, errors.New(`VLESS users: invalid user`).Base(err)
  235. }
  236. }
  237. account := new(vless.Account)
  238. if c.Address != nil {
  239. account.Id = c.Id
  240. account.Flow = c.Flow
  241. //account.Seed = c.Seed
  242. account.Encryption = c.Encryption
  243. account.Reverse = c.Reverse
  244. } else {
  245. if err := json.Unmarshal(rawUser, account); err != nil {
  246. return nil, errors.New(`VLESS users: invalid user`).Base(err)
  247. }
  248. }
  249. u, err := uuid.ParseString(account.Id)
  250. if err != nil {
  251. return nil, err
  252. }
  253. account.Id = u.String()
  254. switch account.Flow {
  255. case "", vless.XRV, vless.XRV + "-udp443":
  256. default:
  257. return nil, errors.New(`VLESS users: "flow" doesn't support "` + account.Flow + `" in this version`)
  258. }
  259. if !func() bool {
  260. s := strings.Split(account.Encryption, ".")
  261. if len(s) < 4 || s[0] != "mlkem768x25519plus" {
  262. return false
  263. }
  264. switch s[1] {
  265. case "native":
  266. case "xorpub":
  267. account.XorMode = 1
  268. case "random":
  269. account.XorMode = 2
  270. default:
  271. return false
  272. }
  273. switch s[2] {
  274. case "1rtt":
  275. case "0rtt":
  276. account.Seconds = 1
  277. default:
  278. return false
  279. }
  280. padding := 0
  281. for _, r := range s[3:] {
  282. if len(r) < 20 {
  283. padding += len(r) + 1
  284. continue
  285. }
  286. if b, _ := base64.RawURLEncoding.DecodeString(r); len(b) != 32 && len(b) != 1184 {
  287. return false
  288. }
  289. }
  290. account.Encryption = account.Encryption[27+len(s[2]):]
  291. if padding > 0 {
  292. account.Padding = account.Encryption[:padding-1]
  293. account.Encryption = account.Encryption[padding:]
  294. }
  295. return true
  296. }() && account.Encryption != "none" {
  297. if account.Encryption == "" {
  298. return nil, errors.New(`VLESS users: please add/set "encryption":"none" for every user`)
  299. }
  300. return nil, errors.New(`VLESS users: unsupported "encryption": ` + account.Encryption)
  301. }
  302. if account.Reverse != nil && account.Reverse.Tag == "" {
  303. return nil, errors.New(`VLESS clients: "tag" can't be empty for "reverse"`)
  304. }
  305. user.Account = serial.ToTypedMessage(account)
  306. spec.User = user
  307. break
  308. }
  309. config.Vnext = spec
  310. break
  311. }
  312. return config, nil
  313. }