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 37 kB

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
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
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
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Timers;
  7. using NLog;
  8. using Shadowsocks.Controller.Strategy;
  9. using Shadowsocks.Encryption;
  10. using Shadowsocks.Encryption.AEAD;
  11. using Shadowsocks.Encryption.Exception;
  12. using Shadowsocks.Model;
  13. using Shadowsocks.Proxy;
  14. using Shadowsocks.Util.Sockets;
  15. using static Shadowsocks.Encryption.EncryptorBase;
  16. namespace Shadowsocks.Controller
  17. {
  18. internal class TCPRelay : Listener.Service
  19. {
  20. public event EventHandler<SSTCPConnectedEventArgs> OnConnected;
  21. public event EventHandler<SSTransmitEventArgs> OnInbound;
  22. public event EventHandler<SSTransmitEventArgs> OnOutbound;
  23. public event EventHandler<SSRelayEventArgs> OnFailed;
  24. private static readonly Logger logger = LogManager.GetCurrentClassLogger();
  25. private readonly ShadowsocksController _controller;
  26. private DateTime _lastSweepTime;
  27. private readonly Configuration _config;
  28. public ISet<TCPHandler> Handlers { get; set; }
  29. public TCPRelay(ShadowsocksController controller, Configuration conf)
  30. {
  31. _controller = controller;
  32. _config = conf;
  33. Handlers = new HashSet<TCPHandler>();
  34. _lastSweepTime = DateTime.Now;
  35. }
  36. public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)
  37. {
  38. if (socket.ProtocolType != ProtocolType.Tcp
  39. || (length < 2 || firstPacket[0] != 5))
  40. {
  41. return false;
  42. }
  43. socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  44. TCPHandler handler = new TCPHandler(_controller, _config, socket);
  45. handler.OnConnected += OnConnected;
  46. handler.OnInbound += OnInbound;
  47. handler.OnOutbound += OnOutbound;
  48. handler.OnFailed += OnFailed;
  49. handler.OnClosed += (h, arg) =>
  50. {
  51. lock (Handlers)
  52. {
  53. Handlers.Remove(handler);
  54. }
  55. };
  56. IList<TCPHandler> handlersToClose = new List<TCPHandler>();
  57. lock (Handlers)
  58. {
  59. Handlers.Add(handler);
  60. DateTime now = DateTime.Now;
  61. if (now - _lastSweepTime > TimeSpan.FromSeconds(1))
  62. {
  63. _lastSweepTime = now;
  64. foreach (TCPHandler handler1 in Handlers)
  65. {
  66. if (now - handler1.lastActivity > TimeSpan.FromSeconds(900))
  67. {
  68. handlersToClose.Add(handler1);
  69. }
  70. }
  71. }
  72. }
  73. foreach (TCPHandler handler1 in handlersToClose)
  74. {
  75. logger.Debug("Closing timed out TCP connection.");
  76. handler1.Close();
  77. }
  78. /*
  79. * Start after we put it into Handlers set. Otherwise if it failed in handler.Start()
  80. * then it will call handler.Close() before we add it into the set.
  81. * Then the handler will never release until the next Handle call. Sometimes it will
  82. * cause odd problems (especially during memory profiling).
  83. */
  84. handler.Start(firstPacket, length);
  85. return true;
  86. }
  87. public override void Stop()
  88. {
  89. List<TCPHandler> handlersToClose = new List<TCPHandler>();
  90. lock (Handlers)
  91. {
  92. handlersToClose.AddRange(Handlers);
  93. }
  94. handlersToClose.ForEach(h => h.Close());
  95. }
  96. }
  97. public class SSRelayEventArgs : EventArgs
  98. {
  99. public readonly Server server;
  100. public SSRelayEventArgs(Server server)
  101. {
  102. this.server = server;
  103. }
  104. }
  105. public class SSTransmitEventArgs : SSRelayEventArgs
  106. {
  107. public readonly long length;
  108. public SSTransmitEventArgs(Server server, long length) : base(server)
  109. {
  110. this.length = length;
  111. }
  112. }
  113. public class SSTCPConnectedEventArgs : SSRelayEventArgs
  114. {
  115. public readonly TimeSpan latency;
  116. public SSTCPConnectedEventArgs(Server server, TimeSpan latency) : base(server)
  117. {
  118. this.latency = latency;
  119. }
  120. }
  121. internal class TCPHandler
  122. {
  123. public event EventHandler<SSTCPConnectedEventArgs> OnConnected;
  124. public event EventHandler<SSTransmitEventArgs> OnInbound;
  125. public event EventHandler<SSTransmitEventArgs> OnOutbound;
  126. public event EventHandler<SSRelayEventArgs> OnClosed;
  127. public event EventHandler<SSRelayEventArgs> OnFailed;
  128. private class AsyncSession
  129. {
  130. public IProxy Remote { get; }
  131. public AsyncSession(IProxy remote)
  132. {
  133. Remote = remote;
  134. }
  135. }
  136. private class AsyncSession<T> : AsyncSession
  137. {
  138. public T State { get; set; }
  139. public AsyncSession(IProxy remote, T state) : base(remote)
  140. {
  141. State = state;
  142. }
  143. public AsyncSession(AsyncSession session, T state) : base(session.Remote)
  144. {
  145. State = state;
  146. }
  147. }
  148. private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
  149. private readonly int _serverTimeout;
  150. private readonly int _proxyTimeout;
  151. // each recv size.
  152. public const int RecvSize = 2048;
  153. // overhead of one chunk, reserved for AEAD ciphers
  154. public const int ChunkOverheadSize = 16 * 2 /* two tags */ + AEADEncryptor.CHUNK_LEN_BYTES;
  155. // max chunk size
  156. public const uint MaxChunkSize = AEADEncryptor.CHUNK_LEN_MASK + AEADEncryptor.CHUNK_LEN_BYTES + 16 * 2;
  157. // In general, the ciphertext length, we should take overhead into account
  158. public const int BufferSize = RecvSize + (int)MaxChunkSize + 32 /* max salt len */;
  159. public DateTime lastActivity;
  160. private readonly ShadowsocksController _controller;
  161. private readonly ProxyConfig _config;
  162. private readonly Socket _connection;
  163. private IEncryptor _encryptor;
  164. private Server _server;
  165. private AsyncSession _currentRemoteSession;
  166. private bool _proxyConnected;
  167. private bool _destConnected;
  168. private byte _command;
  169. private byte[] _firstPacket;
  170. private int _firstPacketLength;
  171. private const int CMD_CONNECT = 0x01;
  172. private const int CMD_BIND = 0x02;
  173. private const int CMD_UDP_ASSOC = 0x03;
  174. private int _addrBufLength = -1;
  175. private int _totalRead = 0;
  176. private int _totalWrite = 0;
  177. // remote -> local proxy (ciphertext, before decrypt)
  178. private readonly byte[] _remoteRecvBuffer = new byte[BufferSize];
  179. // client -> local proxy (plaintext, before encrypt)
  180. private readonly byte[] _connetionRecvBuffer = new byte[BufferSize];
  181. // local proxy -> remote (plaintext, after decrypt)
  182. private readonly byte[] _remoteSendBuffer = new byte[BufferSize];
  183. // local proxy -> client (ciphertext, before decrypt)
  184. private readonly byte[] _connetionSendBuffer = new byte[BufferSize];
  185. private bool _connectionShutdown = false;
  186. private bool _remoteShutdown = false;
  187. private bool _closed = false;
  188. // instance-based lock without static
  189. private readonly object _encryptionLock = new object();
  190. private readonly object _decryptionLock = new object();
  191. private readonly object _closeConnLock = new object();
  192. private DateTime _startConnectTime;
  193. private DateTime _startReceivingTime;
  194. private DateTime _startSendingTime;
  195. private EndPoint _destEndPoint = null;
  196. // TODO: decouple controller
  197. public TCPHandler(ShadowsocksController controller, Configuration config, Socket socket)
  198. {
  199. _controller = controller;
  200. _config = config.proxy;
  201. _connection = socket;
  202. _proxyTimeout = config.proxy.proxyTimeout * 1000;
  203. _serverTimeout = config.GetCurrentServer().timeout * 1000;
  204. lastActivity = DateTime.Now;
  205. }
  206. public void CreateRemote()
  207. {
  208. Server server = _controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)_connection.RemoteEndPoint,
  209. _destEndPoint);
  210. if (server == null || server.server == "")
  211. {
  212. throw new ArgumentException("No server configured");
  213. }
  214. _encryptor = EncryptorFactory.GetEncryptor(server.method, server.password);
  215. _server = server;
  216. /* prepare address buffer length for AEAD */
  217. Logger.Trace($"_addrBufLength={_addrBufLength}");
  218. _encryptor.AddrBufLength = _addrBufLength;
  219. }
  220. public void Start(byte[] firstPacket, int length)
  221. {
  222. _firstPacket = firstPacket;
  223. _firstPacketLength = length;
  224. HandshakeReceive();
  225. }
  226. private void CheckClose()
  227. {
  228. if (_connectionShutdown && _remoteShutdown)
  229. {
  230. Close();
  231. }
  232. }
  233. private void ErrorClose(Exception e)
  234. {
  235. Logger.LogUsefulException(e);
  236. Close();
  237. }
  238. public void Close()
  239. {
  240. lock (_closeConnLock)
  241. {
  242. if (_closed)
  243. {
  244. return;
  245. }
  246. _closed = true;
  247. }
  248. OnClosed?.Invoke(this, new SSRelayEventArgs(_server));
  249. try
  250. {
  251. _connection.Shutdown(SocketShutdown.Both);
  252. _connection.Close();
  253. }
  254. catch (Exception e)
  255. {
  256. Logger.LogUsefulException(e);
  257. }
  258. if (_currentRemoteSession != null)
  259. {
  260. try
  261. {
  262. IProxy remote = _currentRemoteSession.Remote;
  263. remote.Shutdown(SocketShutdown.Both);
  264. remote.Close();
  265. }
  266. catch (Exception e)
  267. {
  268. Logger.LogUsefulException(e);
  269. }
  270. }
  271. lock (_encryptionLock)
  272. {
  273. lock (_decryptionLock)
  274. {
  275. _encryptor?.Dispose();
  276. }
  277. }
  278. }
  279. private void HandshakeReceive()
  280. {
  281. if (_closed)
  282. {
  283. return;
  284. }
  285. try
  286. {
  287. int bytesRead = _firstPacketLength;
  288. if (bytesRead > 1)
  289. {
  290. byte[] response = { 5, 0 };
  291. if (_firstPacket[0] != 5)
  292. {
  293. // reject socks 4
  294. response = new byte[] { 0, 91 };
  295. Logger.Error("socks 5 protocol error");
  296. }
  297. _connection.BeginSend(response, 0, response.Length, SocketFlags.None,
  298. HandshakeSendCallback, null);
  299. }
  300. else
  301. {
  302. Close();
  303. }
  304. }
  305. catch (Exception e)
  306. {
  307. ErrorClose(e);
  308. }
  309. }
  310. private void HandshakeSendCallback(IAsyncResult ar)
  311. {
  312. if (_closed)
  313. {
  314. return;
  315. }
  316. try
  317. {
  318. _connection.EndSend(ar);
  319. // +-----+-----+-------+------+----------+----------+
  320. // | VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
  321. // +-----+-----+-------+------+----------+----------+
  322. // | 1 | 1 | X'00' | 1 | Variable | 2 |
  323. // +-----+-----+-------+------+----------+----------+
  324. // Skip first 3 bytes, and read 2 more bytes to analysis the address.
  325. // 2 more bytes is designed if address is domain then we don't need to read once more to get the addr length.
  326. // validate is unnecessary, we did it in first packet, but we can do it in future version
  327. _connection.BeginReceive(_connetionRecvBuffer, 0, 3 + ADDR_ATYP_LEN + 1, SocketFlags.None,
  328. AddressReceiveCallback, null);
  329. }
  330. catch (Exception e)
  331. {
  332. ErrorClose(e);
  333. }
  334. }
  335. private void AddressReceiveCallback(IAsyncResult ar)
  336. {
  337. if (_closed)
  338. {
  339. return;
  340. }
  341. try
  342. {
  343. int bytesRead = _connection.EndReceive(ar);
  344. if (bytesRead >= 5)
  345. {
  346. _command = _connetionRecvBuffer[1];
  347. switch (_command)
  348. {
  349. case CMD_CONNECT:
  350. // +----+-----+-------+------+----------+----------+
  351. // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
  352. // +----+-----+-------+------+----------+----------+
  353. // | 1 | 1 | X'00' | 1 | Variable | 2 |
  354. // +----+-----+-------+------+----------+----------+
  355. byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
  356. _connection.BeginSend(response, 0, response.Length, SocketFlags.None,
  357. ConnectResponseCallback, null);
  358. break;
  359. case CMD_UDP_ASSOC:
  360. ReadAddress(HandleUDPAssociate);
  361. break;
  362. case CMD_BIND: // not implemented
  363. default:
  364. Logger.Debug("Unsupported CMD=" + _command);
  365. Close();
  366. break;
  367. }
  368. }
  369. else
  370. {
  371. Logger.Debug(
  372. "failed to recv data in Shadowsocks.Controller.TCPHandler.handshakeReceive2Callback()");
  373. Close();
  374. }
  375. }
  376. catch (Exception e)
  377. {
  378. ErrorClose(e);
  379. }
  380. }
  381. private void ConnectResponseCallback(IAsyncResult ar)
  382. {
  383. try
  384. {
  385. _connection.EndSend(ar);
  386. ReadAddress(StartConnect);
  387. }
  388. catch (Exception e)
  389. {
  390. ErrorClose(e);
  391. }
  392. }
  393. private void ReadAddress(Action onSuccess)
  394. {
  395. int atyp = _connetionRecvBuffer[3];
  396. switch (atyp)
  397. {
  398. case ATYP_IPv4: // IPv4 address, 4 bytes
  399. ReadAddress(4 + ADDR_PORT_LEN - 1, onSuccess);
  400. break;
  401. case ATYP_DOMAIN: // domain name, length + str
  402. int len = _connetionRecvBuffer[4];
  403. ReadAddress(len + ADDR_PORT_LEN, onSuccess);
  404. break;
  405. case ATYP_IPv6: // IPv6 address, 16 bytes
  406. ReadAddress(16 + ADDR_PORT_LEN - 1, onSuccess);
  407. break;
  408. default:
  409. Logger.Debug("Unsupported ATYP=" + atyp);
  410. Close();
  411. break;
  412. }
  413. }
  414. private void ReadAddress(int bytesRemain, Action onSuccess)
  415. {
  416. // drop [ VER | CMD | RSV ]
  417. Array.Copy(_connetionRecvBuffer, 3, _connetionRecvBuffer, 0, ADDR_ATYP_LEN + 1);
  418. // Read the remain address bytes
  419. _connection.BeginReceive(_connetionRecvBuffer, 2, RecvSize - 2, SocketFlags.None, OnAddressFullyRead,
  420. new object[] { bytesRemain, onSuccess });
  421. }
  422. private void OnAddressFullyRead(IAsyncResult ar)
  423. {
  424. if (_closed)
  425. {
  426. return;
  427. }
  428. try
  429. {
  430. int bytesRead = _connection.EndReceive(ar);
  431. object[] states = (object[])ar.AsyncState;
  432. int bytesRemain = (int)states[0];
  433. Action onSuccess = (Action)states[1];
  434. if (bytesRead >= bytesRemain)
  435. {
  436. _firstPacketLength = bytesRead + 2;
  437. int atyp = _connetionRecvBuffer[0];
  438. string dstAddr = "Unknown";
  439. int dstPort = -1;
  440. switch (atyp)
  441. {
  442. case ATYP_IPv4: // IPv4 address, 4 bytes
  443. dstAddr = new IPAddress(_connetionRecvBuffer.Skip(1).Take(4).ToArray()).ToString();
  444. dstPort = (_connetionRecvBuffer[5] << 8) + _connetionRecvBuffer[6];
  445. _addrBufLength = ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
  446. break;
  447. case ATYP_DOMAIN: // domain name, length + str
  448. int len = _connetionRecvBuffer[1];
  449. dstAddr = System.Text.Encoding.UTF8.GetString(_connetionRecvBuffer, 2, len);
  450. dstPort = (_connetionRecvBuffer[len + 2] << 8) + _connetionRecvBuffer[len + 3];
  451. _addrBufLength = ADDR_ATYP_LEN + 1 + len + ADDR_PORT_LEN;
  452. break;
  453. case ATYP_IPv6: // IPv6 address, 16 bytes
  454. dstAddr = $"[{new IPAddress(_connetionRecvBuffer.Skip(1).Take(16).ToArray())}]";
  455. dstPort = (_connetionRecvBuffer[17] << 8) + _connetionRecvBuffer[18];
  456. _addrBufLength = ADDR_ATYP_LEN + 16 + ADDR_PORT_LEN;
  457. break;
  458. }
  459. Logger.Debug($"connect to {dstAddr}:{dstPort}");
  460. _destEndPoint = SocketUtil.GetEndPoint(dstAddr, dstPort);
  461. onSuccess.Invoke(); /* StartConnect() */
  462. }
  463. else
  464. {
  465. Logger.Debug("failed to recv data in Shadowsocks.Controller.TCPHandler.OnAddressFullyRead()");
  466. Close();
  467. }
  468. }
  469. catch (Exception e)
  470. {
  471. ErrorClose(e);
  472. }
  473. }
  474. private void HandleUDPAssociate()
  475. {
  476. IPEndPoint endPoint = (IPEndPoint)_connection.LocalEndPoint;
  477. byte[] address = endPoint.Address.GetAddressBytes();
  478. int port = endPoint.Port;
  479. byte[] response = new byte[4 + address.Length + ADDR_PORT_LEN];
  480. response[0] = 5;
  481. switch (endPoint.AddressFamily)
  482. {
  483. case AddressFamily.InterNetwork:
  484. response[3] = ATYP_IPv4;
  485. break;
  486. case AddressFamily.InterNetworkV6:
  487. response[3] = ATYP_IPv6;
  488. break;
  489. }
  490. address.CopyTo(response, 4);
  491. response[response.Length - 1] = (byte)(port & 0xFF);
  492. response[response.Length - 2] = (byte)((port >> 8) & 0xFF);
  493. _connection.BeginSend(response, 0, response.Length, SocketFlags.None, ReadAll, true);
  494. }
  495. private void ReadAll(IAsyncResult ar)
  496. {
  497. if (_closed)
  498. {
  499. return;
  500. }
  501. try
  502. {
  503. if (ar.AsyncState != null)
  504. {
  505. _connection.EndSend(ar);
  506. _connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None,
  507. ReadAll, null);
  508. }
  509. else
  510. {
  511. int bytesRead = _connection.EndReceive(ar);
  512. if (bytesRead > 0)
  513. {
  514. _connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None,
  515. ReadAll, null);
  516. }
  517. else
  518. {
  519. Close();
  520. }
  521. }
  522. }
  523. catch (Exception e)
  524. {
  525. ErrorClose(e);
  526. }
  527. }
  528. // inner class
  529. private class ProxyTimer : Timer
  530. {
  531. public AsyncSession Session;
  532. public EndPoint DestEndPoint;
  533. public Server Server;
  534. public ProxyTimer(int p) : base(p)
  535. {
  536. }
  537. }
  538. private class ServerTimer : Timer
  539. {
  540. public AsyncSession Session;
  541. public Server Server;
  542. public ServerTimer(int p) : base(p)
  543. {
  544. }
  545. }
  546. private void StartConnect()
  547. {
  548. try
  549. {
  550. CreateRemote();
  551. // Setting up proxy
  552. IProxy remote;
  553. EndPoint proxyEP = null;
  554. EndPoint serverEP = SocketUtil.GetEndPoint(_server.server, _server.server_port);
  555. EndPoint pluginEP = _controller.GetPluginLocalEndPointIfConfigured(_server);
  556. if (pluginEP != null)
  557. {
  558. serverEP = pluginEP;
  559. remote = new DirectConnect();
  560. }
  561. else if (_config.useProxy)
  562. {
  563. switch (_config.proxyType)
  564. {
  565. case ProxyConfig.PROXY_SOCKS5:
  566. remote = new Socks5Proxy();
  567. break;
  568. case ProxyConfig.PROXY_HTTP:
  569. remote = new HttpProxy();
  570. break;
  571. default:
  572. throw new NotSupportedException("Unknown forward proxy.");
  573. }
  574. proxyEP = SocketUtil.GetEndPoint(_config.proxyServer, _config.proxyPort);
  575. }
  576. else
  577. {
  578. remote = new DirectConnect();
  579. }
  580. AsyncSession session = new AsyncSession(remote);
  581. lock (_closeConnLock)
  582. {
  583. if (_closed)
  584. {
  585. remote.Close();
  586. return;
  587. }
  588. _currentRemoteSession = session;
  589. }
  590. ProxyTimer proxyTimer = new ProxyTimer(_proxyTimeout) { AutoReset = false };
  591. proxyTimer.Elapsed += ProxyConnectTimer_Elapsed;
  592. proxyTimer.Enabled = true;
  593. proxyTimer.Session = session;
  594. proxyTimer.DestEndPoint = serverEP;
  595. proxyTimer.Server = _server;
  596. _proxyConnected = false;
  597. // Connect to the proxy server.
  598. remote.BeginConnectProxy(proxyEP, ProxyConnectCallback,
  599. new AsyncSession<ProxyTimer>(remote, proxyTimer));
  600. }
  601. catch (Exception e)
  602. {
  603. ErrorClose(e);
  604. }
  605. }
  606. private void ProxyConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
  607. {
  608. ProxyTimer timer = (ProxyTimer)sender;
  609. timer.Elapsed -= ProxyConnectTimer_Elapsed;
  610. timer.Enabled = false;
  611. timer.Dispose();
  612. if (_proxyConnected || _destConnected || _closed)
  613. {
  614. return;
  615. }
  616. IProxy proxy = timer.Session.Remote;
  617. Logger.Info($"Proxy {proxy.ProxyEndPoint} timed out");
  618. proxy.Close();
  619. Close();
  620. }
  621. private void ProxyConnectCallback(IAsyncResult ar)
  622. {
  623. if (_closed)
  624. {
  625. return;
  626. }
  627. try
  628. {
  629. AsyncSession<ProxyTimer> session = (AsyncSession<ProxyTimer>)ar.AsyncState;
  630. ProxyTimer timer = session.State;
  631. EndPoint destEndPoint = timer.DestEndPoint;
  632. Server server = timer.Server;
  633. timer.Elapsed -= ProxyConnectTimer_Elapsed;
  634. timer.Enabled = false;
  635. timer.Dispose();
  636. IProxy remote = session.Remote;
  637. // Complete the connection.
  638. remote.EndConnectProxy(ar);
  639. _proxyConnected = true;
  640. if (!(remote is DirectConnect))
  641. {
  642. Logger.Debug($"Socket connected to proxy {remote.ProxyEndPoint}");
  643. }
  644. _startConnectTime = DateTime.Now;
  645. ServerTimer connectTimer = new ServerTimer(_serverTimeout) { AutoReset = false };
  646. connectTimer.Elapsed += DestConnectTimer_Elapsed;
  647. connectTimer.Enabled = true;
  648. connectTimer.Session = session;
  649. connectTimer.Server = server;
  650. _destConnected = false;
  651. NetworkCredential auth = null;
  652. if (_config.useAuth)
  653. {
  654. auth = new NetworkCredential(_config.authUser, _config.authPwd);
  655. }
  656. // Connect to the remote endpoint.
  657. remote.BeginConnectDest(destEndPoint, ConnectCallback,
  658. new AsyncSession<ServerTimer>(session, connectTimer), auth);
  659. }
  660. catch (ArgumentException)
  661. {
  662. }
  663. catch (Exception e)
  664. {
  665. ErrorClose(e);
  666. }
  667. }
  668. private void DestConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
  669. {
  670. ServerTimer timer = (ServerTimer)sender;
  671. timer.Elapsed -= DestConnectTimer_Elapsed;
  672. timer.Enabled = false;
  673. timer.Dispose();
  674. if (_destConnected || _closed)
  675. {
  676. return;
  677. }
  678. AsyncSession session = timer.Session;
  679. Server server = timer.Server;
  680. OnFailed?.Invoke(this, new SSRelayEventArgs(_server));
  681. Logger.Info($"{server.ToString()} timed out");
  682. session.Remote.Close();
  683. Close();
  684. }
  685. private void ConnectCallback(IAsyncResult ar)
  686. {
  687. if (_closed)
  688. {
  689. return;
  690. }
  691. try
  692. {
  693. AsyncSession<ServerTimer> session = (AsyncSession<ServerTimer>)ar.AsyncState;
  694. ServerTimer timer = session.State;
  695. _server = timer.Server;
  696. timer.Elapsed -= DestConnectTimer_Elapsed;
  697. timer.Enabled = false;
  698. timer.Dispose();
  699. IProxy remote = session.Remote;
  700. // Complete the connection.
  701. remote.EndConnectDest(ar);
  702. _destConnected = true;
  703. Logger.Debug($"Socket connected to ss server: {_server.ToString()}");
  704. TimeSpan latency = DateTime.Now - _startConnectTime;
  705. OnConnected?.Invoke(this, new SSTCPConnectedEventArgs(_server, latency));
  706. StartPipe(session);
  707. }
  708. catch (ArgumentException)
  709. {
  710. }
  711. catch (Exception e)
  712. {
  713. if (_server != null)
  714. {
  715. OnFailed?.Invoke(this, new SSRelayEventArgs(_server));
  716. }
  717. ErrorClose(e);
  718. }
  719. }
  720. private void TryReadAvailableData()
  721. {
  722. int available = Math.Min(_connection.Available, RecvSize - _firstPacketLength);
  723. if (available > 0)
  724. {
  725. int size = _connection.Receive(_connetionRecvBuffer, _firstPacketLength, available,
  726. SocketFlags.None);
  727. _firstPacketLength += size;
  728. }
  729. }
  730. private void StartPipe(AsyncSession session)
  731. {
  732. if (_closed)
  733. {
  734. return;
  735. }
  736. try
  737. {
  738. _startReceivingTime = DateTime.Now;
  739. session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None,
  740. PipeRemoteReceiveCallback, session);
  741. TryReadAvailableData();
  742. Logger.Trace($"_firstPacketLength = {_firstPacketLength}");
  743. SendToServer(_firstPacketLength, session);
  744. }
  745. catch (Exception e)
  746. {
  747. ErrorClose(e);
  748. }
  749. }
  750. private void PipeRemoteReceiveCallback(IAsyncResult ar)
  751. {
  752. if (_closed)
  753. {
  754. return;
  755. }
  756. try
  757. {
  758. AsyncSession session = (AsyncSession)ar.AsyncState;
  759. int bytesRead = session.Remote.EndReceive(ar);
  760. _totalRead += bytesRead;
  761. OnInbound?.Invoke(this, new SSTransmitEventArgs(_server, bytesRead));
  762. if (bytesRead > 0)
  763. {
  764. lastActivity = DateTime.Now;
  765. int bytesToSend = -1;
  766. lock (_decryptionLock)
  767. {
  768. try
  769. {
  770. _encryptor.Decrypt(_remoteRecvBuffer, bytesRead, _remoteSendBuffer, out bytesToSend);
  771. }
  772. catch (CryptoErrorException)
  773. {
  774. Logger.Error("decryption error");
  775. Close();
  776. return;
  777. }
  778. }
  779. if (bytesToSend == 0)
  780. {
  781. // need more to decrypt
  782. Logger.Trace("Need more to decrypt");
  783. session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None,
  784. PipeRemoteReceiveCallback, session);
  785. return;
  786. }
  787. Logger.Trace($"start sending {bytesToSend}");
  788. _connection.BeginSend(_remoteSendBuffer, 0, bytesToSend, SocketFlags.None,
  789. PipeConnectionSendCallback, new object[] { session, bytesToSend });
  790. }
  791. else
  792. {
  793. _connection.Shutdown(SocketShutdown.Send);
  794. _connectionShutdown = true;
  795. CheckClose();
  796. }
  797. }
  798. catch (Exception e)
  799. {
  800. ErrorClose(e);
  801. }
  802. }
  803. private void PipeConnectionReceiveCallback(IAsyncResult ar)
  804. {
  805. if (_closed)
  806. {
  807. return;
  808. }
  809. try
  810. {
  811. int bytesRead = _connection.EndReceive(ar);
  812. AsyncSession session = (AsyncSession)ar.AsyncState;
  813. IProxy remote = session.Remote;
  814. if (bytesRead > 0)
  815. {
  816. SendToServer(bytesRead, session);
  817. }
  818. else
  819. {
  820. remote.Shutdown(SocketShutdown.Send);
  821. _remoteShutdown = true;
  822. CheckClose();
  823. }
  824. }
  825. catch (Exception e)
  826. {
  827. ErrorClose(e);
  828. }
  829. }
  830. private void SendToServer(int length, AsyncSession session)
  831. {
  832. _totalWrite += length;
  833. int bytesToSend;
  834. lock (_encryptionLock)
  835. {
  836. try
  837. {
  838. _encryptor.Encrypt(_connetionRecvBuffer, length, _connetionSendBuffer, out bytesToSend);
  839. }
  840. catch (CryptoErrorException)
  841. {
  842. Logger.Debug("encryption error");
  843. Close();
  844. return;
  845. }
  846. }
  847. OnOutbound?.Invoke(this, new SSTransmitEventArgs(_server, bytesToSend));
  848. _startSendingTime = DateTime.Now;
  849. session.Remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None,
  850. PipeRemoteSendCallback, new object[] { session, bytesToSend });
  851. }
  852. private void PipeRemoteSendCallback(IAsyncResult ar)
  853. {
  854. if (_closed)
  855. {
  856. return;
  857. }
  858. try
  859. {
  860. object[] container = (object[])ar.AsyncState;
  861. AsyncSession session = (AsyncSession)container[0];
  862. int bytesShouldSend = (int)container[1];
  863. int bytesSent = session.Remote.EndSend(ar);
  864. if (bytesSent > 0)
  865. {
  866. lastActivity = DateTime.Now;
  867. }
  868. int bytesRemaining = bytesShouldSend - bytesSent;
  869. if (bytesRemaining > 0)
  870. {
  871. Logger.Info("reconstruct _connetionSendBuffer to re-send");
  872. Buffer.BlockCopy(_connetionSendBuffer, bytesSent, _connetionSendBuffer, 0, bytesRemaining);
  873. session.Remote.BeginSend(_connetionSendBuffer, 0, bytesRemaining, SocketFlags.None,
  874. PipeRemoteSendCallback, new object[] { session, bytesRemaining });
  875. return;
  876. }
  877. _connection.BeginReceive(_connetionRecvBuffer, 0, RecvSize, SocketFlags.None,
  878. PipeConnectionReceiveCallback, session);
  879. }
  880. catch (Exception e)
  881. {
  882. ErrorClose(e);
  883. }
  884. }
  885. // In general, we assume there is no delay between local proxy and client, add this for sanity
  886. private void PipeConnectionSendCallback(IAsyncResult ar)
  887. {
  888. try
  889. {
  890. object[] container = (object[])ar.AsyncState;
  891. AsyncSession session = (AsyncSession)container[0];
  892. int bytesShouldSend = (int)container[1];
  893. int bytesSent = _connection.EndSend(ar);
  894. int bytesRemaining = bytesShouldSend - bytesSent;
  895. if (bytesRemaining > 0)
  896. {
  897. Logger.Info("reconstruct _remoteSendBuffer to re-send");
  898. Buffer.BlockCopy(_remoteSendBuffer, bytesSent, _remoteSendBuffer, 0, bytesRemaining);
  899. _connection.BeginSend(_remoteSendBuffer, 0, bytesRemaining, SocketFlags.None,
  900. PipeConnectionSendCallback, new object[] { session, bytesRemaining });
  901. return;
  902. }
  903. session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None,
  904. PipeRemoteReceiveCallback, session);
  905. }
  906. catch (Exception e)
  907. {
  908. ErrorClose(e);
  909. }
  910. }
  911. }
  912. }