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