Skip to main content

Core proxy (SOCKS4, SOCKS5, HTTP tunneling) functionality for Python

Project description

python-socks

Build Status Coverage Status PyPI version

The python-socks package provides a core proxy client functionality for Python. Supports SOCKS4(a), SOCKS5(h), HTTP (tunneling) proxy and provides sync and async (asyncio, trio, curio, anyio) APIs. You probably don't need to use python-socks directly. It is used internally by aiohttp-socks and httpx-socks packages.

Requirements

  • Python >= 3.6
  • async-timeout >= 3.0.1 (optional)
  • trio >= 0.16.0 (optional)
  • curio >= 1.4 (optional)
  • anyio >= 3.3.4 (optional)

Installation

only sync proxy support:

pip install python-socks

to include optional asyncio support:

pip install python-socks[asyncio]

to include optional trio support:

pip install python-socks[trio]

to include optional curio support:

pip install python-socks[curio]

to include optional anyio support:

pip install python-socks[anyio]

Simple usage

We are making secure HTTP GET request via SOCKS5 proxy

Sync

import ssl
from python_socks.sync import Proxy

proxy = Proxy.from_url('socks5://user:password@127.0.0.1:1080')

# `connect` returns standard Python socket in blocking mode
sock = proxy.connect(dest_host='check-host.net', dest_port=443)

sock = ssl.create_default_context().wrap_socket(
    sock=sock,
    server_hostname='check-host.net'
)

request = (
    b'GET /ip HTTP/1.1\r\n'
    b'Host: check-host.net\r\n'
    b'Connection: close\r\n\r\n'
)
sock.sendall(request)
response = sock.recv(4096)
print(response)

Async (asyncio)

import ssl
import asyncio
from python_socks.async_.asyncio import Proxy

proxy = Proxy.from_url('socks5://user:password@127.0.0.1:1080')

# `connect` returns standard Python socket in non-blocking mode 
# so we can pass it to asyncio.open_connection(...)
sock = await proxy.connect(dest_host='check-host.net', dest_port=443)

reader, writer = await asyncio.open_connection(
    host=None,
    port=None,
    sock=sock,
    ssl=ssl.create_default_context(),
    server_hostname='check-host.net',
)

request = (
    b'GET /ip HTTP/1.1\r\n'
    b'Host: check-host.net\r\n'
    b'Connection: close\r\n\r\n'
)

writer.write(request)
response = await reader.read(-1)
print(response)

Async (trio)

import ssl
import trio
from python_socks.async_.trio import Proxy

proxy = Proxy.from_url('socks5://user:password@127.0.0.1:1080')

# `connect` returns trio socket 
# so we can pass it to trio.SocketStream
sock = await proxy.connect(dest_host='check-host.net', dest_port=443)

stream = trio.SocketStream(sock)

stream = trio.SSLStream(
    stream, ssl.create_default_context(),
    server_hostname='check-host.net'
)
await stream.do_handshake()

request = (
    b'GET /ip HTTP/1.1\r\n'
    b'Host: check-host.net\r\n'
    b'Connection: close\r\n\r\n'
)

await stream.send_all(request)
response = await stream.receive_some(4096)
print(response)

Async (curio)

import curio.ssl as curiossl
from python_socks.async_.curio import Proxy

proxy = Proxy.from_url('socks5://user:password@127.0.0.1:1080')
# `connect` returns curio.io.Socket
sock = await proxy.connect(
    dest_host='check-host.net',
    dest_port=443
)

request = (
    b'GET /ip HTTP/1.1\r\n'
    b'Host: check-host.net\r\n'
    b'Connection: close\r\n\r\n'
)

ssl_context = curiossl.create_default_context()
sock = await ssl_context.wrap_socket(
    sock, do_handshake_on_connect=False, server_hostname='check-host.net'
)

await sock.do_handshake()

stream = sock.as_stream()

await stream.write(request)
response = await stream.read(1024)
print(response)

