← Back to Research

Overview

Peer-to-peer email routing for censorship resistance, decentralization, and resilience against outages and surveillance.

Problem Statement

Traditional email is centralized and fragile: - Single points of failure: MX records, centralized MTAs - Censorship: Governments can block mail servers - Surveillance: Traffic analysis at chokepoints - Reliability: Server down = no mail - Trust: Must trust your MTA provider

Vision

Peer-to-Peer Email Network

Traditional:
  Sender → MTA → Internet → MTA → Recipient
          (centralized)

Mesh Network:
  Sender → Peer A → Peer B → Peer C → Recipient
          (decentralized, multiple routes)

- No single point of failure
- Routes around censorship
- End-to-end encrypted
- Self-healing network
- Works offline (store-and-forward)

Architecture

1. Mesh Network Topology

        User A ←→ User B
          ↕         ↕
        User C ←→ User D ←→ msgs.global (gateway)
          ↕                      ↕
        User E ←→ User F   Internet (SMTP)

Each node:
- Routes messages for others
- Stores messages when offline
- Discovers peers automatically
- Encrypts all traffic

2. Message Routing

class MeshRouter:
    """Mesh network routing protocol"""

    def __init__(self):
        self.peers = []  # Connected peers
        self.routing_table = {}  # Known routes to destinations
        self.message_store = []  # Store-and-forward buffer

    def discover_peers(self):
        """Discover peers via mDNS, DHT, or rendezvous servers"""
        # Local network: mDNS
        local_peers = mdns_discover('_meshemail._tcp.local.')

        # Internet: Distributed Hash Table (Kademlia)
        dht_peers = dht.find_nodes(node_id)

        # Fallback: Rendezvous server
        rendezvous_peers = requests.get('https://msgs.global/mesh/peers').json()

        self.peers = local_peers + dht_peers + rendezvous_peers

    def route_message(self, message, destination):
        """Route message through mesh network"""
        # 1. Check if destination is direct peer
        if destination in self.peers:
            return self.send_direct(destination, message)

        # 2. Find route via routing table
        if destination in self.routing_table:
            next_hop = self.routing_table[destination]
            return self.forward_to_peer(next_hop, message)

        # 3. Flood to all peers (discovery)
        if self.should_flood(message):
            return self.flood_message(message)

        # 4. Store-and-forward (destination offline)
        self.message_store.append({
            'message': message,
            'destination': destination,
            'ttl': 7 * 24 * 3600  # 7 days
        })

    def flood_message(self, message):
        """Flood message to all peers for discovery"""
        # Prevent loops: track seen messages
        if message.id in self.seen_messages:
            return

        self.seen_messages.add(message.id)

        # Forward to all peers (except sender)
        for peer in self.peers:
            if peer != message.sender:
                self.send_to_peer(peer, message)

    def store_and_forward(self):
        """Retry stored messages periodically"""
        while True:
            for stored in self.message_store:
                # Check if destination now reachable
                if self.can_reach(stored['destination']):
                    self.route_message(stored['message'], stored['destination'])
                    self.message_store.remove(stored)

                # Check TTL
                if time.time() > stored['created'] + stored['ttl']:
                    self.message_store.remove(stored)

            time.sleep(300)  # Check every 5 minutes

3. Peer Discovery

Local Network (mDNS):

import zeroconf

class MeshPeerDiscovery:
    """Discover peers on local network"""

    def __init__(self):
        self.zeroconf = zeroconf.Zeroconf()

    def advertise(self, port):
        """Advertise mesh email service"""
        info = zeroconf.ServiceInfo(
            '_meshemail._tcp.local.',
            f'mesh-{get_node_id()}._meshemail._tcp.local.',
            addresses=[socket.inet_aton(get_local_ip())],
            port=port,
            properties={
                'version': '1.0',
                'pubkey': get_public_key_base64(),
                'capabilities': 'routing,storage'
            }
        )
        self.zeroconf.register_service(info)

    def discover(self):
        """Discover peers on local network"""
        browser = zeroconf.ServiceBrowser(
            self.zeroconf,
            '_meshemail._tcp.local.',
            handlers=[self.on_service_found]
        )

    def on_service_found(self, zeroconf, service_type, name):
        """Handle discovered peer"""
        info = zeroconf.get_service_info(service_type, name)
        peer = {
            'address': socket.inet_ntoa(info.addresses[0]),
            'port': info.port,
            'pubkey': info.properties[b'pubkey'].decode()
        }
        self.add_peer(peer)

Internet Discovery (DHT):

from kademlia.network import Server

