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

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