Table of Contents
PRD: OpenWRT One Router Configuration
Date: 2026-03-28
Status: Ready for implementation
Hardware: OpenWRT One (mediatek/filogic,
aarch64_cortex-a53) Firmware: OpenWrt
SNAPSHOT r27876+1 (kernel 6.6.57) Upstream:
CYTA VDSL modem (double NAT) Config repo:
~/Work/openwrt-config/
1. Executive Summary
Configure the OpenWRT One router from factory defaults to a production home network with:
- WiFi — Dual-band (2.4GHz + 5GHz), SSID “Lexmechanic Traffic Shrine”, WPA2/WPA3
- Beeline WireGuard tunnel — Policy-routed split tunnel for Russian service IP ranges
- VPN server capability — WireGuard server for future remote access (outbound-only tunnel through mesh VPS initially, inbound when fiber arrives)
- System hardening — Timezone, hostname, DNS, NTP, SSH keys
2. Current State (Factory Defaults)
| Setting | Current | Target |
|---|---|---|
| Hostname | OpenWrt |
lexmechanic |
| Timezone | UTC |
EET-2EEST,M3.5.0/3,M10.5.0/4 (Cyprus) |
| WiFi SSID | OpenWrt (open) |
Lexmechanic Traffic Shrine (WPA2/WPA3) |
| WiFi bands | 2.4GHz ch1 + 5GHz ch36 | Both, auto channel |
| WAN | DHCP from CYTA | DHCP from CYTA (unchanged) |
| LAN | 192.168.1.0/24 | 192.168.1.0/24 (unchanged) |
| WireGuard | Not installed | Beeline client + VPN server |
| Package manager | opkg (old SNAPSHOT) |
Verify — may need apk on newer builds |
3. Network Topology
Internet
│
CYTA VDSL Modem (NAT, DHCP server on 192.168.0.x or similar)
│
├─ eth0 (WAN) ── OpenWRT One ── eth1 (LAN bridge)
│ │ │
│ ┌────┴────┐ Physical LAN
│ │ WireGuard│ devices
│ │ Tunnels │
│ ├──────────┤
│ │ beeline │──→ 188.68.168.24:65215 (Russian services)
│ │ wg_mesh │──→ 57.129.12.112:65215 (Mesh VPN, future)
│ │ wg_srv │←── Remote clients (future, via mesh VPS)
│ └──────────┘
│
├─ radio0 (2.4GHz) ── "Lexmechanic Traffic Shrine"
└─ radio1 (5GHz) ── "Lexmechanic Traffic Shrine"
4. Implementation Phases
Phase 1: Base System (Day 1)
Goal: Working WiFi, secure SSH, correct timezone.
4.1.1 System Config
(/etc/config/system)
config system
option hostname 'lexmechanic'
option timezone 'EET-2EEST,M3.5.0/3,M10.5.0/4'
option zonename 'Europe/Nicosia'
option ttylogin '0'
option log_size '128'
option urandom_seed '0'
config timeserver 'ntp'
option enabled '1'
option enable_server '0'
list server '0.openwrt.pool.ntp.org'
list server '1.openwrt.pool.ntp.org'
list server '2.openwrt.pool.ntp.org'
list server '3.openwrt.pool.ntp.org'
4.1.2 WiFi Config
(/etc/config/wireless)
config wifi-device 'radio0'
option type 'mac80211'
option path 'platform/soc/18000000.wifi'
option band '2g'
option channel 'auto'
option htmode 'HE40'
option country 'CY'
option cell_density '0'
option disabled '0'
config wifi-iface 'default_radio0'
option device 'radio0'
option network 'lan'
option mode 'ap'
option ssid 'Lexmechanic Traffic Shrine'
option encryption 'sae-mixed'
option key 'mimkip99'
option ieee80211w '1'
config wifi-device 'radio1'
option type 'mac80211'
option path 'platform/soc/18000000.wifi+1'
option band '5g'
option channel 'auto'
option htmode 'HE80'
option country 'CY'
option cell_density '0'
option disabled '0'
config wifi-iface 'default_radio1'
option device 'radio1'
option network 'lan'
option mode 'ap'
option ssid 'Lexmechanic Traffic Shrine'
option encryption 'sae-mixed'
option key 'mimkip99'
option ieee80211w '1'
Notes: - sae-mixed =
WPA3-SAE + WPA2-PSK backwards compatibility (older devices
still connect) - ieee80211w '1' = Protected
Management Frames (optional, required for pure WPA3) -
country 'CY' = Cyprus regulatory domain
(enables correct channels/power) -
channel 'auto' = let the radio pick
least-congested channel
4.1.3 SSH Hardening
# Copy your public key to the router
ssh-copy-id root@192.168.1.1
# Then on the router, disable password auth:
uci set dropbear.@dropbear[0].PasswordAuth='0'
uci set dropbear.@dropbear[0].RootPasswordAuth='0'
uci commit dropbear
/etc/init.d/dropbear restart4.1.4 DNS — Use Cloudflare/Google instead of CYTA defaults
Add to /etc/config/dhcp:
config dnsmasq
# ... existing options ...
list server '1.1.1.1'
list server '8.8.8.8'
option noresolv '1'
noresolv '1' prevents dnsmasq from using the
upstream CYTA DNS (which may be slow or filter content).
Phase 2: Beeline WireGuard Tunnel (Day 1)
Goal: Russian service traffic from all LAN clients routed through Beeline VPN.
4.2.1 Install Required Packages
# Check which package manager is active
which apk && echo "apk" || echo "opkg"
# For SNAPSHOT with apk:
apk update && apk add \
kmod-wireguard \
wireguard-tools \
luci-proto-wireguard \
pbr \
luci-app-pbr
# For older SNAPSHOT with opkg:
opkg update && opkg install \
kmod-wireguard \
wireguard-tools \
luci-proto-wireguard \
pbr \
luci-app-pbr4.2.2 Generate Router Keys
umask go=
mkdir -p /etc/wireguard
wg genkey | tee /etc/wireguard/beeline.key | wg pubkey > /etc/wireguard/beeline.pubImportant: The existing Beeline config
from the PC uses a specific private key (starts with
EB1V...). You need to decide: - Option
A: Reuse the same keypair (move the tunnel from PC
to router) — simpler, but PC loses direct Beeline access -
Option B: Generate new keypair for router,
get a new peer registered with Beeline VPN provider — both
PC and router have independent tunnels - Option C
(recommended): Move tunnel to router, PC gets
Russian traffic via router’s policy routing automatically
since it’s on LAN
4.2.3
WireGuard Interface (/etc/config/network —
append)
config interface 'beeline'
option proto 'wireguard'
option private_key '<BEELINE_PRIVATE_KEY>'
list addresses '10.0.0.14/24'
option mtu '1420'
config wireguard_beeline 'beeline_peer'
option public_key 'fCX4n9VPFH6MIFbQOgBBiLHoQhfqy6eiY9l7SBXbbQ8='
option endpoint_host '188.68.168.24'
option endpoint_port '65215'
option persistent_keepalive '25'
option route_allowed_ips '0'
list allowed_ips '0.0.0.0/0'
Critical:
route_allowed_ips '0' — disables automatic
route injection. PBR handles routing instead.
4.2.4
Firewall Zone for Beeline (/etc/config/firewall
— append)
config zone 'beeline_zone'
option name 'beeline'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
option masq '1'
option mtu_fix '1'
list network 'beeline'
config forwarding 'lan_to_beeline'
option src 'lan'
option dest 'beeline'
4.2.5
Policy-Based Routing (/etc/config/pbr)
config pbr 'config'
option enabled '1'
option verbosity '2'
option strict_enforcement '1'
option resolver_set 'none'
option ipv6_enabled '0'
option boot_timeout '30'
list supported_interface 'beeline'
config policy 'beeline_ru_services'
option name 'Russian-Services-via-Beeline'
option enabled '1'
option interface 'beeline'
option dest_addr '37.9.244.0/23 80.243.78.0/23 46.17.203.0/24 95.213.45.0/24 95.213.44.0/24 95.213.0.0/18 95.213.0.0/17 95.142.207.0/24 95.142.206.0/24 95.142.204.0/23 95.142.203.0/24 95.142.202.0/24 95.142.201.0/24 95.142.192.0/21 95.142.192.0/20 93.186.232.0/21 93.186.224.0/21 93.186.224.0/20 87.240.167.0/24 87.240.166.0/24 87.240.128.0/18 79.137.180.0/24 79.137.167.0/24 79.137.164.0/24 79.137.139.0/24 79.137.132.0/24 185.32.251.0/24 185.32.249.0/24 185.32.248.0/22 185.29.130.0/24 185.29.128.0/22'
These are the exact CIDRs from your existing
beeline.conf AllowedIPs. All LAN traffic to
these destinations will go through Beeline
automatically.
4.2.6 Adding Beeline Mesh Subnet
The 10.0.0.0/24 subnet (Beeline internal)
also needs routing:
config policy 'beeline_internal'
option name 'Beeline-Internal-Mesh'
option enabled '1'
option interface 'beeline'
option dest_addr '10.0.0.0/24'
Phase 3: VPN Server — Outbound Tunnel via Mesh VPS (Day 2)
Goal: Remote access to home LAN via existing mesh VPS at 57.129.12.112.
Why outbound-only: CYTA VDSL = double NAT. Inbound connections require CYTA modem changes (bridge mode or port forwarding). The outbound approach works immediately with zero CYTA changes.
Architecture:
Remote client → 57.129.12.112 (mesh VPS) → WireGuard tunnel → OpenWRT → LAN
OpenWRT initiates outbound to VPS. VPS routes client traffic back through the tunnel.
4.3.1 Generate Mesh Keys
wg genkey | tee /etc/wireguard/mesh.key | wg pubkey > /etc/wireguard/mesh.pub4.3.2
WireGuard Mesh Interface (/etc/config/network —
append)
config interface 'wg_mesh'
option proto 'wireguard'
option private_key '<MESH_PRIVATE_KEY>'
list addresses '10.21.0.5/24'
config wireguard_wg_mesh 'mesh_gateway'
option public_key 'U7UvsR0uu7MZ56vLDLayzgsuj8cnijK8rY7qrwcdvyE='
option endpoint_host '57.129.12.112'
option endpoint_port '65215'
option persistent_keepalive '25'
option route_allowed_ips '1'
list allowed_ips '10.21.0.0/24'
Note: IP 10.21.0.5 is the
next free address in your mesh (after .1 gateway, .2 laptop,
.3 pc, .4 imac, .6 phone, .7 mio).
4.3.3
Mesh Firewall Zone (/etc/config/firewall —
append)
config zone 'mesh_zone'
option name 'mesh'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
list network 'wg_mesh'
config forwarding 'mesh_to_lan'
option src 'mesh'
option dest 'lan'
config forwarding 'lan_to_mesh'
option src 'lan'
option dest 'mesh'
4.3.4 VPS-Side Configuration (infrastructure-vpn repo)
Add new peer on the mesh gateway:
[Peer]
# OpenWRT One (lexmechanic)
PublicKey = <OPENWRT_MESH_PUBLIC_KEY>
AllowedIPs = 10.21.0.5/32, 192.168.1.0/24The 192.168.1.0/24 in AllowedIPs lets the
VPS route traffic destined for the home LAN through the
OpenWRT tunnel.
Phase 4: Future — Direct Inbound VPN (When Fiber Arrives)
When CYTA fiber is installed:
- Request bridge mode on the fiber ONT (call CYTA 132/150)
- Configure PPPoE on OpenWRT WAN (VLAN 42, LLC, MTU 1492)
- Install DDNS:
apk add luci-app-ddns ddns-scripts ddns-scripts-cloudflare curl ca-bundle - Add WireGuard server interface with
listen_port '51820' - Open port on WAN firewall: UDP 51820
- Generate client configs for phone, laptop
This phase is documented here for reference but NOT implemented now.
4.4.1 DDNS Config (for reference)
# /etc/config/ddns
config service 'wg_ddns'
option service_name 'cloudflare.com-v4'
option enabled '1'
option domain 'vpn.yourdomain.com'
option username 'your@email.com'
option password '<cloudflare_api_token>'
option interface 'wan'
option ip_source 'network'
option ip_network 'wan'
4.4.2 WireGuard Server Config (for reference)
config interface 'wg_srv'
option proto 'wireguard'
option private_key '<SERVER_PRIVATE_KEY>'
option listen_port '51820'
list addresses '192.168.9.1/24'
config wireguard_wg_srv 'peer_phone'
option description 'phone'
option public_key '<PHONE_PUBLIC_KEY>'
list allowed_ips '192.168.9.2/32'
config wireguard_wg_srv 'peer_laptop'
option description 'laptop'
option public_key '<LAPTOP_PUBLIC_KEY>'
list allowed_ips '192.168.9.3/32'
5. IP Address Plan
| Subnet | Purpose | Range |
|---|---|---|
| 192.168.1.0/24 | LAN (home network) | .1 = router, .100-.249 = DHCP |
| 10.0.0.0/24 | Beeline VPN mesh | .14 = router (or PC if separate) |
| 10.21.0.0/24 | WireGuard mesh VPN | .5 = router |
| 192.168.9.0/24 | VPN server clients (future) | .1 = router, .2+ = clients |
6. Package Inventory
| Package | Purpose | Phase |
|---|---|---|
kmod-wireguard |
WireGuard kernel module | 2 |
wireguard-tools |
wg CLI tool |
2 |
luci-proto-wireguard |
LuCI WireGuard UI | 2 |
pbr |
Policy-based routing engine | 2 |
luci-app-pbr |
LuCI PBR management UI | 2 |
luci-app-ddns |
DDNS management UI | 4 (future) |
ddns-scripts |
DDNS update client | 4 (future) |
ddns-scripts-cloudflare |
Cloudflare DDNS provider | 4 (future) |
curl |
HTTPS client for DDNS | 4 (future) |
ca-bundle |
CA certificates | Already installed |
7. Firewall Summary
| Zone | Input | Output | Forward | Masq | Networks |
|---|---|---|---|---|---|
| lan | ACCEPT | ACCEPT | ACCEPT | no | br-lan |
| wan | REJECT | ACCEPT | REJECT | yes | eth0, wan6 |
| beeline | REJECT | ACCEPT | REJECT | yes | beeline |
| mesh | ACCEPT | ACCEPT | ACCEPT | no | wg_mesh |
| Forwarding | Direction |
|---|---|
| lan → wan | Default internet |
| lan → beeline | Russian services (PBR) |
| lan ↔︎ mesh | Mesh VPN access |
| mesh → lan | Remote access to LAN |
8. Risks & Mitigations
| Risk | Impact | Mitigation |
|---|---|---|
| Beeline key conflict (PC vs router) | One device loses VPN | Move tunnel to router entirely (Option C) — PC gets routing via LAN |
| CYTA firmware resets bridge mode | VPN server unreachable | Use outbound-only tunnel (Phase 3) until fiber |
| SNAPSHOT package incompatibility | kmod version mismatch | Pin firmware version, don’t upgrade without checking kmod availability |
| PBR strict_enforcement drops traffic if Beeline is down | Russian sites unreachable | Acceptable — VPN is required for access anyway |
| Double NAT breaks VPN server | No inbound connections | Phase 3 (outbound via VPS) solves this without CYTA changes |
9. Implementation Checklist
Phase 1: Base System
Phase 2: Beeline WireGuard
Phase 3: Mesh VPN (optional, day 2)
Phase 4: VPN Server (future — when fiber arrives)
10. Rollback Plan
All configs are in ~/Work/openwrt-config/.
If anything breaks:
# Pull factory configs (already committed as baseline)
cd ~/Work/openwrt-config
git checkout HEAD~1 -- hosts/openwrt-one/config/
# Deploy
./scripts/deploy.sh openwrt-one
# Nuclear option: factory reset via hardware button
# Hold reset button 10+ seconds while powered on11. Config Repo Changes
After implementation, update
~/Work/openwrt-config/:
openwrt-config/
├── hosts/openwrt-one/
│ ├── config/
│ │ ├── dhcp # Updated DNS servers
│ │ ├── dropbear # SSH key-only auth
│ │ ├── firewall # + beeline zone, mesh zone
│ │ ├── network # + beeline WG, mesh WG interfaces
│ │ ├── pbr # NEW — policy routing config
│ │ ├── system # Updated hostname, timezone
│ │ └── wireless # Updated SSID, encryption
│ ├── keys/ # NEW — WireGuard public keys (NOT private)
│ │ ├── beeline.pub
│ │ └── mesh.pub
│ └── packages.txt # Updated package list
└── scripts/
├── deploy.sh # Update to include pbr config
└── pull.sh # Update to pull pbr config