Lightweight event forwarder for OpenWrt routers to central server Version 2.0 - Lua + WebSocket implementation
Lightweight Lua scripts that listen to OpenWrt events (WiFi, DHCP, network) and forward them to a central server via WebSocket with auto-reconnect and local buffering.
| Feature | Bash (v1) | Lua + WS (v2) |
|---|---|---|
| Connection | HTTP polling | WebSocket (persistent) |
| Auto-reconnect | Manual | Built-in |
| Offline buffer | File only | In-memory + file |
| Error handling | Basic | Exception-safe |
| Size | ~20KB | ~30KB inc. deps |
┌─────────────────┐ WebSocket ┌─────────────────┐
│ OpenWrt │ ════════════════► │ Central Server │
│ Router │ │ │
│ │ │ - Receive │
│ - DHCP │ │ - Store │
│ - WiFi │ │ - Real-time │
│ - Network │ │ - LuIS UI │
│ │ │ │
│ Buffer [offline]│─► sync when ──► │ │
└─────────────────┘ online └─────────────────┘
# Install dependencies
opkg update
opkg install lua luasocket
# Copy files
scp -r etc root@router:/etc/
scp -r usr root@router:/usr/
# Make executable
chmod +x /etc/init.d/event-forwarder
chmod +x /usr/sbin/event-forwarder.lua
# Configure
uci set event-forwarder.server.url='wss://your-server.com/ws'
uci set event-forwarder.server.token='your-secret-token'
uci set event-forwarder.general.enabled='1'
uci commit event-forwarder
# Enable and start
/etc/init.d/event-forwarder enable
/etc/init.d/event-forwarder start
# Check logs
logread -f -e client2server
cd server
npm install express ws
node server.js
| File | Purpose |
|---|---|
usr/sbin/client2server.lua |
Main Lua forwarder |
usr/sbin/event-forwarder.lua |
Original Lua prototype |
etc/init.d/event-forwarder |
Init script |
etc/config/event-forwarder |
UCI config |
server/index.js |
Central Node.js receiver |
README.md |
This file |
# /etc/config/event-forwarder
config event-forwarder 'general'
option enabled '1'
config server
option url 'wss://your-server.com/ws'
option token 'CHANGE_ME_SECRET_TOKEN'
config router
option id 'router-hostname'
export SERVER_URL="wss://your-server.com/ws"
export SERVER_TOKEN="your-token"
export ROUTER_ID="router-name"
| Event | Source | Payload |
|---|---|---|
dhcp_lease |
dnsmasq | mac, ip, hostname, action |
wifi_connect |
hostapd | mac, signal, ssid |
wifi_disconnect |
hostapd | mac, reason |
interface_up |
netifd | device |
interface_down |
netifd | device |
{
"router_id": "router-name",
"hostname": "openwrt-device",
"event_type": "dhcp_lease",
"timestamp": "2026-06-04T18:00:00Z",
"payload": {
"mac": "AA:BB:CC:DD:EE:FF",
"ip": "192.168.1.100",
"hostname": "iphone",
"action": "new"
}
}
// Expects WebSocket connection
wss://your-server.com/ws
// Or HTTP POST fallback
POST /api/events
Authorization: Bearer <token>
Content-Type: application/json
/tmp/event_buffer# Check if running
pgrep -a client2server
# View logs
logread -f -e client2server
# Check buffer
cat /tmp/event_buffer
# Manual test
lua /usr/sbin/client2server.lua
# Force stop
killall -9 client2server
lua, luasocketexpress, ws (npm)MIT - Luis Rosales 2026