CLI tool for managing the Zyxel AX7501-B0 router (Digi ISP) via the DAL API.
The authentication flow (AES-256-CBC + RSA hybrid encryption) is based on the reverse-engineering work from the ha-zyxel project:
- Python 3.8+
requestspycryptodome
pipx installs the CLI into its own virtualenv and puts
zyxel-cli on your PATH, without polluting the system Python.
# From a clone of this repo
pipx install .
# Or directly from git
pipx install git+https://github.com/millaguie/zyxel-cli
# Upgrade later
pipx upgrade zyxel-cli
# Uninstall
pipx uninstall zyxel-clipip install .
# or just the runtime deps, to use the standalone ./zyxel-cli script:
pip install requests pycryptodomeThe repo also ships a zyxel-cli launcher script at the root. Once deps are
installed you can run it directly from the clone:
./zyxel-cli statusSet environment variables or use command-line flags:
| Variable | Flag | Default |
|---|---|---|
ZYXEL_HOST |
--host |
192.168.1.1 |
ZYXEL_USER |
--user |
user |
ZYXEL_PASS |
--password |
user |
zyxel-cli statusShows model, firmware, serial number, uptime, CPU/RAM usage, and active ports.
zyxel-cli dns list
zyxel-cli dns add trenes.millaguie.net 192.168.1.7
zyxel-cli dns delete trenes.millaguie.net
zyxel-cli dns delete --index 5zyxel-cli dhcp list
zyxel-cli dhcp add AA:BB:CC:DD:EE:FF 192.168.1.100
zyxel-cli dhcp delete AA:BB:CC:DD:EE:FF
zyxel-cli dhcp delete --index 3zyxel-cli nat list
zyxel-cli nat add "Web Server" 80 192.168.1.10 80 --proto tcp
zyxel-cli nat add "Game" 27015 192.168.1.50 27015 --proto udp
zyxel-cli nat add "Range" 8000 192.168.1.10 8000 --ext-port-end 8010 --int-port-end 8010
zyxel-cli nat delete "Web Server"
zyxel-cli nat delete --index 2zyxel-cli route list
# route a subnet reachable through a gateway on your LAN:
zyxel-cli route add remote-lan 10.0.0.0 255.255.255.0 192.168.1.2
# route a destination out a specific WAN interface instead of the LAN:
zyxel-cli route add via-wan 203.0.113.0 255.255.255.0 0.0.0.0 --interface IP.Interface.3
zyxel-cli route delete remote-lan
zyxel-cli route delete --index 1--interface defaults to Default (the LAN bridge; the router resolves it to
IP.Interface.1). Pass a WAN interface path (see zyxel-cli raw wan for the
ipIfacePath values, e.g. IP.Interface.3) to route via that WAN.
zyxel-cli wanShows IP address, gateway, DNS servers, encapsulation, VLAN, PPP info, and IPv6.
The router answers the DNS queries of the LAN and forwards them to these servers. By default they come from the ISP.
# Show the change, apply nothing
zyxel-cli wan set-dns --ipv4 208.67.222.222,208.67.220.220 \
--ipv6 2620:119:35::35,2620:119:53::53
# Apply it
zyxel-cli wan set-dns --ipv4 208.67.222.222,208.67.220.220 \
--ipv6 2620:119:35::35,2620:119:53::53 --yes
# Back to the ISP DNS servers
zyxel-cli wan set-dns --auto --yesIt changes the interface with the default gateway. Use --interface NAME for
another one. Without --ipv6, IPv6 DNS comes from the ISP.
⚠️ The router re-applies the interface: a PPPoE link drops for about 20 s and the public IP may change.
zyxel-cli wifiShows all SSIDs with band, channel, bandwidth, security mode, and visibility.
zyxel-cli pppoe
zyxel-cli sip
zyxel-cli gpon
zyxel-cli pppoe --show-secretsShows what you need to replace the ISP router with your own one:
pppoe: PPPoE user and password, VLAN, MTU, IP mode and DNS servers.sip: VoIP number, SIP user and password, registrar, proxy, codecs, and the voice WAN interface (VLAN, IP, gateway, DNS).gpon: GPON serial number, PLOAM password (SLID), SFP module and optical power.
Passwords are hidden by default. Add --show-secrets to print them.
zyxel-cli raw lan
zyxel-cli raw firewall
zyxel-cli raw gponQueries any DAL OID and prints the raw JSON response. Useful for exploring undocumented features.
The Zyxel DAL (Device Abstraction Layer) API exposes data via OIDs queried at:
GET /cgi-bin/DAL?oid=<OID>&sessionkey=<KEY>
All requests and responses are AES-256-CBC encrypted.
| OID | Description | Managed by zyxel-cli |
|---|---|---|
status |
System dashboard (model, firmware, uptime, CPU, RAM, ports) | status |
dns |
DNS host overrides (split-horizon) | dns |
static_dhcp |
Static DHCP reservations | dhcp |
nat |
NAT / port forwarding rules | nat |
wan |
WAN interfaces (IP, gateway, DNS, PPP, IPv6) | wan |
wlan |
WiFi SSIDs and radio settings | wifi |
lan |
LAN interfaces and DHCP server config | raw lan |
firewall |
Firewall rules and levels | raw firewall |
macfilter |
MAC address filtering | raw macfilter |
qos |
QoS settings | raw qos |
ddns |
Dynamic DNS configuration | raw ddns |
time |
NTP and timezone settings | raw time |
gpon |
GPON/fiber stats (Rx/Tx power, ONU state) | raw gpon |
wps |
WPS settings | raw wps |
snmp |
SNMP configuration | raw snmp |
The following OIDs were tested and returned no data or errors. They may work on other firmware versions or with different configurations:
acl, account, auto_provision, bandwidth_mgmt, cellular, certificate,
classfy, content_filter, dhcpv6, disk, dns_route, dsl, dyndns, email,
ethwan, ftpd, guest_wifi, home_auto, httpd, ipsec, ipv6, log, loopback,
mcast, mesh, nat_passthrough, network_map, noti, openvpn, parental,
port_trigger, pptp, ripd, routing, schedulerule, skin, sshd, storage,
switch, tr069, trust_domain, upnp, url_filter, usb, voip, vpn,
wifisonc, wlan_macfilter, wlan_scheduler, wwan, zebra
- Use
zyxel-cli raw <oid>to query any OID - The response includes a
resultfield:ZCFG_SUCCESSmeans the OID exists - Data is in the
Objectfield (list of entries or a single dict) - The router web UI can also reveal OIDs — inspect network requests in browser DevTools (the DAL endpoint paths contain the OID names)
- POST to create entries, DELETE with
&Index=Nto remove them