gpon-mcp
by bsiamer
README.md
# gpon-godmode
I made this so I could open ports without having to log into my router's web dashboard every time, and so my server apps (Minecraft servers, game lobbies, self-hosted backends) can open the ports they need automatically.
It targets the **Nokia / Alcatel-Lucent G-240W-F** fiber router distributed by Algérie Télécom. Logging into that web interface just to forward a port for a game or server is painfully slow and clunky. This project reverse-engineers the frontend's login crypto (RSA-1024 + AES-128-CBC) to talk straight to the router's internal CGI endpoints over plain HTTP in ~200ms. No browser automation or Playwright required.
```mermaid
flowchart LR
subgraph Clients["Clients"]
direction TB
ServerApps["Game Servers & Apps (Auto-Port Forward)"]
CLI["Terminal (gpon ports add)"]
Agent["AI Agents (MCP)"]
end
subgraph Core["gpon_godmode"]
direction TB
Engine["HTTP Client"]
Crypto["SJCL Crypto (RSA + AES)"]
Daemon["REST Daemon (:8254)"]
Engine --- Crypto
end
subgraph Router["Nokia G-240W-F"]
CGI["Router NAT / CGI"]
end
ServerApps -->|Open / Close Ports| Daemon --> Engine
CLI --> Core
Agent --> Core
Engine -->|HTTP POST/GET| CGI
```
---
## What it does
- **Automated port forwarding for server apps**: Let your game servers or backends request port forwards on startup and clean them up on shutdown. Comes with a zero-dependency Java SDK (including an auto-forwarding Paper/Spigot Minecraft plugin) and a Go SDK.
- **Port management without the web UI**: Open, list, or delete NAT port forwards straight from your terminal (`./gpon.sh ports add 25565 25565 192.168.1.154`) or via a local REST API on port `8254`.
- **Zero-RAM sleep (systemd socket activation)**: The local API daemon can sleep at 0 MB RAM until a server app calls it to forward a port, stay warm in memory for 60 seconds, and shut down automatically when idle.
- **Gaming latency fix**: One command (`./gpon.sh gaming <ip>`) to put your gaming rig into DMZ, turn on UPnP, and disable the broken firewall DoS filter and voice-corrupting ALGs that drop packets in games like Fortnite.
- **Line diagnostics**: Read fiber optic signal power (TX/RX dBm) and check physical LAN port speeds (1000M vs 100M cable bottlenecks).
- **AI Agent support**: Built-in Model Context Protocol (MCP) server so agents in Claude or Cursor can manage router settings.
---
## Setup
```bash
git clone https://github.com/bsiamer/gpon-godmode.git
cd gpon-godmode
python3 -m venv venv
source venv/bin/activate
pip install -e ".[mcp]"
cp .env.example .env
```
Set your router credentials in `.env`:
```ini
ROUTER_IP=http://192.168.1.254
ROUTER_USER=userAdmin
ROUTER_PASS=your_password
GPON_API_PORT=8254
GPON_API_HOST=127.0.0.1
```
---
## CLI
The `./gpon.sh` wrapper runs in your current shell and maps commands directly to the core package:
```bash
# Check router status, uptime, CPU temp, and WAN IP
./gpon.sh status
# List connected LAN and Wi-Fi devices
./gpon.sh devices
# Fiber optic power levels (TX/RX dBm)
./gpon.sh optical
# Check LAN 1-4 link speeds (spot 100M cable caps)
./gpon.sh ethernet
# Check or change Wi-Fi channel
./gpon.sh wifi status
./gpon.sh wifi channel 6
# Port forwarding
./gpon.sh ports list
./gpon.sh ports add 25565 25565 192.168.1.154 --proto TCP
./gpon.sh ports del 25565
# DMZ (routes all unsolicited traffic to target; add -y to skip prompt)
./gpon.sh dmz get
./gpon.sh dmz set 192.168.1.74 -y
./gpon.sh dmz disable
# Fix gaming packet drops (DMZ + disable DoS filter + disable SIP ALG + UPnP)
./gpon.sh gaming 192.168.1.74 -y
# Change DHCP DNS servers
./gpon.sh dns 1.1.1.1 1.0.0.1
# Soft-reboot
./gpon.sh reboot
```
Add `--json` to any command for structured output:
```bash
./gpon.sh optical --json
```
---
## Model Context Protocol (MCP)
Add this to your MCP client config (`claude_desktop_config.json`, `.cursor/mcp.json`, or Antigravity):
```json
{
"mcpServers": {
"gpon": {
"command": "/home/noe/Projects/gpon-godmode/venv/bin/gpon-mcp",
"env": {
"ROUTER_IP": "http://192.168.1.254",
"ROUTER_USER": "userAdmin",
"ROUTER_PASS": "your_password"
}
}
}
}
```
The server exposes 12 tools covering router status, devices, optical power, Wi-Fi channel selection, Ethernet speeds, port forwards, DMZ, and gaming optimization. Full parameter references are in [`docs/AGENTS.md`](docs/AGENTS.md).
---
## REST API & Socket Activation
If you have local services that need router automation, you can run the daemon on port 8254:
```bash
# Run persistently in foreground
./gpon.sh daemon --port 8254
# Or exit after 60s of silence to save RAM
./gpon.sh daemon --port 8254 --idle-timeout 60
```
Swagger UI is at `http://127.0.0.1:8254/docs` and the OpenAPI spec is at `/openapi.json`.
### Zero-RAM On-Demand Sleep (Linux / systemd)
On Linux systems running systemd, you don't need a Python process sitting in RAM 24/7. Systemd can hold port 8254 in the kernel at 0 MB RAM, launch the daemon on the first request, keep it warm for 60 seconds, and kill it when idle:
```bash
# Enable user socket activation
./gpon.sh enable-service
# Check service and socket status
./gpon.sh service-status
# Disable
./gpon.sh disable-service
```
---
## Fiber Telemetry & Gaming Optimization
### Optical signal levels
The router reads transceiver data via `wan_status.cgi?gpon`. Raw milliwatts get converted to dBm:
$$\text{dBm} = 10 \cdot \log_{10}(\text{RawPower} \cdot 10^{-4})$$
| RX Power | State | What it means |
| :--- | :--- | :--- |
| $> -8.0\text{ dBm}$ | Overload | Signal too strong. Optical receiver saturates; needs an attenuator. |
| $-8.0\text{ to } -24.9\text{ dBm}$ | Good | Standard Class B+ budget. Clean line rate. |
| $-25.0\text{ to } -27.9\text{ dBm}$ | Marginal | High attenuation. Jitter and micro-drops under load. Check for tight bends. |
| $< -28.0\text{ dBm}$ | Critical | Below sensitivity limit. Periodic PPPoE drops. Call your ISP. |
### Why the gaming macro exists
Algérie Télécom's stock firmware has three quirks that ruin games like Fortnite, Call of Duty, and voice chat:
1. **Broken DoS filter**: Rapid UDP matchmaking bursts trigger the router's "Attack Protection", dropping packets mid-game.
2. **SIP / RTSP ALGs**: These rewrite packet payloads thinking they're helping VoIP, but end up corrupting Discord, PlayStation Party, and game traffic.
3. **Strict NAT**: Without UPnP or DMZ, inbound game sessions get blocked.
Running `./gpon.sh gaming <your-ip>` disables the DoS filter, turns off the bad ALGs, enables UPnP, and routes unmatched traffic to your machine via DMZ.
> **Security warning:** Putting a device in DMZ and disabling the DoS filter exposes that machine directly to all unsolicited internet traffic. Only run this for a gaming console or a PC with its own local firewall running (like Windows Firewall or ufw/nftables), never for an unprotected device or a machine hosting sensitive unauthenticated services.
---
## SDKs
### Python
```python
from gpon_godmode import GPONClient
with GPONClient() as client:
status = client.get_status()
print(f"Model: {status.model_name} | IP: {status.wan_ip}")
optical = client.get_optical_status()
print(f"Fiber RX: {optical.rx_power_dbm} dBm ({optical.signal_quality})")
client.optimize_gaming("192.168.1.74")
```
### Java (Minecraft Paper/Spigot Plugin & Standalone)
Located in [`sdk/java`](sdk/java). Zero third-party dependencies (pure Java 11 `HttpClient` + minimal JSON parser). Falls back to running `gpon <cmd> --json` via process execution if the HTTP daemon isn't running.
Includes a ready-to-build Paper/Spigot plugin that forwards port 25565 on server startup, monitors fiber line health, and deletes the rule on server stop.
```java
import com.gpon.godmode.GponClient;
GponClient client = GponClient.builder()
.port(8254)
.fallbackToCli(true)
.build();
// Forward port for your server
client.addPortForward(25565, 25565, "192.168.1.154", "TCP");
```
### Go
Located in [`sdk/go`](sdk/go). Standard library only (`net/http`, `context`).
```go
package main
import (
"context"
"fmt"
"time"
"github.com/bsiamer/gpon-godmode/sdk/go"
)
func main() {
client := gpon.NewClient(
gpon.WithAPIPort(8254),
gpon.WithCLIFallback(true),
)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
optical, err := client.GetOpticalStatus(ctx)
if err != nil {
panic(err)
}
fmt.Printf("Fiber RX: %.2f dBm (%s)\n", optical.RXPowerDBm, optical.SignalQuality)
}
```
---
## Supported Hardware & Limitations
This was reverse-engineered specifically for my home setup:
- **Router**: Nokia / Alcatel-Lucent G-240W-F (GPON Home Gateway)
- **ISP**: Algérie Télécom (Idoom Fibre)
- **Hardware Revision**: `3FE46597AAAA`
- **Firmware Version**: `3FE46606BGBB24` (EcoNet/MediaTek MTK7526G SoC, U-Boot Dec-31-2016)
### Limitations
Other ISPs and other GPON models (Huawei HG8245, ZTE F660/F670, Fiberhome, Sagemcom) use completely different login flows (HTTP digest auth, challenge-response salts, different public keys) and different internal CGI endpoints. This tool won't work out of the box on those without an adapter.
---
## Contributing
I don't intend to turn this into a giant enterprise project, but if you're dealing with a locked-down router from your ISP and want to add support for your model, PRs are welcome.
---
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues