Прийшов час трохи привести в порядок SSH на самому FreeBSD та на клієнтах – ноутбуках з Arch Linux, бо на домашніх машинках досі використовую парольну аутентифікацію.
Власне, описані нижче налаштування не специфічні ні для FreeBSD, ні для Linux, бо SSH server один і той самий на всіх системах (OpenSSH_9.9p2 на FreeBSD 14.3 і OpenSSH_10.2p1 на Arch Linux).
1Password користуюсь вже давно, класна інтеграція і GUI, хоча паралельно є локальний KeePassXC, в який до окремої бази періодично бекаплю дані із 1Password – див. How to export your data from the 1Password desktop app та Migrating from 1Password to KeePass, KeePassXC and KeePassium.
Це пост – частина серії по сетапу домашнього NAS на FreeBSD (див. початок у FreeBSD: Home NAS, part 1 – налаштування ZFS mirror), але вирішив його зробити окремою темою, бо тут виключно про SSH.
Що маю в поточному сетапі:
- хост з FreeBSD/NAS: доступний тільки в локальній мережі і VPN, тому SSH brute force не очікується (але при параної або на публічно доступних серверах можна додати Fail2Ban чи SSHGuard)
pffirewall: як перша лінія захисту з лімітом того, звідки SSH доступний (див. FreeBSD: Home NAS, part 2 – знайомство з Packet Filter (PF) firewall)sshd: друга лінія захисту, базові налаштування доступу
Зміст
SSH та аутентифікація по ключам
Перше і основне – це налаштувати доступ по ключам замість парольної аутентифікації.
Зробимо це, потім доступ по паролям відключимо взагалі.
На клієнті, ноутбуці з Linux, створюємо ключі:
[setevoy@setevoy-work ~] $ ssh-keygen -t ed25519 -C "setevoy@setevoy" Generating public/private ed25519 key pair. Enter file in which to save the key (/home/setevoy/.ssh/id_ed25519): /home/setevoy/.ssh/freebsd-nas Enter passphrase for "/home/setevoy/.ssh/freebsd-nas" (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/setevoy/.ssh/freebsd-nas Your public key has been saved in /home/setevoy/.ssh/freebsd-nas.pub
Копіюємо на хост з FreeBSD:
[setevoy@setevoy-work ~] $ ssh-copy-id -i /home/setevoy/.ssh/freebsd-nas [email protected] /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/setevoy/.ssh/freebsd-nas.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys ([email protected]) Password for setevoy@setevoy-nas: Number of key(s) added: 1 Now try logging into the machine, with: "ssh -i /home/setevoy/.ssh/freebsd-nas '[email protected]'" and check to make sure that only the key(s) you wanted were added.
Перевіряємо файл ~/.ssh/authorized_keys на FreeBSD у юзера setevoy:
root@setevoy-nas:/home/setevoy # cat .ssh/authorized_keys ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILb2zkJzflngGx0qY71xYyHVvKI8A2GTAGTqppS0yVz2 setevoy@setevoy
Пробуємо підключення з Linux:
[setevoy@setevoy-work ~] $ ssh -i /home/setevoy/.ssh/freebsd-nas '[email protected]' Last login: Sat Dec 27 09:01:47 2025 from 192.168.0.4 FreeBSD 14.3-RELEASE (GENERIC) releng/14.3-n271432-8c9ce319fef7 Welcome to FreeBSD! ... [setevoy@setevoy-nas ~]$
Все працює – можна налаштувати SSH Agent.
FreeBSD та 1Password client
Тут просто для приклада – установка і підключення клієнта 1Password на FreeBSD.
Встановлюємо:
root@setevoy-nas:/home/setevoy # pkg install -y 1password-client2
Додаємо акаунт:
root@setevoy-nas:/home/setevoy # op account add Enter your sign-in address (example.1password.com): my.1password.com Enter the email address for your account on my.1password.com: <ACCOUNT_EMAIL> Enter the Secret Key for [email protected] on my.1password.com: <SECRET_KEY> Enter the password for [email protected] at my.1password.com: Enter your six-digit authentication code: <OTP_CODE> Now run 'eval $(op signin)' to sign in.
Перевіряємо акаунти:
root@setevoy-nas:/home/setevoy # op account list SHORTHAND URL EMAIL USER ID my https://my.1password.com [email protected] 7BS***KMM
Логінимось:
root@setevoy-nas:/home/setevoy # eval $(op signin) Enter the password for [email protected] at my.1password.com:
І маємо доступ до сікретів.
Наприклад, отримати ключ, який додамо далі:
root@setevoy-nas:/home/setevoy # op item get "FreeBSD NAS SSH" ID: ulz***4ce Title: FreeBSD NAS SSH Vault: Personal (wb7***guq) Created: 1 week ago Updated: 1 week ago by Arseny Favorite: false Tags: FreeBSD,SSH Version: 1 Category: LOGIN Fields: password: [use 'op item get ulz***4ce --reveal' to reveal] username: setevoy
Linux, 1Password та SSH Agent
Колись більш детально писав в пості SSH: RSA-ключи и ssh-agent – управление SSH-ключами и их паролями (2019 рік), але так як зараз активно користуюсь 1Password, який вміє як зберігати самі ключі – так і виступати в ролі SSH Agent.
Документація – 1Password SSH agent та Get started with 1Password for SSH.
Отримуємо приватний ключ:
[setevoy@setevoy-work ~] $ cat .ssh/freebsd-nas -----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW ... vKI8A2GTAGTqppS0yVz2AAAAD3NldGV2b3lAc2V0ZXZveQECAwQFBg== -----END OPENSSH PRIVATE KEY-----
Копіюємо, і додаємо новий ключ в 1Password (хоча він може генерувати ключі сам):
Переходимо в Settings:
Переходимо в Developer – Set up the SSH Agent:
1Password покаже зміст файлу ~/.ssh/config і навіть запропонує оновити його:
Але в мене зараз в конфігу вже є трохи налаштувань:
# GitHub.com Host github.com PreferredAuthentications publickey IdentityFile /home/setevoy/.ssh/setevoy_main_priv_openssh ExitOnForwardFailure yes
Тому додаємо в кінець файлу вручну.
Вказуємо два хости – nas.setevoy та, на випадок, якщо Unbound недоступний, то IP-адресу хоста з FreeBSD:
... Host nas.setevoy 192.168.0.2 IdentityAgent ~/.1password/agent.sock
Виконуємо ssh nas.setevoy, 1Password запросить підтвердження – пароль самого 1Password:
І тепер все працює через його SSH Agent:
[setevoy@setevoy-work ~] $ ssh nas.setevoy ... Last login: Sat Dec 27 09:03:15 2025 from 192.168.0.4 FreeBSD 14.3-RELEASE (GENERIC) releng/14.3-n271432-8c9ce319fef7 Welcome to FreeBSD! ... [setevoy@setevoy-nas ~]$
Як працює SSH Agent
При підключені SSH-клієнт:
- читає конфігурацію (
~/.ssh/config, опції CLI) - підключається до SSH-агента (у нашому випадку 1Password) і отримує список доступних публічних ключів
- по черзі пропонує серверу публічні ключі, які в нього є (з агента і, за відсутності обмежень, з
~/.ssh/) sshdна сервері дивиться в~/.ssh/authorized_keysконкретного юзера і перевіряє, чи є там запропонований публічний ключ- коли сервер знаходить збіг, він приймає цей публічний ключ і надсилає клієнту дані для підпису (випадковий набір чисел)
- клієнт передає ці дані SSH-агенту, який володіє відповідним приватним ключем
- агент створює криптографічний підпис приватним ключем і повертає його клієнту
- сервер перевіряє підпис публічним ключем і завершує аутентифікацію
Глянути це можемо з ssh -v user@host:
[setevoy@setevoy-work ~] $ ssh -v [email protected] debug1: OpenSSH_10.2p1, OpenSSL 3.6.0 1 Oct 2025 debug1: Reading configuration data /home/setevoy/.ssh/config ... debug1: Connecting to nas.setevoy [192.168.0.2] port 22. debug1: Connection established. ... debug1: Authenticating to nas.setevoy:22 as 'setevoy' ... debug1: Will attempt key: RTFM RSA SHA256:nedb3Qgpkxgu57MRP7/eXShHgw6N6b7SjZ3S1rNyFb4 agent debug1: Will attempt key: FreeBSD-NAS ED25519 SHA256:ZuJ77z6BNMwra41BiTKDrJSSQrDJ0/u+4wZRCvGJMpA agent debug1: Will attempt key: /home/setevoy/.ssh/id_rsa debug1: Will attempt key: /home/setevoy/.ssh/id_ecdsa debug1: Will attempt key: /home/setevoy/.ssh/id_ecdsa_sk debug1: Will attempt key: /home/setevoy/.ssh/id_ed25519 ED25519 SHA256:X8L1lCBQz8Bk7K5rMGqiE+tlSthCbgaqK7ryLZ6gVWU debug1: Will attempt key: /home/setevoy/.ssh/id_ed25519_sk debug1: Offering public key: RTFM RSA SHA256:nedb3Qgpkxgu57MRP7/eXShHgw6N6b7SjZ3S1rNyFb4 agent debug1: Authentications that can continue: publickey debug1: Offering public key: FreeBSD-NAS ED25519 SHA256:ZuJ77z6BNMwra41BiTKDrJSSQrDJ0/u+4wZRCvGJMpA agent debug1: Server accepts key: FreeBSD-NAS ED25519 SHA256:ZuJ77z6BNMwra41BiTKDrJSSQrDJ0/u+4wZRCvGJMpA agent Authenticated to nas.setevoy ([192.168.0.2]:22) using "publickey". ... Last login: Sun Dec 28 13:44:51 2025 from 192.168.0.4 FreeBSD 14.3-RELEASE (GENERIC) releng/14.3-n271432-8c9ce319fef7 Welcome to FreeBSD! ... [setevoy@setevoy-nas ~]$
І для ключів “Will attempt key: RTFM RSA [...] та FreeBSD-NAS [...] як раз бачимо, що вони були отримані від agent.
SSH Agent та помилка “Too many authentication failures”
Вище бачили, що передається ціла пачка ключів, і якщо їх багато – то сервер може відкинути подальшу аутентифікацію.
Кількість спроб задається на сервері параметром MaxAuthTries (дефолт “6”) в /etc/ssh/sshd_config. Тобто, якщо маємо 7 ключів, і перші 6 не підійшли – то підключитись не зможемо.
Аби вказати SSH клієнту який конкретно приватний ключ з агента використовувати – вказуємо публічний ключ та задаємо IdentitiesOnly:
... Host nas.setevoy 192.168.0.2 IdentityAgent ~/.1password/agent.sock IdentityFile ~/.ssh/freebsd-nas.pub IdentitiesOnly yes
І тепер під час підключення клієнт буде передавати тільки цей ключі:
[setevoy@setevoy-work ~] $ ssh -v [email protected] ... debug1: get_agent_identities: agent returned 2 keys debug1: Will attempt key: /home/setevoy/.ssh/freebsd-nas.pub ED25519 SHA256:ZuJ77z6BNMwra41BiTKDrJSSQrDJ0/u+4wZRCvGJMpA explicit agent debug1: Offering public key: /home/setevoy/.ssh/freebsd-nas.pub ED25519 SHA256:ZuJ77z6BNMwra41BiTKDrJSSQrDJ0/u+4wZRCvGJMpA explicit agent debug1: Server accepts key: /home/setevoy/.ssh/freebsd-nas.pub ED25519 SHA256:ZuJ77z6BNMwra41BiTKDrJSSQrDJ0/u+4wZRCvGJMpA explicit agent Authenticated to nas.setevoy ([192.168.0.2]:22) using "publickey". ... Last login: Sun Dec 28 13:44:57 2025 from 192.168.0.4 FreeBSD 14.3-RELEASE (GENERIC) releng/14.3-n271432-8c9ce319fef7 Welcome to FreeBSD! ... [setevoy@setevoy-nas ~]$
Basic SSH Server Hardening
Див. sshd_config.
Перевірити поточну конфігурацію можна з sshd -T:
root@setevoy-nas:/home/setevoy # sshd -T port 22 addressfamily any listenaddress 0.0.0.0:22 ...
Наприклад, чи дозволений логін root:
root@setevoy-nas:/home/setevoy # sshd -T | grep root permitrootlogin no
Редагуємо конфіг /etc/ssh/sshd_config, задаємо мінімальні параметри, і нехай буде PermitRootLogin no вказаний тут явно.
Плюс явно вказуємо дозвіл на PubkeyAuthentication та PasswordAuthentication – парольну аутентифікацію відключимо пізніше, коли впевнимось, що все працює:
PermitRootLogin no PubkeyAuthentication yes PasswordAuthentication yes
Перевіряємо синтаксис з sshd -t, якщо все добре – то команда просто нічого не виведе:
root@setevoy-nas:/home/setevoy # sshd -t; echo $? 0
Виконуємо reload конфігу:
root@setevoy-nas:/home/setevoy # service sshd reload Performing sanity check on sshd configuration.
Перевіряємо чи працює доступ з Linux:
[setevoy@setevoy-work ~] $ ssh nas.setevoy ... [setevoy@setevoy-nas ~]$
pf вже налаштований, див. FreeBSD: Home NAS, part 2 – знайомство з Packet Filter (PF) firewall:
... # allow SSH from Office LAN (192.168.0.0/24) to FreeBSD host pass in log on em0 proto tcp from 192.168.0.0/24 to (em0) port 22 keep state # allow SSH from Home network (192.168.100.0/24) to FreeBSD host pass in log on em0 proto tcp from 192.168.100.0/24 to (em0) port 22 keep state # allow SSH from VPN clients to FreeBSD host pass in on wg0 proto tcp from 10.8.0.0/24 to (wg0) port 22 keep state ...
Можна мережі вказати як { 192.168.0.0/24, 192.168.100.0/24, 10.8.0.0/24 }, але для SSH вирішив залишити в такому вигляді, аби було явно видно.
Далі можна додати ще трохи параметрів:
PermitRootLogin no: заборона підключенняroot, це вже єPubkeyAuthentication yes: аутентифікація по ключам, теж вже єPasswordAuthentication yes: пароль аутентифікація, поки залишаємо включеноюChallengeResponseAuthentication no: вимикаємо keyboard-interactive аутентифікацію через PAM, яка не потрібна без 2FA- тут ще нюанс в тому, що навіть якщо відключити
PasswordAuthentication, алеChallengeResponseAuthenticationбуде “yes” і приUsePAM= “yes” – то система все одно може запросити парольну аутентифікацію
- тут ще нюанс в тому, що навіть якщо відключити
UsePAM yes: залишаємо включеним для логування, обліку сесій, політик доступу (див. Practical Effects of Setting “UsePAM yes” on SSH in Linux)AllowUsers setevoyабоAllowGroups wheel: яким юзерам або групам можна підключатись по SSHX11Forwarding no: блокуємо форвард X11 – графічного серверу тут все одно немаAllowAgentForwarding no: забороняємо можливість використання локальних SSH-ключів клієнта з сервера через SSH-агент клієнтаAllowTcpForwarding no: забороняємо SSH-тунелі – на домашньому NAS це точно не треба (див. SSH-туннели в примерах – мій пост за 2013 рік, OMG… та SSH Tunnels: Secure Remote Access and Port Forwarding)AuthorizedKeysFile .ssh/authorized_keys: це дефолтне значення, але задамо явно
Перевіряємо ще раз з sshd -t, виконуємо reload, перевіряємо підключення з ключем з клієнта.
Якщо все ОК – то додаємо ще трохи тюнингу:
PasswordAuthentication no: тепер відключаємо парольну аутентифікаціюAuthenticationMethods publickey: явно заборонити всі механізми окрім ключівMaxSessions 2: максимальна кількість активних сесій на одне TCP-підключенняLoginGraceTime 30: кількість секунд, за яку клієнт має пройти аутентифікацію
Для ще більшої безпеки – можна налаштувати інший порт замість 22 (наприклад, задати Port 2222), обмежити IP, на яких слухає sshd (параметр ListenAddress 192.168.0.2), і навіть налаштувати Two-factor Authentication For SSH – але для домашнього сервера з доступом тільки з локальних мереж це вже overkill.




