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.
 
 

180 lines
6.3 KiB

  1. import aiosocks
  2. import aiohttp
  3. import pytest
  4. from yarl import URL
  5. from unittest import mock
  6. from aiohttp.test_utils import make_mocked_coro
  7. from aiohttp import BasicAuth
  8. from aiosocks.connector import ProxyConnector, ProxyClientRequest
  9. from aiosocks.helpers import Socks4Auth, Socks5Auth
  10. async def test_connect_proxy_ip():
  11. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  12. with mock.patch('aiosocks.connector.create_connection',
  13. make_mocked_coro((tr, proto))):
  14. loop_mock = mock.Mock()
  15. loop_mock.getaddrinfo = make_mocked_coro(
  16. [[0, 0, 0, 0, ['127.0.0.1', 1080]]])
  17. req = ProxyClientRequest(
  18. 'GET', URL('http://python.org'), loop=loop_mock,
  19. proxy=URL('socks5://proxy.org'))
  20. connector = ProxyConnector(loop=loop_mock)
  21. conn = await connector.connect(req)
  22. assert loop_mock.getaddrinfo.called
  23. assert conn.protocol is proto
  24. conn.close()
  25. async def test_connect_proxy_domain():
  26. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  27. with mock.patch('aiosocks.connector.create_connection',
  28. make_mocked_coro((tr, proto))):
  29. loop_mock = mock.Mock()
  30. req = ProxyClientRequest(
  31. 'GET', URL('http://python.org'), loop=loop_mock,
  32. proxy=URL('socks5://proxy.example'))
  33. connector = ProxyConnector(loop=loop_mock)
  34. connector._resolve_host = make_mocked_coro([mock.MagicMock()])
  35. conn = await connector.connect(req)
  36. assert connector._resolve_host.call_count == 1
  37. assert conn.protocol is proto
  38. conn.close()
  39. async def test_connect_remote_resolve(loop):
  40. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  41. with mock.patch('aiosocks.connector.create_connection',
  42. make_mocked_coro((tr, proto))):
  43. req = ProxyClientRequest(
  44. 'GET', URL('http://python.org'), loop=loop,
  45. proxy=URL('socks5://127.0.0.1'))
  46. connector = ProxyConnector(loop=loop, remote_resolve=True)
  47. connector._resolve_host = make_mocked_coro([mock.MagicMock()])
  48. conn = await connector.connect(req)
  49. assert connector._resolve_host.call_count == 1
  50. assert conn.protocol is proto
  51. conn.close()
  52. async def test_connect_locale_resolve(loop):
  53. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  54. with mock.patch('aiosocks.connector.create_connection',
  55. make_mocked_coro((tr, proto))):
  56. req = ProxyClientRequest(
  57. 'GET', URL('http://python.org'), loop=loop,
  58. proxy=URL('socks5://proxy.example'))
  59. connector = ProxyConnector(loop=loop, remote_resolve=False)
  60. connector._resolve_host = make_mocked_coro([mock.MagicMock()])
  61. conn = await connector.connect(req)
  62. assert connector._resolve_host.call_count == 2
  63. assert conn.protocol is proto
  64. conn.close()
  65. async def test_proxy_connect_fail(loop):
  66. loop_mock = mock.Mock()
  67. loop_mock.getaddrinfo = make_mocked_coro(
  68. [[0, 0, 0, 0, ['127.0.0.1', 1080]]])
  69. cc_coro = make_mocked_coro(
  70. raise_exception=aiosocks.SocksConnectionError())
  71. with mock.patch('aiosocks.connector.create_connection', cc_coro):
  72. req = ProxyClientRequest(
  73. 'GET', URL('http://python.org'), loop=loop,
  74. proxy=URL('socks5://127.0.0.1'))
  75. connector = ProxyConnector(loop=loop_mock)
  76. with pytest.raises(aiohttp.ClientConnectionError):
  77. await connector.connect(req)
  78. async def test_proxy_negotiate_fail(loop):
  79. loop_mock = mock.Mock()
  80. loop_mock.getaddrinfo = make_mocked_coro(
  81. [[0, 0, 0, 0, ['127.0.0.1', 1080]]])
  82. with mock.patch('aiosocks.connector.create_connection',
  83. make_mocked_coro(raise_exception=aiosocks.SocksError())):
  84. req = ProxyClientRequest(
  85. 'GET', URL('http://python.org'), loop=loop,
  86. proxy=URL('socks5://127.0.0.1'))
  87. connector = ProxyConnector(loop=loop_mock)
  88. with pytest.raises(aiosocks.SocksError):
  89. await connector.connect(req)
  90. async def test_proxy_connect_http(loop):
  91. tr, proto = mock.Mock(name='transport'), mock.Mock(name='protocol')
  92. loop_mock = mock.Mock()
  93. loop_mock.getaddrinfo = make_mocked_coro([
  94. [0, 0, 0, 0, ['127.0.0.1', 1080]]])
  95. loop_mock.create_connection = make_mocked_coro((tr, proto))
  96. req = ProxyClientRequest(
  97. 'GET', URL('http://python.org'), loop=loop,
  98. proxy=URL('http://127.0.0.1'))
  99. connector = ProxyConnector(loop=loop_mock)
  100. await connector.connect(req)
  101. @pytest.mark.parametrize('proxy', [
  102. (URL('socks4://proxy.org'), Socks4Auth('login')),
  103. (URL('socks5://proxy.org'), Socks5Auth('login', 'password')),
  104. (URL('http://proxy.org'), BasicAuth('login')), (None, BasicAuth('login')),
  105. (URL('socks4://proxy.org'), None), (None, None)])
  106. def test_proxy_client_request_valid(proxy, loop):
  107. proxy, proxy_auth = proxy
  108. p = ProxyClientRequest('GET', URL('http://python.org'),
  109. proxy=proxy, proxy_auth=proxy_auth, loop=loop)
  110. assert p.proxy is proxy
  111. assert p.proxy_auth is proxy_auth
  112. def test_proxy_client_request_invalid(loop):
  113. with pytest.raises(ValueError) as cm:
  114. ProxyClientRequest(
  115. 'GET', URL('http://python.org'),
  116. proxy=URL('socks6://proxy.org'), proxy_auth=None, loop=loop)
  117. assert 'Only http, socks4 and socks5 proxies are supported' in str(cm)
  118. with pytest.raises(ValueError) as cm:
  119. ProxyClientRequest(
  120. 'GET', URL('http://python.org'), loop=loop,
  121. proxy=URL('http://proxy.org'), proxy_auth=Socks4Auth('l'))
  122. assert 'proxy_auth must be None or BasicAuth() ' \
  123. 'tuple for http proxy' in str(cm)
  124. with pytest.raises(ValueError) as cm:
  125. ProxyClientRequest(
  126. 'GET', URL('http://python.org'), loop=loop,
  127. proxy=URL('socks4://proxy.org'), proxy_auth=BasicAuth('l'))
  128. assert 'proxy_auth must be None or Socks4Auth() ' \
  129. 'tuple for socks4 proxy' in str(cm)
  130. with pytest.raises(ValueError) as cm:
  131. ProxyClientRequest(
  132. 'GET', URL('http://python.org'), loop=loop,
  133. proxy=URL('socks5://proxy.org'), proxy_auth=Socks4Auth('l'))
  134. assert 'proxy_auth must be None or Socks5Auth() ' \
  135. 'tuple for socks5 proxy' in str(cm)