shadowsocks_test.go 16 KB

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