github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/infra/conf/v4/transport_internet.go (about) 1 package v4 2 3 import ( 4 "encoding/json" 5 "strings" 6 7 "github.com/golang/protobuf/proto" 8 9 "github.com/v2fly/v2ray-core/v5/common/protocol" 10 "github.com/v2fly/v2ray-core/v5/common/serial" 11 "github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon" 12 "github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon/loader" 13 "github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon/socketcfg" 14 "github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon/tlscfg" 15 "github.com/v2fly/v2ray-core/v5/transport/internet" 16 "github.com/v2fly/v2ray-core/v5/transport/internet/domainsocket" 17 httpheader "github.com/v2fly/v2ray-core/v5/transport/internet/headers/http" 18 "github.com/v2fly/v2ray-core/v5/transport/internet/http" 19 "github.com/v2fly/v2ray-core/v5/transport/internet/kcp" 20 "github.com/v2fly/v2ray-core/v5/transport/internet/quic" 21 "github.com/v2fly/v2ray-core/v5/transport/internet/tcp" 22 "github.com/v2fly/v2ray-core/v5/transport/internet/websocket" 23 ) 24 25 var ( 26 kcpHeaderLoader = loader.NewJSONConfigLoader(loader.ConfigCreatorCache{ 27 "none": func() interface{} { return new(NoOpAuthenticator) }, 28 "srtp": func() interface{} { return new(SRTPAuthenticator) }, 29 "utp": func() interface{} { return new(UTPAuthenticator) }, 30 "wechat-video": func() interface{} { return new(WechatVideoAuthenticator) }, 31 "dtls": func() interface{} { return new(DTLSAuthenticator) }, 32 "wireguard": func() interface{} { return new(WireguardAuthenticator) }, 33 }, "type", "") 34 35 tcpHeaderLoader = loader.NewJSONConfigLoader(loader.ConfigCreatorCache{ 36 "none": func() interface{} { return new(NoOpConnectionAuthenticator) }, 37 "http": func() interface{} { return new(Authenticator) }, 38 }, "type", "") 39 ) 40 41 type KCPConfig struct { 42 Mtu *uint32 `json:"mtu"` 43 Tti *uint32 `json:"tti"` 44 UpCap *uint32 `json:"uplinkCapacity"` 45 DownCap *uint32 `json:"downlinkCapacity"` 46 Congestion *bool `json:"congestion"` 47 ReadBufferSize *uint32 `json:"readBufferSize"` 48 WriteBufferSize *uint32 `json:"writeBufferSize"` 49 HeaderConfig json.RawMessage `json:"header"` 50 Seed *string `json:"seed"` 51 } 52 53 // Build implements Buildable. 54 func (c *KCPConfig) Build() (proto.Message, error) { 55 config := new(kcp.Config) 56 57 if c.Mtu != nil { 58 mtu := *c.Mtu 59 if mtu < 576 || mtu > 1460 { 60 return nil, newError("invalid mKCP MTU size: ", mtu).AtError() 61 } 62 config.Mtu = &kcp.MTU{Value: mtu} 63 } 64 if c.Tti != nil { 65 tti := *c.Tti 66 if tti < 10 || tti > 100 { 67 return nil, newError("invalid mKCP TTI: ", tti).AtError() 68 } 69 config.Tti = &kcp.TTI{Value: tti} 70 } 71 if c.UpCap != nil { 72 config.UplinkCapacity = &kcp.UplinkCapacity{Value: *c.UpCap} 73 } 74 if c.DownCap != nil { 75 config.DownlinkCapacity = &kcp.DownlinkCapacity{Value: *c.DownCap} 76 } 77 if c.Congestion != nil { 78 config.Congestion = *c.Congestion 79 } 80 if c.ReadBufferSize != nil { 81 size := *c.ReadBufferSize 82 if size > 0 { 83 config.ReadBuffer = &kcp.ReadBuffer{Size: size * 1024 * 1024} 84 } else { 85 config.ReadBuffer = &kcp.ReadBuffer{Size: 512 * 1024} 86 } 87 } 88 if c.WriteBufferSize != nil { 89 size := *c.WriteBufferSize 90 if size > 0 { 91 config.WriteBuffer = &kcp.WriteBuffer{Size: size * 1024 * 1024} 92 } else { 93 config.WriteBuffer = &kcp.WriteBuffer{Size: 512 * 1024} 94 } 95 } 96 if len(c.HeaderConfig) > 0 { 97 headerConfig, _, err := kcpHeaderLoader.Load(c.HeaderConfig) 98 if err != nil { 99 return nil, newError("invalid mKCP header config.").Base(err).AtError() 100 } 101 ts, err := headerConfig.(cfgcommon.Buildable).Build() 102 if err != nil { 103 return nil, newError("invalid mKCP header config").Base(err).AtError() 104 } 105 config.HeaderConfig = serial.ToTypedMessage(ts) 106 } 107 108 if c.Seed != nil { 109 config.Seed = &kcp.EncryptionSeed{Seed: *c.Seed} 110 } 111 112 return config, nil 113 } 114 115 type TCPConfig struct { 116 HeaderConfig json.RawMessage `json:"header"` 117 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 118 } 119 120 // Build implements Buildable. 121 func (c *TCPConfig) Build() (proto.Message, error) { 122 config := new(tcp.Config) 123 if len(c.HeaderConfig) > 0 { 124 headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig) 125 if err != nil { 126 return nil, newError("invalid TCP header config").Base(err).AtError() 127 } 128 ts, err := headerConfig.(cfgcommon.Buildable).Build() 129 if err != nil { 130 return nil, newError("invalid TCP header config").Base(err).AtError() 131 } 132 config.HeaderSettings = serial.ToTypedMessage(ts) 133 } 134 if c.AcceptProxyProtocol { 135 config.AcceptProxyProtocol = c.AcceptProxyProtocol 136 } 137 return config, nil 138 } 139 140 type WebSocketConfig struct { 141 Path string `json:"path"` 142 Headers map[string]string `json:"headers"` 143 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 144 MaxEarlyData int32 `json:"maxEarlyData"` 145 UseBrowserForwarding bool `json:"useBrowserForwarding"` 146 EarlyDataHeaderName string `json:"earlyDataHeaderName"` 147 } 148 149 // Build implements Buildable. 150 func (c *WebSocketConfig) Build() (proto.Message, error) { 151 path := c.Path 152 header := make([]*websocket.Header, 0, 32) 153 for key, value := range c.Headers { 154 header = append(header, &websocket.Header{ 155 Key: key, 156 Value: value, 157 }) 158 } 159 config := &websocket.Config{ 160 Path: path, 161 Header: header, 162 MaxEarlyData: c.MaxEarlyData, 163 UseBrowserForwarding: c.UseBrowserForwarding, 164 EarlyDataHeaderName: c.EarlyDataHeaderName, 165 } 166 if c.AcceptProxyProtocol { 167 config.AcceptProxyProtocol = c.AcceptProxyProtocol 168 } 169 return config, nil 170 } 171 172 type HTTPConfig struct { 173 Host *cfgcommon.StringList `json:"host"` 174 Path string `json:"path"` 175 Method string `json:"method"` 176 Headers map[string]*cfgcommon.StringList `json:"headers"` 177 } 178 179 // Build implements Buildable. 180 func (c *HTTPConfig) Build() (proto.Message, error) { 181 config := &http.Config{ 182 Path: c.Path, 183 } 184 if c.Host != nil { 185 config.Host = []string(*c.Host) 186 } 187 if c.Method != "" { 188 config.Method = c.Method 189 } 190 if len(c.Headers) > 0 { 191 config.Header = make([]*httpheader.Header, 0, len(c.Headers)) 192 headerNames := sortMapKeys(c.Headers) 193 for _, key := range headerNames { 194 value := c.Headers[key] 195 if value == nil { 196 return nil, newError("empty HTTP header value: " + key).AtError() 197 } 198 config.Header = append(config.Header, &httpheader.Header{ 199 Name: key, 200 Value: append([]string(nil), (*value)...), 201 }) 202 } 203 } 204 return config, nil 205 } 206 207 type QUICConfig struct { 208 Header json.RawMessage `json:"header"` 209 Security string `json:"security"` 210 Key string `json:"key"` 211 } 212 213 // Build implements Buildable. 214 func (c *QUICConfig) Build() (proto.Message, error) { 215 config := &quic.Config{ 216 Key: c.Key, 217 } 218 219 if len(c.Header) > 0 { 220 headerConfig, _, err := kcpHeaderLoader.Load(c.Header) 221 if err != nil { 222 return nil, newError("invalid QUIC header config.").Base(err).AtError() 223 } 224 ts, err := headerConfig.(cfgcommon.Buildable).Build() 225 if err != nil { 226 return nil, newError("invalid QUIC header config").Base(err).AtError() 227 } 228 config.Header = serial.ToTypedMessage(ts) 229 } 230 231 var st protocol.SecurityType 232 switch strings.ToLower(c.Security) { 233 case "aes-128-gcm": 234 st = protocol.SecurityType_AES128_GCM 235 case "chacha20-poly1305": 236 st = protocol.SecurityType_CHACHA20_POLY1305 237 default: 238 st = protocol.SecurityType_NONE 239 } 240 241 config.Security = &protocol.SecurityConfig{ 242 Type: st, 243 } 244 245 return config, nil 246 } 247 248 type DomainSocketConfig struct { 249 Path string `json:"path"` 250 Abstract bool `json:"abstract"` 251 Padding bool `json:"padding"` 252 } 253 254 // Build implements Buildable. 255 func (c *DomainSocketConfig) Build() (proto.Message, error) { 256 return &domainsocket.Config{ 257 Path: c.Path, 258 Abstract: c.Abstract, 259 Padding: c.Padding, 260 }, nil 261 } 262 263 type TransportProtocol string 264 265 // Build implements Buildable. 266 func (p TransportProtocol) Build() (string, error) { 267 switch strings.ToLower(string(p)) { 268 case "tcp": 269 return "tcp", nil 270 case "kcp", "mkcp": 271 return "mkcp", nil 272 case "ws", "websocket": 273 return "websocket", nil 274 case "h2", "http": 275 return "http", nil 276 case "ds", "domainsocket": 277 return "domainsocket", nil 278 case "quic": 279 return "quic", nil 280 case "gun", "grpc": 281 return "gun", nil 282 default: 283 return "", newError("Config: unknown transport protocol: ", p) 284 } 285 } 286 287 type StreamConfig struct { 288 Network *TransportProtocol `json:"network"` 289 Security string `json:"security"` 290 TLSSettings *tlscfg.TLSConfig `json:"tlsSettings"` 291 TCPSettings *TCPConfig `json:"tcpSettings"` 292 KCPSettings *KCPConfig `json:"kcpSettings"` 293 WSSettings *WebSocketConfig `json:"wsSettings"` 294 HTTPSettings *HTTPConfig `json:"httpSettings"` 295 DSSettings *DomainSocketConfig `json:"dsSettings"` 296 QUICSettings *QUICConfig `json:"quicSettings"` 297 GunSettings *GunConfig `json:"gunSettings"` 298 GRPCSettings *GunConfig `json:"grpcSettings"` 299 SocketSettings *socketcfg.SocketConfig `json:"sockopt"` 300 } 301 302 // Build implements Buildable. 303 func (c *StreamConfig) Build() (*internet.StreamConfig, error) { 304 config := &internet.StreamConfig{ 305 ProtocolName: "tcp", 306 } 307 if c.Network != nil { 308 protocol, err := c.Network.Build() 309 if err != nil { 310 return nil, err 311 } 312 config.ProtocolName = protocol 313 } 314 if strings.EqualFold(c.Security, "tls") { 315 tlsSettings := c.TLSSettings 316 if tlsSettings == nil { 317 tlsSettings = &tlscfg.TLSConfig{} 318 } 319 ts, err := tlsSettings.Build() 320 if err != nil { 321 return nil, newError("Failed to build TLS config.").Base(err) 322 } 323 tm := serial.ToTypedMessage(ts) 324 config.SecuritySettings = append(config.SecuritySettings, tm) 325 config.SecurityType = serial.V2Type(tm) 326 } 327 if c.TCPSettings != nil { 328 ts, err := c.TCPSettings.Build() 329 if err != nil { 330 return nil, newError("Failed to build TCP config.").Base(err) 331 } 332 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 333 ProtocolName: "tcp", 334 Settings: serial.ToTypedMessage(ts), 335 }) 336 } 337 if c.KCPSettings != nil { 338 ts, err := c.KCPSettings.Build() 339 if err != nil { 340 return nil, newError("Failed to build mKCP config.").Base(err) 341 } 342 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 343 ProtocolName: "mkcp", 344 Settings: serial.ToTypedMessage(ts), 345 }) 346 } 347 if c.WSSettings != nil { 348 ts, err := c.WSSettings.Build() 349 if err != nil { 350 return nil, newError("Failed to build WebSocket config.").Base(err) 351 } 352 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 353 ProtocolName: "websocket", 354 Settings: serial.ToTypedMessage(ts), 355 }) 356 } 357 if c.HTTPSettings != nil { 358 ts, err := c.HTTPSettings.Build() 359 if err != nil { 360 return nil, newError("Failed to build HTTP config.").Base(err) 361 } 362 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 363 ProtocolName: "http", 364 Settings: serial.ToTypedMessage(ts), 365 }) 366 } 367 if c.DSSettings != nil { 368 ds, err := c.DSSettings.Build() 369 if err != nil { 370 return nil, newError("Failed to build DomainSocket config.").Base(err) 371 } 372 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 373 ProtocolName: "domainsocket", 374 Settings: serial.ToTypedMessage(ds), 375 }) 376 } 377 if c.QUICSettings != nil { 378 qs, err := c.QUICSettings.Build() 379 if err != nil { 380 return nil, newError("Failed to build QUIC config.").Base(err) 381 } 382 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 383 ProtocolName: "quic", 384 Settings: serial.ToTypedMessage(qs), 385 }) 386 } 387 if c.GunSettings == nil { 388 c.GunSettings = c.GRPCSettings 389 } 390 if c.GunSettings != nil { 391 gs, err := c.GunSettings.Build() 392 if err != nil { 393 return nil, newError("Failed to build Gun config.").Base(err) 394 } 395 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 396 ProtocolName: "gun", 397 Settings: serial.ToTypedMessage(gs), 398 }) 399 } 400 if c.SocketSettings != nil { 401 ss, err := c.SocketSettings.Build() 402 if err != nil { 403 return nil, newError("Failed to build sockopt.").Base(err) 404 } 405 config.SocketSettings = ss 406 } 407 return config, nil 408 }