Generated by report-publish

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:

  1. WiFi — Dual-band (2.4GHz + 5GHz), SSID “Lexmechanic Traffic Shrine”, WPA2/WPA3
  2. Beeline WireGuard tunnel — Policy-routed split tunnel for Russian service IP ranges
  3. VPN server capability — WireGuard server for future remote access (outbound-only tunnel through mesh VPS initially, inbound when fiber arrives)
  4. 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 restart

4.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-pbr

4.2.2 Generate Router Keys

umask go=
mkdir -p /etc/wireguard
wg genkey | tee /etc/wireguard/beeline.key | wg pubkey > /etc/wireguard/beeline.pub

Important: 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.pub

4.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/24

The 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:

  1. Request bridge mode on the fiber ONT (call CYTA 132/150)
  2. Configure PPPoE on OpenWRT WAN (VLAN 42, LLC, MTU 1492)
  3. Install DDNS: apk add luci-app-ddns ddns-scripts ddns-scripts-cloudflare curl ca-bundle
  4. Add WireGuard server interface with listen_port '51820'
  5. Open port on WAN firewall: UDP 51820
  6. 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 on

11. 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