Skip to content

reekeer/fognode

Repository files navigation

fognode

headless secure encrypted data transmission

License Python Platform black ruff


Peer-to-peer encrypted channel library for headless projects. Built for speed and zero-trust networking.

Security Stack

Layer Technology
Transport TLS 1.2+ with self-signed RSA-4096 certs
Key Exchange X25519 ephemeral ECDH
Session Keys HKDF-SHA256
Channel Cipher mini-MTProto (AES-256-IGE + SHA-256 msg_key)
Password Derivation PBKDF2-HMAC-SHA256 (390k iterations)
Auth Challenge HMAC-SHA256 over random nonce
Cert Pinning SHA-256 fingerprint verification

How connection works

fognode connection flow

Install

pip install fognode

Quick Start

Server

from fognode import Server, MessageEvent, ConnectEvent, DisconnectEvent

server = Server(host="0.0.0.0", port=9443, password="secret")

@server.on_event(MessageEvent)
async def on_message(ctx):
    if ctx.event.text:
        await ctx.answer(f"echo: {ctx.event.text}")

@server.on_event(ConnectEvent)
async def on_connect(ctx):
    print("+ peer connected")

@server.on_event(DisconnectEvent)
async def on_disconnect(ctx):
    print("- peer disconnected")

if __name__ == "__main__":
    server.run()

Client

from fognode import Client, MessageEvent, ClosedEvent, ErrorEvent

client = Client(connect_string="7sf9Tn:9443", password="secret")

@client.on_event(MessageEvent)
async def on_message(ctx):
    print(f"msg: {ctx.event.text}")

@client.on_event(ClosedEvent)
async def on_closed(ctx):
    print("connection closed")

@client.on_event(ErrorEvent)
async def on_error(ctx):
    print(f"error: {ctx.event.exception}")

if __name__ == "__main__":
    client.connect()

Classic API

from fognode import start_server, client_connect

ip, code, fp = start_server("0.0.0.0", 9443, "secret")
print(f"Server running at {code}:9443")  # e.g. 7sf9Tn:9443

Events

Event Server Client Description
StartEvent yes yes Server/client started
ConnectEvent yes yes Peer connected
DisconnectEvent yes yes Peer disconnected
MessageEvent yes yes Message received (type, text, ts)
ClosedEvent no yes Connection closed
ErrorEvent no yes Error occurred (exception)

Decorators

# Specific event
@server.on_event(MessageEvent)
async def handler(ctx):
    pass

# Aliases
@server.on_connect()
@server.on_disconnect()
@server.on_message()
@client.on_closed()
@client.on_error()

How mini-MTProto Works

Each message is encrypted independently using a simplified MTProto 2.0 scheme:

  1. Serialize JSON payload to bytes
  2. Pad to AES block size (16 bytes)
  3. Compute msg_key = SHA-256(padded)[8:24] (128 bits)
  4. Derive AES key = SHA-256(auth_key + msg_key)
  5. Derive AES IV = SHA-256(msg_key + auth_key)
  6. Encrypt with AES-256-IGE
  7. Send length(4 bytes) + msg_key(16 bytes) + ciphertext

Decryption reverses the process and verifies msg_key integrity.

CLI

# Run server
fognode server --host 0.0.0.0 --port 9443 --password secret

# Interactive client
fognode client 7sf9Tn:9443 --password secret

# Probe TLS fingerprint (no auth)
fognode probe 7sf9Tn:9443

# Server status via authenticated channel
fognode status 7sf9Tn:9443 --password secret

# Send one message and exit
fognode send 7sf9Tn:9443 --password secret --text "hello"

# Monitor messages only
fognode monitor 7sf9Tn:9443 --password secret

# Show certificate info
fognode cert --file fognode_cert.pem

Project Structure

src/fognode/
├── app.py              # Server, Client, Context
├── cipher.py           # mini-MTProto AES-256-IGE encrypt/decrypt
├── cli/
│   └── entrypoint.py   # argparse CLI
├── core/
│   ├── client.py       # client_connect()
│   ├── events.py       # Event classes
│   ├── probe.py        # probe_server()
│   └── server.py       # start_server()
├── crypto/
│   ├── cert.py         # Self-signed cert generation
│   ├── channel.py      # SecureChannel (mini-MTProto)
│   ├── kdf.py          # Session key helpers
│   ├── kx.py           # X25519 keypair + shared secret
│   ├── password.py     # PBKDF2 password store
│   └── primitives.py   # pbkdf2, hmac256, hkdf_expand
├── filters/            # BaseFilter, Command, Text
├── handlers/           # HandlerObject
├── types/              # constants, exceptions, protocol
├── utils/              # ipwords, ratelimit, net
└── wire/               # Length-prefixed JSON framing

MIT © reekeer

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages