{"id":4694,"library":"proxy-protocol","title":"PROXY Protocol Library for Asyncio","description":"The `proxy-protocol` library provides an implementation of the PROXY protocol, including an `asyncio` server implementation, for Python. It currently supports versions 0.11.3 and is actively maintained with regular minor releases, focusing on improvements, bug fixes, and broader platform support.","status":"active","version":"0.11.3","language":"en","source_language":"en","source_url":"https://github.com/icgood/proxy-protocol/","tags":["asyncio","networking","proxy-protocol","server","load-balancing","proxy"],"install":[{"cmd":"pip install proxy-protocol","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Required Python version as specified by PyPI metadata.","package":"python>=3.8","optional":false},{"reason":"Optional dependency for PROXY protocol v2 checksum validation. If missing, v2 handling might raise exceptions or lack full validation.","package":"crc32c","optional":true}],"imports":[{"symbol":"ProxyProtocolDetect","correct":"from proxyprotocol.detect import ProxyProtocolDetect"},{"symbol":"ProxyProtocolReader","correct":"from proxyprotocol.reader import ProxyProtocolReader"},{"symbol":"SocketInfo","correct":"from proxyprotocol.sock import SocketInfo"},{"symbol":"ProxyProtocolVersion","correct":"from proxyprotocol.version import ProxyProtocolVersion"}],"quickstart":{"code":"import asyncio\nfrom asyncio import StreamReader, StreamWriter\nfrom proxyprotocol.detect import ProxyProtocolDetect\nfrom proxyprotocol.reader import ProxyProtocolReader\nfrom proxyprotocol.sock import SocketInfo\n\nasync def on_connection(reader: StreamReader, writer: StreamWriter, info: SocketInfo) -> None:\n    print(f\"Connection from: {info.family.name} {info.peername}\")\n    print(f\"Original client: {info.source_addr}:{info.source_port} -> {info.dest_addr}:{info.dest_port}\")\n    # Echo back received data (optional, for demonstration)\n    while True:\n        data = await reader.read(1024)\n        if not data: break\n        writer.write(data)\n        await writer.drain()\n    writer.close()\n    await writer.wait_closed()\n\nasync def main(host: str, port: int) -> None:\n    pp_detect = ProxyProtocolDetect()\n    callback = ProxyProtocolReader(pp_detect).get_callback(on_connection)\n    server = await asyncio.start_server(callback, host, port)\n    async with server:\n        await server.serve_forever()\n\nif __name__ == '__main__':\n    # To test, configure your proxy (e.g., HAProxy, NGINX) to send PROXY protocol\n    # to localhost:10007. Then connect to the proxy directly.\n    # Example with `netcat` after a proxy is set up:\n    # echo 'hello' | nc -q 1 localhost 10007\n    try:\n        asyncio.run(main('127.0.0.1', 10007))\n    except KeyboardInterrupt:\n        print(\"Server stopped.\")","lang":"python","description":"This example sets up an asyncio server that listens for incoming connections. It uses `ProxyProtocolDetect` to automatically detect PROXY protocol v1 or v2 headers. Once a connection is established and the header is parsed (if present), the `on_connection` callback receives a `SocketInfo` object containing the original client and destination address details, and then echoes any received data back to the client. This demonstrates how to integrate `proxy-protocol` with a standard `asyncio.start_server` setup."},"warnings":[{"fix":"Review code that interacts with `SocketInfo.family` or other address family-related attributes. Ensure compatibility with potentially updated or normalized `AF_*` values, especially if you manually handle socket families.","message":"Version 0.11.0 changed how address family (AF_*) constants are handled internally to enable support for Windows. This change 'Avoid using AF_* as proxy result type' might subtly affect applications that previously relied on specific `AF_*` values or behavior on non-Windows platforms, although it primarily enabled broader compatibility.","severity":"breaking","affected_versions":"0.11.0"},{"fix":"Consult the official release notes and documentation for 0.9.0 and later to understand the new API structure. Update import paths and method calls according to the new abstractions, particularly around `ProxyProtocolReader` and how callbacks are registered.","message":"Version 0.9.0 introduced a 'rework of the API with better abstractions.' This signifies significant changes to the library's interfaces and how components are used. Existing code written against older APIs will likely break.","severity":"breaking","affected_versions":"0.9.0"},{"fix":"For robust PROXY protocol v2 handling, especially in environments where checksum validation is critical, ensure `crc32c` is installed (`pip install crc32c`). If not installed, be aware that v2 checksums cannot be validated, even if the library handles the missing module gracefully.","message":"The `proxy-protocol` library, when handling PROXY protocol v2, can throw a 'bad exception' if the optional `crc32c` module is missing. While fixed in 0.11.2 to gracefully handle the absence, earlier versions might crash or behave unexpectedly. Even with the fix, performance or full checksum validation for v2 might be impacted without `crc32c`.","severity":"gotcha","affected_versions":"<0.11.2 (potential for hard crash), >=0.11.2 (graceful, but missing feature)"},{"fix":"Carefully configure `ProxyProtocolReader` or `ProxyProtocolVersion`. If you intend to detect and use PROXY protocol headers, use `ProxyProtocolVersion.get('detect')`, `ProxyProtocolVersion.get('v1')`, or `ProxyProtocolVersion.get('v2')` as appropriate, rather than `None`.","message":"Using `ProxyProtocolVersion.get(None)` or similar configurations for a `ProxyProtocolReader` explicitly disables PROXY protocol header detection. This means the server will treat all connections as direct, without parsing any PROXY headers, potentially leading to incorrect source IP information.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}