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