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
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
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.