You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

TCPRelay.cs 22 kB

12 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
10 years ago
12 years ago
10 years ago
10 years ago
12 years ago
10 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
10 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Net.Sockets;
  5. using System.Net;
  6. using Shadowsocks.Encryption;
  7. using Shadowsocks.Model;
  8. using Shadowsocks.Controller.Strategy;
  9. using System.Timers;
  10. namespace Shadowsocks.Controller
  11. {
  12. class TCPRelay : Listener.Service
  13. {
  14. private ShadowsocksController _controller;
  15. private DateTime _lastSweepTime;
  16. public ISet<Handler> Handlers
  17. {
  18. get; set;
  19. }
  20. public TCPRelay(ShadowsocksController controller)
  21. {
  22. this._controller = controller;
  23. this.Handlers = new HashSet<Handler>();
  24. this._lastSweepTime = DateTime.Now;
  25. }
  26. public bool Handle(byte[] firstPacket, int length, Socket socket, object state)
  27. {
  28. if (socket.ProtocolType != ProtocolType.Tcp)
  29. {
  30. return false;
  31. }
  32. if (length < 2 || firstPacket[0] != 5)
  33. {
  34. return false;
  35. }
  36. socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  37. Handler handler = new Handler();
  38. handler.connection = socket;
  39. handler.controller = _controller;
  40. handler.relay = this;
  41. handler.Start(firstPacket, length);
  42. IList<Handler> handlersToClose = new List<Handler>();
  43. lock (this.Handlers)
  44. {
  45. this.Handlers.Add(handler);
  46. Logging.Debug($"connections: {Handlers.Count}");
  47. DateTime now = DateTime.Now;
  48. if (now - _lastSweepTime > TimeSpan.FromSeconds(1))
  49. {
  50. _lastSweepTime = now;
  51. foreach (Handler handler1 in this.Handlers)
  52. {
  53. if (now - handler1.lastActivity > TimeSpan.FromSeconds(900))
  54. {
  55. handlersToClose.Add(handler1);
  56. }
  57. }
  58. }
  59. }
  60. foreach (Handler handler1 in handlersToClose)
  61. {
  62. Logging.Debug("Closing timed out connection");
  63. handler1.Close();
  64. }
  65. return true;
  66. }
  67. }
  68. class Handler
  69. {
  70. //public Encryptor encryptor;
  71. public IEncryptor encryptor;
  72. public Server server;
  73. // Client socket.
  74. public Socket remote;
  75. public Socket connection;
  76. public ShadowsocksController controller;
  77. public TCPRelay relay;
  78. public DateTime lastActivity;
  79. private int retryCount = 0;
  80. private bool connected;
  81. private byte command;
  82. private byte[] _firstPacket;
  83. private int _firstPacketLength;
  84. // Size of receive buffer.
  85. public const int RecvSize = 8192;
  86. public const int RecvReserveSize = IVEncryptor.ONETIMEAUTH_BYTES + IVEncryptor.AUTH_BYTES; // reserve for one-time auth
  87. public const int BufferSize = RecvSize + RecvReserveSize + 32;
  88. private int totalRead = 0;
  89. private int totalWrite = 0;
  90. // remote receive buffer
  91. private byte[] remoteRecvBuffer = new byte[BufferSize];
  92. // remote send buffer
  93. private byte[] remoteSendBuffer = new byte[BufferSize];
  94. // connection receive buffer
  95. private byte[] connetionRecvBuffer = new byte[BufferSize];
  96. // connection send buffer
  97. private byte[] connetionSendBuffer = new byte[BufferSize];
  98. // Received data string.
  99. private bool connectionShutdown = false;
  100. private bool remoteShutdown = false;
  101. private bool closed = false;
  102. private object encryptionLock = new object();
  103. private object decryptionLock = new object();
  104. private DateTime _startConnectTime;
  105. public void CreateRemote()
  106. {
  107. Server server = controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)connection.RemoteEndPoint);
  108. if (server == null || server.server == "")
  109. {
  110. throw new ArgumentException("No server configured");
  111. }
  112. this.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.auth, false);
  113. this.server = server;
  114. }
  115. public void Start(byte[] firstPacket, int length)
  116. {
  117. this._firstPacket = firstPacket;
  118. this._firstPacketLength = length;
  119. this.HandshakeReceive();
  120. this.lastActivity = DateTime.Now;
  121. }
  122. private void CheckClose()
  123. {
  124. if (connectionShutdown && remoteShutdown)
  125. {
  126. this.Close();
  127. }
  128. }
  129. public void Close()
  130. {
  131. lock (relay.Handlers)
  132. {
  133. Logging.Debug($"connections: {relay.Handlers.Count}");
  134. relay.Handlers.Remove(this);
  135. }
  136. lock (this)
  137. {
  138. if (closed)
  139. {
  140. return;
  141. }
  142. closed = true;
  143. }
  144. if (connection != null)
  145. {
  146. try
  147. {
  148. connection.Shutdown(SocketShutdown.Both);
  149. connection.Close();
  150. }
  151. catch (Exception e)
  152. {
  153. Logging.LogUsefulException(e);
  154. }
  155. }
  156. if (remote != null)
  157. {
  158. try
  159. {
  160. remote.Shutdown(SocketShutdown.Both);
  161. remote.Close();
  162. }
  163. catch (Exception e)
  164. {
  165. Logging.LogUsefulException(e);
  166. }
  167. }
  168. lock (encryptionLock)
  169. {
  170. lock (decryptionLock)
  171. {
  172. if (encryptor != null)
  173. {
  174. ((IDisposable)encryptor).Dispose();
  175. }
  176. }
  177. }
  178. }
  179. private void HandshakeReceive()
  180. {
  181. if (closed)
  182. {
  183. return;
  184. }
  185. try
  186. {
  187. int bytesRead = _firstPacketLength;
  188. if (bytesRead > 1)
  189. {
  190. byte[] response = { 5, 0 };
  191. if (_firstPacket[0] != 5)
  192. {
  193. // reject socks 4
  194. response = new byte[] { 0, 91 };
  195. Console.WriteLine("socks 5 protocol error");
  196. }
  197. Logging.Debug($"======Send Local Port, size:" + response.Length);
  198. connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null);
  199. }
  200. else
  201. {
  202. this.Close();
  203. }
  204. }
  205. catch (Exception e)
  206. {
  207. Logging.LogUsefulException(e);
  208. this.Close();
  209. }
  210. }
  211. private void HandshakeSendCallback(IAsyncResult ar)
  212. {
  213. if (closed)
  214. {
  215. return;
  216. }
  217. try
  218. {
  219. connection.EndSend(ar);
  220. // +----+-----+-------+------+----------+----------+
  221. // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
  222. // +----+-----+-------+------+----------+----------+
  223. // | 1 | 1 | X'00' | 1 | Variable | 2 |
  224. // +----+-----+-------+------+----------+----------+
  225. // Skip first 3 bytes
  226. // TODO validate
  227. Logging.Debug($"======Receive Local Port, size:" + 3);
  228. connection.BeginReceive(connetionRecvBuffer, 0, 3, 0,
  229. new AsyncCallback(handshakeReceive2Callback), null);
  230. }
  231. catch (Exception e)
  232. {
  233. Logging.LogUsefulException(e);
  234. this.Close();
  235. }
  236. }
  237. private void handshakeReceive2Callback(IAsyncResult ar)
  238. {
  239. if (closed)
  240. {
  241. return;
  242. }
  243. try
  244. {
  245. int bytesRead = connection.EndReceive(ar);
  246. if (bytesRead >= 3)
  247. {
  248. command = connetionRecvBuffer[1];
  249. if (command == 1)
  250. {
  251. byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
  252. Logging.Debug($"======Send Local Port, size:" + response.Length);
  253. connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(ResponseCallback), null);
  254. }
  255. else if (command == 3)
  256. {
  257. HandleUDPAssociate();
  258. }
  259. }
  260. else
  261. {
  262. Console.WriteLine("failed to recv data in handshakeReceive2Callback");
  263. this.Close();
  264. }
  265. }
  266. catch (Exception e)
  267. {
  268. Logging.LogUsefulException(e);
  269. this.Close();
  270. }
  271. }
  272. private void HandleUDPAssociate()
  273. {
  274. IPEndPoint endPoint = (IPEndPoint)connection.LocalEndPoint;
  275. byte[] address = endPoint.Address.GetAddressBytes();
  276. int port = endPoint.Port;
  277. byte[] response = new byte[4 + address.Length + 2];
  278. response[0] = 5;
  279. if (endPoint.AddressFamily == AddressFamily.InterNetwork)
  280. {
  281. response[3] = 1;
  282. }
  283. else if (endPoint.AddressFamily == AddressFamily.InterNetworkV6)
  284. {
  285. response[3] = 4;
  286. }
  287. address.CopyTo(response, 4);
  288. response[response.Length - 1] = (byte)(port & 0xFF);
  289. response[response.Length - 2] = (byte)((port >> 8) & 0xFF);
  290. Logging.Debug($"======Send Local Port, size:" + response.Length);
  291. connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(ReadAll), true);
  292. }
  293. private void ReadAll(IAsyncResult ar)
  294. {
  295. if (closed)
  296. {
  297. return;
  298. }
  299. try
  300. {
  301. if (ar.AsyncState != null)
  302. {
  303. connection.EndSend(ar);
  304. Logging.Debug($"======Receive Local Port, size:" + RecvSize);
  305. connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
  306. new AsyncCallback(ReadAll), null);
  307. }
  308. else
  309. {
  310. int bytesRead = connection.EndReceive(ar);
  311. if (bytesRead > 0)
  312. {
  313. Logging.Debug($"======Receive Local Port, size:" + RecvSize);
  314. connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
  315. new AsyncCallback(ReadAll), null);
  316. }
  317. else
  318. {
  319. this.Close();
  320. }
  321. }
  322. }
  323. catch (Exception e)
  324. {
  325. Logging.LogUsefulException(e);
  326. this.Close();
  327. }
  328. }
  329. private void ResponseCallback(IAsyncResult ar)
  330. {
  331. try
  332. {
  333. connection.EndSend(ar);
  334. StartConnect();
  335. }
  336. catch (Exception e)
  337. {
  338. Logging.LogUsefulException(e);
  339. this.Close();
  340. }
  341. }
  342. private class ServerTimer : Timer
  343. {
  344. public Server Server;
  345. public ServerTimer(int p) :base(p)
  346. {
  347. }
  348. }
  349. private void StartConnect()
  350. {
  351. try
  352. {
  353. CreateRemote();
  354. // TODO async resolving
  355. IPAddress ipAddress;
  356. bool parsed = IPAddress.TryParse(server.server, out ipAddress);
  357. if (!parsed)
  358. {
  359. IPHostEntry ipHostInfo = Dns.GetHostEntry(server.server);
  360. ipAddress = ipHostInfo.AddressList[0];
  361. }
  362. IPEndPoint remoteEP = new IPEndPoint(ipAddress, server.server_port);
  363. remote = new Socket(ipAddress.AddressFamily,
  364. SocketType.Stream, ProtocolType.Tcp);
  365. remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  366. _startConnectTime = DateTime.Now;
  367. ServerTimer connectTimer = new ServerTimer(3000);
  368. connectTimer.AutoReset = false;
  369. connectTimer.Elapsed += connectTimer_Elapsed;
  370. connectTimer.Enabled = true;
  371. connectTimer.Server = server;
  372. connected = false;
  373. // Connect to the remote endpoint.
  374. Logging.Debug($"++++++Connect Server Port");
  375. remote.BeginConnect(remoteEP,
  376. new AsyncCallback(ConnectCallback), connectTimer);
  377. }
  378. catch (Exception e)
  379. {
  380. Logging.LogUsefulException(e);
  381. this.Close();
  382. }
  383. }
  384. private void connectTimer_Elapsed(object sender, ElapsedEventArgs e)
  385. {
  386. if (connected)
  387. {
  388. return;
  389. }
  390. Server server = ((ServerTimer)sender).Server;
  391. IStrategy strategy = controller.GetCurrentStrategy();
  392. if (strategy != null)
  393. {
  394. strategy.SetFailure(server);
  395. }
  396. Console.WriteLine(String.Format("{0} timed out", server.FriendlyName()));
  397. remote.Close();
  398. RetryConnect();
  399. }
  400. private void RetryConnect()
  401. {
  402. if (retryCount < 4)
  403. {
  404. Logging.Debug("Connection failed, retrying");
  405. StartConnect();
  406. retryCount++;
  407. }
  408. else
  409. {
  410. this.Close();
  411. }
  412. }
  413. private void ConnectCallback(IAsyncResult ar)
  414. {
  415. Server server = null;
  416. if (closed)
  417. {
  418. return;
  419. }
  420. try
  421. {
  422. ServerTimer timer = (ServerTimer)ar.AsyncState;
  423. server = timer.Server;
  424. timer.Elapsed -= connectTimer_Elapsed;
  425. timer.Enabled = false;
  426. timer.Dispose();
  427. // Complete the connection.
  428. remote.EndConnect(ar);
  429. connected = true;
  430. //Console.WriteLine("Socket connected to {0}",
  431. // remote.RemoteEndPoint.ToString());
  432. var latency = DateTime.Now - _startConnectTime;
  433. IStrategy strategy = controller.GetCurrentStrategy();
  434. if (strategy != null)
  435. {
  436. strategy.UpdateLatency(server, latency);
  437. }
  438. StartPipe();
  439. }
  440. catch (ArgumentException)
  441. {
  442. }
  443. catch (Exception e)
  444. {
  445. if (server != null)
  446. {
  447. IStrategy strategy = controller.GetCurrentStrategy();
  448. if (strategy != null)
  449. {
  450. strategy.SetFailure(server);
  451. }
  452. }
  453. Logging.LogUsefulException(e);
  454. RetryConnect();
  455. }
  456. }
  457. private void StartPipe()
  458. {
  459. if (closed)
  460. {
  461. return;
  462. }
  463. try
  464. {
  465. Logging.Debug($"++++++Receive Server Port, size:" + RecvSize);
  466. remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0,
  467. new AsyncCallback(PipeRemoteReceiveCallback), null);
  468. Logging.Debug($"======Receive Local Port, size:"+ RecvSize);
  469. connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
  470. new AsyncCallback(PipeConnectionReceiveCallback), null);
  471. }
  472. catch (Exception e)
  473. {
  474. Logging.LogUsefulException(e);
  475. this.Close();
  476. }
  477. }
  478. private void PipeRemoteReceiveCallback(IAsyncResult ar)
  479. {
  480. if (closed)
  481. {
  482. return;
  483. }
  484. try
  485. {
  486. int bytesRead = remote.EndReceive(ar);
  487. totalRead += bytesRead;
  488. if (bytesRead > 0)
  489. {
  490. this.lastActivity = DateTime.Now;
  491. int bytesToSend;
  492. lock (decryptionLock)
  493. {
  494. if (closed)
  495. {
  496. return;
  497. }
  498. encryptor.Decrypt(remoteRecvBuffer, bytesRead, remoteSendBuffer, out bytesToSend);
  499. }
  500. Logging.Debug($"======Send Local Port, size:" + bytesToSend);
  501. connection.BeginSend(remoteSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeConnectionSendCallback), null);
  502. IStrategy strategy = controller.GetCurrentStrategy();
  503. if (strategy != null)
  504. {
  505. strategy.UpdateLastRead(this.server);
  506. }
  507. }
  508. else
  509. {
  510. //Console.WriteLine("bytesRead: " + bytesRead.ToString());
  511. connection.Shutdown(SocketShutdown.Send);
  512. connectionShutdown = true;
  513. CheckClose();
  514. if (totalRead == 0)
  515. {
  516. // closed before anything received, reports as failure
  517. // disable this feature
  518. // controller.GetCurrentStrategy().SetFailure(this.server);
  519. }
  520. }
  521. }
  522. catch (Exception e)
  523. {
  524. Logging.LogUsefulException(e);
  525. this.Close();
  526. }
  527. }
  528. private void PipeConnectionReceiveCallback(IAsyncResult ar)
  529. {
  530. if (closed)
  531. {
  532. return;
  533. }
  534. try
  535. {
  536. int bytesRead = connection.EndReceive(ar);
  537. totalWrite += bytesRead;
  538. if (bytesRead > 0)
  539. {
  540. int bytesToSend;
  541. lock (encryptionLock)
  542. {
  543. if (closed)
  544. {
  545. return;
  546. }
  547. encryptor.Encrypt(connetionRecvBuffer, bytesRead, connetionSendBuffer, out bytesToSend);
  548. }
  549. Logging.Debug($"++++++Send Server Port, size:" + bytesToSend);
  550. remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null);
  551. IStrategy strategy = controller.GetCurrentStrategy();
  552. if (strategy != null)
  553. {
  554. strategy.UpdateLastWrite(this.server);
  555. }
  556. }
  557. else
  558. {
  559. remote.Shutdown(SocketShutdown.Send);
  560. remoteShutdown = true;
  561. CheckClose();
  562. }
  563. }
  564. catch (Exception e)
  565. {
  566. Logging.LogUsefulException(e);
  567. this.Close();
  568. }
  569. }
  570. private void PipeRemoteSendCallback(IAsyncResult ar)
  571. {
  572. if (closed)
  573. {
  574. return;
  575. }
  576. try
  577. {
  578. remote.EndSend(ar);
  579. Logging.Debug($"======Receive Local Port, size:" + RecvSize);
  580. connection.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0,
  581. new AsyncCallback(PipeConnectionReceiveCallback), null);
  582. }
  583. catch (Exception e)
  584. {
  585. Logging.LogUsefulException(e);
  586. this.Close();
  587. }
  588. }
  589. private void PipeConnectionSendCallback(IAsyncResult ar)
  590. {
  591. if (closed)
  592. {
  593. return;
  594. }
  595. try
  596. {
  597. connection.EndSend(ar);
  598. Logging.Debug($"++++++Receive Server Port, size:" + RecvSize);
  599. remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0,
  600. new AsyncCallback(PipeRemoteReceiveCallback), null);
  601. }
  602. catch (Exception e)
  603. {
  604. Logging.LogUsefulException(e);
  605. this.Close();
  606. }
  607. }
  608. }
  609. }