class MeshDHT:
    """Distributed Hash Table for peer discovery"""

    def __init__(self):
        self.server = Server()

    async def bootstrap(self):
        """Bootstrap DHT"""
        await self.server.listen(8468)

        # Connect to bootstrap nodes
        await self.server.bootstrap([
            ('bootstrap1.msgs.global', 8468),
            ('bootstrap2.msgs.global', 8468)
        ])

    async def announce(self, user_email, peer_info):
        """Announce presence in DHT"""
        # Hash email to DHT key
        key = hashlib.sha256(user_email.encode()).digest()

        # Store peer info
        await self.server.set(key, json.dumps(peer_info))

    async def find_peer(self, user_email):
        """Find peer for user"""
        key = hashlib.sha256(user_email.encode()).digest()
        peer_info = await self.server.get(key)
        return json.loads(peer_info) if peer_info else None

4. End-to-End Encryption (Mandatory)

class MeshEncryption:
    """All mesh traffic is E2E encrypted"""

    def encrypt_message(self, message, recipient_pubkey):
        """Double-ratchet encryption (Signal protocol)"""
        # Initialize session if needed
        if recipient_pubkey not in self.sessions:
            self.sessions[recipient_pubkey] = DoubleRatchet(recipient_pubkey)

        session = self.sessions[recipient_pubkey]

        # Encrypt message
        ciphertext, message_key = session.encrypt(message)

        return {
            'ciphertext': ciphertext,
            'ephemeral_pubkey': session.ephemeral_pubkey,
            'previous_chain_length': session.previous_chain_length
        }

    def decrypt_message(self, encrypted_msg, sender_pubkey):
        """Decrypt message using double ratchet"""
        session = self.sessions.get(sender_pubkey)
        if not session:
            # Initialize from first message
            session = DoubleRatchet.from_header(
                encrypted_msg['ephemeral_pubkey']
            )
            self.sessions[sender_pubkey] = session

        plaintext = session.decrypt(
            encrypted_msg['ciphertext'],
            encrypted_msg['ephemeral_pubkey']
        )

        return plaintext

5. Gateway to Traditional SMTP

class MeshSMTPGateway:
    """Bridge mesh network to traditional email"""

    def mesh_to_smtp(self, mesh_message):
        """Deliver mesh message to SMTP recipient"""
        if is_mesh_address(mesh_message.to):
            # Route via mesh
            return mesh_router.route_message(mesh_message)
        else:
            # Gateway to SMTP
            smtp_message = convert_to_smtp(mesh_message)
            return send_via_postfix(smtp_message)

    def smtp_to_mesh(self, smtp_message):
        """Receive SMTP and deliver via mesh"""
        if is_mesh_user(smtp_message.to):
            mesh_message = convert_to_mesh(smtp_message)
            return mesh_router.route_message(mesh_message)
        else:
            # Normal SMTP delivery
            return deliver_via_imap(smtp_message)

Database Schema

-- Mesh peers
CREATE TABLE mesh_peers (
    id SERIAL PRIMARY KEY,
    peer_id VARCHAR(64) UNIQUE,
    public_key TEXT,
    addresses JSONB, -- [{"ip": "1.2.3.4", "port": 8468}]
    last_seen TIMESTAMP,
    reputation_score FLOAT,
    capabilities JSONB,
    active BOOLEAN DEFAULT TRUE
);

-- Routing table
CREATE TABLE mesh_routes (
    id SERIAL PRIMARY KEY,
    destination VARCHAR(255), -- Email or peer_id
    next_hop VARCHAR(64) REFERENCES mesh_peers(peer_id),
    hop_count INTEGER,
    updated_at TIMESTAMP DEFAULT NOW()
);

-- Store-and-forward queue
CREATE TABLE mesh_message_store (
    id SERIAL PRIMARY KEY,
    message_id VARCHAR(64) UNIQUE,
    destination VARCHAR(255),
    encrypted_message BYTEA,
    created_at TIMESTAMP DEFAULT NOW(),
    expires_at TIMESTAMP,
    retry_count INTEGER DEFAULT 0
);

-- Seen messages (prevent loops)
CREATE TABLE mesh_seen_messages (
    message_id VARCHAR(64) PRIMARY KEY,
    first_seen TIMESTAMP DEFAULT NOW(),
    expires_at TIMESTAMP
);

CREATE INDEX idx_mesh_routes_dest ON mesh_routes(destination);
CREATE INDEX idx_mesh_store_expires ON mesh_message_store(expires_at);

Censorship Resistance

Techniques

  1. Multiple Routes: Message routed via many peers
  2. Onion Routing: Like Tor, hide destination
  3. Steganography: Hide mesh traffic in normal traffic
  4. Domain Fronting: Access via CDN
  5. Pluggable Transports: Disguise as HTTPS, DNS, etc.

