Manage iKuai router programmatically: status, NAT/port-forward, DHCP, routing, QoS, firewall, VPN, auth, system.
Scanned 8/30/2026
Install to Claude Code
npx -y skills add lenzhang/ikuai-router-skill --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of ikuai-router?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lenzhang-ikuai-router)More formats (shields.io, HTML) on the badges page.
---
name: ikuai-router
description: "Manage iKuai router programmatically: status, NAT/port-forward, DHCP, routing, QoS, firewall, VPN, auth, system."
version: 1.0.0
metadata:
tags: [router, network, ikuai, devops, networking]
requires_env: [IKUAI_BASE_URL, IKUAI_USER, IKUAI_PASS]
---
# iKuai Router Management
Control an iKuai router via its private `/Action/login` + `/Action/call` API.
Authenticated session is auto-managed, including re-login on `Result: 10014`.
This skill ships a fully-typed Python helper at `helpers/ikuai.py` covering 105
verified `func_name`s discovered via Chrome DevTools Protocol on a real iKuai
3.7.8 (IK-M50) device. **Always import the helper rather than crafting HTTP by
hand** — it handles auth, pagination, error mapping, and parameter quirks.
## Setup (one-time)
Provide credentials via env vars (`.env` file, shell, or skill-runtime config):
```bash
IKUAI_BASE_URL=http://192.168.1.1
IKUAI_USER=admin
IKUAI_PASS=<plaintext password>
```
Verify:
```python
from helpers.ikuai import IKuai
ik = IKuai() # reads env, lazy-logs-in
print(ik.status.sysstat()) # → {verinfo, stream, cputemp}
```
## Quick reference — what's where
| Domain | Module | Common methods |
|---|---|---|
| **Health / monitor** | `ik.status` | `sysstat()`, `homepage()`, `monitor_iface()`, `monitor_lanip()`, `monitor_app_flow()`, `monitor_system()`, `arp()`, `iksyscheck()` |
| **Network basics** | `ik.network` | `lan()`, `wan()`, `vlan()`, `dns()`, `dns_replace()`, `ipgroup()`, `macgroup()`, `domain_group()`, `ddns()`, `nat_ddns()`, `igmp_proxy()`, `ipv6group()` |
| **DHCP** | `ik.dhcp` | `server()`, `static()`, `lease()`, `acl_mac()` |
| **NAT / port-forward** ⭐ | `ik.nat` | `dnat_list()`, `dnat_add(...)`, `dnat_del(id)`, `dnat_toggle(id, enabled)`, `netmap()`, `nat_rule()`, `upnpd()`, `upnpd_leases()` |
| **Routing** | `ik.routing` | `static_rt()`, `static_rt_table()`, `lb_pcc()` |
| **QoS / 流控** | `ik.qos` | `mac_qos()`, `simple_qos()`, `stream_control()`, `stream_domain()`, `stream_ipport()`, `stream_updown()` |
| **Firewall / ACL** | `ik.firewall` | `acl()`, `acl_mac()`, `acl_qq()`, `conn_limit()`, `dprotos()`, `alg()` |
| **URL / domain filter** | `ik.filter` | `url_black()`, `url_keywords()`, `url_redirect()`, `url_replace()`, `domain_blacklist()` |
| **VPN** | `ik.vpn` | `pptp_server()`, `pptp_client()`, `l2tp_client()`, `openvpn_client()`, `ipsec()`, `wireguard()`, `ike_server()`, `ike_client()` |
| **Auth / PPPoE** | `ik.auth` | `webuser()`, `webauth()`, `pppuser()`, `pppoe_server()`, `pppoe_proxy()`, `ppp_online()`, `ppp_passwd()`, `ppp_package()`, `ppp_paylog()`, `coupon()` |
| **Wireless / AC** | `ik.ac` | `server()`, `group()`, `online_clt()`, `status()`, `upgrade()`, `net_optimize()`, `wls_black()`, `wls_mvlan()`, `camera()` |
| **Logs (syslog)** | `ik.logs` | `arp()`, `dhcpd()`, `webadmin()`, `pppauth()`, `sysevent()`, `wanpppoe()`, `apaction()`, `ddns()`, `notice()` |
| **System** | `ik.system` | `basic()`, `register()`, `advanced()`, `remote_control()`, `watchdog()`, `upgrade()`, `ik_sysctl()`, `dingtalk()`, `notice_temp()`, `notice_cycle()`, `notice_remind()`, `notice_expires()` |
| **Tools** | `ik.tools` | `speedtest()`, `iperf()`, `tcpdump()`, `wakeup()`, `cflow()`, `tcp_proxy()`, `dev_control()`, `mac_comment_list()` |
| **Catch-all** | `ik.call(func, action, param)` | For any uncovered combination |
## Read patterns
```python
# table-style — paginated list
rules = ik.nat.dnat_list() # default first 100
rules = ik.nat.dnat_list(limit="0,500") # explicit page
print(rules) # list of dicts with id/lan_addr/lan_port/wan_port/protocol/enabled/comment
# single-config (no pagination)
print(ik.network.wan()) # → {data: {...}}
print(ik.status.sysstat()) # → {verinfo, stream, cputemp}
```
## Write patterns (port-forward example)
For destructive ops, briefly state the intended write in chat before
executing — this gives the user visibility even when running unattended.
```python
ik.nat.dnat_add(
comment="Web API",
interface="wan1",
lan_addr="192.168.1.10",
lan_port="19119",
wan_port="19119",
protocol="tcp",
src_addr="", # empty = any source
enabled="yes",
)
ik.nat.dnat_del(id=7)
ik.nat.dnat_toggle(id=7, enabled="no")
```
For other write ops not wrapped, use `ik.call(...)`:
```python
ik.call("dhcp_static", "add", {
"interface": "lan1",
"ip_addr": "192.168.1.51",
"mac": "aa:bb:cc:dd:ee:ff",
"comment": "Static binding",
"enabled": "yes",
})
```
## Behaviour rules for the agent
1. **Never expose `IKUAI_PASS`** in chat replies or logs.
2. For destructive ops (`del`, sys reboot, firewall rule changes that may
block traffic), reply with a **one-line preview** ("Going to delete dnat
rule id=7 (5000→9443 on .6). Doing it now.") **before** executing, so the
user has visibility even in YOLO mode.
3. Read methods are free — call them liberally to ground answers in current
state instead of guessing.
4. If a method raises `RouterAPIError`, the message is human-readable; surface
it in the reply rather than retrying blindly.
5. Schema reference: `helpers/funcs.json` has all 105 verified
`(func_name, action, param_keys)` triples in case you need to hand-craft a
call via `ik.call()`.
## Common port-forward fields (dnat schema)
Captured live from this device, so it's accurate for iKuai 3.7.8 / IK-M50:
| Field | Type | Notes |
|---|---|---|
| `id` | int | server-assigned, omit on add |
| `enabled` | "yes" / "no" | |
| `comment` | string | free text |
| `interface` | string | e.g. `wan1` |
| `src_addr` | string | source filter, empty = any |
| `lan_addr` | string | dest LAN IP |
| `lan_addr_int` | int | server computes from lan_addr; do not set |
| `protocol` | "tcp" / "udp" / "tcp+udp" | |
| `wan_port` | string | external port (yes, string not int) |
| `lan_port` | string | internal port |
## Troubleshooting
- `RouterAPIError: 'no login authentication'` → token expired. Helper
re-logs-in automatically; if persistent, password is wrong.
- HTTP 404 on `/Action/call` → wrong base URL.
- `Result != 30000` → operation rejected at iKuai layer; inspect `ErrMsg` for
detail (param name typo, value out of range, etc.).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!