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
12 years ago
10 years ago
12 years ago
12 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
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
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 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
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.Timers;
  6. using Shadowsocks.Controller.Strategy;
  7. using Shadowsocks.Encryption;
  8. using Shadowsocks.ForwardProxy;
  9. using Shadowsocks.Model;
  10. using Shadowsocks.Util.Sockets;
  11. namespace Shadowsocks.Controller.Service
  12. {
  13. class TCPRelay : Listener.Service
  14. {
  15. private ShadowsocksController _controller;
  16. private DateTime _lastSweepTime;
  17. private Configuration _config;
  18. private readonly List<ITCPHandlerFactory> _factories = new List<ITCPHandlerFactory>();
  19. public ISet<TCPHandler> Handlers { get; } = new HashSet<TCPHandler>();
  20. public TCPRelay(ShadowsocksController controller, Configuration conf)
  21. {
  22. _controller = controller;
  23. _config = conf;
  24. _lastSweepTime = DateTime.Now;
  25. _factories.Add(new Socks5HandlerFactory());
  26. _factories.Add(new HttpHandlerHandlerFactory());
  27. }
  28. public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)
  29. {
  30. TCPHandler handler = null;
  31. foreach (var factory in _factories)
  32. {
  33. if (factory.CanHandle(firstPacket, length))
  34. {
  35. handler = factory.NewHandler(_controller, _config, this, socket);
  36. break;
  37. }
  38. }
  39. if (handler == null)
  40. {
  41. return false;
  42. }
  43. socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  44. IList<TCPHandler> handlersToClose = new List<TCPHandler>();
  45. lock (Handlers)
  46. {
  47. Handlers.Add(handler);
  48. DateTime now = DateTime.Now;
  49. if (now - _lastSweepTime > TimeSpan.FromSeconds(1))
  50. {
  51. _lastSweepTime = now;
  52. foreach (TCPHandler handler1 in Handlers)
  53. if (now - handler1.lastActivity > TimeSpan.FromSeconds(900))
  54. handlersToClose.Add(handler1);
  55. }
  56. }
  57. foreach (TCPHandler handler1 in handlersToClose)
  58. {
  59. Logging.Debug("Closing timed out TCP connection.");
  60. handler1.Close();
  61. }
  62. /*
  63. * Start after we put it into Handlers set. Otherwise if it failed in handler.Start()
  64. * then it will call handler.Close() before we add it into the set.
  65. * Then the handler will never release until the next Handle call. Sometimes it will
  66. * cause odd problems (especially during memory profiling).
  67. */
  68. handler.StartHandshake(firstPacket, length);
  69. return true;
  70. }
  71. public override void Stop()
  72. {
  73. List<TCPHandler> handlersToClose = new List<TCPHandler>();
  74. lock (Handlers)
  75. {
  76. handlersToClose.AddRange(Handlers);
  77. }
  78. handlersToClose.ForEach(h => h.Close());
  79. }
  80. public void UpdateInboundCounter(Server server, long n)
  81. {
  82. _controller.UpdateInboundCounter(server, n);
  83. }
  84. public void UpdateOutboundCounter(Server server, long n)
  85. {
  86. _controller.UpdateOutboundCounter(server, n);
  87. }
  88. public void UpdateLatency(Server server, TimeSpan latency)
  89. {
  90. _controller.UpdateLatency(server, latency);
  91. }
  92. }
  93. interface ITCPHandlerFactory
  94. {
  95. bool CanHandle(byte[] firstPacket, int length);
  96. TCPHandler NewHandler(ShadowsocksController controller, Configuration config, TCPRelay tcprelay, Socket socket);
  97. }
  98. abstract class TCPHandler
  99. {
  100. public abstract void StartHandshake(byte[] firstPacket, int length);
  101. protected abstract void OnServerConnected(AsyncSession session);
  102. protected class AsyncSession
  103. {
  104. public IForwardProxy Remote { get; }
  105. public AsyncSession(IForwardProxy remote)
  106. {
  107. Remote = remote;
  108. }
  109. }
  110. protected class AsyncSession<T> : AsyncSession
  111. {
  112. public T State { get; set; }
  113. public AsyncSession(IForwardProxy remote, T state) : base(remote)
  114. {
  115. State = state;
  116. }
  117. public AsyncSession(AsyncSession session, T state) : base(session.Remote)
  118. {
  119. State = state;
  120. }
  121. }
  122. private readonly int _serverTimeout;
  123. private readonly int _proxyTimeout;
  124. // Size of receive buffer.
  125. public static readonly int RecvSize = 8192;
  126. public static readonly int RecvReserveSize = IVEncryptor.ONETIMEAUTH_BYTES + IVEncryptor.AUTH_BYTES; // reserve for one-time auth
  127. public static readonly int BufferSize = RecvSize + RecvReserveSize + 32;
  128. public DateTime lastActivity;
  129. private ShadowsocksController _controller;
  130. protected Configuration Config { get; }
  131. private TCPRelay _tcprelay;
  132. protected Socket Connection { get; }
  133. private Server _server;
  134. private AsyncSession _currentRemoteSession;
  135. private bool _proxyConnected;
  136. private bool _destConnected;
  137. private int _totalRead = 0;
  138. private int _totalWrite = 0;
  139. protected byte[] RemoteRecvBuffer { get; } = new byte[BufferSize];
  140. private readonly byte[] _remoteSendBuffer = new byte[BufferSize];
  141. protected byte[] ConnetionRecvBuffer { get; } = new byte[BufferSize];
  142. private readonly byte[] _connetionSendBuffer = new byte[BufferSize];
  143. private IEncryptor _encryptor;
  144. private readonly object _encryptionLock = new object();
  145. private readonly object _decryptionLock = new object();
  146. private bool _connectionShutdown = false;
  147. private bool _remoteShutdown = false;
  148. protected bool Closed { get; private set; }= false;
  149. private readonly object _closeConnLock = new object();
  150. private DateTime _startConnectTime;
  151. private DateTime _startReceivingTime;
  152. private DateTime _startSendingTime;
  153. private EndPoint _destEndPoint = null;
  154. public TCPHandler(ShadowsocksController controller, Configuration config, TCPRelay tcprelay, Socket socket, bool autoAppendHeader = true)
  155. {
  156. _controller = controller;
  157. Config = config;
  158. _tcprelay = tcprelay;
  159. Connection = socket;
  160. _proxyTimeout = config.proxy.proxyTimeout * 1000;
  161. _serverTimeout = config.GetCurrentServer().timeout * 1000;
  162. lastActivity = DateTime.Now;
  163. _serverHeaderSent = !autoAppendHeader;
  164. }
  165. private void CreateRemote()
  166. {
  167. Server server = _controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)Connection.RemoteEndPoint, _destEndPoint);
  168. if (server == null || server.server == "")
  169. throw new ArgumentException("No server configured");
  170. lock (_encryptionLock)
  171. {
  172. lock (_decryptionLock)
  173. {
  174. _encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.auth, false);
  175. }
  176. }
  177. this._server = server;
  178. }
  179. private void CheckClose()
  180. {
  181. if (_connectionShutdown && _remoteShutdown)
  182. Close();
  183. }
  184. public void Close()
  185. {
  186. lock (_closeConnLock)
  187. {
  188. if (Closed) return;
  189. Closed = true;
  190. }
  191. lock (_tcprelay.Handlers)
  192. {
  193. _tcprelay.Handlers.Remove(this);
  194. }
  195. try
  196. {
  197. Connection.Shutdown(SocketShutdown.Both);
  198. Connection.Close();
  199. }
  200. catch (Exception e)
  201. {
  202. Logging.LogUsefulException(e);
  203. }
  204. try
  205. {
  206. var remote = _currentRemoteSession.Remote;
  207. remote.Shutdown(SocketShutdown.Both);
  208. remote.Close();
  209. }
  210. catch (Exception e)
  211. {
  212. Logging.LogUsefulException(e);
  213. }
  214. lock (_encryptionLock)
  215. {
  216. lock (_decryptionLock)
  217. {
  218. _encryptor?.Dispose();
  219. }
  220. }
  221. }
  222. // inner class
  223. private class ProxyTimer : Timer
  224. {
  225. public AsyncSession Session;
  226. public EndPoint DestEndPoint;
  227. public Server Server;
  228. public ProxyTimer(int p) : base(p)
  229. {
  230. }
  231. }
  232. private class ServerTimer : Timer
  233. {
  234. public AsyncSession Session;
  235. public Server Server;
  236. public ServerTimer(int p) : base(p) { }
  237. }
  238. protected void StartConnect(EndPoint target)
  239. {
  240. try
  241. {
  242. _destEndPoint = target;
  243. CreateRemote();
  244. // Setting up proxy
  245. IForwardProxy remote;
  246. EndPoint proxyEP;
  247. if (Config.proxy.useProxy)
  248. {
  249. switch (Config.proxy.proxyType)
  250. {
  251. case ProxyConfig.PROXY_SOCKS5:
  252. remote = new Socks5Proxy();
  253. break;
  254. case ProxyConfig.PROXY_HTTP:
  255. remote = new HttpProxy();
  256. break;
  257. default:
  258. throw new NotSupportedException("Unknown forward proxy.");
  259. }
  260. proxyEP = SocketUtil.GetEndPoint(Config.proxy.proxyServer, Config.proxy.proxyPort);
  261. }
  262. else
  263. {
  264. remote = new DirectConnect();
  265. proxyEP = null;
  266. }
  267. var session = new AsyncSession(remote);
  268. _currentRemoteSession = session;
  269. ProxyTimer proxyTimer = new ProxyTimer(_proxyTimeout);
  270. proxyTimer.AutoReset = false;
  271. proxyTimer.Elapsed += proxyConnectTimer_Elapsed;
  272. proxyTimer.Enabled = true;
  273. proxyTimer.Session = session;
  274. proxyTimer.DestEndPoint = SocketUtil.GetEndPoint(_server.server, _server.server_port);
  275. proxyTimer.Server = _server;
  276. _proxyConnected = false;
  277. // Connect to the proxy server.
  278. remote.BeginConnectProxy(proxyEP, ProxyConnectCallback, new AsyncSession<ProxyTimer>(remote, proxyTimer));
  279. }
  280. catch (Exception e)
  281. {
  282. Logging.LogUsefulException(e);
  283. Close();
  284. }
  285. }
  286. private void proxyConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
  287. {
  288. var timer = (ProxyTimer)sender;
  289. timer.Elapsed -= proxyConnectTimer_Elapsed;
  290. timer.Enabled = false;
  291. timer.Dispose();
  292. if (_proxyConnected || _destConnected || Closed)
  293. {
  294. return;
  295. }
  296. var proxy = timer.Session.Remote;
  297. Logging.Info($"Proxy {proxy.ProxyEndPoint} timed out");
  298. proxy.Close();
  299. Close();
  300. }
  301. private void ProxyConnectCallback(IAsyncResult ar)
  302. {
  303. Server server = null;
  304. if (Closed)
  305. {
  306. return;
  307. }
  308. try
  309. {
  310. var session = (AsyncSession<ProxyTimer>)ar.AsyncState;
  311. ProxyTimer timer = session.State;
  312. var destEndPoint = timer.DestEndPoint;
  313. server = timer.Server;
  314. timer.Elapsed -= proxyConnectTimer_Elapsed;
  315. timer.Enabled = false;
  316. timer.Dispose();
  317. var remote = session.Remote;
  318. // Complete the connection.
  319. remote.EndConnectProxy(ar);
  320. _proxyConnected = true;
  321. if (Config.isVerboseLogging)
  322. {
  323. if (!(remote is DirectConnect))
  324. {
  325. Logging.Info($"Socket connected to proxy {remote.ProxyEndPoint}");
  326. }
  327. }
  328. _startConnectTime = DateTime.Now;
  329. ServerTimer connectTimer = new ServerTimer(_serverTimeout);
  330. connectTimer.AutoReset = false;
  331. connectTimer.Elapsed += destConnectTimer_Elapsed;
  332. connectTimer.Enabled = true;
  333. connectTimer.Session = session;
  334. connectTimer.Server = server;
  335. _destConnected = false;
  336. // Connect to the remote endpoint.
  337. remote.BeginConnectDest(destEndPoint, ConnectCallback, new AsyncSession<ServerTimer>(session, connectTimer));
  338. }
  339. catch (ArgumentException)
  340. {
  341. }
  342. catch (Exception e)
  343. {
  344. Logging.LogUsefulException(e);
  345. Close();
  346. }
  347. }
  348. private void destConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
  349. {
  350. var timer = (ServerTimer)sender;
  351. timer.Elapsed -= destConnectTimer_Elapsed;
  352. timer.Enabled = false;
  353. timer.Dispose();
  354. if (_destConnected || Closed)
  355. {
  356. return;
  357. }
  358. var session = timer.Session;
  359. Server server = timer.Server;
  360. IStrategy strategy = _controller.GetCurrentStrategy();
  361. strategy?.SetFailure(server);
  362. Logging.Info($"{server.FriendlyName()} timed out");
  363. session.Remote.Close();
  364. Close();
  365. }
  366. private void ConnectCallback(IAsyncResult ar)
  367. {
  368. if (Closed) return;
  369. try
  370. {
  371. var session = (AsyncSession<ServerTimer>)ar.AsyncState;
  372. ServerTimer timer = session.State;
  373. _server = timer.Server;
  374. timer.Elapsed -= destConnectTimer_Elapsed;
  375. timer.Enabled = false;
  376. timer.Dispose();
  377. var remote = session.Remote;
  378. // Complete the connection.
  379. remote.EndConnectDest(ar);
  380. _destConnected = true;
  381. if (Config.isVerboseLogging)
  382. {
  383. Logging.Info($"Socket connected to ss server: {_server.FriendlyName()}");
  384. }
  385. var latency = DateTime.Now - _startConnectTime;
  386. IStrategy strategy = _controller.GetCurrentStrategy();
  387. strategy?.UpdateLatency(_server, latency);
  388. _tcprelay.UpdateLatency(_server, latency);
  389. OnServerConnected(session);
  390. }
  391. catch (ArgumentException)
  392. {
  393. }
  394. catch (Exception e)
  395. {
  396. if (_server != null)
  397. {
  398. IStrategy strategy = _controller.GetCurrentStrategy();
  399. strategy?.SetFailure(_server);
  400. }
  401. Logging.LogUsefulException(e);
  402. Close();
  403. }
  404. }
  405. protected void StartPipe(AsyncSession session)
  406. {
  407. if (Closed) return;
  408. try
  409. {
  410. _startReceivingTime = DateTime.Now;
  411. session.Remote.BeginReceive(RemoteRecvBuffer, 0, RecvSize, SocketFlags.None, PipeRemoteReceiveCallback, session);
  412. Connection.BeginReceive(ConnetionRecvBuffer, 0, RecvSize, SocketFlags.None, PipeConnectionReceiveCallback, session);
  413. }
  414. catch (Exception e)
  415. {
  416. Logging.LogUsefulException(e);
  417. Close();
  418. }
  419. }
  420. private void PipeRemoteReceiveCallback(IAsyncResult ar)
  421. {
  422. if (Closed) return;
  423. try
  424. {
  425. var session = (AsyncSession)ar.AsyncState;
  426. int bytesRead = session.Remote.EndReceive(ar);
  427. _totalRead += bytesRead;
  428. _tcprelay.UpdateInboundCounter(_server, bytesRead);
  429. if (bytesRead > 0)
  430. {
  431. lastActivity = DateTime.Now;
  432. int bytesToSend;
  433. lock (_decryptionLock)
  434. {
  435. _encryptor.Decrypt(RemoteRecvBuffer, bytesRead, _remoteSendBuffer, out bytesToSend);
  436. }
  437. Connection.BeginSend(_remoteSendBuffer, 0, bytesToSend, SocketFlags.None, PipeConnectionSendCallback, session);
  438. IStrategy strategy = _controller.GetCurrentStrategy();
  439. strategy?.UpdateLastRead(_server);
  440. }
  441. else
  442. {
  443. Connection.Shutdown(SocketShutdown.Send);
  444. _connectionShutdown = true;
  445. CheckClose();
  446. }
  447. }
  448. catch (Exception e)
  449. {
  450. Logging.LogUsefulException(e);
  451. Close();
  452. }
  453. }
  454. private void PipeConnectionReceiveCallback(IAsyncResult ar)
  455. {
  456. if (Closed) return;
  457. try
  458. {
  459. int bytesRead = Connection.EndReceive(ar);
  460. var session = (AsyncSession)ar.AsyncState;
  461. var remote = session.Remote;
  462. if (bytesRead > 0)
  463. {
  464. SendToServer(bytesRead, session);
  465. }
  466. else
  467. {
  468. remote.Shutdown(SocketShutdown.Send);
  469. _remoteShutdown = true;
  470. CheckClose();
  471. }
  472. }
  473. catch (Exception e)
  474. {
  475. Logging.LogUsefulException(e);
  476. Close();
  477. }
  478. }
  479. private void SendToServer(int length, AsyncSession session)
  480. {
  481. BeginSendToServer(length, session, PipeRemoteSendCallback);
  482. }
  483. private bool _serverHeaderSent;
  484. protected void BeginSendToServer(int length, AsyncSession session, AsyncCallback callback)
  485. {
  486. if (!_serverHeaderSent)
  487. {
  488. _serverHeaderSent = true;
  489. // Append socks5 header
  490. int len = Socks5Util.HeaderAddrLength(_destEndPoint);
  491. Array.Copy(ConnetionRecvBuffer, 0, ConnetionRecvBuffer, len, length);
  492. Socks5Util.FillHeaderAddr(ConnetionRecvBuffer, 0, _destEndPoint);
  493. length += len;
  494. }
  495. _totalWrite += length;
  496. int bytesToSend;
  497. lock (_encryptionLock)
  498. {
  499. _encryptor.Encrypt(ConnetionRecvBuffer, length, _connetionSendBuffer, out bytesToSend);
  500. }
  501. _tcprelay.UpdateOutboundCounter(_server, bytesToSend);
  502. _startSendingTime = DateTime.Now;
  503. session.Remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, callback, session);
  504. IStrategy strategy = _controller.GetCurrentStrategy();
  505. strategy?.UpdateLastWrite(_server);
  506. }
  507. protected AsyncSession EndSendToServer(IAsyncResult ar)
  508. {
  509. var session = (AsyncSession)ar.AsyncState;
  510. session.Remote.EndSend(ar);
  511. return session;
  512. }
  513. private void PipeRemoteSendCallback(IAsyncResult ar)
  514. {
  515. if (Closed) return;
  516. try
  517. {
  518. var session = EndSendToServer(ar);
  519. Connection.BeginReceive(ConnetionRecvBuffer, 0, RecvSize, SocketFlags.None, PipeConnectionReceiveCallback, session);
  520. }
  521. catch (Exception e)
  522. {
  523. Logging.LogUsefulException(e);
  524. Close();
  525. }
  526. }
  527. private void PipeConnectionSendCallback(IAsyncResult ar)
  528. {
  529. try
  530. {
  531. var session = (AsyncSession)ar.AsyncState;
  532. Connection.EndSend(ar);
  533. session.Remote.BeginReceive(RemoteRecvBuffer, 0, RecvSize, SocketFlags.None, PipeRemoteReceiveCallback, session);
  534. }
  535. catch (Exception e)
  536. {
  537. Logging.LogUsefulException(e);
  538. Close();
  539. }
  540. }
  541. }
  542. }