fix(tollgate): fix nodogsplash provisioning order (found live: gated br-lan)
Deploying the previous commit's fix live exposed a real bug: nodogsplash's OpenWrt package postinst auto-enables and starts the service immediately on install, using its stock default config — gatewayinterface=br-lan. Since NoDogSplash only touches IPv4 iptables, this silently cut IPv4 (not IPv6) connectivity for anything on br-lan, including the admin management box plugged into this router's LAN port, for the window between install and our own configure step. Split nodogsplash provisioning into install_and_stop() (runs first, closes that window immediately) and configure() (runs after wifi::provision_ssid has created br-tollgate, so gatewayinterface is pointed at the isolated tollgate bridge instead of br-lan).
This commit is contained in:
parent
a252eb12fd
commit
7439a1251c
@ -14,12 +14,14 @@ use crate::{opkg::PkgManager, Router};
|
||||
|
||||
/// Full TollGate provisioning sequence:
|
||||
/// 1. Install tollgate-module-basic-go
|
||||
/// 2. Install and configure NoDogSplash (client gating — tollgate-wrt has no
|
||||
/// firewall/enforcement code of its own; see `nodogsplash::provision`)
|
||||
/// 2. Install NoDogSplash and immediately stop it (its postinst auto-starts
|
||||
/// it against `br-lan` by default — see `nodogsplash::install_and_stop`)
|
||||
/// 3. Write TollGate config: UCI (status/detection only) + the JSON file the
|
||||
/// daemon actually reads
|
||||
/// 4. Create the pay-as-you-go WiFi SSID and its dedicated bridge/network
|
||||
/// 5. Restart affected services
|
||||
/// 5. Configure NoDogSplash to gate that bridge (now that it exists) —
|
||||
/// client gating; tollgate-wrt has no enforcement code of its own
|
||||
/// 6. Restart affected services
|
||||
pub async fn provision(router: &Router, config: &TollGateConfig) -> Result<()> {
|
||||
info!("[{}] Starting TollGate provisioning", router.host);
|
||||
|
||||
@ -40,9 +42,11 @@ pub async fn provision(router: &Router, config: &TollGateConfig) -> Result<()> {
|
||||
// the raw .ipk-extraction fallback (used whenever the package isn't in a
|
||||
// feed, and always on ApkNative) skips dependency resolution entirely.
|
||||
// Without it, tollgate-wrt runs and accepts payments but never actually
|
||||
// blocks unpaid clients.
|
||||
nodogsplash::provision(router, pkg_mgr, config)
|
||||
.context("provision nodogsplash — tollgate-wrt cannot gate clients without it")?;
|
||||
// blocks unpaid clients. Install + stop happens before anything else so
|
||||
// its auto-started default config (gating br-lan) is live for as little
|
||||
// time as possible.
|
||||
nodogsplash::install_and_stop(router, pkg_mgr)
|
||||
.context("install nodogsplash — tollgate-wrt cannot gate clients without it")?;
|
||||
|
||||
config::apply(router, config)?;
|
||||
wifi::provision_ssid(router, config)?;
|
||||
@ -50,6 +54,11 @@ pub async fn provision(router: &Router, config: &TollGateConfig) -> Result<()> {
|
||||
// the daemon restart below — config.json is only read at startup.
|
||||
config::apply_daemon_config(router, config)
|
||||
.context("write /etc/tollgate/config.json — tollgate-wrt reads this, not UCI")?;
|
||||
// Also must come after provision_ssid: points gatewayinterface at
|
||||
// br-tollgate, which provision_ssid is what creates.
|
||||
nodogsplash::configure(router, config)
|
||||
.context("configure nodogsplash — tollgate-wrt cannot gate clients without it")?;
|
||||
|
||||
restart_services(router, config.enabled)?;
|
||||
nodogsplash::restart(router)?;
|
||||
|
||||
|
||||
@ -4,23 +4,40 @@ use crate::opkg::PkgManager;
|
||||
use crate::tollgate::TollGateConfig;
|
||||
use crate::Router;
|
||||
|
||||
/// Install and configure NoDogSplash — the captive-portal engine that
|
||||
/// `tollgate-wrt` delegates all MAC authorization and gate open/close to via
|
||||
/// `ndsctl`. `tollgate-wrt` contains no firewall/netfilter code of its own
|
||||
/// (confirmed: its binary has no `nft`/`ipset`/`iptables` calls at all); the
|
||||
/// upstream package therefore hard-depends on `+nodogsplash` and its postinst
|
||||
/// restarts it. Without NoDogSplash actually running, nothing blocks
|
||||
/// unauthenticated clients from reaching the internet, regardless of what
|
||||
/// TollGate itself is configured to charge.
|
||||
/// Install NoDogSplash and immediately stop it, before configuring anything.
|
||||
///
|
||||
/// Gates the dedicated `br-tollgate` bridge (see `wifi::provision_network`),
|
||||
/// not `br-lan` — the paid SSID here lives on its own isolated network/subnet
|
||||
/// rather than the canonical upstream layout where it's bridged into `lan`.
|
||||
pub fn provision(router: &Router, pkg_mgr: PkgManager, cfg: &TollGateConfig) -> Result<()> {
|
||||
/// The OpenWrt package's postinst auto-enables and starts nodogsplash on
|
||||
/// install using its stock default config — critically, `gatewayinterface`
|
||||
/// defaults to `br-lan`. On a fresh install that window is real: NoDogSplash
|
||||
/// only manages IPv4 iptables, so anything plugged into `br-lan` (e.g. an
|
||||
/// admin's own management box) silently loses IPv4 connectivity (DHCP still
|
||||
/// listens, but the gate blocks the client until ndsctl authorizes its MAC)
|
||||
/// until we get a chance to repoint it — a full network re-scan can take
|
||||
/// long enough for that to matter. Stopping it right after install, before
|
||||
/// `configure()` ever runs, closes that window as early as possible.
|
||||
///
|
||||
/// `tollgate-wrt` delegates all MAC authorization and gate open/close to
|
||||
/// NoDogSplash via `ndsctl` — it has no firewall/netfilter code of its own
|
||||
/// (confirmed: its binary has no `nft`/`ipset`/`iptables` calls at all).
|
||||
/// Upstream's package therefore hard-depends on `+nodogsplash`, but neither
|
||||
/// of our install paths (see `tollgate::install`) pull it in automatically.
|
||||
pub fn install_and_stop(router: &Router, pkg_mgr: PkgManager) -> Result<()> {
|
||||
router
|
||||
.install_package(pkg_mgr, "nodogsplash")
|
||||
.context("install nodogsplash — required by tollgate-wrt for client gating")?;
|
||||
router.run_ok("/etc/init.d/nodogsplash stop || true")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Configure NoDogSplash to gate the dedicated `br-tollgate` bridge (see
|
||||
/// `wifi::provision_network`), not `br-lan` — the paid SSID here lives on its
|
||||
/// own isolated network/subnet rather than the canonical upstream layout
|
||||
/// where it's bridged into `lan`.
|
||||
///
|
||||
/// Must run after `wifi::provision_ssid` has created `br-tollgate` — pointing
|
||||
/// `gatewayinterface` at a bridge that doesn't exist yet is at best a no-op
|
||||
/// and at worst leaves NoDogSplash in a confused state.
|
||||
pub fn configure(router: &Router, cfg: &TollGateConfig) -> Result<()> {
|
||||
router.run_ok("touch /etc/config/nodogsplash")?;
|
||||
router.uci_set("nodogsplash.main", "nodogsplash")?;
|
||||
router.uci_set("nodogsplash.main.enabled", "1")?;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user