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.

Socks5Proxy.cs 10 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using System.Threading;
  6. using Shadowsocks.Controller;
  7. using Shadowsocks.Util.Sockets;
  8. namespace Shadowsocks.Proxy
  9. {
  10. public class Socks5Proxy : IProxy
  11. {
  12. private class FakeAsyncResult : IAsyncResult
  13. {
  14. public readonly Socks5State innerState;
  15. private readonly IAsyncResult r;
  16. public FakeAsyncResult(IAsyncResult orig, Socks5State state)
  17. {
  18. r = orig;
  19. innerState = state;
  20. }
  21. public bool IsCompleted => r.IsCompleted;
  22. public WaitHandle AsyncWaitHandle => r.AsyncWaitHandle;
  23. public object AsyncState => innerState.AsyncState;
  24. public bool CompletedSynchronously => r.CompletedSynchronously;
  25. }
  26. private class Socks5State
  27. {
  28. public AsyncCallback Callback { get; set; }
  29. public object AsyncState { get; set; }
  30. public int BytesToRead;
  31. public Exception ex { get; set; }
  32. }
  33. private WrappedSocket _remote = new WrappedSocket();
  34. private const int Socks5PktMaxSize = 4 + 16 + 2;
  35. private readonly byte[] _receiveBuffer = new byte[Socks5PktMaxSize];
  36. public EndPoint LocalEndPoint => _remote.LocalEndPoint;
  37. public EndPoint ProxyEndPoint { get; private set; }
  38. public EndPoint DestEndPoint { get; private set; }
  39. public void BeginConnectProxy(EndPoint remoteEP, AsyncCallback callback, object state)
  40. {
  41. var st = new Socks5State();
  42. st.Callback = callback;
  43. st.AsyncState = state;
  44. ProxyEndPoint = remoteEP;
  45. _remote.BeginConnect(remoteEP, ConnectCallback, st);
  46. }
  47. public void EndConnectProxy(IAsyncResult asyncResult)
  48. {
  49. var state = ((FakeAsyncResult)asyncResult).innerState;
  50. if (state.ex != null)
  51. {
  52. throw state.ex;
  53. }
  54. }
  55. public void BeginConnectDest(EndPoint destEndPoint, AsyncCallback callback, object state)
  56. {
  57. DestEndPoint = destEndPoint;
  58. byte[] request = null;
  59. byte atyp = 0;
  60. int port;
  61. var dep = destEndPoint as DnsEndPoint;
  62. if (dep != null)
  63. {
  64. // is a domain name, we will leave it to server
  65. atyp = 3; // DOMAINNAME
  66. var enc = Encoding.UTF8;
  67. var hostByteCount = enc.GetByteCount(dep.Host);
  68. request = new byte[4 + 1/*length byte*/ + hostByteCount + 2];
  69. request[4] = (byte)hostByteCount;
  70. enc.GetBytes(dep.Host, 0, dep.Host.Length, request, 5);
  71. port = dep.Port;
  72. }
  73. else
  74. {
  75. switch (DestEndPoint.AddressFamily)
  76. {
  77. case AddressFamily.InterNetwork:
  78. request = new byte[4 + 4 + 2];
  79. atyp = 1; // IP V4 address
  80. break;
  81. case AddressFamily.InterNetworkV6:
  82. request = new byte[4 + 16 + 2];
  83. atyp = 4; // IP V6 address
  84. break;
  85. default:
  86. throw new Exception(I18N.GetString("Proxy request failed"));
  87. }
  88. port = ((IPEndPoint) DestEndPoint).Port;
  89. var addr = ((IPEndPoint)DestEndPoint).Address.GetAddressBytes();
  90. Array.Copy(addr, 0, request, 4, request.Length - 4 - 2);
  91. }
  92. // 构造request包剩余部分
  93. request[0] = 5;
  94. request[1] = 1;
  95. request[2] = 0;
  96. request[3] = atyp;
  97. request[request.Length - 2] = (byte) ((port >> 8) & 0xff);
  98. request[request.Length - 1] = (byte) (port & 0xff);
  99. var st = new Socks5State();
  100. st.Callback = callback;
  101. st.AsyncState = state;
  102. _remote?.BeginSend(request, 0, request.Length, 0, Socks5RequestSendCallback, st);
  103. }
  104. public void EndConnectDest(IAsyncResult asyncResult)
  105. {
  106. var state = ((FakeAsyncResult)asyncResult).innerState;
  107. if (state.ex != null)
  108. {
  109. throw state.ex;
  110. }
  111. }
  112. public void BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback,
  113. object state)
  114. {
  115. _remote?.BeginSend(buffer, offset, size, socketFlags, callback, state);
  116. }
  117. public int EndSend(IAsyncResult asyncResult)
  118. {
  119. return _remote.EndSend(asyncResult);
  120. }
  121. public void BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback,
  122. object state)
  123. {
  124. _remote?.BeginReceive(buffer, offset, size, socketFlags, callback, state);
  125. }
  126. public int EndReceive(IAsyncResult asyncResult)
  127. {
  128. return _remote.EndReceive(asyncResult);
  129. }
  130. public void Shutdown(SocketShutdown how)
  131. {
  132. _remote?.Shutdown(how);
  133. }
  134. public void Close()
  135. {
  136. _remote?.Dispose();
  137. }
  138. private void ConnectCallback(IAsyncResult ar)
  139. {
  140. var state = (Socks5State) ar.AsyncState;
  141. try
  142. {
  143. _remote.EndConnect(ar);
  144. _remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
  145. byte[] handshake = {5, 1, 0};
  146. _remote.BeginSend(handshake, 0, handshake.Length, 0, Socks5HandshakeSendCallback, state);
  147. }
  148. catch (Exception ex)
  149. {
  150. state.ex = ex;
  151. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  152. }
  153. }
  154. private void Socks5HandshakeSendCallback(IAsyncResult ar)
  155. {
  156. var state = (Socks5State)ar.AsyncState;
  157. try
  158. {
  159. _remote.EndSend(ar);
  160. _remote.BeginReceive(_receiveBuffer, 0, 2, 0, Socks5HandshakeReceiveCallback, state);
  161. }
  162. catch (Exception ex)
  163. {
  164. state.ex = ex;
  165. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  166. }
  167. }
  168. private void Socks5HandshakeReceiveCallback(IAsyncResult ar)
  169. {
  170. Exception ex = null;
  171. var state = (Socks5State)ar.AsyncState;
  172. try
  173. {
  174. var bytesRead = _remote.EndReceive(ar);
  175. if (bytesRead >= 2)
  176. {
  177. if (_receiveBuffer[0] != 5 || _receiveBuffer[1] != 0)
  178. {
  179. ex = new Exception(I18N.GetString("Proxy handshake failed"));
  180. }
  181. }
  182. else
  183. {
  184. ex = new Exception(I18N.GetString("Proxy handshake failed"));
  185. }
  186. }
  187. catch (Exception ex2)
  188. {
  189. ex = ex2;
  190. }
  191. state.ex = ex;
  192. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  193. }
  194. private void Socks5RequestSendCallback(IAsyncResult ar)
  195. {
  196. var state = (Socks5State)ar.AsyncState;
  197. try
  198. {
  199. _remote.EndSend(ar);
  200. _remote.BeginReceive(_receiveBuffer, 0, 4, 0, Socks5ReplyReceiveCallback, state);
  201. }
  202. catch (Exception ex)
  203. {
  204. state.ex = ex;
  205. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  206. }
  207. }
  208. private void Socks5ReplyReceiveCallback(IAsyncResult ar)
  209. {
  210. var state = (Socks5State)ar.AsyncState;
  211. try
  212. {
  213. var bytesRead = _remote.EndReceive(ar);
  214. if (bytesRead >= 4)
  215. {
  216. if (_receiveBuffer[0] == 5 && _receiveBuffer[1] == 0)
  217. {
  218. // 跳过剩下的reply
  219. switch (_receiveBuffer[3]) // atyp
  220. {
  221. case 1:
  222. state.BytesToRead = 4 + 2;
  223. _remote.BeginReceive(_receiveBuffer, 0, 4 + 2, 0, Socks5ReplyReceiveCallback2, state);
  224. break;
  225. case 4:
  226. state.BytesToRead = 16 + 2;
  227. _remote.BeginReceive(_receiveBuffer, 0, 16 + 2, 0, Socks5ReplyReceiveCallback2, state);
  228. break;
  229. default:
  230. state.ex = new Exception(I18N.GetString("Proxy request failed"));
  231. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  232. break;
  233. }
  234. }
  235. else
  236. {
  237. state.ex = new Exception(I18N.GetString("Proxy request failed"));
  238. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  239. }
  240. }
  241. else
  242. {
  243. state.ex = new Exception(I18N.GetString("Proxy request failed"));
  244. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  245. }
  246. }
  247. catch (Exception ex)
  248. {
  249. state.ex = ex;
  250. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  251. }
  252. }
  253. private void Socks5ReplyReceiveCallback2(IAsyncResult ar)
  254. {
  255. Exception ex = null;
  256. var state = (Socks5State)ar.AsyncState;
  257. try
  258. {
  259. var bytesRead = _remote.EndReceive(ar);
  260. var bytesNeedSkip = state.BytesToRead;
  261. if (bytesRead < bytesNeedSkip)
  262. {
  263. ex = new Exception(I18N.GetString("Proxy request failed"));
  264. }
  265. }
  266. catch (Exception ex2)
  267. {
  268. ex = ex2;
  269. }
  270. state.ex = ex;
  271. state.Callback?.Invoke(new FakeAsyncResult(ar, state));
  272. }
  273. }
  274. }