Files
tilde.club/docs/ssh.md
T

175 lines
7.2 KiB
Markdown

# SSH access and MFA
## Member keys
Use an SSH client already supplied with Linux, macOS, or Windows OpenSSH. On
Windows, PowerShell can run the same `ssh` and `ssh-keygen` commands. PuTTY is
also fine if the user prefers it; submit the OpenSSH-format public-key line,
not a `.ppk` private key.
On your own computer, generate a separate key if you do not already have one
you want to use. Choose a new filename rather than overwriting an existing key:
```bash
ssh-keygen -t ed25519 -a 64 -f ~/.ssh/tilde_ed25519
```
Use a passphrase. Send only `tilde_ed25519.pub` to the operator or signup form.
The file without `.pub` is private and stays on your computer. A hardware-backed
key can also be used when both the client and host support it.
Connect with:
```bash
ssh -i ~/.ssh/tilde_ed25519 member@tilde.example.net
```
A local `~/.ssh/config` entry saves typing:
```sshconfig
Host mytilde
HostName tilde.example.net
User member
IdentityFile ~/.ssh/tilde_ed25519
IdentitiesOnly yes
ForwardAgent no
```
Verify a new host's fingerprint through a separate trusted channel. If it
changes later, ask why before replacing the saved host key. Agent forwarding
is normally unnecessary for using the host; enable it only for a specific
reason you understand.
## What the collected host does
The main daemon reads `/etc/ssh/sshd_config`. It has public-key support,
`PasswordAuthentication no`, keyboard-interactive authentication enabled, and
`UsePAM yes`. `AuthenticationMethods` is not set to require a combination;
the observed effective value is `any`.
Its SSH PAM authentication stack requires `pam_unix` and
`pam_google_authenticator`, except for a special help account. That means the
PAM route asks for the Unix password and a TOTP code. It does **not** mean
public-key login must also complete that route: the collected SSH configuration
accepts a valid public key on its own. Existing account-specific exceptions and
a separate restricted help command must be reviewed locally rather than copied
into a new installation.
`setup-2fa` is a small wrapper around `/usr/bin/google-authenticator`.
`check_google_authenticator.sh` is not referenced by the collected SSH PAM file;
its printed output is not an enforced authentication policy.
The main config collected from this host does not contain an `Include` for
`sshd_config.d`. The presence of files in that directory does not make them
active. Check the actual service command and configuration before assuming a
drop-in changes anything.
## Key-only baseline for a new host
Use [the example drop-in](../examples/ssh/00-tilde.conf) only after admin key
login and sudo have been tested. Put it in a directory that the actual main
config includes at global scope. Fedora's default layout normally provides
`/etc/ssh/sshd_config.d/*.conf`; existing customized configs may not.
OpenSSH generally uses the first value it obtains for a setting. A file placed
later in the include order will not necessarily override an earlier value.
Keep `Match` sections at the end and finish a conditional section with
`Match all` before adding unrelated global settings.
Before applying anything, keep a backup of the main file, its includes, the
SSH PAM file, and any unit overrides. Keep a working connection and the provider
console available. Validate the **effective** settings as well as syntax:
```bash
sshd -t
sshd -T -C user=member,host=client.example.net,addr=192.0.2.20
systemctl reload sshd
```
Run connection tests from a second terminal on your own computer. Test the
admin and member separately. Match rules based on source address or local port
also need representative `addr`, `laddr`, and `lport` values in the test context.
A successful syntax check alone does not establish that the intended method
will be accepted.
## Require MFA after enrollment
For a new host, keep the key-only baseline working while enrolling people.
The following is an example policy, not a report of the production host's
current enforcement:
1. Install `google-authenticator` and ensure time synchronization is healthy.
2. Create a group named `mfa-ready`.
3. Have the test member run `google-authenticator` interactively in their own
account. Use time-based tokens, save the recovery codes somewhere private
off the host, and complete a code check. Keep `.google_authenticator` private.
4. Keep the Fedora SSH PAM account/session stack. Add
`auth required pam_google_authenticator.so` to `/etc/pam.d/sshd` after its
normal authentication rules. Do not use `nullok` for an account that must
provide a second factor. Do not edit authselect-generated shared files to
make this SSH-only change.
5. Add the following conditional block at the end of the effective SSH config,
after the baseline global settings:
```sshconfig
Match Group mfa-ready
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive:pam
Match all
```
With Fedora's password authentication PAM substack retained, this asks for a
key, the Unix password, and the authenticator code. If you want a key plus TOTP
without the Unix password, design and test that SSH-specific PAM stack instead
of removing password checks from the shared system authentication configuration.
Validate the config, then add only the enrolled test account to the group:
```bash
groupadd -f mfa-ready
usermod --append --groups mfa-ready member
sshd -t
sshd -T -C user=member,host=client.example.net,addr=192.0.2.20
systemctl reload sshd
```
From the client, test correct and incorrect codes and confirm that key-only
batch authentication fails for the enrolled account:
```bash
ssh -o BatchMode=yes -o PreferredAuthentications=publickey \
-i ~/.ssh/tilde_ed25519 member@tilde.example.net
```
That last command is a negative test and should fail under the enforced policy.
Also verify normal interactive login, SFTP if offered, recovery codes, and admin
recovery. Scripts using SSH need a separately documented policy; silently
exempting all automation defeats a blanket MFA claim.
Only enroll more members after the full test passes. A user-editable startup
file or `.new_user` marker is onboarding state, not an access-control boundary.
## Legacy SSH
The existing host has a second daemon on TCP 2222. Its service reads
`/etc/ssh/sshd_config_legacy`, disables root and password login, restricts its
allowed user, and deliberately enables old RSA/SHA-1 and group1 algorithms.
This is a compatibility exception, not a general access method.
A new tilde does not need this service. If you have a specific legacy client
requirement, isolate it in a separate daemon and source/identity policy, verify
its effective settings with `sshd -T -f PATH`, and record who needs it and when
it can be retired. Do not weaken the normal daemon or the host-wide crypto
policy for every member.
## Recovery
Verify the person's identity before replacing a key or resetting MFA. Remove
lost factors, invalidate unused recovery codes when re-enrolling, and check
whether other services share the same account password. Test that the revoked
key or factor no longer works. Do not ask someone to send a private SSH key or
their TOTP secret in an ordinary support message.
References: [OpenSSH server configuration](https://man.openbsd.org/sshd_config)
and [Google Authenticator PAM](https://github.com/google/google-authenticator-libpam).