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