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-passwordmakes a hash for a file that you edit by hand.- The sign-ins are in
sessions.jsonin 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 asuser. 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.
| Group | Members |
|---|---|
everyone | Each visitor, signed in or not. The Public dashboard and Public listen switches are its grants. |
users | Each signed-in account. |
admins | The 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 groups | The 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_domaingets a Let's Encrypt certificate. A server on TCP port 80 answers the checks and sends other requests to HTTPS. The cache ismutara-certs/.web.tls_certandweb.tls_keyuse 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.
permitlimits 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_accessto limit this.
Signed updates #
The service runs as the unprivileged mutara user. It cannot install software. An upgrade has these steps:
Text version of figure 1
- The mutara service downloads the release.
- It checks the ed25519 signature of the checksum file, SHA256SUMS.sig.
- It leaves an upgrade request.
- The systemd unit mutara-upgrade.path starts a job as root.
- The root job checks the signature again with the installed program.
- The root job runs install.sh of the release.
- If the service stays up for 15 seconds and the dashboard answers, the upgrade is done.
- If not, install.sh puts the old program, mutara.prev, back and restarts it.
- The node looks for releases every 6 hours.
update.check: falseturns 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-releasechecks the signature of a release by hand.
The service #
- The installer makes the
mutarasystem user and a udev rule, so that the user can open the HID device of the USB interface. - The systemd unit runs as the
mutarauser 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.