github.com/v2fly/v2ray-core/v4@v4.45.2/infra/conf/v2ray_test.go (about) 1 package conf_test 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "testing" 7 8 "github.com/golang/protobuf/proto" 9 "github.com/google/go-cmp/cmp" 10 11 core "github.com/v2fly/v2ray-core/v4" 12 "github.com/v2fly/v2ray-core/v4/app/dispatcher" 13 "github.com/v2fly/v2ray-core/v4/app/log" 14 "github.com/v2fly/v2ray-core/v4/app/proxyman" 15 "github.com/v2fly/v2ray-core/v4/app/router" 16 "github.com/v2fly/v2ray-core/v4/common" 17 clog "github.com/v2fly/v2ray-core/v4/common/log" 18 "github.com/v2fly/v2ray-core/v4/common/net" 19 "github.com/v2fly/v2ray-core/v4/common/protocol" 20 "github.com/v2fly/v2ray-core/v4/common/serial" 21 . "github.com/v2fly/v2ray-core/v4/infra/conf" 22 "github.com/v2fly/v2ray-core/v4/proxy/blackhole" 23 dns_proxy "github.com/v2fly/v2ray-core/v4/proxy/dns" 24 "github.com/v2fly/v2ray-core/v4/proxy/freedom" 25 "github.com/v2fly/v2ray-core/v4/proxy/vmess" 26 "github.com/v2fly/v2ray-core/v4/proxy/vmess/inbound" 27 "github.com/v2fly/v2ray-core/v4/transport/internet" 28 "github.com/v2fly/v2ray-core/v4/transport/internet/http" 29 "github.com/v2fly/v2ray-core/v4/transport/internet/tls" 30 "github.com/v2fly/v2ray-core/v4/transport/internet/websocket" 31 ) 32 33 func TestV2RayConfig(t *testing.T) { 34 createParser := func() func(string) (proto.Message, error) { 35 return func(s string) (proto.Message, error) { 36 config := new(Config) 37 if err := json.Unmarshal([]byte(s), config); err != nil { 38 return nil, err 39 } 40 return config.Build() 41 } 42 } 43 44 runMultiTestCase(t, []TestCase{ 45 { 46 Input: `{ 47 "outbound": { 48 "protocol": "freedom", 49 "settings": {} 50 }, 51 "log": { 52 "access": "/var/log/v2ray/access.log", 53 "loglevel": "error", 54 "error": "/var/log/v2ray/error.log" 55 }, 56 "inbound": { 57 "streamSettings": { 58 "network": "ws", 59 "wsSettings": { 60 "headers": { 61 "host": "example.domain" 62 }, 63 "path": "" 64 }, 65 "tlsSettings": { 66 "alpn": "h2" 67 }, 68 "security": "tls" 69 }, 70 "protocol": "vmess", 71 "port": 443, 72 "settings": { 73 "clients": [ 74 { 75 "alterId": 100, 76 "security": "aes-128-gcm", 77 "id": "0cdf8a45-303d-4fed-9780-29aa7f54175e" 78 } 79 ] 80 } 81 }, 82 "inbounds": [{ 83 "streamSettings": { 84 "network": "ws", 85 "wsSettings": { 86 "headers": { 87 "host": "example.domain" 88 }, 89 "path": "" 90 }, 91 "tlsSettings": { 92 "alpn": "h2" 93 }, 94 "security": "tls" 95 }, 96 "protocol": "vmess", 97 "port": "443-500", 98 "allocate": { 99 "strategy": "random", 100 "concurrency": 3 101 }, 102 "settings": { 103 "clients": [ 104 { 105 "alterId": 100, 106 "security": "aes-128-gcm", 107 "id": "0cdf8a45-303d-4fed-9780-29aa7f54175e" 108 } 109 ] 110 } 111 }], 112 "outboundDetour": [ 113 { 114 "tag": "blocked", 115 "protocol": "blackhole" 116 }, 117 { 118 "protocol": "dns" 119 } 120 ], 121 "routing": { 122 "strategy": "rules", 123 "settings": { 124 "rules": [ 125 { 126 "ip": [ 127 "10.0.0.0/8" 128 ], 129 "type": "field", 130 "outboundTag": "blocked" 131 } 132 ] 133 } 134 }, 135 "transport": { 136 "httpSettings": { 137 "path": "/test" 138 } 139 } 140 }`, 141 Parser: createParser(), 142 Output: &core.Config{ 143 App: []*serial.TypedMessage{ 144 serial.ToTypedMessage(&log.Config{ 145 ErrorLogType: log.LogType_File, 146 ErrorLogPath: "/var/log/v2ray/error.log", 147 ErrorLogLevel: clog.Severity_Error, 148 AccessLogType: log.LogType_File, 149 AccessLogPath: "/var/log/v2ray/access.log", 150 }), 151 serial.ToTypedMessage(&dispatcher.Config{}), 152 serial.ToTypedMessage(&proxyman.InboundConfig{}), 153 serial.ToTypedMessage(&proxyman.OutboundConfig{}), 154 serial.ToTypedMessage(&router.Config{ 155 DomainStrategy: router.Config_AsIs, 156 Rule: []*router.RoutingRule{ 157 { 158 Geoip: []*router.GeoIP{ 159 { 160 Cidr: []*router.CIDR{ 161 { 162 Ip: []byte{10, 0, 0, 0}, 163 Prefix: 8, 164 }, 165 }, 166 }, 167 }, 168 TargetTag: &router.RoutingRule_Tag{ 169 Tag: "blocked", 170 }, 171 }, 172 }, 173 }), 174 }, 175 Outbound: []*core.OutboundHandlerConfig{ 176 { 177 SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ 178 StreamSettings: &internet.StreamConfig{ 179 ProtocolName: "tcp", 180 TransportSettings: []*internet.TransportConfig{ 181 { 182 ProtocolName: "http", 183 Settings: serial.ToTypedMessage(&http.Config{ 184 Path: "/test", 185 }), 186 }, 187 }, 188 }, 189 }), 190 ProxySettings: serial.ToTypedMessage(&freedom.Config{ 191 DomainStrategy: freedom.Config_AS_IS, 192 UserLevel: 0, 193 }), 194 }, 195 { 196 Tag: "blocked", 197 SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ 198 StreamSettings: &internet.StreamConfig{ 199 ProtocolName: "tcp", 200 TransportSettings: []*internet.TransportConfig{ 201 { 202 ProtocolName: "http", 203 Settings: serial.ToTypedMessage(&http.Config{ 204 Path: "/test", 205 }), 206 }, 207 }, 208 }, 209 }), 210 ProxySettings: serial.ToTypedMessage(&blackhole.Config{}), 211 }, 212 { 213 SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ 214 StreamSettings: &internet.StreamConfig{ 215 ProtocolName: "tcp", 216 TransportSettings: []*internet.TransportConfig{ 217 { 218 ProtocolName: "http", 219 Settings: serial.ToTypedMessage(&http.Config{ 220 Path: "/test", 221 }), 222 }, 223 }, 224 }, 225 }), 226 ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{ 227 Server: &net.Endpoint{}, 228 }), 229 }, 230 }, 231 Inbound: []*core.InboundHandlerConfig{ 232 { 233 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 234 PortRange: &net.PortRange{ 235 From: 443, 236 To: 443, 237 }, 238 StreamSettings: &internet.StreamConfig{ 239 ProtocolName: "websocket", 240 TransportSettings: []*internet.TransportConfig{ 241 { 242 ProtocolName: "websocket", 243 Settings: serial.ToTypedMessage(&websocket.Config{ 244 Header: []*websocket.Header{ 245 { 246 Key: "host", 247 Value: "example.domain", 248 }, 249 }, 250 }), 251 }, 252 { 253 ProtocolName: "http", 254 Settings: serial.ToTypedMessage(&http.Config{ 255 Path: "/test", 256 }), 257 }, 258 }, 259 SecurityType: "v2ray.core.transport.internet.tls.Config", 260 SecuritySettings: []*serial.TypedMessage{ 261 serial.ToTypedMessage(&tls.Config{ 262 NextProtocol: []string{"h2"}, 263 }), 264 }, 265 }, 266 }), 267 ProxySettings: serial.ToTypedMessage(&inbound.Config{ 268 User: []*protocol.User{ 269 { 270 Level: 0, 271 Account: serial.ToTypedMessage(&vmess.Account{ 272 Id: "0cdf8a45-303d-4fed-9780-29aa7f54175e", 273 AlterId: 100, 274 SecuritySettings: &protocol.SecurityConfig{ 275 Type: protocol.SecurityType_AES128_GCM, 276 }, 277 }), 278 }, 279 }, 280 }), 281 }, 282 { 283 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 284 PortRange: &net.PortRange{ 285 From: 443, 286 To: 500, 287 }, 288 AllocationStrategy: &proxyman.AllocationStrategy{ 289 Type: proxyman.AllocationStrategy_Random, 290 Concurrency: &proxyman.AllocationStrategy_AllocationStrategyConcurrency{ 291 Value: 3, 292 }, 293 }, 294 StreamSettings: &internet.StreamConfig{ 295 ProtocolName: "websocket", 296 TransportSettings: []*internet.TransportConfig{ 297 { 298 ProtocolName: "websocket", 299 Settings: serial.ToTypedMessage(&websocket.Config{ 300 Header: []*websocket.Header{ 301 { 302 Key: "host", 303 Value: "example.domain", 304 }, 305 }, 306 }), 307 }, 308 { 309 ProtocolName: "http", 310 Settings: serial.ToTypedMessage(&http.Config{ 311 Path: "/test", 312 }), 313 }, 314 }, 315 SecurityType: "v2ray.core.transport.internet.tls.Config", 316 SecuritySettings: []*serial.TypedMessage{ 317 serial.ToTypedMessage(&tls.Config{ 318 NextProtocol: []string{"h2"}, 319 }), 320 }, 321 }, 322 }), 323 ProxySettings: serial.ToTypedMessage(&inbound.Config{ 324 User: []*protocol.User{ 325 { 326 Level: 0, 327 Account: serial.ToTypedMessage(&vmess.Account{ 328 Id: "0cdf8a45-303d-4fed-9780-29aa7f54175e", 329 AlterId: 100, 330 SecuritySettings: &protocol.SecurityConfig{ 331 Type: protocol.SecurityType_AES128_GCM, 332 }, 333 }), 334 }, 335 }, 336 }), 337 }, 338 }, 339 }, 340 }, 341 }) 342 } 343 344 func TestMuxConfig_Build(t *testing.T) { 345 tests := []struct { 346 name string 347 fields string 348 want *proxyman.MultiplexingConfig 349 }{ 350 {"default", `{"enabled": true, "concurrency": 16}`, &proxyman.MultiplexingConfig{ 351 Enabled: true, 352 Concurrency: 16, 353 }}, 354 {"empty def", `{}`, &proxyman.MultiplexingConfig{ 355 Enabled: false, 356 Concurrency: 8, 357 }}, 358 {"not enable", `{"enabled": false, "concurrency": 4}`, &proxyman.MultiplexingConfig{ 359 Enabled: false, 360 Concurrency: 4, 361 }}, 362 {"forbidden", `{"enabled": false, "concurrency": -1}`, nil}, 363 } 364 for _, tt := range tests { 365 t.Run(tt.name, func(t *testing.T) { 366 m := &MuxConfig{} 367 common.Must(json.Unmarshal([]byte(tt.fields), m)) 368 if got := m.Build(); !reflect.DeepEqual(got, tt.want) { 369 t.Errorf("MuxConfig.Build() = %v, want %v", got, tt.want) 370 } 371 }) 372 } 373 } 374 375 func TestConfig_Override(t *testing.T) { 376 tests := []struct { 377 name string 378 orig *Config 379 over *Config 380 fn string 381 want *Config 382 }{ 383 { 384 "combine/empty", 385 &Config{}, 386 &Config{ 387 LogConfig: &LogConfig{}, 388 RouterConfig: &RouterConfig{}, 389 DNSConfig: &DNSConfig{}, 390 Transport: &TransportConfig{}, 391 Policy: &PolicyConfig{}, 392 API: &APIConfig{}, 393 Stats: &StatsConfig{}, 394 Reverse: &ReverseConfig{}, 395 }, 396 "", 397 &Config{ 398 LogConfig: &LogConfig{}, 399 RouterConfig: &RouterConfig{}, 400 DNSConfig: &DNSConfig{}, 401 Transport: &TransportConfig{}, 402 Policy: &PolicyConfig{}, 403 API: &APIConfig{}, 404 Stats: &StatsConfig{}, 405 Reverse: &ReverseConfig{}, 406 }, 407 }, 408 { 409 "combine/newattr", 410 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "old"}}}, 411 &Config{LogConfig: &LogConfig{}}, "", 412 &Config{LogConfig: &LogConfig{}, InboundConfigs: []InboundDetourConfig{{Tag: "old"}}}, 413 }, 414 { 415 "replace/inbounds", 416 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 417 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}}}, 418 "", 419 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos0"}, {Tag: "pos1", Protocol: "kcp"}}}, 420 }, 421 { 422 "replace/inbounds-replaceall", 423 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 424 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}, {Tag: "pos2", Protocol: "kcp"}}}, 425 "", 426 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}, {Tag: "pos2", Protocol: "kcp"}}}, 427 }, 428 { 429 "replace/notag-append", 430 &Config{InboundConfigs: []InboundDetourConfig{{}, {Protocol: "vmess"}}}, 431 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}}}, 432 "", 433 &Config{InboundConfigs: []InboundDetourConfig{{}, {Protocol: "vmess"}, {Tag: "pos1", Protocol: "kcp"}}}, 434 }, 435 { 436 "replace/outbounds", 437 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 438 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}}}, 439 "", 440 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Tag: "pos1", Protocol: "kcp"}}}, 441 }, 442 { 443 "replace/outbounds-prepend", 444 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 445 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}, {Tag: "pos2", Protocol: "kcp"}}}, 446 "config.json", 447 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}, {Tag: "pos2", Protocol: "kcp"}}}, 448 }, 449 { 450 "replace/outbounds-append", 451 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 452 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos2", Protocol: "kcp"}}}, 453 "config_tail.json", 454 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}, {Tag: "pos2", Protocol: "kcp"}}}, 455 }, 456 } 457 for _, tt := range tests { 458 t.Run(tt.name, func(t *testing.T) { 459 tt.orig.Override(tt.over, tt.fn) 460 if r := cmp.Diff(tt.orig, tt.want); r != "" { 461 t.Error(r) 462 } 463 }) 464 } 465 }