An attempt at adding UDP support to aiosocks. Untested due to lack of server support.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

294 lines
10 KiB

  1. import pytest
  2. import aiosocks
  3. import aiohttp
  4. import os
  5. import ssl
  6. from aiohttp import web
  7. from aiohttp.test_utils import RawTestServer
  8. from aiosocks.test_utils import FakeSocksSrv, FakeSocks4Srv
  9. from aiosocks.connector import ProxyConnector, ProxyClientRequest
  10. async def test_socks4_connect_success(loop):
  11. pld = b'\x00\x5a\x04W\x01\x01\x01\x01test'
  12. async with FakeSocksSrv(loop, pld) as srv:
  13. addr = aiosocks.Socks4Addr('127.0.0.1', srv.port)
  14. auth = aiosocks.Socks4Auth('usr')
  15. dst = ('python.org', 80)
  16. transport, protocol = await aiosocks.create_connection(
  17. None, addr, auth, dst, loop=loop)
  18. assert protocol.proxy_sockname == ('1.1.1.1', 1111)
  19. data = await protocol._stream_reader.read(4)
  20. assert data == b'test'
  21. transport.close()
  22. async def test_socks4_invalid_data(loop):
  23. pld = b'\x01\x5a\x04W\x01\x01\x01\x01'
  24. async with FakeSocksSrv(loop, pld) as srv:
  25. addr = aiosocks.Socks4Addr('127.0.0.1', srv.port)
  26. auth = aiosocks.Socks4Auth('usr')
  27. dst = ('python.org', 80)
  28. with pytest.raises(aiosocks.SocksError) as ct:
  29. await aiosocks.create_connection(
  30. None, addr, auth, dst, loop=loop)
  31. assert 'invalid data' in str(ct)
  32. async def test_socks4_srv_error(loop):
  33. pld = b'\x00\x5b\x04W\x01\x01\x01\x01'
  34. async with FakeSocksSrv(loop, pld) as srv:
  35. addr = aiosocks.Socks4Addr('127.0.0.1', srv.port)
  36. auth = aiosocks.Socks4Auth('usr')
  37. dst = ('python.org', 80)
  38. with pytest.raises(aiosocks.SocksError) as ct:
  39. await aiosocks.create_connection(
  40. None, addr, auth, dst, loop=loop)
  41. assert '0x5b' in str(ct)
  42. async def test_socks5_connect_success_anonymous(loop):
  43. pld = b'\x05\x00\x05\x00\x00\x01\x01\x01\x01\x01\x04Wtest'
  44. async with FakeSocksSrv(loop, pld) as srv:
  45. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  46. auth = aiosocks.Socks5Auth('usr', 'pwd')
  47. dst = ('python.org', 80)
  48. transport, protocol = await aiosocks.create_connection(
  49. None, addr, auth, dst, loop=loop)
  50. assert protocol.proxy_sockname == ('1.1.1.1', 1111)
  51. data = await protocol._stream_reader.read(4)
  52. assert data == b'test'
  53. transport.close()
  54. async def test_socks5_connect_success_usr_pwd(loop):
  55. pld = b'\x05\x02\x01\x00\x05\x00\x00\x01\x01\x01\x01\x01\x04Wtest'
  56. async with FakeSocksSrv(loop, pld) as srv:
  57. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  58. auth = aiosocks.Socks5Auth('usr', 'pwd')
  59. dst = ('python.org', 80)
  60. transport, protocol = await aiosocks.create_connection(
  61. None, addr, auth, dst, loop=loop)
  62. assert protocol.proxy_sockname == ('1.1.1.1', 1111)
  63. data = await protocol._stream_reader.read(4)
  64. assert data == b'test'
  65. transport.close()
  66. async def test_socks5_auth_ver_err(loop):
  67. async with FakeSocksSrv(loop, b'\x04\x02') as srv:
  68. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  69. auth = aiosocks.Socks5Auth('usr', 'pwd')
  70. dst = ('python.org', 80)
  71. with pytest.raises(aiosocks.SocksError) as ct:
  72. await aiosocks.create_connection(
  73. None, addr, auth, dst, loop=loop)
  74. assert 'invalid version' in str(ct)
  75. async def test_socks5_auth_method_rejected(loop):
  76. async with FakeSocksSrv(loop, b'\x05\xFF') as srv:
  77. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  78. auth = aiosocks.Socks5Auth('usr', 'pwd')
  79. dst = ('python.org', 80)
  80. with pytest.raises(aiosocks.SocksError) as ct:
  81. await aiosocks.create_connection(
  82. None, addr, auth, dst, loop=loop)
  83. assert 'authentication methods were rejected' in str(ct)
  84. async def test_socks5_auth_status_invalid(loop):
  85. async with FakeSocksSrv(loop, b'\x05\xF0') as srv:
  86. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  87. auth = aiosocks.Socks5Auth('usr', 'pwd')
  88. dst = ('python.org', 80)
  89. with pytest.raises(aiosocks.SocksError) as ct:
  90. await aiosocks.create_connection(
  91. None, addr, auth, dst, loop=loop)
  92. assert 'invalid data' in str(ct)
  93. async def test_socks5_auth_status_invalid2(loop):
  94. async with FakeSocksSrv(loop, b'\x05\x02\x02\x00') as srv:
  95. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  96. auth = aiosocks.Socks5Auth('usr', 'pwd')
  97. dst = ('python.org', 80)
  98. with pytest.raises(aiosocks.SocksError) as ct:
  99. await aiosocks.create_connection(
  100. None, addr, auth, dst, loop=loop)
  101. assert 'invalid data' in str(ct)
  102. async def test_socks5_auth_failed(loop):
  103. async with FakeSocksSrv(loop, b'\x05\x02\x01\x01') as srv:
  104. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  105. auth = aiosocks.Socks5Auth('usr', 'pwd')
  106. dst = ('python.org', 80)
  107. with pytest.raises(aiosocks.SocksError) as ct:
  108. await aiosocks.create_connection(
  109. None, addr, auth, dst, loop=loop)
  110. assert 'authentication failed' in str(ct)
  111. async def test_socks5_cmd_ver_err(loop):
  112. async with FakeSocksSrv(loop, b'\x05\x02\x01\x00\x04\x00\x00') as srv:
  113. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  114. auth = aiosocks.Socks5Auth('usr', 'pwd')
  115. dst = ('python.org', 80)
  116. with pytest.raises(aiosocks.SocksError) as ct:
  117. await aiosocks.create_connection(
  118. None, addr, auth, dst, loop=loop)
  119. assert 'invalid version' in str(ct)
  120. async def test_socks5_cmd_not_granted(loop):
  121. async with FakeSocksSrv(loop, b'\x05\x02\x01\x00\x05\x01\x00') as srv:
  122. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  123. auth = aiosocks.Socks5Auth('usr', 'pwd')
  124. dst = ('python.org', 80)
  125. with pytest.raises(aiosocks.SocksError) as ct:
  126. await aiosocks.create_connection(
  127. None, addr, auth, dst, loop=loop)
  128. assert 'General SOCKS server failure' in str(ct)
  129. async def test_socks5_invalid_address_type(loop):
  130. async with FakeSocksSrv(loop, b'\x05\x02\x01\x00\x05\x00\x00\xFF') as srv:
  131. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  132. auth = aiosocks.Socks5Auth('usr', 'pwd')
  133. dst = ('python.org', 80)
  134. with pytest.raises(aiosocks.SocksError) as ct:
  135. await aiosocks.create_connection(
  136. None, addr, auth, dst, loop=loop)
  137. assert 'invalid data' in str(ct)
  138. async def test_socks5_atype_ipv4(loop):
  139. pld = b'\x05\x02\x01\x00\x05\x00\x00\x01\x01\x01\x01\x01\x04W'
  140. async with FakeSocksSrv(loop, pld) as srv:
  141. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  142. auth = aiosocks.Socks5Auth('usr', 'pwd')
  143. dst = ('python.org', 80)
  144. transport, protocol = await aiosocks.create_connection(
  145. None, addr, auth, dst, loop=loop)
  146. assert protocol.proxy_sockname == ('1.1.1.1', 1111)
  147. transport.close()
  148. async def test_socks5_atype_ipv6(loop):
  149. pld = b'\x05\x02\x01\x00\x05\x00\x00\x04\x00\x00\x00\x00' \
  150. b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x11\x04W'
  151. async with FakeSocksSrv(loop, pld) as srv:
  152. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  153. auth = aiosocks.Socks5Auth('usr', 'pwd')
  154. dst = ('python.org', 80)
  155. transport, protocol = await aiosocks.create_connection(
  156. None, addr, auth, dst, loop=loop)
  157. assert protocol.proxy_sockname == ('::111', 1111)
  158. transport.close()
  159. async def test_socks5_atype_domain(loop):
  160. pld = b'\x05\x02\x01\x00\x05\x00\x00\x03\x0apython.org\x04W'
  161. async with FakeSocksSrv(loop, pld) as srv:
  162. addr = aiosocks.Socks5Addr('127.0.0.1', srv.port)
  163. auth = aiosocks.Socks5Auth('usr', 'pwd')
  164. dst = ('python.org', 80)
  165. transport, protocol = await aiosocks.create_connection(
  166. None, addr, auth, dst, loop=loop)
  167. assert protocol.proxy_sockname == (b'python.org', 1111)
  168. transport.close()
  169. async def test_http_connect(loop):
  170. async def handler(request):
  171. return web.Response(text='Test message')
  172. async with RawTestServer(handler, host='127.0.0.1', loop=loop) as ws:
  173. async with FakeSocks4Srv(loop) as srv:
  174. conn = ProxyConnector(loop=loop, remote_resolve=False)
  175. async with aiohttp.ClientSession(
  176. connector=conn, loop=loop,
  177. request_class=ProxyClientRequest) as ses:
  178. proxy = 'socks4://127.0.0.1:{}'.format(srv.port)
  179. async with ses.get(ws.make_url('/'), proxy=proxy) as resp:
  180. assert resp.status == 200
  181. assert (await resp.text()) == 'Test message'
  182. async def test_https_connect(loop):
  183. async def handler(request):
  184. return web.Response(text='Test message')
  185. here = os.path.join(os.path.dirname(__file__), '..', 'tests')
  186. keyfile = os.path.join(here, 'sample.key')
  187. certfile = os.path.join(here, 'sample.crt')
  188. sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
  189. sslcontext.load_cert_chain(certfile, keyfile)
  190. ws = RawTestServer(handler, scheme='https', host='127.0.0.1', loop=loop)
  191. await ws.start_server(loop=loop, ssl=sslcontext)
  192. v_fp = b's\x93\xfd:\xed\x08\x1do\xa9\xaeq9\x1a\xe3\xc5\x7f\x89\xe7l\xf9'
  193. inv_fp = b's\x93\xfd:\xed\x08\x1do\xa9\xaeq9\x1a\xe3\xc5\x7f\x89\xe7l\x10'
  194. async with FakeSocks4Srv(loop) as srv:
  195. v_conn = ProxyConnector(loop=loop, remote_resolve=False,
  196. verify_ssl=False, fingerprint=v_fp)
  197. inv_conn = ProxyConnector(loop=loop, remote_resolve=False,
  198. verify_ssl=False, fingerprint=inv_fp)
  199. async with aiohttp.ClientSession(
  200. connector=v_conn, loop=loop,
  201. request_class=ProxyClientRequest) as ses:
  202. proxy = 'socks4://127.0.0.1:{}'.format(srv.port)
  203. async with ses.get(ws.make_url('/'), proxy=proxy) as resp:
  204. assert resp.status == 200
  205. assert (await resp.text()) == 'Test message'
  206. async with aiohttp.ClientSession(
  207. connector=inv_conn, loop=loop,
  208. request_class=ProxyClientRequest) as ses:
  209. proxy = 'socks4://127.0.0.1:{}'.format(srv.port)
  210. with pytest.raises(aiohttp.ServerFingerprintMismatch):
  211. async with ses.get(ws.make_url('/'), proxy=proxy) as resp:
  212. assert resp.status == 200