Skip to main content

Python relay-proxy server and library to build reliable TCP and UDP tunnels for TCP traffic

Project description

Python relay-proxy server and library to build reliable TCP and UDP tunnels for TCP traffic

pypi version

Features

Hides TCP traffic in encrypted TCP/UDP traffic between relay and proxy servers

TCP/UDP tunneling

Requirements

  • Python 3.11

  • pbjson 1.18.0

  • cryptography 41.0.2

Install

python3.11 -m venv .env
source .env/bin/activate
pip install ouija

Usage

ouija <config.json>

tcp-relay.json - HTTPS proxy server interface with TCP connectors:

{
  "protocol": "TCP",
  "mode": "RELAY",
  "debug": true,
  "monitor": true,
  "relay_host": "127.0.0.1",
  "relay_port": 9000,
  "proxy_host": "127.0.0.1",
  "proxy_port": 50000,
  "key": "bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI=",
  "token": "secret",
  "serving_timeout": 20.0,
  "tcp_buffer": 1024,
  "tcp_timeout": 1.0,
  "message_timeout": 5.0
}

tcp-proxy.json - TCP-relayed proxy server:

{
  "protocol": "TCP",
  "mode": "PROXY",
  "debug": true,
  "monitor": true,
  "proxy_host": "0.0.0.0",
  "proxy_port": 50000,
  "key": "bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI=",
  "token": "secret",
  "serving_timeout": 20.0,
  "tcp_buffer": 1024,
  "tcp_timeout": 1.0,
  "message_timeout": 5.0
}

udp-relay.json - HTTPS proxy server interface with UDP connectors:

{
  "protocol": "UDP",
  "mode": "RELAY",
  "debug": true,
  "monitor": true,
  "relay_host": "127.0.0.1",
  "relay_port": 9000,
  "proxy_host": "127.0.0.1",
  "proxy_port": 50000,
  "key": "bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI=",
  "token": "secret",
  "serving_timeout": 20.0,
  "tcp_buffer": 1024,
  "tcp_timeout": 1.0,
  "udp_payload": 1024,
  "udp_timeout": 2.0,
  "udp_retries": 5,
  "udp_capacity": 10000,
  "udp_resend_sleep": 0.25
}

udp-proxy.json - UDP-relayed proxy server:

{
  "protocol": "UDP",
  "mode": "PROXY",
  "debug": true,
  "monitor": true,
  "proxy_host": "0.0.0.0",
  "proxy_port": 50000,
  "key": "bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI=",
  "token": "secret",
  "serving_timeout": 20.0,
  "tcp_buffer": 1024,
  "tcp_timeout": 1.0,
  "udp_payload": 1024,
  "udp_timeout": 2.0,
  "udp_retries": 5,
  "udp_capacity": 10000,
  "udp_resend_sleep": 0.25
}

Relay and proxy setup configuration with supervisord - ouija-config

Protocols

  • Stream - TCP

  • Datagram - UDP

Entities

  • Tuning - relay-proxy interaction settings

  • Relay - HTTPS proxy server interface

  • Connector - relay connector, which communicates with proxy link

  • Proxy - proxy server, which gets requests from relay and sends back responses from remote servers

  • Link - proxy link with relay connector

Tuning - TCP

  • fernet - Fernet instance with provided secret key - use Fernet.generate_key()

  • token - your secret token - UUID4 or anything else

  • serving_timeout - timeout for serve/resend workers, 2X for handlers, seconds

  • tcp_buffer - TCP buffer size, bytes

  • tcp_timeout - TCP awaiting timeout, seconds

  • message_timeout - TCP service message timeout, seconds