Example: Onion Routing in Mesh

def create_onion_route(message, destination, num_hops=3):
    """Create onion-routed mesh message"""
    # Select random route
    route = select_random_peers(num_hops)
    route.append(destination)

    # Encrypt in layers (like Tor)
    payload = encrypt(message, destination.pubkey)

    for peer in reversed(route[:-1]):
        payload = {
            'next_hop': route[route.index(peer) + 1],
            'encrypted_payload': payload
        }
        payload = encrypt(payload, peer.pubkey)

    # Send to first hop
    send_to_peer(route[0], payload)

Offline Operation

Store-and-Forward

class OfflineMailbox:
    """Store messages when user is offline"""

    def store_for_offline_user(self, user, message):
        """Store message until user comes online"""
        db.execute("""
            INSERT INTO mesh_message_store (
                message_id, destination, encrypted_message, expires_at
            ) VALUES (?, ?, ?, NOW() + INTERVAL '7 days')
        """, message.id, user.email, encrypt(message, user.pubkey))

        # Notify when online (via DHT presence)
        watch_for_online(user.email, callback=deliver_stored_messages)

    def sync_on_reconnect(self, user):
        """Deliver stored messages when user comes online"""
        stored = db.query("""
            SELECT * FROM mesh_message_store
            WHERE destination = ?
        """, user.email)

        for msg in stored:
            deliver_message(user, decrypt(msg.encrypted_message))
            db.execute("DELETE FROM mesh_message_store WHERE id = ?", msg.id)

Integration with msgs.global

Hybrid Mode

msgs.global users can choose:

1. Traditional SMTP (default)
   - Centralized, fast, compatible

2. Mesh Mode (opt-in)
   - Decentralized, censorship-resistant, private

3. Hybrid (smart routing)
   - Mesh for mesh users
   - SMTP for external
   - Automatic fallback

Configuration

@app.route('/api/v1/mesh/enable', methods=['POST'])
def enable_mesh_mode():
    """Enable mesh networking for user"""
    user = request.current_user

    # Generate mesh keypair
    mesh_key = generate_ed25519_keypair()

    user.mesh_enabled = True
    user.mesh_public_key = mesh_key.public
    user.mesh_private_key = encrypt(mesh_key.private)  # Encrypted storage

    db.session.commit()

    # Announce to DHT
    mesh_dht.announce(user.email, {
        'pubkey': mesh_key.public,
        'gateway': 'msgs.global',
        'capabilities': ['routing', 'storage']
    })

    return jsonify({
        'mesh_enabled': True,
        'peer_id': generate_peer_id(mesh_key.public)
    })

Performance Characteristics

Metric SMTP Mesh Network
Delivery time <1 sec 5-30 sec
Reliability 99.9% 95-99%
Censorship resistance Low High
Privacy Medium High (onion)
Offline capability No Yes (store-and-forward)
Bandwidth overhead Low High (routing)

Use Cases

  1. Activists: Censorship-resistant communication
  2. Journalists: Protect sources
  3. Dissidents: Evade surveillance
  4. Disaster Recovery: Email when infrastructure down
  5. Off-grid: Rural areas with intermittent connectivity
  6. Privacy-focused: Users who distrust centralized email

Challenges

  1. Spam: No centralized filtering
  2. Solution: Proof-of-work, reputation systems

  3. Reliability: Messages may be delayed

  4. Solution: Hybrid mode, fallback to SMTP

  5. Scalability: Flooding doesn't scale

  6. Solution: DHT-based routing, not flooding

  7. NAT Traversal: Users behind firewalls

  8. Solution: Relay servers, STUN/TURN

  9. Energy: Mobile devices battery drain

  10. Solution: Lightweight mode, push notifications

Related Technologies

  • Briar: P2P messaging app (Bluetooth, Tor, WiFi)
  • Scuttlebutt: Decentralized social network
  • I2P: Anonymous network layer
  • Freenet: Decentralized information storage
  • IPFS: InterPlanetary File System

Status

🔬 Research & Experimentation Phase

Next Steps

  1. [ ] Prototype mesh routing protocol
  2. [ ] Implement peer discovery (mDNS + DHT)
  3. [ ] Test store-and-forward reliability
  4. [ ] Build SMTP gateway
  5. [ ] Measure latency and reliability
  6. [ ] User testing (censored regions)
  7. [ ] Optimize battery usage (mobile)

Legal Considerations

  • Some jurisdictions prohibit bypassing censorship
  • Mesh nodes may route illegal content unknowingly
  • Requires clear terms of service
  • May need legal entity in friendly jurisdiction

Recommendation: Start as research project, expand to production with legal guidance