Описал, как цеплял sftp шару вместо самбы

This commit is contained in:
4aiman 2025-11-30 00:28:38 +03:00
commit b7121be08b

156
two.md
View file

@ -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`. <br>
Где-то в конце добавляем такое:
```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 - это нифига не файловая система, которую понимает ядро.<br>
Мы не можем просто взять и засунуть что-то типа такого в сервис:
```bash
mount <параметры> <адрес_шары> <точка_монтирования>
```
2. И, кроме самого ssh, придётся доустановить fuse3
```bash
sudo apt install sshfs fuse3
```
2. Типов юнитов для сервисов systemd, оказывается, тоже бывает больше одного.<br>
Хорошо, что хоть тут нам это знать не обязательно.
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 <симлинк>`