Tuning - UDP

  • fernet - Fernet instance with provided secret key - use Fernet.generate_key()

  • token - your secret token - UUID4 or anything else

  • serving_timeout - timeout for serve/resend workers, 2X for handlers, seconds

  • tcp_buffer - TCP buffer size, bytes

  • tcp_timeout - TCP awaiting timeout, seconds

  • udp_payload - UDP payload size, bytes

  • udp_timeout - UDP awaiting timeout, seconds

  • udp_retries - UDP max retry count per interaction

  • udp_capacity - UDP send/receive buffer capacity - max packet count

  • udp_resend_sleep - UDP resend sleep between retries, seconds

Library usage

stream-relay.py - HTTPS proxy server interface with TCP connectors:

import asyncio

from cryptography.fernet import Fernet

from ouija import StreamRelay as Relay, StreamTuning as Tuning, StreamTelemetry as Telemetry


async def main() -> None:
    tuning = Tuning(
        fernet=Fernet('bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI='),
        token='secret',
        serving_timeout=20.0,
        tcp_buffer=1024,
        tcp_timeout=1.0,
        message_timeout=5.0,
    )
    relay = Relay(
        telemetry=Telemetry(),
        tuning=tuning,
        relay_host='127.0.0.1',
        relay_port=9000,
        proxy_host='127.0.0.1',
        proxy_port=50000,
    )
    asyncio.create_task(relay.debug())
    await relay.serve()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.run_forever()

stream-proxy.py - TCP-relayed proxy server:

import asyncio

from cryptography.fernet import Fernet

from ouija import StreamProxy as Proxy, StreamTelemetry as Telemetry, StreamTuning as Tuning


async def main() -> None:
    tuning = Tuning(
        fernet=Fernet('bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI='),
        token='secret',
        serving_timeout=20.0,
        tcp_buffer=1024,
        tcp_timeout=1.0,
        message_timeout=5.0,
    )
    proxy = Proxy(
        telemetry=Telemetry(),
        tuning=tuning,
        proxy_host='0.0.0.0',
        proxy_port=50000,
    )
    asyncio.create_task(proxy.debug())
    await proxy.serve()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.run_forever()

datagram-relay.py - HTTPS proxy server interface with UDP connectors:

import asyncio

from cryptography.fernet import Fernet

from ouija import DatagramRelay as Relay, DatagramTuning as Tuning, DatagramTelemetry as Telemetry


async def main() -> None:
    tuning = Tuning(
        fernet=Fernet('bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI='),
        token='secret',
        serving_timeout=20.0,
        tcp_buffer=1024,
        tcp_timeout=1.0,
        udp_payload=1024,
        udp_timeout=2.0,
        udp_retries=5,
        udp_capacity=10000,
        udp_resend_sleep=0.1,
    )
    relay = Relay(
        telemetry=Telemetry(),
        tuning=tuning,
        relay_host='127.0.0.1',
        relay_port=9000,
        proxy_host='127.0.0.1',
        proxy_port=50000,
    )
    asyncio.create_task(relay.debug())
    await relay.serve()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.run_forever()

datagram-proxy.py - UDP-relayed proxy server:

import asyncio

from cryptography.fernet import Fernet

from ouija import DatagramProxy as Proxy, DatagramTelemetry as Telemetry, DatagramTuning as Tuning


async def main() -> None:
    tuning = Tuning(
        fernet=Fernet('bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI='),
        token='secret',
        serving_timeout=20.0,
        tcp_buffer=1024,
        tcp_timeout=1.0,
        udp_payload=1024,
        udp_timeout=2.0,
        udp_retries=5,
        udp_capacity=10000,
        udp_resend_sleep=0.1,
    )
    proxy = Proxy(
        telemetry=Telemetry(),
        tuning=tuning,
        proxy_host='0.0.0.0',
        proxy_port=50000,
    )
    asyncio.create_task(proxy.debug())
    await proxy.serve()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.run_forever()

Tests

pytest --cov-report html:htmlcov --cov=ouija tests/

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

ouija-1.2.4.tar.gz (19.3 kB view hashes)

Uploaded Source

Built Distribution

ouija-1.2.4-py3-none-any.whl (16.3 kB view hashes)

Uploaded Python 3

Supported by

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