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
- Multiple Routes: Message routed via many peers
- Onion Routing: Like Tor, hide destination
- Steganography: Hide mesh traffic in normal traffic
- Domain Fronting: Access via CDN
- 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
- Activists: Censorship-resistant communication
- Journalists: Protect sources
- Dissidents: Evade surveillance
- Disaster Recovery: Email when infrastructure down
- Off-grid: Rural areas with intermittent connectivity
- Privacy-focused: Users who distrust centralized email
Challenges
- Spam: No centralized filtering
-
Solution: Proof-of-work, reputation systems
-
Reliability: Messages may be delayed
-
Solution: Hybrid mode, fallback to SMTP
-
Scalability: Flooding doesn't scale
-
Solution: DHT-based routing, not flooding
-
NAT Traversal: Users behind firewalls
-
Solution: Relay servers, STUN/TURN
-
Energy: Mobile devices battery drain
- 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
- [ ] Prototype mesh routing protocol
- [ ] Implement peer discovery (mDNS + DHT)
- [ ] Test store-and-forward reliability
- [ ] Build SMTP gateway
- [ ] Measure latency and reliability
- [ ] User testing (censored regions)
- [ ] 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