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