Mutara

Security

This page tells you how Mutara protects the dashboard, the IAX2 port and the updates.

Accounts and sign-in #

  • Dashboard passwords are kept as bcrypt hashes in password_hash. First-run setup, each save from Settings and a restore change a written password into a hash. A password from {env: NAME} or {file: /path} stays as it is.
  • mutara -hash-password makes a hash for a file that you edit by hand.
  • The sign-ins are in sessions.json in the state folder. A restart or an upgrade does not sign anyone out. The file has mode 0600. It holds a SHA-256 hash of each sign-in token, not the token, so a copy of the file does not sign anyone in. It holds at most 512 sign-ins: a new sign-in past that ends the one used longest ago. If the file is damaged, the node writes a warning to the log and everyone signs in again.
  • At start, the node ends the saved sign-ins of an account that is not in the configuration, or whose password or role changed while the node was stopped.
  • A new password or a deleted account signs that account out on every browser. A change of a group or a grant does not sign anyone out: it applies within a few seconds, also to an open audio connection.
  • A sign-in lasts 7 days. An account keeps at most 64 sign-ins. A new sign-in past that ends the oldest one.
  • After 10 failed sign-ins from one address in 10 minutes, the node refuses sign-ins from that address for 10 minutes. The answer to a wrong name takes the same time as the answer to a wrong password, so the answer does not tell which names exist. Behind a reverse proxy on this machine or the private network, the node counts the failures of each browser address that the proxy gives (X-Forwarded-For, Forwarded or X-Real-IP). Thus one browser cannot lock out the other users of the proxy. All browsers through one proxy address together get 100 failed sign-ins in 10 minutes.
  • With web.public, a visitor who is not signed in sees the callsign of an account, not its user name, in the ports, the talkers, the activity and Last heard. An account without a callsign shows as user. The addresses of the links are hidden too.
  • The Settings page and the settings API can set only an inline value for a secret. A secret written as {env: NAME} or {file: /path} from the web keeps the current value. Only the configuration file can set those forms.

Each module has its own grants: what each group and each account may do on it. Settings shows them as a grid on the module's page, under Access.

Groups
GroupMembers
everyoneEach visitor, signed in or not. The Public dashboard and Public listen switches are its grants.
usersEach signed-in account.
adminsThe install admins. They may do everything on every module, and only they may change the settings of the install, the groups and the grants.
Your own groupsThe accounts that you add, for example club or net-control.

The actions are view, listen, talk, rf, link, dtmf, chat_read, chat_post, clips, download and manage. Read access. The rights of a user add up from the groups and the user's own grants; no grant takes a right away. A request for a module without the right gets 403.

An older file with role, transmit, rf and modules on each account still loads, with the same rights. Read The old keys.

First-run setup #

When there is no admin account, the dashboard asks for one. This works only from a private address, a link-local address or a Tailscale address, with no proxy header (X-Forwarded-For, Forwarded or X-Real-IP). A request through a reverse proxy cannot do the setup. Make the admin account before you put Mutara behind a proxy.

HTTPS #

  • The dashboard port also speaks HTTPS. The node makes its own certificate and keeps it in mutara-tls/ in the state folder.
  • web.autocert_domain gets a Let's Encrypt certificate. A server on TCP port 80 answers the checks and sends other requests to HTTPS. The cache is mutara-certs/.
  • web.tls_cert and web.tls_key use your own certificate files.
  • The Health page shows the SHA-256 fingerprint of the certificate. The apps show the same fingerprint before you trust a node, and warn when it changes.

The browser opens the microphone only while you talk, use open mic or check the mic level. It closes the microphone 2 seconds after that.

The IAX2 port #

  • The node asks each caller for a call token before it answers, as ASL3 does.
  • Answers outside a call (to a POKE, or a call token for a NEW) are limited for each address: 64 at once, then 16 a second. Thus a false source address cannot use the node to send much traffic to another host.
  • The texts that a linked node passes on to the other links (T, M and D texts, key queries) are limited for each link. The limits are far above normal traffic.
  • A calling node must come from the address that its number resolves to.
  • IAX2 users sign in with MD5. permit limits the addresses of a user.
  • By default, IAX2 users cannot send DTMF commands.
  • Linked nodes can run every command, as in stock AllStarLink. Use function_access to limit this.

Signed updates #

The service runs as the unprivileged mutara user. It cannot install software. An upgrade has these steps:

Figure 1. The steps of an upgrade.
Text version of figure 1
  1. The mutara service downloads the release.
  2. It checks the ed25519 signature of the checksum file, SHA256SUMS.sig.
  3. It leaves an upgrade request.
  4. The systemd unit mutara-upgrade.path starts a job as root.
  5. The root job checks the signature again with the installed program.
  6. The root job runs install.sh of the release.
  7. If the service stays up for 15 seconds and the dashboard answers, the upgrade is done.
  8. If not, install.sh puts the old program, mutara.prev, back and restarts it.
  • The node looks for releases every 6 hours. update.check: false turns this off.
  • Four days after the first notice, the node upgrades itself at a quiet time. A newer release in those days does not start the count again.
  • A failed automatic upgrade is tried again after 30 minutes, then after longer waits, up to one day.
  • The result of the root job is in /var/lib/mutara-upgrade/result.
  • mutara -verify-release checks the signature of a release by hand.

The service #

  • The installer makes the mutara system user and a udev rule, so that the user can open the HID device of the USB interface.
  • The systemd unit runs as the mutara user with NoNewPrivileges, ProtectSystem=strict, ProtectHome and only the CAP_NET_BIND_SERVICE capability. It restarts the node if it stops.
  • The service can write its own configuration in /etc/mutara.

Secrets in files #

  • The backup file has the node password, the IAX user secrets, the other keys and tokens in the settings and the password hashes of the accounts. Keep it private.
  • The diagnostics file has the settings without passwords.
  • The registration log hides the node password.

Limits #

  • Each signed-in user, or each address of a visitor who is not signed in, can have at most 8 audio connections (a module's audio or the scan) and 32 event connections (/api/ws). The node accepts at most 256 audio and 1024 event connections in total. Visitors from the loopback address, for example through a proxy on the same computer, count only in the total.
  • A connection over a limit closes with WebSocket code 1013 and a reason. The dashboard shows the reason.
  • A browser that talks is unkeyed after web.talk_limit, 90 seconds by default.
  • When the recorded clips are over recording.max_total_mb, the node deletes the M4A copies first, oldest clip first, and then the oldest clips. A listener who asks for M4A copies cannot make the node delete clips.