diff options
| author | info@mode42.com <info@mode42.com> | 2026-08-08 03:54:55 +0000 |
|---|---|---|
| committer | info@mode42.com <info@mode42.com> | 2026-08-08 03:54:55 +0000 |
| commit | 20cb29c2f8c5c87bc590896854a20b1473ceb358 (patch) | |
| tree | 2857f41513a56ad41af97b57362639298aa7f033 /share | |
#2
Diffstat (limited to 'share')
26 files changed, 1354 insertions, 0 deletions
diff --git a/share/THIRD_PARTY_NOTICES.txt b/share/THIRD_PARTY_NOTICES.txt new file mode 100644 index 0000000..cf2c7c9 --- /dev/null +++ b/share/THIRD_PARTY_NOTICES.txt @@ -0,0 +1,22 @@ +HyBBX third-party notices +========================= + +libssh +------ + +The SSH transport plugin (`plugins/ssh/`) uses libssh for the SSHv2 server +protocol. + + Project: https://www.libssh.org/ + License: GNU Lesser General Public License v2.1 or later (LGPL-2.1+) + +HyBBX links against the shared libssh library (`libssh.so`) at build and +runtime. HyBBX source code does not incorporate libssh source. + +Under the LGPL you may replace the libssh shared library with a compatible +version without rebuilding HyBBX. Corresponding source code for the libssh +version you use is available from the libssh project and your OS distributor. + + SPDX-License-Identifier: LGPL-2.1-or-later + +See also LICENSE.txt for HyBBX (GPL-3.0). diff --git a/share/areas.yaml b/share/areas.yaml new file mode 100644 index 0000000..8a10d54 --- /dev/null +++ b/share/areas.yaml @@ -0,0 +1,66 @@ +# HyBBX menu layout — areas, per-level menu, and full index. +# Command help, aliases, access, and account rights: commands.yaml (loaded after). + +meta: + menu_header: "HyBBX commands /help <cmd> for more" + index_header: "HyBBX command-index /help <cmd> for more" + alias_header: "HyBBX aliases /help <cmd> for more" + +user_groups: + - Sysop + - Admin + - Mod + - User + - Guest + +areas: + - label: General + commands: [help, menu, index, alias, news, banner, motd, rules, who, users, session, version] + - label: Screen + commands: [clear, echo] + - label: Areas + commands: [leave, main, chat, conference, mail, proxymail, proxychat, exit] + - label: Account + commands: [login, changeme, register, deleteme] + - label: Admin + commands: [usercreate, activate, changeuser, promote, demote, delete] + - label: Sysop + commands: [deleteuser, shutdown, restart, broadcast, monitor] + +menu: + Guest: + - General + - Screen + - Account + - Areas + User: + - General + - Screen + - Areas + - Account + Mod: + - General + - Screen + - Areas + - Account + Admin: + - General + - Screen + - Areas + - Account + - Admin + Sysop: + - General + - Screen + - Areas + - Account + - Admin + - Sysop + +index: + - General + - Screen + - Areas + - Account + - Admin + - Sysop diff --git a/share/cgi/hybbx-telnet.cgi.example b/share/cgi/hybbx-telnet.cgi.example new file mode 100644 index 0000000..ba96ec4 --- /dev/null +++ b/share/cgi/hybbx-telnet.cgi.example @@ -0,0 +1,18 @@ +#!/bin/sh +# Example CGI bridge: hybbx-telnet to local HyBBX (telnet transport). +# Prefer WebSocket + reverse proxy when available — see docs/WEBSOCKET.md. +# +# Install: copy to cgi-bin, chmod +x, set HYBBX_TELNET and paths below. + +HYBBX_TELNET="${HYBBX_TELNET:-/usr/local/hybbx/hybbx-telnet}" +HOST="${HYBBX_HOST:-127.0.0.1}" +PORT="${HYBBX_PORT:-2323}" + +printf 'Content-Type: text/plain; charset=utf-8\r\n\r\n' + +if [ ! -x "$HYBBX_TELNET" ]; then + printf 'hybbx-telnet not found\n' + exit 1 +fi + +exec "$HYBBX_TELNET" -H "$HOST" -p "$PORT" --pace no diff --git a/share/commands.yaml b/share/commands.yaml new file mode 100644 index 0000000..0f97200 --- /dev/null +++ b/share/commands.yaml @@ -0,0 +1,306 @@ +# HyBBX command registry — help text, aliases, access levels, account rights. +# Menu layout and user groups: areas.yaml (loaded first). +# +# Help format (2 lines, max 80 cols): +# /<verb> placeholders +# Help: summary. More: subcommands or aliases +# No square brackets in session help/menu text. + +rights: + userchange: + - actor: Sysop + targets: [Admin, Mod, User] + - actor: Admin + targets: [Mod, User] + userdelete: + - actor: Sysop + targets: [Admin, Mod, User, Guest] + delete: + - actor: Sysop + targets: [Admin, Mod, User] + - actor: Admin + targets: [Mod, User] + promote: + - actor: Sysop + to: Admin + from: [User, Mod] + - actor: Sysop + to: Mod + from: [User] + - actor: Admin + to: Mod + from: [User] + demote: + - actor: Sysop + from: [Admin, Mod] + - actor: Admin + from: [Mod] + +aliases: + help: + - "?" + - command + - cmd + - commands + banner: + - loginmsg + rules: + - legal + who: + - online + version: + - ver + session: + - info + leave: + - back + clear: + - cls + - reset + exit: + - logout + - bye + - quit + delete: + - del + conference: + - meeting + usercreate: + - createuser + changeuser: + - userchange + deleteuser: + - userdelete + broadcast: + - announce + monitor: + - mon + proxymail: + - /mail proxymail + proxychat: + - /chat proxychat + +commands: + help: + group: general + min: Guest + line1: "/help cmd" + line2: "Help: Full command-index or /help <cmd>. More: /menu /alias." + + menu: + group: general + min: Guest + line1: "/menu" + line2: "Help: Full command-index for this Main. Same as /index." + + index: + group: general + min: Guest + line1: "/index" + line2: "Help: Full command-index for this Main. Same as /menu." + + alias: + group: general + min: Guest + line1: "/alias" + line2: "Help: Alternate names for commands. More: see /alias output." + + news: + group: general + min: Guest + line1: "/news" + line2: "Help: Show system news from news.txt." + + banner: + group: general + min: Guest + line1: "/banner" + line2: "Help: Show login banner from banner.txt. More: /loginmsg" + + motd: + group: general + min: Guest + line1: "/motd" + line2: "Help: Show message of the day." + + rules: + group: general + min: Guest + line1: "/rules" + line2: "Help: Show terms of use from rules.txt. More: /legal" + + who: + group: general + min: Guest + line1: "/who" + line2: "Help: Online interactive users (telnet/SSH/Web). More: /online" + + users: + group: general + min: User + line1: "/users" + line2: "Help: Registered users by level (Sysop Admin Mod User Guest)." + + session: + group: general + min: Guest + line1: "/session" + line2: "Help: Username, session id, transport. More: /info" + + version: + group: general + min: Guest + line1: "/version" + line2: "Help: Show text/version.txt (@version@ @os@). More: /ver" + + clear: + group: screen + min: Guest + line1: "/clear" + line2: "Help: Clear screen and discard input line. More: /cls /reset" + + echo: + group: screen + min: Guest + line1: "/echo yes|no" + line2: "Help: Show or set typed-character echo." + + leave: + group: areas + min: User + line1: "/leave" + line2: "Help: Up one area level. More: /back" + + main: + group: areas + min: User + line1: "/main" + line2: "Help: Return to main prompt." + + chat: + group: areas + min: User + line1: "/chat n|name|show|showall|proxychat" + line2: "Help: Join or list chat channels. More: /chat proxychat" + + conference: + group: areas + min: User + line1: "/conference topic user" + line2: "Help: Private two-user channel. More: /meeting" + + mail: + group: areas + min: User + line1: "/mail list|read|send|delete|recycle|proxymail ..." + line2: "Help: Personal mailbox on this Main. More: list read send delete" + + proxymail: + group: areas + min: User + line1: "/proxymail" + line2: "Help: mail to user@other-main. More: list read send delete recycle." + + proxychat: + group: areas + min: User + line1: "/proxychat" + line2: "Help: Chat with users on other mains. More: /chat proxychat" + + exit: + group: areas + min: Guest + line1: "/exit" + line2: "Help: Close connection. More: /quit /logout /bye" + + login: + group: account + min: Guest + line1: "/login username password" + line2: "Help: Log in with a registered account." + + register: + group: account + min: Guest + only: Guest + line1: "/register user name country location email password" + line2: "Help: Self-registration. Guest only. Sysop and Admin notified." + + changeme: + group: account + min: User + line1: "/changeme old new name country location email" + line2: "Help: Update own profile and password." + + deleteme: + group: account + min: User + max: Admin + line1: "/deleteme yes|no" + line2: "Help: Permanently delete own account." + + usercreate: + group: admin + min: Admin + line1: "/usercreate user name country location email" + line2: "Help: Create user account. Inactive until /activate. More: /createuser" + + activate: + group: admin + min: Admin + line1: "/activate username" + line2: "Help: Set username activated." + + changeuser: + group: admin + min: Admin + line1: "/changeuser user name country location email password" + line2: "Help: Overwrite user profile and password. More: /userchange" + + promote: + group: admin + min: Admin + line1: "/promote username admin|mod" + line2: "Help: Raise user to Admin or Mod." + + demote: + group: admin + min: Admin + line1: "/demote username" + line2: "Help: Set user to User level." + + delete: + group: admin + min: Admin + line1: "/delete username" + line2: "Help: Permanently remove account. More: /del" + + deleteuser: + group: sysop + min: Sysop + line1: "/deleteuser username" + line2: "Help: Delete any non-Sysop account. More: /userdelete" + + shutdown: + group: sysop + min: Sysop + line1: "/shutdown" + line2: "Help: Stop the HyBBX daemon." + + restart: + group: sysop + min: Sysop + line1: "/restart" + line2: "Help: Restart the HyBBX daemon." + + broadcast: + group: sysop + min: Sysop + line1: "/broadcast message | ax25" + line2: "Help: Local +++ announce or sequential RF beacon. More: /announce" + + monitor: + group: sysop + min: Sysop + line1: "/monitor on|off|list|cmds|meet user" + line2: "Help: Live log monitor and sysop admin menu. More: /mon" diff --git a/share/data.gitkeep b/share/data.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/share/data.gitkeep diff --git a/share/fail2ban/filter.d/hybbx-circuit.conf b/share/fail2ban/filter.d/hybbx-circuit.conf new file mode 100644 index 0000000..901e8a2 --- /dev/null +++ b/share/fail2ban/filter.d/hybbx-circuit.conf @@ -0,0 +1,10 @@ +# HyBBX HBX circuit link authentication failures (security.log). +# Matches failed LINK_AUTH on [circuit] port (default 7323). + +[INCLUDES] +before = common.conf + +[Definition] +_daemon = hybbx +failregex = ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} link_auth_fail ip=<HOST> .*transport=circuit +ignoreregex = diff --git a/share/fail2ban/filter.d/hybbx-ssh.conf b/share/fail2ban/filter.d/hybbx-ssh.conf new file mode 100644 index 0000000..407be52 --- /dev/null +++ b/share/fail2ban/filter.d/hybbx-ssh.conf @@ -0,0 +1,11 @@ +# HyBBX SSH transport login brute-force (security.log). +# Enable when [transport.ssh] is running and logs login_fail +# with transport=ssh to security.log. + +[INCLUDES] +before = common.conf + +[Definition] +_daemon = hybbx +failregex = ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} login_fail ip=<HOST> user=.* transport=ssh +ignoreregex = diff --git a/share/fail2ban/filter.d/hybbx-telnet.conf b/share/fail2ban/filter.d/hybbx-telnet.conf new file mode 100644 index 0000000..f6dfa53 --- /dev/null +++ b/share/fail2ban/filter.d/hybbx-telnet.conf @@ -0,0 +1,10 @@ +# HyBBX telnet login brute-force (security.log). +# Install: copy to /etc/fail2ban/filter.d/ and enable hybbx-telnet in jail.d. + +[INCLUDES] +before = common.conf + +[Definition] +_daemon = hybbx +failregex = ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} login_fail ip=<HOST> user=.* transport=telnet +ignoreregex = diff --git a/share/fail2ban/filter.d/hybbx-websocket.conf b/share/fail2ban/filter.d/hybbx-websocket.conf new file mode 100644 index 0000000..2166ee7 --- /dev/null +++ b/share/fail2ban/filter.d/hybbx-websocket.conf @@ -0,0 +1,11 @@ +# HyBBX WebSocket transport login brute-force (security.log). +# Enable when [transport.websocket] is running and logs login_fail +# with transport=websocket to security.log. + +[INCLUDES] +before = common.conf + +[Definition] +_daemon = hybbx +failregex = ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} login_fail ip=<HOST> user=.* transport=websocket +ignoreregex = diff --git a/share/fail2ban/jail.d/hybbx.local.example b/share/fail2ban/jail.d/hybbx.local.example new file mode 100644 index 0000000..3d91296 --- /dev/null +++ b/share/fail2ban/jail.d/hybbx.local.example @@ -0,0 +1,45 @@ +# Example fail2ban jails for HyBBX security.log +# +# HyBBX v2.0.0+ includes built-in [security] bans — these filters are optional +# for site-wide iptables/nftables integration alongside the daemon. +# +# 1. Copy filter.d/*.conf to /etc/fail2ban/filter.d/ +# 2. Copy this file to /etc/fail2ban/jail.d/hybbx.local +# 3. Set logpath to your HyBBX logs directory ([log] dir in hybbx.ini) +# 4. sudo fail2ban-client reload + +[hybbx-telnet] +enabled = true +filter = hybbx-telnet +port = 2323 +logpath = /usr/local/hybbx/logs/security.log +maxretry = 5 +findtime = 600 +bantime = 600 + +[hybbx-circuit] +enabled = true +filter = hybbx-circuit +port = 7323 +logpath = /usr/local/hybbx/logs/security.log +maxretry = 5 +findtime = 600 +bantime = 600 + +[hybbx-ssh] +enabled = false +filter = hybbx-ssh +port = 3232 +logpath = /usr/local/hybbx/logs/security.log +maxretry = 5 +findtime = 600 +bantime = 600 + +[hybbx-websocket] +enabled = false +filter = hybbx-websocket +port = 4591 +logpath = /usr/local/hybbx/logs/security.log +maxretry = 5 +findtime = 600 +bantime = 600 diff --git a/share/hybbx-main.ini.example b/share/hybbx-main.ini.example new file mode 100644 index 0000000..8573620 --- /dev/null +++ b/share/hybbx-main.ini.example @@ -0,0 +1,97 @@ +; SUPERSEDED — use share/hybbxd-main.ini.example (hybbxd Main instance) +; HyBBX v2.8.0 — Main (users + HBX hub; RF on remote Secondary) +; Pair with: share/hybbx-secondary.ini.example on the remote RF host +; Copy: cp share/hybbx-main.ini.example hybbx.ini + +[service] +name = hyBBX +login_announce = no +; login_announce = yes — "*** User login: user@plugin" (not Guest; not invisible Sysop); +; /who and /online list as user@plugin + +[storage] +backend = flatfile +path = data + +[auth] +auto_login = yes + +[traffic] +baud = 2400 +line_width = 80 +pace_output = yes +ansi = no + +[log] +enabled = yes +dir = logs +level = warn + + +[monitor] +enabled = yes +follow_hybbx = yes +follow_security = yes +invisible-sysop = no +invite_timeout_sec = 20 +; allow = Alice,Bob +; invisible-sysop = yes — Sysop always hidden from /who (even without /monitor on) + +[security] +enabled = yes +telnet = yes +ssh = yes +websocket = yes +circuit = yes + +[mail] +enabled = yes +path = mail + +[networks] +ax25 = no +baycom = no +tmodem = no +ssh = yes +websocket = yes +circuit = yes +mains_proxy = no + +[transport.telnet] +bind = 0.0.0.0 +port = 2323 + +[transport.ssh] +enabled = yes +bind = 0.0.0.0 +port = 3232 +hostkey_dir = keys + +[circuit] +bind = 127.0.0.1 +port = 7323 +link_auth = yes +link_password = changeme +max_links = 8 +balance = yes + +[broadcast] +enabled = yes +ax25 = yes +ax25_auto = yes +ax25_auto_interval = 300 +ax25_auto_stagger = 0 +ax25_auto_message = Broadcast: @service@ online +ax25_mycall = HYBBX +ax25_dest = QST + +[ax25] +frequency1 = 27.205 +frequency1_label = remote-A + +; Bridge registry — link_id/password/MHz must match Secondary [transport.packet_radioN] +[transport.packet_radio1] +link_id = secondary-1 +link_password = changeme +link_role = link +frequency_mhz = 27.205 diff --git a/share/hybbx-mesh.ini.example b/share/hybbx-mesh.ini.example new file mode 100644 index 0000000..6225048 --- /dev/null +++ b/share/hybbx-mesh.ini.example @@ -0,0 +1,93 @@ +; SUPERSEDED — use share/hybbxd-main.ini.example + hybbxsd-secondary / hybbxpd-proxy +; HyBBX v2.8.0 — Main + proxy mesh (mains_proxy) + remote Secondary RF +; Build: -DHYBBX_PLUGIN_MAINS_PROXY=ON · Pair Secondary: hybbx-secondary.ini.example +; Reciprocal peer INI required on remote Main. Docs: docs/MAINS_PROXY.md + +[service] +name = main-west +login_announce = no +; login_announce = yes — "*** User login: user@plugin" (not Guest; not invisible Sysop); +; /who and /online list as user@plugin + +[storage] +backend = flatfile +path = data + +[auth] +auto_login = yes + +[log] +enabled = yes +dir = logs +level = warn + + +[monitor] +enabled = yes +follow_hybbx = yes +follow_security = yes +invisible-sysop = no +invite_timeout_sec = 20 +; allow = Alice,Bob +; invisible-sysop = yes — Sysop always hidden from /who (even without /monitor on) + +[security] +enabled = yes +telnet = yes +ssh = yes +circuit = yes + +[mail] +enabled = yes +path = mail + +[networks] +ax25 = no +baycom = no +tmodem = no +ssh = yes +circuit = yes +mains_proxy = yes + +[transport.telnet] +bind = 0.0.0.0 +port = 2323 + +[circuit] +bind = 127.0.0.1 +port = 7323 +link_auth = yes +link_password = changeme +max_links = 8 +balance = yes + +[broadcast] +enabled = yes +ax25 = yes +ax25_auto = yes +ax25_auto_interval = 300 + +[ax25] +frequency1 = 27.205 + +; Outbound proxy peer (HBX to remote Main) +[transport.mains_proxy1] +peer_id = main-east +circuit_host = 192.0.2.10 +circuit_port = 7323 +link_id = main-west +link_password = changeme +wire = circuit +duplex = full + +; Inbound registry for remote peer (match their link_id on LINK_AUTH) +[transport.mains_proxy2] +peer_id = main-east +link_id = main-east +link_password = changeme + +; RF bridge — remote Secondary packet_radio +[transport.packet_radio1] +link_id = secondary-1 +link_password = changeme +frequency_mhz = 27.205 diff --git a/share/hybbx-secondary.ini.example b/share/hybbx-secondary.ini.example new file mode 100644 index 0000000..ab9db5e --- /dev/null +++ b/share/hybbx-secondary.ini.example @@ -0,0 +1,64 @@ +; SUPERSEDED — use share/hybbxsd-secondary.ini.example (hybbxsd Secondary instance) +; HyBBX v2.8.0 — Secondary (RF host → Main HBX hub) +; Pair with: share/hybbx-main.ini.example or share/hybbx-mesh.ini.example +; Prerequisite: max25d preps serial on this host — HyBBX KISS attach only. +; link_id / link_password / frequency_mhz must match Main [transport.packet_radioN] + +[service] +name = hyBBX-secondary +login_announce = no +; login_announce = yes — "*** User login: user@plugin" (not Guest; not invisible Sysop); +; /who and /online list as user@plugin + +[storage] +backend = flatfile +path = data-secondary + +[auth] +auto_login = no + +[log] +enabled = yes +dir = logs +level = warn + + +[monitor] +enabled = yes +follow_hybbx = yes +follow_security = yes +invisible-sysop = no +invite_timeout_sec = 20 +; allow = Alice,Bob +; invisible-sysop = yes — Sysop always hidden from /who (even without /monitor on) + +[networks] +ax25 = yes +baycom = no +tmodem = no +circuit = no + +[max25] +check = yes +host = 127.0.0.1 +port = 7325 +; error/voice STATUS: max25d [reporting] only (3×20s passes, 50% min good, defaults) + +[transport.packet_radio1] +circuit_host = main.example.com +circuit_port = 7323 +link_id = secondary-1 +link_password = changeme +frequency_mhz = 27.205 +tnc = tnc2c +protocol = kiss +device = /dev/ttyUSB0 +baud = 9600 +kiss_entry = none +modem = tcm3105 +radio_baud = 1200 +radio_band = amateur +radio_duplex = half + +[ax25] +frequency1 = 27.205 diff --git a/share/hybbx-standalone.ini.example b/share/hybbx-standalone.ini.example new file mode 100644 index 0000000..86cff32 --- /dev/null +++ b/share/hybbx-standalone.ini.example @@ -0,0 +1,125 @@ +; HyBBX v2.8.0 — Standalone Main (users + local RF on one host) +; Copy: cp share/hybbx-standalone.ini.example hybbx.ini +; Prerequisite: max25d (MAX25-Stack) preps serial/KISS — HyBBX attach only. +; PC-COM / BayCom/based: max25d max25e0 → /tmp/max25-bcpr/kiss-bc0 +; Docs: docs/MANUAL.md · docs/TNCS.md · docs/BAYCOM.md · docs/TOPOLOGY.md + +[instance] +standalone = yes + +[service] +name = hyBBX +; Process owner — required when started as root (hybbxd must not stay root) +user = hybbx +group = hybbx +login_announce = no +; login_announce = yes — "*** User login: user@plugin" (not Guest; not invisible Sysop); +; /who and /online list as user@plugin + +[storage] +backend = flatfile +path = data + +[auth] +auto_login = yes + +[traffic] +baud = 2400 +line_width = 80 +pace_output = yes +ansi = no + +[log] +enabled = yes +dir = logs +level = warn + + +[monitor] +enabled = yes +follow_hybbx = yes +follow_security = yes +invisible-sysop = no +invite_timeout_sec = 20 +; allow = Alice,Bob +; invisible-sysop = yes — Sysop always hidden from /who (even without /monitor on) + +[security] +enabled = yes +telnet = yes +ssh = yes +circuit = yes + +[mail] +enabled = yes +path = mail + +[networks] +; Standalone Main: enable local RF transports (TNC and/or BayCom/based) +ax25 = no +baycom = yes +tmodem = no +ssh = yes +circuit = yes + +[max25] +check = yes +host = 127.0.0.1 +port = 7325 +; error/voice STATUS: max25d [reporting] only (3×20s passes, 50% min good, defaults) + +[circuit] +bind = 127.0.0.1 +port = 7323 +link_auth = yes +link_password = changeme +max_links = 8 +balance = yes + +[broadcast] +enabled = yes +ax25 = yes +ax25_auto = yes +ax25_auto_interval = 300 +ax25_auto_stagger = 0 +ax25_auto_message = Broadcast: @service@ online +ax25_mycall = HYBBX +ax25_dest = QST + +[ax25] +frequency1 = 27.205 +frequency1_label = local-A + +; BayCom/based via MAX25 prep — KISS attach (PC-COM / SER12 userspace path) +[transport.baycom1] +backend = kiss +device = /tmp/max25-bcpr/kiss-bc0 +serial_baud = 1200 +radio_baud = 1200 +txdelay = 35 +slot = 10 +persist = 128 +txtail = 2 +circuit_host = 127.0.0.1 +circuit_port = 7323 +link_id = local-pccom +link_password = changeme +link_role = link +frequency_mhz = 27.205 + +; Optional TNC path (enable [networks] ax25=yes and comment out baycom if TNC-only) +; [transport.packet_radio1] +; link_id = local-radio1 +; link_password = changeme +; frequency_mhz = 27.205 +; circuit_host = 127.0.0.1 +; circuit_port = 7323 +; tnc = tnc2c +; protocol = kiss +; device = /dev/ttyUSB0 +; baud = 9600 +; kiss_entry = none +; modem = tcm3105 +; radio_baud = 1200 +; radio_band = amateur +; radio_duplex = half diff --git a/share/hybbx.ini.example b/share/hybbx.ini.example new file mode 100644 index 0000000..f730f46 --- /dev/null +++ b/share/hybbx.ini.example @@ -0,0 +1,17 @@ +; HyBBX v2.8.0 — INI topology (three instance binaries) +; +; Layout (hardcoded per binary): +; +; hybbxd Main — local BBX; WebSocket→reverse-proxy; mains_proxy↔Secondary +; hybbxsd Secondary — peer Mains via mains_proxy; transport plugins; no user BBX +; hybbxpd Proxy — TCP hybrid bridge; circuit→Main; no WebSocket/RF in-process +; +; Templates: +; hybbxd-main.ini.example Main (hybbxd) +; hybbxsd-secondary.ini.example Secondary (hybbxsd) +; hybbxpd-proxy.ini.example Proxy (hybbxpd) +; +; Legacy (superseded): hybbx-main.ini.example, hybbx-secondary.ini.example, +; hybbx-mesh.ini.example, hybbx-standalone.ini.example +; +; Default install: hybbxd-main.ini.example → hybbx.ini diff --git a/share/hybbxd-main.ini.example b/share/hybbxd-main.ini.example new file mode 100644 index 0000000..efcadf6 --- /dev/null +++ b/share/hybbxd-main.ini.example @@ -0,0 +1,82 @@ +; HyBBX Main — binary: hybbxd +; Local BBX (users/mail/chat). Remote users: WebSocket → reverse-proxy only. +; HBX circuit hub for Proxy (hybbxpd). mains_proxy for Secondary peers (hybbxsd). +; Copy: cp share/hybbxd-main.ini.example local/hybbx.ini + +[service] +name = hyBBX +; Required when hybbxd is started as root — process drops here before plugins bind +user = hybbx +group = hybbx +login_announce = no + +[storage] +backend = flatfile +path = data + +[auth] +auto_login = yes + +[traffic] +baud = 2400 +line_width = 80 +pace_output = yes +ansi = no + +[log] +enabled = yes +dir = logs +level = warn + +[monitor] +enabled = yes +follow_hybbx = yes +follow_security = yes +invisible-sysop = no +invite_timeout_sec = 20 + +[security] +enabled = yes +telnet = no +ssh = no +websocket = yes +circuit = yes + +[mail] +enabled = yes +path = mail + +[networks] +; Main layout: WebSocket user path + circuit hub + optional mains_proxy +telnet = no +ssh = no +websocket = yes +ax25 = no +baycom = no +tmodem = no +ardop = no +crdop = no +circuit = yes +mains_proxy = no + +[transport.websocket] +bind = 127.0.0.1 +port = 8080 +; Put nginx/caddy reverse-proxy in front for public TLS. + +[circuit] +enabled = yes +bind = 0.0.0.0 +port = 7323 +link_auth = yes +link_password = changeme +max_links = 8 +balance = yes + +; Example Proxy registry row (hybbxpd attaches with matching link_id/password) +; [transport.packet_radio1] — superseded: RF via MAX25 + hybbxpd, not Main packet_radio +[transport.baycom1] +link_id = proxy-1 +link_password = changeme +link_role = link +; Bridge credentials only on Main — no local device on hybbxd diff --git a/share/hybbxpd-proxy.ini.example b/share/hybbxpd-proxy.ini.example new file mode 100644 index 0000000..26a4f4b --- /dev/null +++ b/share/hybbxpd-proxy.ini.example @@ -0,0 +1,61 @@ +; HyBBX Proxy — binary: hybbxpd +; Hybrid bridge (router/gateway/relay posture). TCP/IP primary. +; No WebSocket. No in-process AX.25/packet_radio — RF via MAX25-Stack +; (relay / gateway / digipeater for hyBBX). +; Attach to Main (hybbxd) over HBX circuit. +; Copy: cp share/hybbxpd-proxy.ini.example local/hybbxpd.ini + +[service] +name = hyBBX-proxy + +[storage] +backend = flatfile +path = data-proxy + +[auth] +auto_login = no + +[log] +enabled = yes +dir = logs +level = warn + +[networks] +telnet = yes +ssh = yes +websocket = no +ax25 = no +baycom = no +tmodem = no +ardop = no +crdop = no +circuit = yes +mains_proxy = no + +[transport.telnet] +bind = 127.0.0.1 +port = 2323 + +[transport.ssh] +bind = 0.0.0.0 +port = 3232 + +; Client attach toward Main hub (not a circuit listener) +[circuit] +enabled = yes +; Proxy uses circuit_host on edge transports — hub stays on Main. + +; Example: TCP/hybrid edge toward Main (credentials must match Main bridge row) +[transport.baycom1] +enabled = no +; Prefer MAX25 relay/gateway/digipeater instead of in-process BayCom RF. +circuit_host = 192.0.2.1 +circuit_port = 7323 +link_id = proxy-1 +link_password = changeme +link_role = link + +[max25] +check = yes +host = 127.0.0.1 +port = 7325 diff --git a/share/hybbxsd-secondary.ini.example b/share/hybbxsd-secondary.ini.example new file mode 100644 index 0000000..25d737e --- /dev/null +++ b/share/hybbxsd-secondary.ini.example @@ -0,0 +1,41 @@ +; HyBBX Secondary — binary: hybbxsd +; Peer other Mains via mains_proxy only. Not a local user BBX (no hybbxd behaviour). +; Copy: cp share/hybbxsd-secondary.ini.example local/hybbxsd.ini + +[service] +name = hyBBX-secondary-peer + +[storage] +backend = flatfile +path = data-secondary + +[auth] +auto_login = no + +[log] +enabled = yes +dir = logs +level = warn + +[networks] +; Secondary = other-Main peers (mains_proxy). No user telnet/ssh/websocket. +telnet = no +ssh = no +websocket = no +ax25 = no +baycom = no +tmodem = no +ardop = no +crdop = no +circuit = no +mains_proxy = yes + +; Reciprocal peer on remote Main (hybbxd with mains_proxy=yes) +[transport.mains_proxy1] +enabled = yes +peer_id = main-east +circuit_host = 192.0.2.10 +circuit_port = 7323 +link_id = mesh-west-east +link_password = changeme +link_role = proxy diff --git a/share/logs.gitkeep b/share/logs.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/share/logs.gitkeep diff --git a/share/reverse-proxy/README.txt b/share/reverse-proxy/README.txt new file mode 100644 index 0000000..a11d1cc --- /dev/null +++ b/share/reverse-proxy/README.txt @@ -0,0 +1,6 @@ +HyBBX reverse-proxy examples. WebSocket plugin = session data on loopback only. + +1. HTTPD_DOCROOT=/srv/www # your httpd document root +2. cp -r docroot/hybbx-websocket $HTTPD_DOCROOT/ +3. Add nginx/apache/lighttpd snippet (adjust paths) +4. hybbx.ini [transport.websocket] — see docs/WEBSOCKET.md diff --git a/share/reverse-proxy/apache2.conf.example b/share/reverse-proxy/apache2.conf.example new file mode 100644 index 0000000..a361532 --- /dev/null +++ b/share/reverse-proxy/apache2.conf.example @@ -0,0 +1,24 @@ +# HyBBX — Apache httpd 2.4. HTTPD_DOCROOT example: /srv/www + +<IfModule mod_proxy.c> + ProxyPreserveHost On + ProxyTimeout 3600 + SSLProxyEngine On + SSLProxyVerify none + SSLProxyCheckPeerCN off + SSLProxyCheckPeerName off + + ProxyPass "/hybbx-websocket/ws" "wss://127.0.0.1:4591/hybbx" timeout=3600 keepalive=On + ProxyPassReverse "/hybbx-websocket/ws" "wss://127.0.0.1:4591/hybbx" +</IfModule> + +Alias /hybbx-websocket /srv/www/hybbx-websocket +<Directory /srv/www/hybbx-websocket> + DirectoryIndex index.php + Require all granted + <FilesMatch \.php$> + SetHandler application/x-httpd-php + </FilesMatch> +</Directory> + +# UI: cp -r reverse-proxy/docroot/hybbx-websocket $HTTPD_DOCROOT/ diff --git a/share/reverse-proxy/docroot/README.txt b/share/reverse-proxy/docroot/README.txt new file mode 100644 index 0000000..0c820fe --- /dev/null +++ b/share/reverse-proxy/docroot/README.txt @@ -0,0 +1,7 @@ +Copy docroot/hybbx-websocket/ to HTTPD_DOCROOT (not HYBBX_ROOT). +HyBBX websocket plugin ships session data only on loopback :4591. + + HTTPD_DOCROOT=/srv/www + cp -r docroot/hybbx-websocket $HTTPD_DOCROOT/ + +Match URL paths in hybbx.ini and the httpd snippets in docs/WEBSOCKET.md. diff --git a/share/reverse-proxy/docroot/hybbx-websocket/hybbx-terminal.js b/share/reverse-proxy/docroot/hybbx-websocket/hybbx-terminal.js new file mode 100644 index 0000000..50fb826 --- /dev/null +++ b/share/reverse-proxy/docroot/hybbx-websocket/hybbx-terminal.js @@ -0,0 +1,95 @@ +(function () { + 'use strict'; + + var term = document.getElementById('term'); + var status = document.getElementById('status'); + var form = document.getElementById('input-bar'); + var input = document.getElementById('cmd'); + var wsUrl = window.HYBBX_WS_URL; + var ws = null; + var reconnectTimer = null; + var reconnectDelayMs = 2000; + var reconnectAttempt = 0; + + function append(text) { + term.textContent += text; + term.scrollTop = term.scrollHeight; + } + + function setStatus(s) { + status.textContent = s; + } + + function scheduleReconnect() { + if (reconnectTimer) { + return; + } + + reconnectAttempt += 1; + setStatus('reconnecting in ' + (reconnectDelayMs / 1000) + 's'); + reconnectTimer = window.setTimeout(function () { + reconnectTimer = null; + connect(); + }, reconnectDelayMs); + } + + function setInputEnabled(enabled) { + input.disabled = !enabled; + if (enabled) { + input.focus(); + } + } + + function sendLine(text) { + if (!ws || ws.readyState !== WebSocket.OPEN) { + return; + } + + ws.send(text + '\r'); + } + + function connect() { + setStatus('connecting'); + setInputEnabled(false); + ws = new WebSocket(wsUrl); + + ws.onopen = function () { + reconnectAttempt = 0; + setStatus('connected'); + setInputEnabled(true); + }; + + ws.onmessage = function (ev) { + append(ev.data); + }; + + ws.onclose = function (ev) { + var reason = ev.reason ? ' (' + ev.reason + ')' : ''; + + append('\n[websocket disconnected: code ' + ev.code + reason + ']\n'); + setStatus('disconnected: ' + ev.code); + ws = null; + setInputEnabled(false); + scheduleReconnect(); + }; + + ws.onerror = function () { + setStatus('error'); + setInputEnabled(false); + }; + } + + form.addEventListener('submit', function (ev) { + ev.preventDefault(); + + if (!ws || ws.readyState !== WebSocket.OPEN) { + return; + } + + sendLine(input.value); + input.value = ''; + input.focus(); + }); + + connect(); +})(); diff --git a/share/reverse-proxy/docroot/hybbx-websocket/index.php b/share/reverse-proxy/docroot/hybbx-websocket/index.php new file mode 100644 index 0000000..52a060c --- /dev/null +++ b/share/reverse-proxy/docroot/hybbx-websocket/index.php @@ -0,0 +1,89 @@ +<?php +/** + * HyBBX browser terminal — copy this folder to your httpd document root. + * WebSocket data comes from hybbx only; this file is not part of the daemon. + */ +$base = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? ''), '/'); +$ws_path = ($base !== '' ? $base : '/hybbx-websocket') . '/ws'; +$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'wss' : 'ws'; +$host = $_SERVER['HTTP_HOST'] ?? 'localhost'; +$ws_url = $scheme . '://' . $host . $ws_path; +?><!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>HyBBX</title> + <style> + html, body { height: 100%; margin: 0; } + body { + display: flex; + flex-direction: column; + background: #0a0a12; + color: #c8d0d8; + font-family: ui-monospace, "Cascadia Mono", "Consolas", monospace; + } + #status { + position: fixed; + top: 0; + right: 0; + padding: .5rem 1rem; + font-size: .8rem; + background: #1a1a28; + z-index: 1; + } + #term { + flex: 1; + min-height: 0; + box-sizing: border-box; + width: 100%; + margin: 0; + padding: 1rem; + padding-bottom: .5rem; + white-space: pre-wrap; + overflow-y: auto; + overflow-x: hidden; + } + #input-bar { + flex: none; + display: flex; + width: 100%; + box-sizing: border-box; + border-top: 1px solid #2a2a38; + background: #12121c; + } + #cmd { + flex: 1; + width: 100%; + min-width: 0; + box-sizing: border-box; + border: none; + border-radius: 0; + background: #12121c; + color: #e0e4e8; + font: inherit; + font-size: 1rem; + line-height: 1.4; + padding: .75rem 1rem; + outline: none; + } + #cmd::placeholder { color: #6a7280; } + #cmd:focus { background: #161622; } + #cmd:disabled { opacity: .55; cursor: not-allowed; } + </style> +</head> +<body> + <div id="status">disconnected</div> + <pre id="term"></pre> + <form id="input-bar" autocomplete="off"> + <input type="text" id="cmd" disabled + autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" + enterkeyhint="send" + placeholder="Type command or text — Enter to send"> + </form> + <script> + window.HYBBX_WS_URL = <?php echo json_encode($ws_url, JSON_UNESCAPED_SLASHES); ?>; + </script> + <script src="hybbx-terminal.js"></script> +</body> +</html> diff --git a/share/reverse-proxy/lighttpd.conf.example b/share/reverse-proxy/lighttpd.conf.example new file mode 100644 index 0000000..1ef9244 --- /dev/null +++ b/share/reverse-proxy/lighttpd.conf.example @@ -0,0 +1,26 @@ +# HyBBX — lighttpd 1.4. HTTPD_DOCROOT example: /srv/www + +# Raise idle limits for upgraded WebSocket connections. +server.max-read-idle = 3600 +server.max-write-idle = 3600 + +$HTTP["url"] == "/hybbx-websocket/ws" { + proxy.server = ( "" => ( + "hybbx" => ( + "proxy" => "https://127.0.0.1:4591/hybbx", + "upgrade" => "enable" + ) + )) + proxy.header = ( "upgrade" => "enable" ) +} + +alias.url += ( "/hybbx-websocket/" => "/srv/www/hybbx-websocket/" ) +index-file.names += ( "index.php" ) + +fastcgi.server += ( ".php" => + ( "localhost" => + ( "socket" => "/run/php-fpm/www.sock" ) + ) +) + +# UI: cp -r reverse-proxy/docroot/hybbx-websocket $HTTPD_DOCROOT/ diff --git a/share/reverse-proxy/nginx.conf.example b/share/reverse-proxy/nginx.conf.example new file mode 100644 index 0000000..c916379 --- /dev/null +++ b/share/reverse-proxy/nginx.conf.example @@ -0,0 +1,28 @@ +# HyBBX — nginx. Set HTTPD_DOCROOT (example: /srv/www). + +location = /hybbx-websocket/ws { + proxy_pass https://127.0.0.1:4591/hybbx; + proxy_ssl_verify off; + proxy_http_version 1.1; + proxy_socket_keepalive on; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; +} + +location /hybbx-websocket/ { + root /srv/www; + index index.php; + location ~ \.php$ { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_pass unix:/run/php-fpm/www.sock; + } +} + +# UI: cp -r reverse-proxy/docroot/hybbx-websocket $HTTPD_DOCROOT/ +# Plain ws: proxy_pass http://127.0.0.1:4591/hybbx; |
