# client2server > **Lightweight bi-directional event forwarder for OpenWrt routers** [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) ## Overview ``` ┌─────────────────────────────────────────────────────────────┐ │ client2server Architecture │ ├─────────────────────────────────────────────────────────────┤ │ │ │ OpenWrt Routers │ │ │ │ │ ▼ WebSocket :3843 │ │ ┌──────────────────────────────────────────┐ │ │ │ Caddy Load Balancer │ │ │ │ - Health checks │ │ │ │ - Auto-failover │ │ │ └──────────────────┬───────────────────┘ │ │ │ │ │ ┌───────────┴───────────┐ │ │ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ server1 │ │ server2 │ │ │ │ (Go) │ │ (Go) │ │ │ └─────┬───────┘ └─────┬───────┘ │ │ │ │ │ │ └────────┬─────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ Redpanda │ Events stored │ │ │ (Kafka) │ Persisted │ │ └───────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` ## Features - ✅ **WebSocket connection** with auto-reconnect - ✅ **Local buffer** (store-and-forward while offline) - ✅ **DHCP lease events** (new/expire) - ✅ **WAN link state** (up/down monitoring) - ✅ **WAN IP changes** (new ISP detection) - ✅ **Bidirectional** (receive commands from server) - ✅ **Command executor** (uci_set, shell, reboot, status) - ✅ **Load balancer** ready (Caddy) - ✅ **Event persistence** (Redpanda) ## Quick Start ### Option 1: Docker Compose (Recommended) ```bash # Clone and run git clone https://git3.techno-world.net/lrosales/client2server.git cd client2server # Start all services TOKEN=your-secret-token docker-compose up -d # Check status docker-compose ps ``` ### Option 2: Manual (Development) ```bash # Go server cd server go build -o server . REDPANDA_BROKERS=localhost:9092 TOKEN=*** ./server # On OpenWrt router (copy Lua script) scp package/src/client2server-unified.lua root@router:/usr/sbin/ ssh root@router "chmod +x /usr/sbin/client2server-unified.lua" ``` ## Ports | Service | Port | Protocol | |----------|------|----------| | WebSocket | 3843 | WS | | HTTP API | 3844 | HTTP | | Redpanda | 9092 | Kafka | ## Configuration ### Environment Variables ```bash TOKEN=*** # Authentication token REDPANDA_BROKERS=redpanda:9092 # Redpanda address PORT=3843 # Server port ``` ### UCI Config (on Router) ```bash # /etc/config/client2server config client2server 'general' option enabled '1' config server option url 'wss://your-server.com:3843' option token '***' config wan option interface 'wan' option device 'eth0' ``` ## Commands Send from server to router via WebSocket or HTTP API: ```bash # UCI set curl -X POST http://localhost:3844/api/command \ -H "Authorization: Bearer TOKEN" \ -d '{"router_id":"router1","command":"uci_set","args":{"config":"network","section":"lan","option":"ipaddr","value":"192.168.1.1"}}' # Shell curl -X POST http://localhost:3844/api/command \ -H "Authorization: Bearer TOKEN" \ -d '{"router_id":"router1","command":"shell","args":{"command":"reboot"}}' # Reboot curl -X POST http://localhost:3844/api/command \ -H "Authorization: Bearer TOKEN" \ -d '{"router_id":"router1","command":"reboot"}' ``` ### Available Commands | Command | Description | Arguments | |---------|-------------|-----------| | `uci_set` | Set UCI config value | `config`, `section`, `option`, `value` | | `shell` | Run shell command | `command` | | `reboot` | Reboot router | - | | `wifi_restart` | Restart WiFi | - | | `status` | Get router status | - | ## Events Router sends these events to server: | Event | Source | Payload | |-------|--------|---------| | `dhcp_lease_new` | dnsmasq | `mac`, `ip`, `hostname` | | `dhcp_lease_expire` | dnsmasq | `mac`, `old_ip` | | `wan_link_up` | /sys/class/net/* | `device` | | `wan_link_down` | /sys/class/net/* | `device` | | `wan_dhcp_new` | ubus | `new_ip` | | `wan_dhcp_changed` | ubus | `old_ip`, `new_ip` | ## Project Structure ``` client2server/ ├── ARCHITECTURE.md # Architecture docs ├── README.md # This file ├── Caddyfile # Caddy load balancer ├── docker-compose.yml # Full stack ├── package/ │ ├── Makefile # IPK build │ ├── src/ │ │ └── client2server-unified.lua # Router script │ └── files/ │ ├── etc/init.d/ │ └── etc/config/ └── server/ ├── main.go ├── go.mod ├── Dockerfile └── index.js # HTTP fallback ``` ## Building IPK ```bash # With OpenWrt SDK ./scripts/feeds update -a ./scripts/feeds install client2server-unified make package/client2server-unified/compile make package/client2server-unified/ipk # Output # bin/packages/*/client2server-unified_*.ipk ``` ## Monitoring ```bash # Server logs docker-compose logs -f server1 # Router logs (on OpenWrt) logread -f -e client2server # Redpanda docker-compose logs -f redpanda # API curl http://localhost:3844/api/routers curl http://localhost:3844/api/events ``` ## Security - Token-based auth on both WS and HTTP - Use TLS (wss://) in production - Firewalls: Only allow port 3843 from router network - Redpanda: Enable auth for production ## License MIT - Luis Rosales 2026