github.com/moqsien/xraycore@v1.8.5/infra/conf/xray_test.go (about) 1 package conf_test 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "testing" 7 8 "github.com/google/go-cmp/cmp" 9 "github.com/moqsien/xraycore/app/dispatcher" 10 "github.com/moqsien/xraycore/app/log" 11 "github.com/moqsien/xraycore/app/proxyman" 12 "github.com/moqsien/xraycore/app/router" 13 "github.com/moqsien/xraycore/common" 14 clog "github.com/moqsien/xraycore/common/log" 15 "github.com/moqsien/xraycore/common/net" 16 "github.com/moqsien/xraycore/common/protocol" 17 "github.com/moqsien/xraycore/common/serial" 18 core "github.com/moqsien/xraycore/core" 19 . "github.com/moqsien/xraycore/infra/conf" 20 "github.com/moqsien/xraycore/proxy/blackhole" 21 dns_proxy "github.com/moqsien/xraycore/proxy/dns" 22 "github.com/moqsien/xraycore/proxy/freedom" 23 "github.com/moqsien/xraycore/proxy/vmess" 24 "github.com/moqsien/xraycore/proxy/vmess/inbound" 25 "github.com/moqsien/xraycore/transport/internet" 26 "github.com/moqsien/xraycore/transport/internet/http" 27 "github.com/moqsien/xraycore/transport/internet/tls" 28 "github.com/moqsien/xraycore/transport/internet/websocket" 29 "google.golang.org/protobuf/proto" 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 Non_IPQuery: "drop", 226 }), 227 }, 228 }, 229 Inbound: []*core.InboundHandlerConfig{ 230 { 231 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 232 PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(443)}}, 233 StreamSettings: &internet.StreamConfig{ 234 ProtocolName: "websocket", 235 TransportSettings: []*internet.TransportConfig{ 236 { 237 ProtocolName: "websocket", 238 Settings: serial.ToTypedMessage(&websocket.Config{ 239 Header: []*websocket.Header{ 240 { 241 Key: "host", 242 Value: "example.domain", 243 }, 244 }, 245 }), 246 }, 247 { 248 ProtocolName: "http", 249 Settings: serial.ToTypedMessage(&http.Config{ 250 Path: "/test", 251 }), 252 }, 253 }, 254 SecurityType: "xray.transport.internet.tls.Config", 255 SecuritySettings: []*serial.TypedMessage{ 256 serial.ToTypedMessage(&tls.Config{ 257 NextProtocol: []string{"h2"}, 258 }), 259 }, 260 }, 261 }), 262 ProxySettings: serial.ToTypedMessage(&inbound.Config{ 263 User: []*protocol.User{ 264 { 265 Level: 0, 266 Account: serial.ToTypedMessage(&vmess.Account{ 267 Id: "0cdf8a45-303d-4fed-9780-29aa7f54175e", 268 SecuritySettings: &protocol.SecurityConfig{ 269 Type: protocol.SecurityType_AES128_GCM, 270 }, 271 }), 272 }, 273 }, 274 }), 275 }, 276 { 277 ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 278 PortList: &net.PortList{Range: []*net.PortRange{{ 279 From: 443, 280 To: 500, 281 }}}, 282 AllocationStrategy: &proxyman.AllocationStrategy{ 283 Type: proxyman.AllocationStrategy_Random, 284 Concurrency: &proxyman.AllocationStrategy_AllocationStrategyConcurrency{ 285 Value: 3, 286 }, 287 }, 288 StreamSettings: &internet.StreamConfig{ 289 ProtocolName: "websocket", 290 TransportSettings: []*internet.TransportConfig{ 291 { 292 ProtocolName: "websocket", 293 Settings: serial.ToTypedMessage(&websocket.Config{ 294 Header: []*websocket.Header{ 295 { 296 Key: "host", 297 Value: "example.domain", 298 }, 299 }, 300 }), 301 }, 302 { 303 ProtocolName: "http", 304 Settings: serial.ToTypedMessage(&http.Config{ 305 Path: "/test", 306 }), 307 }, 308 }, 309 SecurityType: "xray.transport.internet.tls.Config", 310 SecuritySettings: []*serial.TypedMessage{ 311 serial.ToTypedMessage(&tls.Config{ 312 NextProtocol: []string{"h2"}, 313 }), 314 }, 315 }, 316 }), 317 ProxySettings: serial.ToTypedMessage(&inbound.Config{ 318 User: []*protocol.User{ 319 { 320 Level: 0, 321 Account: serial.ToTypedMessage(&vmess.Account{ 322 Id: "0cdf8a45-303d-4fed-9780-29aa7f54175e", 323 SecuritySettings: &protocol.SecurityConfig{ 324 Type: protocol.SecurityType_AES128_GCM, 325 }, 326 }), 327 }, 328 }, 329 }), 330 }, 331 }, 332 }, 333 }, 334 }) 335 } 336 337 func TestMuxConfig_Build(t *testing.T) { 338 tests := []struct { 339 name string 340 fields string 341 want *proxyman.MultiplexingConfig 342 }{ 343 {"default", `{"enabled": true, "concurrency": 16}`, &proxyman.MultiplexingConfig{ 344 Enabled: true, 345 Concurrency: 16, 346 XudpConcurrency: 0, 347 XudpProxyUDP443: "reject", 348 }}, 349 {"empty def", `{}`, &proxyman.MultiplexingConfig{ 350 Enabled: false, 351 Concurrency: 0, 352 XudpConcurrency: 0, 353 XudpProxyUDP443: "reject", 354 }}, 355 {"not enable", `{"enabled": false, "concurrency": 4}`, &proxyman.MultiplexingConfig{ 356 Enabled: false, 357 Concurrency: 4, 358 XudpConcurrency: 0, 359 XudpProxyUDP443: "reject", 360 }}, 361 {"forbidden", `{"enabled": false, "concurrency": -1}`, &proxyman.MultiplexingConfig{ 362 Enabled: false, 363 Concurrency: -1, 364 XudpConcurrency: 0, 365 XudpProxyUDP443: "reject", 366 }}, 367 } 368 for _, tt := range tests { 369 t.Run(tt.name, func(t *testing.T) { 370 m := &MuxConfig{} 371 common.Must(json.Unmarshal([]byte(tt.fields), m)) 372 if got, _ := m.Build(); !reflect.DeepEqual(got, tt.want) { 373 t.Errorf("MuxConfig.Build() = %v, want %v", got, tt.want) 374 } 375 }) 376 } 377 } 378 379 func TestConfig_Override(t *testing.T) { 380 tests := []struct { 381 name string 382 orig *Config 383 over *Config 384 fn string 385 want *Config 386 }{ 387 { 388 "combine/empty", 389 &Config{}, 390 &Config{ 391 LogConfig: &LogConfig{}, 392 RouterConfig: &RouterConfig{}, 393 DNSConfig: &DNSConfig{}, 394 Transport: &TransportConfig{}, 395 Policy: &PolicyConfig{}, 396 API: &APIConfig{}, 397 Stats: &StatsConfig{}, 398 Reverse: &ReverseConfig{}, 399 }, 400 "", 401 &Config{ 402 LogConfig: &LogConfig{}, 403 RouterConfig: &RouterConfig{}, 404 DNSConfig: &DNSConfig{}, 405 Transport: &TransportConfig{}, 406 Policy: &PolicyConfig{}, 407 API: &APIConfig{}, 408 Stats: &StatsConfig{}, 409 Reverse: &ReverseConfig{}, 410 }, 411 }, 412 { 413 "combine/newattr", 414 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "old"}}}, 415 &Config{LogConfig: &LogConfig{}}, "", 416 &Config{LogConfig: &LogConfig{}, InboundConfigs: []InboundDetourConfig{{Tag: "old"}}}, 417 }, 418 { 419 "replace/inbounds", 420 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 421 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}}}, 422 "", 423 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos0"}, {Tag: "pos1", Protocol: "kcp"}}}, 424 }, 425 { 426 "replace/inbounds-replaceall", 427 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 428 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}, {Tag: "pos2", Protocol: "kcp"}}}, 429 "", 430 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}, {Tag: "pos2", Protocol: "kcp"}}}, 431 }, 432 { 433 "replace/notag-append", 434 &Config{InboundConfigs: []InboundDetourConfig{{}, {Protocol: "vmess"}}}, 435 &Config{InboundConfigs: []InboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}}}, 436 "", 437 &Config{InboundConfigs: []InboundDetourConfig{{}, {Protocol: "vmess"}, {Tag: "pos1", Protocol: "kcp"}}}, 438 }, 439 { 440 "replace/outbounds", 441 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 442 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}}}, 443 "", 444 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Tag: "pos1", Protocol: "kcp"}}}, 445 }, 446 { 447 "replace/outbounds-prepend", 448 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 449 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}, {Tag: "pos2", Protocol: "kcp"}}}, 450 "config.json", 451 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos1", Protocol: "kcp"}, {Tag: "pos2", Protocol: "kcp"}}}, 452 }, 453 { 454 "replace/outbounds-append", 455 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}}}, 456 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos2", Protocol: "kcp"}}}, 457 "config_tail.json", 458 &Config{OutboundConfigs: []OutboundDetourConfig{{Tag: "pos0"}, {Protocol: "vmess", Tag: "pos1"}, {Tag: "pos2", Protocol: "kcp"}}}, 459 }, 460 } 461 for _, tt := range tests { 462 t.Run(tt.name, func(t *testing.T) { 463 tt.orig.Override(tt.over, tt.fn) 464 if r := cmp.Diff(tt.orig, tt.want); r != "" { 465 t.Error(r) 466 } 467 }) 468 } 469 }