DOOR HUB 0.1.0 - RUNNING A HUB For sysops who want to host games for other BBSes CONTENTS 1. How a hub works 2. What you need 3. Preparing the door BBS (Synchronet) 4. Installing the hub on Linux 5. Installing the hub on Windows 6. Settings 7. Games 8. Member BBSes 9. Players 10. Opening the hub to the internet 11. Logs and statistics 12. Security 13. Backups and moving the hub 14. Troubleshooting 15. Command reference 1. HOW A HUB WORKS ------------------ member BBS --RLogin--> connector --SSH tunnel--> hub --RLogin--> door BBS (caller) (on the member's machine) (doorhub) (your Synchronet) - Each member BBS has a hub account: an SSH user name and password and a system tag. The hub accepts only RLogin tunnels on these accounts; there is no shell, no file access and no other forwarding. - The member's BBS sends: the caller's password, [TAG]Name, and a game code in the RLogin terminal type. The hub checks that the tag belongs to the account that logged in. - The hub keeps its own list of players. The first time it sees [TAG]Name it makes a user on your Synchronet BBS (the "door BBS") called "Name (TAG)", with a random password only the hub knows. - It then logs that user in to your Synchronet by RLogin with the terminal type xtrn=CODE. Synchronet's logon.js runs that door straight away and hangs up when it ends, so the player never sees your BBS's menus. - If the member BBS asked for a game, the player goes back to their BBS when it ends. If they came through the hub menu, they return to the menu. All the hub's data is in one folder: hub.json (settings, member BBSes, games), players.json, the SSH host key host_ed25519, mkuser.js (written by the hub each time it starts) and, for a service, doorhub.log. 2. WHAT YOU NEED ---------------- - Linux (x64 or arm64) or Windows (64-bit) with a Synchronet BBS on the same machine. Door Hub was built and tested with Synchronet 3.22; any recent version with rlogin_auto_xtrn in logon.js works. This BBS is the "door BBS": the games run on it. It can be your main BBS, or a separate one just for the hub. - The doors you want to share, installed and working on that BBS. - For members outside your network: a fixed internet address or a DNS name, and one TCP port forwarded to the hub (2022 by default). - Permission to share each door with other BBSes. Your own doors and free software are fine. Check the licence of commercial doors: some registrations cover one BBS only. 3. PREPARING THE DOOR BBS (SYNCHRONET) -------------------------------------- 3.1 RLogin must be on. In ctrl/sbbs.ini, section [BBS]: Options = ... | ALLOW_RLOGIN RLoginPort = 513 The hub connects from the same machine (127.0.0.1). You don't need to open port 513 to the internet for the hub. 3.2 Direct-to-door logins must be on. In ctrl/modopts.ini, section [logon]: rlogin_auto_xtrn = true 3.3 Check the doors. Each door you share needs an Internal Code (shown in SCFG > External Programs > Online Programs) and must be usable by a new user: - The section's and the program's Access Requirements must allow a new user. Blank, ANSI or NOT GUEST are fine; SYSOP is not. - Hub players are made with your BBS's normal new-user settings (security level, flags, time per day). If you limit new users, hub players are limited the same way. It doesn't matter which section a door is in: the hub starts it by its Internal Code. You can put the shared doors in their own section. 3.4 Doors that run multi-node (LORD, Ember Reach and so on) need Multiple Concurrent Users set, like for any busy BBS. 3.5 If your BBS asks new users questions at logon, that doesn't affect hub players: the hub makes them with jsexec, not through the new-user form. 3.6 Restart Synchronet (or let it recycle) after changing sbbs.ini or modopts.ini. 4. INSTALLING THE HUB ON LINUX ------------------------------ The hub must run as the same user as Synchronet, because it creates users with Synchronet's jsexec. These steps assume that user is "sbbs". sudo mkdir /opt/doorhub sudo cp doorhub /opt/doorhub/ sudo chown -R sbbs: /opt/doorhub sudo chmod 700 /opt/doorhub sudo ln -s /opt/doorhub/doorhub /usr/local/bin/doorhub sudo -u sbbs doorhub init init makes /opt/doorhub/hub.json and the host key and prints the key's fingerprint. Give that fingerprint to member sysops so they can check it. If Synchronet is not in /sbbs: sudo -u sbbs doorhub set jsexec /path/to/sbbs/exec/jsexec sudo -u sbbs doorhub set sbbs_ctrl /path/to/sbbs/ctrl Set your public name (what members put in ssh_host), add games and members (sections 7 and 8), then try it in the foreground: sudo -u sbbs doorhub serve Run it as a service. Edit doorhub.service (from the package) so User, Group and paths match, then: sudo cp doorhub.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now doorhub systemctl status doorhub The admin commands (doorhub bbs ..., doorhub door ...) work while the hub is running, and changes apply at once. Run them as the hub's user (sudo -u sbbs doorhub ...) so the files keep the right owner. The folder is /opt/doorhub unless you use -d folder or the DOORHUB_DIR environment variable. 5. INSTALLING THE HUB ON WINDOWS -------------------------------- 1. Make a folder C:\doorhub and copy doorhub.exe into it. (Another folder works; then add -d C:\your\folder to every command, or set the environment variable DOORHUB_DIR.) 2. Open a Command Prompt as Administrator and run: cd C:\doorhub doorhub init 3. If Synchronet is not in C:\sbbs: doorhub set jsexec D:\sbbs\exec\jsexec.exe doorhub set sbbs_ctrl D:\sbbs\ctrl 4. Set the public name, add games and members (sections 7 and 8), then try it: doorhub serve Windows Firewall asks whether doorhub.exe may accept connections. Allow it on the networks your members connect from. Ctrl+C stops it. 5. Install it as a Windows service so it starts with Windows: doorhub service install doorhub service start The service is "Door Hub" (DoorHub). It runs as Local System and restarts itself if it stops. Its log is C:\doorhub\doorhub.log. To stop or remove it: doorhub service stop doorhub service remove Windows notes: - The hub creates Synchronet users with jsexec.exe. Local System can write to C:\sbbs by default. If Synchronet runs as another account and you have tightened permissions on its folders, set the DoorHub service to log on as that account (services.msc > Door Hub > Log On). - Keep doorhub.exe, jsexec.exe and the Synchronet folders on a local drive. 6. SETTINGS ----------- doorhub settings show them doorhub set change one hub_name Name shown at the top of the hub menu. listen Address and port the hub listens on. ":2022" means every address, port 2022. Needs a hub restart. public_host Your hub's internet name, put into the connector ini that "bbs add" prints. public_port The port members connect to (may differ from listen if your router forwards another port). backend_rlogin Your Synchronet RLogin server, normally 127.0.0.1:513. jsexec Path to Synchronet's jsexec program. sbbs_ctrl Path to Synchronet's ctrl folder. max_sessions_per_bbs How many players one member BBS may have on the hub at once. 0 means no limit. Default 10. new_user_comment The comment set on users the hub creates, so you can find them in your user editor. Everything except listen applies straight away. 7. GAMES -------- doorhub door add "" what member BBSes send to start this game, for example lord. Lower case letters, digits, - and _, up to 20. INTERNAL CODE the door's Internal Code on your Synchronet (SCFG). name shown in the hub menu. Examples (the Kalgoorlie Door Hub): doorhub door add lord LORD "Legend of the Red Dragon" doorhub door add reach REACH "Ember Reach" doorhub door add seal SEAL "The Broken Seal" doorhub door add wake LONGWAKE "The Long Wake" Other commands: doorhub door list games, open or closed, play counts doorhub door disable close a game (it leaves the menu; direct requests get the menu instead) doorhub door enable doorhub door rename "" doorhub door remove The menu lists open games by name, keys 1-9 then A-Z (no Q, which returns the player to their BBS). Send your members the list of codes so they can make direct menu entries (SYSOP.TXT section 6). Test a new game yourself first: log on to your Synchronet as a new user and run it, so you know the door works before members try it. 8. MEMBER BBSES --------------- Adding a BBS: doorhub bbs add "" [--user ] [--contact ""] TAG 2 to 8 letters or digits, shown in front of the BBS's players' names. Must be unique. --user the SSH user name for the BBS (default: tag in lower case followed by _bbs). Lower case letters, digits, _ . and -. --contact anything that helps you reach the sysop (email, netmail). The command prints a complete doorhub-connector.ini, with a new random 32-character password. The password is shown only this once: the hub keeps only a bcrypt hash of it. Send the ini to the member sysop over a private channel (email to a known address, netmail, encrypted file), not in a public message base. Example: $ doorhub bbs add EXB "The Example BBS" --contact "sysop@example.com" Added EXB (The Example BBS). The password is shown only now. ; doorhub-connector.ini for The Example BBS system_tag = EXB ssh_username = exb_bbs ssh_password = 8kQm... local_interface = 127.0.0.1 local_port = 9998 ssh_host = hub.example.com ssh_port = 2022 rlogin_host = 127.0.0.1 rlogin_port = 513 Looking after members: doorhub bbs list all members, enabled or not, last seen doorhub bbs show details and number of players doorhub bbs passwd new password (prints a new ini); the old one stops working for new logins doorhub bbs disable block the BBS. New sessions are refused at once, even through an open tunnel. Games already running carry on. doorhub bbs enable doorhub bbs note "" keep a note (shown by bbs show) doorhub bbs remove delete the account. Its players stay in players.json and on your Synchronet, so game progress isn't lost if the BBS comes back with the same tag. "Last seen" is the last time the BBS's connector logged in. A connector keeps one SSH connection open and reuses it for every caller, so this changes when the connector starts or reconnects, not for every game. 9. PLAYERS ---------- doorhub player list [TAG] players, newest first: hub name, door BBS user, first and last seen, plays per game doorhub player reset "[TAG]Name" forget the player's remote password. The next password that arrives for that name is kept. When the hub first sees [TAG]Name it makes the Synchronet user "Name (TAG)" (shortened to fit Synchronet's 25 characters, with a number added if two players would get the same name). The user's password is random and known only to the hub. Each session the hub runs mkuser.js with jsexec to make sure the user exists and the password is right, so if you delete a hub user in Synchronet it's simply made again (with a fresh start in every game). Each player's first password from their BBS is stored as a bcrypt hash. A different password for the same name is refused with "Your Door Hub password doesn't match". This stops a new caller who takes an old name on a member BBS from playing as the old caller. When a member rebuilds their user base, reset their players. Player names may be up to 30 characters and can't contain [ or ]. 10. OPENING THE HUB TO THE INTERNET ----------------------------------- 1. Give the hub machine a fixed LAN address. 2. On your router, forward one TCP port (2022, or another) to the hub machine's port 2022 (the listen setting). 3. Give it a name. A DNS name (hub.example.com) is better than an IP address, because members don't need to change anything if your address changes. 4. doorhub set public_host hub.example.com doorhub set public_port 2022 (the outside port) 5. From outside your network, check the port answers: ssh -p 2022 test@hub.example.com It should ask for a password and refuse it. (That's the hub: it doesn't allow shells.) Only port 2022 needs to be open. The Synchronet RLogin port does not. The hub will see password guesses from the internet like any SSH server. Every failed login is logged and delayed by two seconds, each connection gets three tries, and member passwords are long and random, so guessing isn't practical. A tool like fail2ban can also watch the log lines "Login refused for ...". 11. LOGS AND STATISTICS ----------------------- The hub logs to standard output (journalctl -u doorhub with the provided unit, or the file it appends to), or to doorhub.log in the hub folder when it runs as a Windows service. Lines look like: BBS KAL connected from 203.0.113.5:51800 New player [KAL]Heisenberg -> "Heisenberg (KAL)" [KAL]Heisenberg started lord [KAL]Heisenberg left lord after 12m40s Login refused for "kal_bbs" from 198.51.100.7:40122 [KAL] refused [KAL]Bob: BBS disabled or removed doorhub door list shows total plays per game; doorhub player list shows plays per player. Play counts are in players.json if you want to make your own score lists. 12. SECURITY ------------ - Members can only open RLogin tunnels. Shell, exec, subsystem (SFTP), port forwarding to other places and every other SSH request are refused. Whatever address a connector asks to reach, the hub only ever talks RLogin to its own door BBS. - A member can only send players with its own tag. A connection claiming another tag is refused and logged. - Member passwords and player passwords are kept only as bcrypt hashes. - Door BBS passwords for hub users are random and stored in players.json, which (like the whole folder) should be readable only by the hub's account. - The host key host_ed25519 identifies your hub. Keep it secret and back it up: if you lose it, every member's connector refuses the new key until they delete their doorhub_known_hosts. - Doors run on your Synchronet as ordinary users, with the same limits as any caller. Treat member players like callers: a door that lets a caller reach a shell or files is just as risky through the hub. 13. BACKUPS AND MOVING THE HUB ------------------------------ Back up the hub folder (hub.json, players.json, host_ed25519) and your Synchronet user base and game folders. To move the hub to another machine, stop it, copy the folder and the games, start it there, and point your DNS name at the new machine. Because the host key comes along, members don't need to change anything. A Linux hub folder works on Windows and the other way round, apart from the jsexec and sbbs_ctrl settings. 14. TROUBLESHOOTING ------------------- "Sorry, your Door Hub account could not be set up" mkuser.js failed. The hub log shows jsexec's last lines. Check the jsexec and sbbs_ctrl settings, that the hub runs as the BBS's user, and that jsexec runs by hand: jsexec -c /sbbs/ctrl -n /opt/doorhub/mkuser.js "Test (TST)" pass123 (Delete that test user afterwards.) "Sorry, the games server is down" The hub couldn't connect to backend_rlogin. Is Synchronet running with RLogin on? (Section 3.1.) "Sorry, the games server refused the login" Synchronet refused the RLogin login. Check Synchronet's log for the user "Name (TAG)". A user marked deleted or inactive in Synchronet, or an RLogin restriction, can cause this. The player sees the Synchronet logon and then is disconnected, or sees your main menu rlogin_auto_xtrn isn't on (section 3.2), or the INTERNAL CODE in "door add" doesn't match SCFG, or the door's access requirements stop new users (section 3.3). Synchronet's log shows "Unable to launch external" for a wrong code. Members can't connect at all Check the port forward (section 10), the firewall on the hub machine, and that the hub is running (doorhub.log / journalctl). Their connector log usually says exactly what failed. "listen tcp :2022: address already in use" Something else (perhaps another hub) uses the port. Change listen. Changes to hub.json by hand You can edit hub.json with a text editor, but use the commands if you can: they lock the file so the running hub never reads half an edit. Don't edit password hashes by hand; use bbs passwd. 15. COMMAND REFERENCE --------------------- doorhub [-d folder] init create hub.json and the host key serve run the hub service install|remove|start|stop Windows service "DoorHub" (as Administrator) settings show settings set change a setting (section 6) bbs add "" [--user u] [--contact c] bbs list | show | passwd | enable | disable bbs note "" | remove door add "" door list | enable | disable | rename "" door remove player list [TAG] | reset "[TAG]Name" help | version