diff --git a/two.md b/two.md index 38a363e..e81e8b5 100644 --- a/two.md +++ b/two.md @@ -707,3 +707,159 @@ const privateKey = execSync('sudo -n cat /etc/letsencrypt/live/4aiman.top/privkey.pem', {encoding: 'utf8'}); const privateCert = execSync('sudo -n cat /etc/letsencrypt/live/4aiman.top/fullchain.pem', {encoding: 'utf8'}); ``` + + +- ### заменяем smb шару на sftp + + #### Сторона сервера + 1. Помним, что в убунтах нет `sshd`, а есть только `ssh` который имеет 2 конфига: + - клиентский + - серверный + + 2. Нас интересует серверный в `/etc/ssh/sshd_config`.
+ Где-то в конце добавляем такое: + ```conf + Match User twc_user + ChrootDirectory /var/twc_sftp + ForceCommand internal-sftp -d / -R + AllowTcpForwarding no + X11Forwarding no + PermitTunnel no + ``` + + Тут мы говорим серверу, что: + - у нас уже есть папка /var/twc_sftp; + - мы не хотим давать подключаться twc_user по ssh, а только sftp - поэтому и форсим команду переходы на подсистему `internal-sftp`: + - `-d` - указание на папку относительно `/var/twc_sftp`; + - `-R` добавили - чтобы папка работала только на чтение); + - мы хотим после подключения клиента "запереть" его в этой папке, прикинувшись, что эта папка и есть "корень" сетевой шары; + - что подключаться к этой шаре может только юзер по имени twc_user (см. директиву `Match User`). + + 3. Но этого мало, папка `/var/twc_sftp` должна принадлежать `root` сервера: + ```sh + $ stat /var/twc_sftp + Файл: /var/twc_sftp + Размер: 4096 Блоков: 8 Блок В/В: 4096 каталог + Устройство: 259/2 Инода: 3159779 Ссылки: 2 + Доступ: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) + Доступ: 2025-11-29 22:29:53.620596968 +0300 + Модифицирован: 2025-11-29 17:09:31.295438858 +0300 + Изменён: 2025-11-29 22:29:53.518597349 +0300 + Создан: 2025-11-29 17:09:18.246423348 +0300 + ``` + + 4. Кроме того, в `/home/twc_user/.ssh/authorized_keys` должен лежать ключ, с которым этот самый twc_user будет подключаться к нашему серверу. + + Ну а для этого и сам юзер должен существовать и домашний каталог его не быть пустым и права на всё это должны быть нормальные. + + По какой-то причине на Ubuntu 24.04 папки юзер не создалась при создании юзера, поэтому пришлось делать вот всё это: + + ```bash + sudo useradd twc_user -s /sbin/nologin + sudo chown twc_user:twc_user /home/twc_user + sudo mkdir -p /home/twc_user/.ssh + sudo chown twc_user:twc_user /home/twc_user/.ssh + sudo chown twc_user:twc_user /home/twc_user/.ssh/authorized_keys + sudo chmod 755 /home/twc_user + sudo chmod 700 /home/twc_user/.ssh + sudo chmod 600 /home/twc_user/.ssh/authorized_keys + ``` + + Напоследок не забываем перегрузить сервис + ```bash + sudo systemctl restart ssh + ``` + + *После этого на сервере есть и юзер и сервис sshd работает как надо (как модуль сервиса ssh).* + + + #### Сторона клиента + 1. Как оказалось, sftp - это нифига не файловая система, которую понимает ядро.
+ Мы не можем просто взять и засунуть что-то типа такого в сервис: + + ```bash + mount <параметры> <адрес_шары> <точка_монтирования> + ``` + + 2. И, кроме самого ssh, придётся доустановить fuse3 + ```bash + sudo apt install sshfs fuse3 + ``` + + + 2. Типов юнитов для сервисов systemd, оказывается, тоже бывает больше одного.
+ Хорошо, что хоть тут нам это знать не обязательно. + + 3. Мы создаём файл сервиса + ```bash + sudo nano /etc/systemd/system/mnt-chaiman_share.service + ``` + И "кладём" туда вот такое содержимое: + ```ini + [Unit] + Description=Ensure SFTP chroot mounted at /mnt/chaiman_share + After=network-online.target + Wants=network-online.target + + [Service] + Type=simple + Restart=on-failure + RestartSec=10 + # keep process running to hold mount; use foreground sshfs (-f) + Environment=SSHFS_SSH_CMD=/usr/bin/ssh -i /root/.ssh/sftp_service_key -oBatchMode=yes -oStrictHostKeyChecking=yes -s sftp + ExecStartPre=/bin/mkdir -p /mnt/chaiman_share + ExecStart=/usr/bin/sshfs -f -oIdentityFile=/root/.ssh/sftp_service_key,allow_other,reconnect,uid=1000,gid=1000,ro,ServerAliveInterval=15,ServerAliveCountMax=3,debug \ + twc_user@10.0.0.10:. /mnt/chaiman_share + ExecStop=/bin/fusermount -u /mnt/chaiman_share + TimeoutStartSec=30 + TimeoutStopSec=30 + + [Install] + WantedBy=multi-user.target + ``` + + Тут всё сложно. + + Без установки `SSHFS_SSH_CMD` в `Environment` сервис работать отказывался: то опции разобрать не мог, то шару найти, то ещё что. Да и тип сервиса `.mount` оказался непригодным для хранения параметров среды. + + Ключевые особенности: + - сервис работает от root; + - видите ли потому, что нужно монтировать шары в папки, которыми обязан владеть root; + - я не понимаю нафига это требование, если оно вообще есть - из ИИшек клещами не вытянуть, так ли это; + - сервис подключается к шаре от имени пользователя `twc_user`; + - чтобы подключаться без пароля, он использует файл закрытого ключа ssh из `/root/.ssh/sftp_service_key`; + - этому `/root/.ssh/sftp_service_key` соответствует файл открытого ключа, что уже лежит на сервере + - сгенерить такой можно вот так: + ```bash + sudo ssh-keygen -t ed25519 -f /root/.ssh/sftp_service_key -N "" + ``` + - при этом пофигу, под каким юзером запускать команду, т.к. тут важно только 2 момента: + - указать закрытый ключ при подключении; + - иметь открытую часть на сервере в папке юзера с тем же именем, которое имеется в команде монтирования (в моём случае `twc_user`); + - опция `reconnect` позволяет переподключать шару, если что-то пошло не так; + - опция `allow_other` должа позволить не только root работать с шарой, но хз; + - подключаться нужно именно как `twc_user` и именно ***в корень*** + + > ***ПЯТЬ** разных ИИшек 4 часа мне* *~~пиз**ли~~ нагло врали, что и на клиенте нужно указывать папку `/var/twc_share`*, *пока я не додумался спросить "а ~~на**уя~~ зачем?".* + + + 4. После создания файла сервиса надо его "включить": + ```bash + sudo systemctl daemon-reload + sudo systemctl enable mnt-chaiman_share.service + sudo systemctl start mnt-chaiman_share.service + ``` + + Если всё ок, то ругани не будет. А если нет - попросит смотреть журнал. + + Попросит криво, лучше смотреть вот так: + ```bash + sudo journalctl -u mnt-chaiman_share.service -e + ``` + + 5. Всё. Теперь есть сервер и клиент и шара будет смотирована куда-то, откуда можно её пробросить через `ln -s /mnt/chaiman_share <симлинк>` + + + + +