feature_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. package scenarios
  2. import (
  3. "net"
  4. "testing"
  5. "time"
  6. xproxy "golang.org/x/net/proxy"
  7. "v2ray.com/core"
  8. "v2ray.com/core/app/proxyman"
  9. "v2ray.com/core/app/router"
  10. v2net "v2ray.com/core/common/net"
  11. "v2ray.com/core/common/protocol"
  12. "v2ray.com/core/common/serial"
  13. "v2ray.com/core/common/uuid"
  14. "v2ray.com/core/proxy/blackhole"
  15. "v2ray.com/core/proxy/dokodemo"
  16. "v2ray.com/core/proxy/freedom"
  17. "v2ray.com/core/proxy/socks"
  18. "v2ray.com/core/proxy/vmess"
  19. "v2ray.com/core/proxy/vmess/inbound"
  20. "v2ray.com/core/proxy/vmess/outbound"
  21. "v2ray.com/core/testing/assert"
  22. "v2ray.com/core/testing/servers/tcp"
  23. "v2ray.com/core/testing/servers/udp"
  24. "v2ray.com/core/transport/internet"
  25. )
  26. func TestPassiveConnection(t *testing.T) {
  27. assert := assert.On(t)
  28. tcpServer := tcp.Server{
  29. MsgProcessor: xor,
  30. SendFirst: []byte("send first"),
  31. }
  32. dest, err := tcpServer.Start()
  33. assert.Error(err).IsNil()
  34. defer tcpServer.Close()
  35. serverPort := pickPort()
  36. serverConfig := &core.Config{
  37. Inbound: []*proxyman.InboundHandlerConfig{
  38. {
  39. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  40. PortRange: v2net.SinglePortRange(serverPort),
  41. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  42. AllowPassiveConnection: true,
  43. }),
  44. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  45. Address: v2net.NewIPOrDomain(dest.Address),
  46. Port: uint32(dest.Port),
  47. NetworkList: &v2net.NetworkList{
  48. Network: []v2net.Network{v2net.Network_TCP},
  49. },
  50. }),
  51. },
  52. },
  53. Outbound: []*proxyman.OutboundHandlerConfig{
  54. {
  55. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  56. },
  57. },
  58. }
  59. assert.Error(InitializeServerConfig(serverConfig)).IsNil()
  60. conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
  61. IP: []byte{127, 0, 0, 1},
  62. Port: int(serverPort),
  63. })
  64. assert.Error(err).IsNil()
  65. {
  66. response := make([]byte, 1024)
  67. nBytes, err := conn.Read(response)
  68. assert.Error(err).IsNil()
  69. assert.String(string(response[:nBytes])).Equals("send first")
  70. }
  71. payload := "dokodemo request."
  72. {
  73. nBytes, err := conn.Write([]byte(payload))
  74. assert.Error(err).IsNil()
  75. assert.Int(nBytes).Equals(len(payload))
  76. }
  77. {
  78. response := make([]byte, 1024)
  79. nBytes, err := conn.Read(response)
  80. assert.Error(err).IsNil()
  81. assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload)))
  82. }
  83. assert.Error(conn.Close()).IsNil()
  84. CloseAllServers()
  85. }
  86. func TestProxy(t *testing.T) {
  87. assert := assert.On(t)
  88. tcpServer := tcp.Server{
  89. MsgProcessor: xor,
  90. }
  91. dest, err := tcpServer.Start()
  92. assert.Error(err).IsNil()
  93. defer tcpServer.Close()
  94. serverUserID := protocol.NewID(uuid.New())
  95. serverPort := pickPort()
  96. serverConfig := &core.Config{
  97. Inbound: []*proxyman.InboundHandlerConfig{
  98. {
  99. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  100. PortRange: v2net.SinglePortRange(serverPort),
  101. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  102. }),
  103. ProxySettings: serial.ToTypedMessage(&inbound.Config{
  104. User: []*protocol.User{
  105. {
  106. Account: serial.ToTypedMessage(&vmess.Account{
  107. Id: serverUserID.String(),
  108. }),
  109. },
  110. },
  111. }),
  112. },
  113. },
  114. Outbound: []*proxyman.OutboundHandlerConfig{
  115. {
  116. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  117. },
  118. },
  119. }
  120. proxyUserID := protocol.NewID(uuid.New())
  121. proxyPort := pickPort()
  122. proxyConfig := &core.Config{
  123. Inbound: []*proxyman.InboundHandlerConfig{
  124. {
  125. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  126. PortRange: v2net.SinglePortRange(proxyPort),
  127. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  128. }),
  129. ProxySettings: serial.ToTypedMessage(&inbound.Config{
  130. User: []*protocol.User{
  131. {
  132. Account: serial.ToTypedMessage(&vmess.Account{
  133. Id: proxyUserID.String(),
  134. }),
  135. },
  136. },
  137. }),
  138. },
  139. },
  140. Outbound: []*proxyman.OutboundHandlerConfig{
  141. {
  142. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  143. },
  144. },
  145. }
  146. clientPort := pickPort()
  147. clientConfig := &core.Config{
  148. Inbound: []*proxyman.InboundHandlerConfig{
  149. {
  150. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  151. PortRange: v2net.SinglePortRange(clientPort),
  152. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  153. }),
  154. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  155. Address: v2net.NewIPOrDomain(dest.Address),
  156. Port: uint32(dest.Port),
  157. NetworkList: &v2net.NetworkList{
  158. Network: []v2net.Network{v2net.Network_TCP},
  159. },
  160. }),
  161. },
  162. },
  163. Outbound: []*proxyman.OutboundHandlerConfig{
  164. {
  165. ProxySettings: serial.ToTypedMessage(&outbound.Config{
  166. Receiver: []*protocol.ServerEndpoint{
  167. {
  168. Address: v2net.NewIPOrDomain(v2net.LocalHostIP),
  169. Port: uint32(serverPort),
  170. User: []*protocol.User{
  171. {
  172. Account: serial.ToTypedMessage(&vmess.Account{
  173. Id: serverUserID.String(),
  174. }),
  175. },
  176. },
  177. },
  178. },
  179. }),
  180. SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
  181. ProxySettings: &internet.ProxyConfig{
  182. Tag: "proxy",
  183. },
  184. }),
  185. },
  186. {
  187. Tag: "proxy",
  188. ProxySettings: serial.ToTypedMessage(&outbound.Config{
  189. Receiver: []*protocol.ServerEndpoint{
  190. {
  191. Address: v2net.NewIPOrDomain(v2net.LocalHostIP),
  192. Port: uint32(proxyPort),
  193. User: []*protocol.User{
  194. {
  195. Account: serial.ToTypedMessage(&vmess.Account{
  196. Id: proxyUserID.String(),
  197. }),
  198. },
  199. },
  200. },
  201. },
  202. }),
  203. },
  204. },
  205. }
  206. assert.Error(InitializeServerConfig(serverConfig)).IsNil()
  207. assert.Error(InitializeServerConfig(proxyConfig)).IsNil()
  208. assert.Error(InitializeServerConfig(clientConfig)).IsNil()
  209. conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
  210. IP: []byte{127, 0, 0, 1},
  211. Port: int(clientPort),
  212. })
  213. assert.Error(err).IsNil()
  214. payload := "dokodemo request."
  215. nBytes, err := conn.Write([]byte(payload))
  216. assert.Error(err).IsNil()
  217. assert.Int(nBytes).Equals(len(payload))
  218. response := make([]byte, 1024)
  219. nBytes, err = conn.Read(response)
  220. assert.Error(err).IsNil()
  221. assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload)))
  222. assert.Error(conn.Close()).IsNil()
  223. CloseAllServers()
  224. }
  225. func TestProxyOverKCP(t *testing.T) {
  226. assert := assert.On(t)
  227. tcpServer := tcp.Server{
  228. MsgProcessor: xor,
  229. }
  230. dest, err := tcpServer.Start()
  231. assert.Error(err).IsNil()
  232. defer tcpServer.Close()
  233. serverUserID := protocol.NewID(uuid.New())
  234. serverPort := pickPort()
  235. serverConfig := &core.Config{
  236. Inbound: []*proxyman.InboundHandlerConfig{
  237. {
  238. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  239. PortRange: v2net.SinglePortRange(serverPort),
  240. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  241. StreamSettings: &internet.StreamConfig{
  242. Protocol: internet.TransportProtocol_MKCP,
  243. },
  244. }),
  245. ProxySettings: serial.ToTypedMessage(&inbound.Config{
  246. User: []*protocol.User{
  247. {
  248. Account: serial.ToTypedMessage(&vmess.Account{
  249. Id: serverUserID.String(),
  250. }),
  251. },
  252. },
  253. }),
  254. },
  255. },
  256. Outbound: []*proxyman.OutboundHandlerConfig{
  257. {
  258. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  259. },
  260. },
  261. }
  262. proxyUserID := protocol.NewID(uuid.New())
  263. proxyPort := pickPort()
  264. proxyConfig := &core.Config{
  265. Inbound: []*proxyman.InboundHandlerConfig{
  266. {
  267. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  268. PortRange: v2net.SinglePortRange(proxyPort),
  269. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  270. }),
  271. ProxySettings: serial.ToTypedMessage(&inbound.Config{
  272. User: []*protocol.User{
  273. {
  274. Account: serial.ToTypedMessage(&vmess.Account{
  275. Id: proxyUserID.String(),
  276. }),
  277. },
  278. },
  279. }),
  280. },
  281. },
  282. Outbound: []*proxyman.OutboundHandlerConfig{
  283. {
  284. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  285. SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
  286. StreamSettings: &internet.StreamConfig{
  287. Protocol: internet.TransportProtocol_MKCP,
  288. },
  289. }),
  290. },
  291. },
  292. }
  293. clientPort := pickPort()
  294. clientConfig := &core.Config{
  295. Inbound: []*proxyman.InboundHandlerConfig{
  296. {
  297. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  298. PortRange: v2net.SinglePortRange(clientPort),
  299. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  300. }),
  301. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  302. Address: v2net.NewIPOrDomain(dest.Address),
  303. Port: uint32(dest.Port),
  304. NetworkList: &v2net.NetworkList{
  305. Network: []v2net.Network{v2net.Network_TCP},
  306. },
  307. }),
  308. },
  309. },
  310. Outbound: []*proxyman.OutboundHandlerConfig{
  311. {
  312. ProxySettings: serial.ToTypedMessage(&outbound.Config{
  313. Receiver: []*protocol.ServerEndpoint{
  314. {
  315. Address: v2net.NewIPOrDomain(v2net.LocalHostIP),
  316. Port: uint32(serverPort),
  317. User: []*protocol.User{
  318. {
  319. Account: serial.ToTypedMessage(&vmess.Account{
  320. Id: serverUserID.String(),
  321. }),
  322. },
  323. },
  324. },
  325. },
  326. }),
  327. SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
  328. ProxySettings: &internet.ProxyConfig{
  329. Tag: "proxy",
  330. },
  331. StreamSettings: &internet.StreamConfig{
  332. Protocol: internet.TransportProtocol_MKCP,
  333. },
  334. }),
  335. },
  336. {
  337. Tag: "proxy",
  338. ProxySettings: serial.ToTypedMessage(&outbound.Config{
  339. Receiver: []*protocol.ServerEndpoint{
  340. {
  341. Address: v2net.NewIPOrDomain(v2net.LocalHostIP),
  342. Port: uint32(proxyPort),
  343. User: []*protocol.User{
  344. {
  345. Account: serial.ToTypedMessage(&vmess.Account{
  346. Id: proxyUserID.String(),
  347. }),
  348. },
  349. },
  350. },
  351. },
  352. }),
  353. },
  354. },
  355. }
  356. assert.Error(InitializeServerConfig(serverConfig)).IsNil()
  357. assert.Error(InitializeServerConfig(proxyConfig)).IsNil()
  358. assert.Error(InitializeServerConfig(clientConfig)).IsNil()
  359. conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
  360. IP: []byte{127, 0, 0, 1},
  361. Port: int(clientPort),
  362. })
  363. assert.Error(err).IsNil()
  364. payload := "dokodemo request."
  365. nBytes, err := conn.Write([]byte(payload))
  366. assert.Error(err).IsNil()
  367. assert.Int(nBytes).Equals(len(payload))
  368. response := make([]byte, 1024)
  369. nBytes, err = conn.Read(response)
  370. assert.Error(err).IsNil()
  371. assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload)))
  372. assert.Error(conn.Close()).IsNil()
  373. CloseAllServers()
  374. }
  375. func TestBlackhole(t *testing.T) {
  376. assert := assert.On(t)
  377. tcpServer := tcp.Server{
  378. MsgProcessor: xor,
  379. }
  380. dest, err := tcpServer.Start()
  381. assert.Error(err).IsNil()
  382. defer tcpServer.Close()
  383. tcpServer2 := tcp.Server{
  384. MsgProcessor: xor,
  385. }
  386. dest2, err := tcpServer2.Start()
  387. assert.Error(err).IsNil()
  388. defer tcpServer2.Close()
  389. serverPort := pickPort()
  390. serverPort2 := pickPort()
  391. serverConfig := &core.Config{
  392. Inbound: []*proxyman.InboundHandlerConfig{
  393. {
  394. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  395. PortRange: v2net.SinglePortRange(serverPort),
  396. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  397. }),
  398. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  399. Address: v2net.NewIPOrDomain(dest.Address),
  400. Port: uint32(dest.Port),
  401. NetworkList: &v2net.NetworkList{
  402. Network: []v2net.Network{v2net.Network_TCP},
  403. },
  404. }),
  405. },
  406. {
  407. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  408. PortRange: v2net.SinglePortRange(serverPort2),
  409. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  410. }),
  411. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  412. Address: v2net.NewIPOrDomain(dest2.Address),
  413. Port: uint32(dest2.Port),
  414. NetworkList: &v2net.NetworkList{
  415. Network: []v2net.Network{v2net.Network_TCP},
  416. },
  417. }),
  418. },
  419. },
  420. Outbound: []*proxyman.OutboundHandlerConfig{
  421. {
  422. Tag: "direct",
  423. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  424. },
  425. {
  426. Tag: "blocked",
  427. ProxySettings: serial.ToTypedMessage(&blackhole.Config{}),
  428. },
  429. },
  430. App: []*serial.TypedMessage{
  431. serial.ToTypedMessage(&router.Config{
  432. Rule: []*router.RoutingRule{
  433. {
  434. Tag: "blocked",
  435. PortRange: v2net.SinglePortRange(dest2.Port),
  436. },
  437. },
  438. }),
  439. },
  440. }
  441. assert.Error(InitializeServerConfig(serverConfig)).IsNil()
  442. conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
  443. IP: []byte{127, 0, 0, 1},
  444. Port: int(serverPort2),
  445. })
  446. assert.Error(err).IsNil()
  447. payload := "dokodemo request."
  448. {
  449. nBytes, err := conn.Write([]byte(payload))
  450. assert.Error(err).IsNil()
  451. assert.Int(nBytes).Equals(len(payload))
  452. }
  453. {
  454. response := make([]byte, 1024)
  455. _, err := conn.Read(response)
  456. assert.Error(err).IsNotNil()
  457. }
  458. assert.Error(conn.Close()).IsNil()
  459. CloseAllServers()
  460. }
  461. func TestForward(t *testing.T) {
  462. assert := assert.On(t)
  463. tcpServer := tcp.Server{
  464. MsgProcessor: xor,
  465. }
  466. dest, err := tcpServer.Start()
  467. assert.Error(err).IsNil()
  468. defer tcpServer.Close()
  469. serverPort := pickPort()
  470. serverConfig := &core.Config{
  471. Inbound: []*proxyman.InboundHandlerConfig{
  472. {
  473. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  474. PortRange: v2net.SinglePortRange(serverPort),
  475. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  476. }),
  477. ProxySettings: serial.ToTypedMessage(&socks.ServerConfig{
  478. AuthType: socks.AuthType_NO_AUTH,
  479. Accounts: map[string]string{
  480. "Test Account": "Test Password",
  481. },
  482. Address: v2net.NewIPOrDomain(v2net.LocalHostIP),
  483. UdpEnabled: false,
  484. }),
  485. },
  486. },
  487. Outbound: []*proxyman.OutboundHandlerConfig{
  488. {
  489. ProxySettings: serial.ToTypedMessage(&freedom.Config{
  490. DestinationOverride: &freedom.DestinationOverride{
  491. Server: &protocol.ServerEndpoint{
  492. Address: v2net.NewIPOrDomain(v2net.LocalHostIP),
  493. Port: uint32(dest.Port),
  494. },
  495. },
  496. }),
  497. },
  498. },
  499. }
  500. assert.Error(InitializeServerConfig(serverConfig)).IsNil()
  501. {
  502. noAuthDialer, err := xproxy.SOCKS5("tcp", v2net.TCPDestination(v2net.LocalHostIP, serverPort).NetAddr(), nil, xproxy.Direct)
  503. assert.Error(err).IsNil()
  504. conn, err := noAuthDialer.Dial("tcp", "google.com:80")
  505. assert.Error(err).IsNil()
  506. payload := "test payload"
  507. nBytes, err := conn.Write([]byte(payload))
  508. assert.Error(err).IsNil()
  509. assert.Int(nBytes).Equals(len(payload))
  510. response := make([]byte, 1024)
  511. nBytes, err = conn.Read(response)
  512. assert.Error(err).IsNil()
  513. assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload)))
  514. assert.Error(conn.Close()).IsNil()
  515. }
  516. CloseAllServers()
  517. }
  518. func TestUDPConnection(t *testing.T) {
  519. assert := assert.On(t)
  520. udpServer := udp.Server{
  521. MsgProcessor: xor,
  522. }
  523. dest, err := udpServer.Start()
  524. assert.Error(err).IsNil()
  525. defer udpServer.Close()
  526. clientPort := pickPort()
  527. clientConfig := &core.Config{
  528. Inbound: []*proxyman.InboundHandlerConfig{
  529. {
  530. ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
  531. PortRange: v2net.SinglePortRange(clientPort),
  532. Listen: v2net.NewIPOrDomain(v2net.LocalHostIP),
  533. }),
  534. ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
  535. Address: v2net.NewIPOrDomain(dest.Address),
  536. Port: uint32(dest.Port),
  537. NetworkList: &v2net.NetworkList{
  538. Network: []v2net.Network{v2net.Network_UDP},
  539. },
  540. }),
  541. },
  542. },
  543. Outbound: []*proxyman.OutboundHandlerConfig{
  544. {
  545. ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
  546. },
  547. },
  548. }
  549. assert.Error(InitializeServerConfig(clientConfig)).IsNil()
  550. {
  551. conn, err := net.DialUDP("udp", nil, &net.UDPAddr{
  552. IP: []byte{127, 0, 0, 1},
  553. Port: int(clientPort),
  554. })
  555. assert.Error(err).IsNil()
  556. payload := "dokodemo request."
  557. for i := 0; i < 5; i++ {
  558. nBytes, err := conn.Write([]byte(payload))
  559. assert.Error(err).IsNil()
  560. assert.Int(nBytes).Equals(len(payload))
  561. response := make([]byte, 1024)
  562. nBytes, err = conn.Read(response)
  563. assert.Error(err).IsNil()
  564. assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload)))
  565. }
  566. assert.Error(conn.Close()).IsNil()
  567. }
  568. time.Sleep(20 * time.Second)
  569. {
  570. conn, err := net.DialUDP("udp", nil, &net.UDPAddr{
  571. IP: []byte{127, 0, 0, 1},
  572. Port: int(clientPort),
  573. })
  574. assert.Error(err).IsNil()
  575. payload := "dokodemo request."
  576. nBytes, err := conn.Write([]byte(payload))
  577. assert.Error(err).IsNil()
  578. assert.Int(nBytes).Equals(len(payload))
  579. response := make([]byte, 1024)
  580. nBytes, err = conn.Read(response)
  581. assert.Error(err).IsNil()
  582. assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload)))
  583. assert.Error(conn.Close()).IsNil()
  584. }
  585. CloseAllServers()
  586. }