github.com/imannamdari/v2ray-core/v5@v5.0.5/infra/conf/v4/vless.go (about) 1 package v4 2 3 import ( 4 "encoding/json" 5 "runtime" 6 "strconv" 7 "syscall" 8 9 "github.com/golang/protobuf/proto" 10 11 "github.com/imannamdari/v2ray-core/v5/common/net" 12 "github.com/imannamdari/v2ray-core/v5/common/protocol" 13 "github.com/imannamdari/v2ray-core/v5/common/serial" 14 "github.com/imannamdari/v2ray-core/v5/infra/conf/cfgcommon" 15 "github.com/imannamdari/v2ray-core/v5/proxy/vless" 16 "github.com/imannamdari/v2ray-core/v5/proxy/vless/inbound" 17 "github.com/imannamdari/v2ray-core/v5/proxy/vless/outbound" 18 ) 19 20 type VLessInboundFallback struct { 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 json.RawMessage `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 if account.Encryption != "" { 50 return nil, newError(`VLESS clients: "encryption" should not in inbound settings`) 51 } 52 53 user.Account = serial.ToTypedMessage(account) 54 config.Clients[idx] = user 55 } 56 57 if c.Decryption != "none" { 58 return nil, newError(`VLESS settings: please add/set "decryption":"none" to every settings`) 59 } 60 config.Decryption = c.Decryption 61 62 if c.Fallback != nil { 63 return nil, newError(`VLESS settings: please use "fallbacks":[{}] instead of "fallback":{}`) 64 } 65 for _, fb := range c.Fallbacks { 66 var i uint16 67 var s string 68 if err := json.Unmarshal(fb.Dest, &i); err == nil { 69 s = strconv.Itoa(int(i)) 70 } else { 71 _ = json.Unmarshal(fb.Dest, &s) 72 } 73 config.Fallbacks = append(config.Fallbacks, &inbound.Fallback{ 74 Alpn: fb.Alpn, 75 Path: fb.Path, 76 Type: fb.Type, 77 Dest: s, 78 Xver: fb.Xver, 79 }) 80 } 81 for _, fb := range config.Fallbacks { 82 /* 83 if fb.Alpn == "h2" && fb.Path != "" { 84 return nil, newError(`VLESS fallbacks: "alpn":"h2" doesn't support "path"`) 85 } 86 */ 87 if fb.Path != "" && fb.Path[0] != '/' { 88 return nil, newError(`VLESS fallbacks: "path" must be empty or start with "/"`) 89 } 90 if fb.Type == "" && fb.Dest != "" { 91 if fb.Dest == "serve-ws-none" { 92 fb.Type = "serve" 93 } else { 94 switch fb.Dest[0] { 95 case '@', '/': 96 fb.Type = "unix" 97 if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && (runtime.GOOS == "linux" || runtime.GOOS == "android") { 98 fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy 99 copy(fullAddr, fb.Dest[1:]) 100 fb.Dest = string(fullAddr) 101 } 102 default: 103 if _, err := strconv.Atoi(fb.Dest); err == nil { 104 fb.Dest = "127.0.0.1:" + fb.Dest 105 } 106 if _, _, err := net.SplitHostPort(fb.Dest); err == nil { 107 fb.Type = "tcp" 108 } 109 } 110 } 111 } 112 if fb.Type == "" { 113 return nil, newError(`VLESS fallbacks: please fill in a valid value for every "dest"`) 114 } 115 if fb.Xver > 2 { 116 return nil, newError(`VLESS fallbacks: invalid PROXY protocol version, "xver" only accepts 0, 1, 2`) 117 } 118 } 119 120 return config, nil 121 } 122 123 type VLessOutboundVnext struct { 124 Address *cfgcommon.Address `json:"address"` 125 Port uint16 `json:"port"` 126 Users []json.RawMessage `json:"users"` 127 } 128 129 type VLessOutboundConfig struct { 130 Vnext []*VLessOutboundVnext `json:"vnext"` 131 } 132 133 // Build implements Buildable 134 func (c *VLessOutboundConfig) Build() (proto.Message, error) { 135 config := new(outbound.Config) 136 137 if len(c.Vnext) == 0 { 138 return nil, newError(`VLESS settings: "vnext" is empty`) 139 } 140 config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext)) 141 for idx, rec := range c.Vnext { 142 if rec.Address == nil { 143 return nil, newError(`VLESS vnext: "address" is not set`) 144 } 145 if len(rec.Users) == 0 { 146 return nil, newError(`VLESS vnext: "users" is empty`) 147 } 148 spec := &protocol.ServerEndpoint{ 149 Address: rec.Address.Build(), 150 Port: uint32(rec.Port), 151 User: make([]*protocol.User, len(rec.Users)), 152 } 153 for idx, rawUser := range rec.Users { 154 user := new(protocol.User) 155 if err := json.Unmarshal(rawUser, user); err != nil { 156 return nil, newError(`VLESS users: invalid user`).Base(err) 157 } 158 account := new(vless.Account) 159 if err := json.Unmarshal(rawUser, account); err != nil { 160 return nil, newError(`VLESS users: invalid user`).Base(err) 161 } 162 163 if account.Encryption != "none" { 164 return nil, newError(`VLESS users: please add/set "encryption":"none" for every user`) 165 } 166 167 user.Account = serial.ToTypedMessage(account) 168 spec.User[idx] = user 169 } 170 config.Vnext[idx] = spec 171 } 172 173 return config, nil 174 }