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 16 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
12 years ago
10 years ago
10 years ago
12 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
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
12 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
12 years ago
10 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
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
12 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
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
12 years ago
12 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  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. namespace Shadowsocks.Controller
  10. {
  11. class TCPRelay : Listener.Service
  12. {
  13. private ShadowsocksController _controller;
  14. public TCPRelay(ShadowsocksController controller)
  15. {
  16. this._controller = controller;
  17. }
  18. public bool Handle(byte[] firstPacket, int length, Socket socket, object state)
  19. {
  20. if (socket.ProtocolType != ProtocolType.Tcp)
  21. {
  22. return false;
  23. }
  24. if (length < 2 || firstPacket[0] != 5)
  25. {
  26. return false;
  27. }
  28. socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  29. Handler handler = new Handler();
  30. handler.connection = socket;
  31. Server server = _controller.GetCurrentStrategy().GetAServer(IStrategyCallerType.TCP, (IPEndPoint)socket.RemoteEndPoint);
  32. handler.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password);
  33. handler.server = server;
  34. handler.controller = _controller;
  35. handler.Start(firstPacket, length);
  36. return true;
  37. }
  38. }
  39. class Handler
  40. {
  41. //public Encryptor encryptor;
  42. public IEncryptor encryptor;
  43. public Server server;
  44. // Client socket.
  45. public Socket remote;
  46. public Socket connection;
  47. public ShadowsocksController controller;
  48. private byte command;
  49. private byte[] _firstPacket;
  50. private int _firstPacketLength;
  51. // Size of receive buffer.
  52. public const int RecvSize = 16384;
  53. public const int BufferSize = RecvSize + 32;
  54. private int totalRead = 0;
  55. private int totalWrite = 0;
  56. // remote receive buffer
  57. private byte[] remoteRecvBuffer = new byte[RecvSize];
  58. // remote send buffer
  59. private byte[] remoteSendBuffer = new byte[BufferSize];
  60. // connection receive buffer
  61. private byte[] connetionRecvBuffer = new byte[RecvSize];
  62. // connection send buffer
  63. private byte[] connetionSendBuffer = new byte[BufferSize];
  64. // Received data string.
  65. private bool connectionShutdown = false;
  66. private bool remoteShutdown = false;
  67. private bool closed = false;
  68. private object encryptionLock = new object();
  69. private object decryptionLock = new object();
  70. private DateTime _startConnectTime;
  71. public void Start(byte[] firstPacket, int length)
  72. {
  73. this._firstPacket = firstPacket;
  74. this._firstPacketLength = length;
  75. this.HandshakeReceive();
  76. }
  77. private void CheckClose()
  78. {
  79. if (connectionShutdown && remoteShutdown)
  80. {
  81. this.Close();
  82. }
  83. }
  84. public void Close()
  85. {
  86. lock (this)
  87. {
  88. if (closed)
  89. {
  90. return;
  91. }
  92. closed = true;
  93. }
  94. if (connection != null)
  95. {
  96. try
  97. {
  98. connection.Shutdown(SocketShutdown.Both);
  99. connection.Close();
  100. }
  101. catch (Exception e)
  102. {
  103. Logging.LogUsefulException(e);
  104. }
  105. }
  106. if (remote != null)
  107. {
  108. try
  109. {
  110. remote.Shutdown(SocketShutdown.Both);
  111. remote.Close();
  112. }
  113. catch (SocketException e)
  114. {
  115. Logging.LogUsefulException(e);
  116. }
  117. }
  118. lock (encryptionLock)
  119. {
  120. lock (decryptionLock)
  121. {
  122. ((IDisposable)encryptor).Dispose();
  123. }
  124. }
  125. }
  126. private void HandshakeReceive()
  127. {
  128. if (closed)
  129. {
  130. return;
  131. }
  132. try
  133. {
  134. int bytesRead = _firstPacketLength;
  135. if (bytesRead > 1)
  136. {
  137. byte[] response = { 5, 0 };
  138. if (_firstPacket[0] != 5)
  139. {
  140. // reject socks 4
  141. response = new byte[] { 0, 91 };
  142. Console.WriteLine("socks 5 protocol error");
  143. }
  144. connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null);
  145. }
  146. else
  147. {
  148. this.Close();
  149. }
  150. }
  151. catch (Exception e)
  152. {
  153. Logging.LogUsefulException(e);
  154. this.Close();
  155. }
  156. }
  157. private void HandshakeSendCallback(IAsyncResult ar)
  158. {
  159. if (closed)
  160. {
  161. return;
  162. }
  163. try
  164. {
  165. connection.EndSend(ar);
  166. // +----+-----+-------+------+----------+----------+
  167. // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
  168. // +----+-----+-------+------+----------+----------+
  169. // | 1 | 1 | X'00' | 1 | Variable | 2 |
  170. // +----+-----+-------+------+----------+----------+
  171. // Skip first 3 bytes
  172. // TODO validate
  173. connection.BeginReceive(connetionRecvBuffer, 0, 3, 0,
  174. new AsyncCallback(handshakeReceive2Callback), null);
  175. }
  176. catch (Exception e)
  177. {
  178. Logging.LogUsefulException(e);
  179. this.Close();
  180. }
  181. }
  182. private void handshakeReceive2Callback(IAsyncResult ar)
  183. {
  184. if (closed)
  185. {
  186. return;
  187. }
  188. try
  189. {
  190. int bytesRead = connection.EndReceive(ar);
  191. if (bytesRead >= 3)
  192. {
  193. command = connetionRecvBuffer[1];
  194. if (command == 1)
  195. {
  196. byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
  197. connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(StartConnect), null);
  198. }
  199. else if (command == 3)
  200. {
  201. HandleUDPAssociate();
  202. }
  203. }
  204. else
  205. {
  206. Console.WriteLine("failed to recv data in handshakeReceive2Callback");
  207. this.Close();
  208. }
  209. }
  210. catch (Exception e)
  211. {
  212. Logging.LogUsefulException(e);
  213. this.Close();
  214. }
  215. }
  216. private void HandleUDPAssociate()
  217. {
  218. IPEndPoint endPoint = (IPEndPoint)connection.LocalEndPoint;
  219. byte[] address = endPoint.Address.GetAddressBytes();
  220. int port = endPoint.Port;
  221. byte[] response = new byte[4 + address.Length + 2];
  222. response[0] = 5;
  223. if (endPoint.AddressFamily == AddressFamily.InterNetwork)
  224. {
  225. response[3] = 1;
  226. }
  227. else if (endPoint.AddressFamily == AddressFamily.InterNetworkV6)
  228. {
  229. response[3] = 4;
  230. }
  231. address.CopyTo(response, 4);
  232. response[response.Length - 1] = (byte)(port & 0xFF);
  233. response[response.Length - 2] = (byte)((port >> 8) & 0xFF);
  234. connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(ReadAll), true);
  235. }
  236. private void ReadAll(IAsyncResult ar)
  237. {
  238. if (closed)
  239. {
  240. return;
  241. }
  242. try
  243. {
  244. if (ar.AsyncState != null)
  245. {
  246. connection.EndSend(ar);
  247. connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
  248. new AsyncCallback(ReadAll), null);
  249. }
  250. else
  251. {
  252. int bytesRead = connection.EndReceive(ar);
  253. if (bytesRead > 0)
  254. {
  255. connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
  256. new AsyncCallback(ReadAll), null);
  257. }
  258. else
  259. {
  260. this.Close();
  261. }
  262. }
  263. }
  264. catch (Exception e)
  265. {
  266. Logging.LogUsefulException(e);
  267. this.Close();
  268. }
  269. }
  270. private void StartConnect(IAsyncResult ar)
  271. {
  272. try
  273. {
  274. connection.EndSend(ar);
  275. // TODO async resolving
  276. IPAddress ipAddress;
  277. bool parsed = IPAddress.TryParse(server.server, out ipAddress);
  278. if (!parsed)
  279. {
  280. IPHostEntry ipHostInfo = Dns.GetHostEntry(server.server);
  281. ipAddress = ipHostInfo.AddressList[0];
  282. }
  283. IPEndPoint remoteEP = new IPEndPoint(ipAddress, server.server_port);
  284. remote = new Socket(ipAddress.AddressFamily,
  285. SocketType.Stream, ProtocolType.Tcp);
  286. remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  287. _startConnectTime = DateTime.Now;
  288. // Connect to the remote endpoint.
  289. remote.BeginConnect(remoteEP,
  290. new AsyncCallback(ConnectCallback), null);
  291. }
  292. catch (Exception e)
  293. {
  294. Logging.LogUsefulException(e);
  295. this.Close();
  296. }
  297. }
  298. private void ConnectCallback(IAsyncResult ar)
  299. {
  300. if (closed)
  301. {
  302. return;
  303. }
  304. try
  305. {
  306. // Complete the connection.
  307. remote.EndConnect(ar);
  308. //Console.WriteLine("Socket connected to {0}",
  309. // remote.RemoteEndPoint.ToString());
  310. var latency = DateTime.Now - _startConnectTime;
  311. controller.GetCurrentStrategy().UpdateLatency(this.server, latency);
  312. StartPipe();
  313. }
  314. catch (Exception e)
  315. {
  316. controller.GetCurrentStrategy().SetFailure(this.server);
  317. Logging.LogUsefulException(e);
  318. this.Close();
  319. }
  320. }
  321. private void StartPipe()
  322. {
  323. if (closed)
  324. {
  325. return;
  326. }
  327. try
  328. {
  329. remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0,
  330. new AsyncCallback(PipeRemoteReceiveCallback), null);
  331. connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
  332. new AsyncCallback(PipeConnectionReceiveCallback), null);
  333. }
  334. catch (Exception e)
  335. {
  336. Logging.LogUsefulException(e);
  337. this.Close();
  338. }
  339. }
  340. private void PipeRemoteReceiveCallback(IAsyncResult ar)
  341. {
  342. if (closed)
  343. {
  344. return;
  345. }
  346. try
  347. {
  348. int bytesRead = remote.EndReceive(ar);
  349. totalRead += bytesRead;
  350. if (bytesRead > 0)
  351. {
  352. int bytesToSend;
  353. lock (decryptionLock)
  354. {
  355. if (closed)
  356. {
  357. return;
  358. }
  359. encryptor.Decrypt(remoteRecvBuffer, bytesRead, remoteSendBuffer, out bytesToSend);
  360. }
  361. connection.BeginSend(remoteSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeConnectionSendCallback), null);
  362. controller.GetCurrentStrategy().UpdateLastRead(this.server);
  363. }
  364. else
  365. {
  366. //Console.WriteLine("bytesRead: " + bytesRead.ToString());
  367. connection.Shutdown(SocketShutdown.Send);
  368. connectionShutdown = true;
  369. CheckClose();
  370. if (totalRead == 0)
  371. {
  372. // closed before anything received, reports as failure
  373. controller.GetCurrentStrategy().SetFailure(this.server);
  374. }
  375. }
  376. }
  377. catch (Exception e)
  378. {
  379. Logging.LogUsefulException(e);
  380. this.Close();
  381. }
  382. }
  383. private void PipeConnectionReceiveCallback(IAsyncResult ar)
  384. {
  385. if (closed)
  386. {
  387. return;
  388. }
  389. try
  390. {
  391. int bytesRead = connection.EndReceive(ar);
  392. totalWrite += bytesRead;
  393. if (bytesRead > 0)
  394. {
  395. int bytesToSend;
  396. lock (encryptionLock)
  397. {
  398. if (closed)
  399. {
  400. return;
  401. }
  402. encryptor.Encrypt(connetionRecvBuffer, bytesRead, connetionSendBuffer, out bytesToSend);
  403. }
  404. remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null);
  405. controller.GetCurrentStrategy().UpdateLastWrite(this.server);
  406. }
  407. else
  408. {
  409. remote.Shutdown(SocketShutdown.Send);
  410. remoteShutdown = true;
  411. CheckClose();
  412. }
  413. }
  414. catch (Exception e)
  415. {
  416. Logging.LogUsefulException(e);
  417. this.Close();
  418. }
  419. }
  420. private void PipeRemoteSendCallback(IAsyncResult ar)
  421. {
  422. if (closed)
  423. {
  424. return;
  425. }
  426. try
  427. {
  428. remote.EndSend(ar);
  429. connection.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0,
  430. new AsyncCallback(PipeConnectionReceiveCallback), null);
  431. }
  432. catch (Exception e)
  433. {
  434. Logging.LogUsefulException(e);
  435. this.Close();
  436. }
  437. }
  438. private void PipeConnectionSendCallback(IAsyncResult ar)
  439. {
  440. if (closed)
  441. {
  442. return;
  443. }
  444. try
  445. {
  446. connection.EndSend(ar);
  447. remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0,
  448. new AsyncCallback(PipeRemoteReceiveCallback), null);
  449. }
  450. catch (Exception e)
  451. {
  452. Logging.LogUsefulException(e);
  453. this.Close();
  454. }
  455. }
  456. }
  457. }