diff --git a/packages/secubox-toolbox/conf/landing.html.j2 b/packages/secubox-toolbox/conf/landing.html.j2 index c5ad5571..33a041b2 100644 --- a/packages/secubox-toolbox/conf/landing.html.j2 +++ b/packages/secubox-toolbox/conf/landing.html.j2 @@ -241,19 +241,40 @@ LXC toolbox-mitm-wg 10.100.0.62 R3 WireGuard - {# ── Install demo ── #} + {# ── Install : auto-detected platform panels (Phase 8.2 #500) ── #}
-

📥 Démo : installer le mode R3 portable

-
    -
  1. Installer l'app WireGuard (gratuite, App Store / Play Store)
  2. -
  3. Aller sur 🌐 page d'install R3 → scanner le QR avec l'app WireGuard
  4. -
  5. Activer le tunnel dans l'app WireGuard → icône VPN apparaît dans iOS
  6. -
  7. Ouvrir n'importe quelle page web → bandeau ToolBox apparaît + rapport temps réel se remplit
  8. -
  9. Désactiver le tunnel à tout moment → retour au surf normal
  10. -
-

- Avantage R3 : marche hors-cabine (4G/5G, autre WiFi). Inclus tout le trafic (HTTPS + QUIC). - Profile + CA bundlés dans un seul fichier .conf. +

📥 Installer R3 sur ton appareil

+

+ On a détecté {{ install_platform }} via ton navigateur — le panneau adapté + est ouvert en premier. Autre appareil ? Déplie le bon panneau ci-dessous. +

+ + {{ install_panels | safe }} +

+ Avantage R3 : marche hors-cabine (4G/5G, autre WiFi). Inclut tout le trafic (HTTPS). + Profil + CA bundlés. Le tunnel est révoquable à tout moment depuis Réglages. + Page équivalente standalone : /wg/onboard.

diff --git a/packages/secubox-toolbox/debian/changelog b/packages/secubox-toolbox/debian/changelog index e8d15357..b57f2107 100644 --- a/packages/secubox-toolbox/debian/changelog +++ b/packages/secubox-toolbox/debian/changelog @@ -1,3 +1,16 @@ +secubox-toolbox (2.4.2-1~bookworm1) bookworm; urgency=medium + + * Landing page kbin.gk2.secubox.in : la section 'Démo install R3' + est remplacée par les panneaux platform-detected du /wg/onboard. + UA sniff côté serveur (iOS / Android / Linux / macOS / Windows), + le panneau de la plate-forme du visiteur est ouvert en premier ; + les autres restent en details collapsed. Single source of truth : + _install_panels_html() partagé entre /wg/onboard et la landing. + Visiteur arrive sur kbin → voit immédiatement le bouton d'install + adapté à son device, sans devoir aller sur une page tierce. + + -- Gérald Kerma lun., 08 juin 2026 15:51:43 +0000 + secubox-toolbox (2.4.1-1~bookworm1) bookworm; urgency=medium * Phase 8.1 perf (#500) — mitm-wg CPU bottleneck under multi-peer. diff --git a/packages/secubox-toolbox/secubox_toolbox/api.py b/packages/secubox-toolbox/secubox_toolbox/api.py index aa543591..0aea5dd2 100644 --- a/packages/secubox-toolbox/secubox_toolbox/api.py +++ b/packages/secubox-toolbox/secubox_toolbox/api.py @@ -411,16 +411,73 @@ async def cumulative_stats_json() -> dict: return _cumulative_stats() +def _ua_platform(ua: str) -> str: + """Cheap UA sniff. Same logic as /wg/onboard so the auto-open panel + matches between the two pages.""" + ua = (ua or "").lower() + if "iphone" in ua or "ipad" in ua or "ios" in ua: + return "ios" + if "android" in ua: + return "android" + if "macintosh" in ua or "mac os x" in ua: + return "macos" + if "windows" in ua: + return "windows" + if "linux" in ua: + return "linux" + return "other" + + +def _install_panels_html(platform: str) -> str: + """Reusable platform-detected install panels for both + /wg/onboard and the landing page. Same content, same CSS classes + so styling stays consistent (the landing page injects matching + classes via its own style block).""" + panels = { + "ios": ("🍎 iPhone / iPad", "ios"), + "android": ("🤖 Android", "android"), + "linux": ("🐧 Linux", "linux"), + "macos": ("🍏 macOS", "macos"), + "windows": ("🪟 Windows", "windows"), + } + order = [platform] + [k for k in panels if k != platform] + order = [k for i, k in enumerate(order) if k in panels and k not in order[:i]] + sections = [] + for key in order: + title, slug = panels[key] + body = _ONBOARD_BODY[slug] + open_attr = " open" if key == order[0] else "" + sections.append( + f'
' + f'{title.split()[0]} ' + f'{title}{body}
' + ) + return "\n".join(sections) + + @router.get("/landing", response_class=HTMLResponse) @router.get("/cabine", response_class=HTMLResponse) async def landing(request: Request) -> HTMLResponse: """Public landing page for the cabine — shown on kbin.gk2.secubox.in. Visitor-facing demo of the project : pitch + 4 levels + install + live - cumulative anonymous stats + open source license + contact.""" + cumulative anonymous stats + open source license + contact. + + Phase 8.2 (#500) — embeds the same platform-detected install + panels as /wg/onboard so visitors get a one-click flow matching + their device right on the landing page. + """ stats = _cumulative_stats() - return HTMLResponse(_env.get_template("landing.html.j2").render(stats=stats), - headers={"Cache-Control": "public, max-age=60"}) + platform = _ua_platform(request.headers.get("user-agent") or "") + install_panels = _install_panels_html(platform) + return HTMLResponse( + _env.get_template("landing.html.j2").render( + stats=stats, + install_panels=install_panels, + install_platform=platform, + ), + headers={"Cache-Control": "private, max-age=60, no-transform"}, + ) @router.get("/ca/webclip-cabine.mobileconfig")