Skip to main content

Python relay/proxy server and library to build reliable encrypted TCP/UDP tunnels with entropy control for TCP traffic

Project description

Python relay/proxy server and library to build reliable encrypted TCP/UDP tunnels with entropy control for TCP traffic

pypi version

Features

  • Easy to install, configure and use

  • TCP/UDP tunneling

  • Pluggable traffic ciphers

  • Pluggable traffic entropy control

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

TCP/UDP tunneling

Requirements

  • Python 3.11

  • pbjson 1.18.0

  • cryptography 41.0.2

  • numpy 1.25.2

Install

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

Usage

Generate cipher_key/token secrets:

ouija_secret

Run relay/proxy server:

ouija <config.json>

tcp-relay.json - TCP relay server - HTTP/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,
  "cipher_key": "bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI=",
  "entropy_rate": 5,
  "token": "395f249c-343a-4f92-9129-68c6d83b5f55",
  "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,
  "cipher_key": "bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI=",
  "entropy_rate": 5,
  "token": "395f249c-343a-4f92-9129-68c6d83b5f55",
  "serving_timeout": 20.0,
  "tcp_buffer": 1024,
  "tcp_timeout": 1.0,
  "message_timeout": 5.0
}

udp-relay.json - UDP relay server - HTTP/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,
  "cipher_key": "bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI=",
  "entropy_rate": 5,
  "token": "395f249c-343a-4f92-9129-68c6d83b5f55",
  "serving_timeout": 20.0,
  "tcp_buffer": 1024,
  "tcp_timeout": 1.0,
  "udp_min_payload": 512,
  "udp_max_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,
  "cipher_key": "bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI=",
  "entropy_rate": 5,
  "token": "395f249c-343a-4f92-9129-68c6d83b5f55",
  "serving_timeout": 20.0,
  "tcp_buffer": 1024,
  "tcp_timeout": 1.0,
  "udp_min_payload": 512,
  "udp_max_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

Cipher and entropy

  • cipher_key - FernetCipher key - use ouija_secret to generate key

  • entropy_rate - SimpleEntropy rate, when rate=N every Nth byte will be generated and payload size will increase, rate=5 means 20% traffic overhead

Protocols

  • Stream - TCP

  • Datagram - UDP

Entities

  • Cipher - cipher implementation - FernetCipher out of the box

  • Entropy - entropy control implementation - SimpleEntropy out of the box

  • Tuning - relay/proxy and connector/link 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

  • cipher - cipher instance, if None then no encryption will be applied

  • entropy - entropy instance, if None then no entropy control will be applied

  • token - your secret token - UUID4 or anything else - use ouija_secret to generate token

  • 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

  • cipher - cipher instance, if None then no encryption will be applied

  • entropy - entropy instance, if None then no entropy control will be applied

  • token - your secret token - UUID4 or anything else - use ouija_secret to generate token

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

  • tcp_buffer - TCP buffer size, bytes

  • tcp_timeout - TCP awaiting timeout, seconds

  • udp_min_payload - UDP min payload size, bytes

  • udp_max_payload - UDP max 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 - TCP relay server - HTTP/HTTPS proxy server interface with TCP connectors:

import asyncio
import logging

from ouija import StreamRelay as Relay, StreamTuning as Tuning, Telemetry, SimpleEntropy, FernetCipher


async def main() -> None:
    tuning = Tuning(
        cipher=FernetCipher(key='bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI='),
        entropy=SimpleEntropy(rate=5),
        token='395f249c-343a-4f92-9129-68c6d83b5f55',
        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
import logging

from ouija import StreamProxy as Proxy, Telemetry, StreamTuning as Tuning, SimpleEntropy, FernetCipher


async def main() -> None:
    tuning = Tuning(
        cipher=FernetCipher(key='bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI='),
        entropy=SimpleEntropy(rate=5),
        token='395f249c-343a-4f92-9129-68c6d83b5f55',
        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 - UDP relay server - HTTPS proxy server interface with UDP connectors:

import asyncio
import logging

from ouija import DatagramRelay as Relay, DatagramTuning as Tuning, Telemetry, SimpleEntropy, FernetCipher


async def main() -> None:
    tuning = Tuning(
        cipher=FernetCipher(key='bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI='),
        entropy=SimpleEntropy(rate=5),
        token='395f249c-343a-4f92-9129-68c6d83b5f55',
        serving_timeout=20.0,
        tcp_buffer=1024,
        tcp_timeout=1.0,
        udp_min_payload=512,
        udp_max_payload=1024,
        udp_timeout=2.0,
        udp_retries=5,
        udp_capacity=10000,
        udp_resend_sleep=0.25,
    )
    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
import logging

from ouija import DatagramProxy as Proxy, Telemetry, DatagramTuning as Tuning, SimpleEntropy, FernetCipher


async def main() -> None:
    tuning = Tuning(
        cipher=FernetCipher(key='bdDmN4VexpDvTrs6gw8xTzaFvIBobFg1Cx2McFB1RmI='),
        entropy=SimpleEntropy(rate=5),
        token='395f249c-343a-4f92-9129-68c6d83b5f55',
        serving_timeout=20.0,
        tcp_buffer=1024,
        tcp_timeout=1.0,
        udp_min_payload=512,
        udp_max_payload=1024,
        udp_timeout=2.0,
        udp_retries=5,
        udp_capacity=10000,
        udp_resend_sleep=0.25,
    )
    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.3.1.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

ouija-1.3.1-py3-none-any.whl (18.9 kB view details)

Uploaded Python 3

File details

Details for the file ouija-1.3.1.tar.gz.

File metadata

  • Download URL: ouija-1.3.1.tar.gz
  • Upload date:
  • Size: 22.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for ouija-1.3.1.tar.gz
Algorithm Hash digest
SHA256 8277b6724364377a4bafd108c3c92953ce4a3c21fcee1595460515f81d395324
MD5 cc4cf5ca46a8252f8f166d5cc8559100
BLAKE2b-256 467300c4798ec9623919dd61e1a7bffc32ca3b03faabdde8d48a5552928d7952

See more details on using hashes here.

File details

Details for the file ouija-1.3.1-py3-none-any.whl.

File metadata

  • Download URL: ouija-1.3.1-py3-none-any.whl
  • Upload date:
  • Size: 18.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for ouija-1.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ac8d9c87700f581d4867131137da0cd4f6553f53fd1946364d36e1d018b917c1
MD5 9a381602531e512c1f8f192b8d2294a5
BLAKE2b-256 2358f59c78bff705b071cfb659bb0b268d9ac1ddedbbb6695142d37386c12c72

See more details on using hashes here.

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