Async (anyio)

import ssl
from python_socks.async_.anyio import Proxy

proxy = Proxy.from_url('socks5://user:password@127.0.0.1:1080')

# `connect` returns AnyioSocketStream
stream = await proxy.connect(
    dest_host='check-host.net',
    dest_port=443,
    dest_ssl=ssl.create_default_context(),
)

request = (
    b'GET /ip HTTP/1.1\r\n'
    b'Host: check-host.net\r\n'
    b'Connection: close\r\n\r\n'
)

await stream.write_all(request)
response = await stream.read()
print(response)

More complex example

A urllib3 PoolManager that routes connections via the proxy

from urllib3 import PoolManager, HTTPConnectionPool, HTTPSConnectionPool
from urllib3.connection import HTTPConnection, HTTPSConnection
from python_socks.sync import Proxy


class ProxyHTTPConnection(HTTPConnection):
    def __init__(self, *args, **kwargs):
        socks_options = kwargs.pop('_socks_options')
        self._proxy_url = socks_options['proxy_url']
        super().__init__(*args, **kwargs)

    def _new_conn(self):
        proxy = Proxy.from_url(self._proxy_url)
        return proxy.connect(
            dest_host=self.host,
            dest_port=self.port,
            timeout=self.timeout
        )


class ProxyHTTPSConnection(ProxyHTTPConnection, HTTPSConnection):
    pass


class ProxyHTTPConnectionPool(HTTPConnectionPool):
    ConnectionCls = ProxyHTTPConnection


class ProxyHTTPSConnectionPool(HTTPSConnectionPool):
    ConnectionCls = ProxyHTTPSConnection


class ProxyPoolManager(PoolManager):
    def __init__(self, proxy_url, timeout=5, num_pools=10, headers=None,
                 **connection_pool_kw):

        connection_pool_kw['_socks_options'] = {'proxy_url': proxy_url}
        connection_pool_kw['timeout'] = timeout

        super().__init__(num_pools, headers, **connection_pool_kw)

        self.pool_classes_by_scheme = {
            'http': ProxyHTTPConnectionPool,
            'https': ProxyHTTPSConnectionPool,
        }


### and how to use it
manager = ProxyPoolManager('socks5://user:password@127.0.0.1:1080')
response = manager.request('GET', 'https://check-host.net/ip')
print(response.data)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python-socks-2.1.1.tar.gz (25.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_socks-2.1.1-py3-none-any.whl (49.7 kB view details)

Uploaded Python 3

File details

Details for the file python-socks-2.1.1.tar.gz.

File metadata

  • Download URL: python-socks-2.1.1.tar.gz
  • Upload date:
  • Size: 25.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/58.0.4 requests-toolbelt/0.9.1 tqdm/4.56.2 CPython/3.7.11

File hashes

Hashes for python-socks-2.1.1.tar.gz
Algorithm Hash digest
SHA256 3bb68964c97690d5a3eab6c12a772f415725f295b148cbe1ca8870cb47ebcb96
MD5 1adfda673d47140315e4bbb2d6ef842b
BLAKE2b-256 4454dc01d98b5eec803d1ce1c213ab1bad4cad41901bc929d93766f31cc1c9f9

See more details on using hashes here.

File details

Details for the file python_socks-2.1.1-py3-none-any.whl.

File metadata

  • Download URL: python_socks-2.1.1-py3-none-any.whl
  • Upload date:
  • Size: 49.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/58.0.4 requests-toolbelt/0.9.1 tqdm/4.56.2 CPython/3.7.11

File hashes

Hashes for python_socks-2.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6174278b0e005bd36b5d43681a0a3d816922852c9bccc2eceb17c60f4c8d4048
MD5 823f0db24305ad9a3f5d9d132bc37cd3
BLAKE2b-256 ce1d9289f0a5ac4b1c822837adee12a091c88bc3c99b8468c631a3c9fbd7588c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page