SFTP z chroot w zależności od klucza publicznego podłączanego użytkownika

9

Chcę zbudować serwer (z systemem Debian lub FreeBSD), który odbiera kopie zapasowe od różnych klientów za pośrednictwem sshfs. Każdy klient powinien mieć możliwość odczytu i zapisu własnych danych kopii zapasowej, ale nie danych innych klientów.

Wpadłem na następujący pomysł: każdy klient łączy się za pomocą klucza publicznego uwierzytelniania z [email protected]. Kopia zapasowa użytkownika ma specjalny plik autoryzowanych_kluczy, taki jak ten:

command="internal-sftp" chroot="/backup/client-1/data" ssh-rsa (key1)
command="internal-sftp" chroot="/backup/client-2/data" ssh-rsa (key2)
command="internal-sftp" chroot="/backup/client-3/data" ssh-rsa (key3)
etc...

Zaletą tego byłoby to, że nie musiałbym używać osobnego użytkownika dla każdego klienta i mogłem z łatwością automatycznie wygenerować plik author_keys za pomocą skryptu.

Jest tylko jeden problem: chroot=...nie działa. Plik autoryzowanych kluczy OpenSSH nie wydaje się mieć odpowiednika dla katalogu ChrootDirectory (który działa w / etc / ssh / sshd_config, globalnie lub w bloku Dopasuj użytkownika).

Czy istnieje rozsądnie prosty sposób na osiągnięcie tego, czego chcę za pomocą OpenSSH? Może command=...w sprytny sposób wykorzystuje dyrektywę? Czy są też inne serwery SFTP, które mogą robić, co chcę?

EDYCJA : Aby wyjaśnić, co chcę osiągnąć: chcę, aby kilku klientów mogło przechowywać pliki na moim serwerze. Każdy klient nie powinien widzieć plików innych klientów. Nie chcę zaśmiecać mojego serwera dziesiątkami kont użytkowników, dlatego chciałbym, aby klienci mogli łatwo zarządzać udostępnianiem konta użytkownika i nadal nie mieli dostępu do plików innych osób.

Xykon42
źródło

Odpowiedzi:

5

Czy są też inne serwery SFTP, które mogą robić, co chcę?

tak, możesz użyć proftpd

Przygotuj środowisko użytkownika. Dzięki ProFTPD nie ma potrzeby podawania użytkownikowi poprawnej powłoki.

# useradd -m -d /vhosts/backup/user1/ -s /sbin/nologin user1
# passwd --lock user1
Locking password for user user1.
passwd: Success

# mkdir /vhosts/backup/user1/.sftp/
# touch /vhosts/backup/user1/.sftp/authorized_keys

# chown -R user1:user1 /vhosts/backup/user1/
# chmod -R 700 /vhosts/backup/user1/

Aby używać kluczy publicznych OpenSSH w kluczach SFTPAuthorizedUserKeys, należy przekonwertować je na format RFC4716. Możesz to zrobić za pomocą narzędzia ssh-keygen:

# ssh-keygen -e -f user1.public.key > /vhosts/backup/user1/.sftp/authorized_keys

Skonfiguruj ProFTPD

ServerName "ProFTPD Default Installation"
ServerType standalone
DefaultServer off

LoadModule mod_tls.c
LoadModule mod_sftp.c
LoadModule mod_rewrite.c

TLSProtocol TLSv1 TLSv1.1 TLSv1.2

# Disable default ftp server
Port 0

UseReverseDNS off
IdentLookups off

# Umask 022 is a good standard umask to prevent new dirs and files
# from being group and world writable.
Umask 022

# PersistentPasswd causes problems with NIS/LDAP.
PersistentPasswd off

MaxInstances 30

# Set the user and group under which the server will run.
User nobody
Group nobody

# Normally, we want files to be overwriteable.
AllowOverwrite                  on

TimesGMT off
SetEnv TZ :/etc/localtime

<VirtualHost sftp.example.net>
    ServerName "SFTP: Backup server."
    DefaultRoot ~
    Umask 002
    Port 2121

    RootRevoke on

    SFTPEngine on
    SFTPLog /var/log/proftpd/sftp.log

    SFTPHostKey /etc/ssh/ssh_host_rsa_key
    SFTPHostKey /etc/ssh/ssh_host_dsa_key
    SFTPDHParamFile /etc/pki/proftpd/dhparam_2048.pem
    SFTPAuthorizedUserKeys file:~/.sftp/authorized_keys

    SFTPCompression delayed
    SFTPAuthMethods publickey
</VirtualHost>

<Global>
    RequireValidShell off
    AllowOverwrite yes

    DenyFilter \*.*/

    <Limit SITE_CHMOD>
        DenyAll
    </Limit>
</Global>

LogFormat default "%h %l %u %t \"%r\" %s %b"
LogFormat auth    "%v [%P] %h %t \"%r\" %s"
ExtendedLog /var/log/proftpd/access.log read,write

Utwórz parametry grupy DH (Diffie-Hellman).

# openssl dhparam -out /etc/pki/proftpd/dhparam_2048.pem 2048

Skonfiguruj dowolnego klienta SFTP. Użyłem FileZilla

Ustawienia serwera FileZilla SFTP

Jeśli uruchomisz ProFPTD w trybie debugowania

# proftpd -n -d 3 

W konsoli zobaczysz coś takiego

2016-02-21 22:12:48,275 sftp.example.net proftpd[50511]: using PCRE 7.8 2008-09-05
2016-02-21 22:12:48,279 sftp.example.net proftpd[50511]: mod_sftp/0.9.9: using OpenSSL 1.0.1e-fips 11 Feb 2013
2016-02-21 22:12:48,462 sftp.example.net proftpd[50511] sftp.example.net: set core resource limits for daemon
2016-02-21 22:12:48,462 sftp.example.net proftpd[50511] sftp.example.net: ProFTPD 1.3.5a (maint) (built Sun Feb 21 2016 21:22:00 UTC) standalone mode STARTUP
2016-02-21 22:12:59,780 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): mod_cap/1.1: adding CAP_SETUID and CAP_SETGID capabilities
2016-02-21 22:12:59,780 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): SSH2 session opened.
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): Preparing to chroot to directory '/vhosts/backup/user1'
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): Environment successfully chroot()ed
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): USER user1: Login successful

I następujące linie w /var/log/sftp.log

2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: sending acceptable userauth methods: publickey
2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: public key MD5 fingerprint: c2:2f:a3:93:59:5d:e4:38:99:4b:fd:b1:6e:fc:54:6c
2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: sending publickey OK
2016-02-21 22:12:59,789 mod_sftp/0.9.9[50309]: public key MD5 fingerprint: c2:2f:a3:93:59:5d:e4:38:99:4b:fd:b1:6e:fc:54:6c
2016-02-21 22:12:59,790 mod_sftp/0.9.9[50309]: sending userauth success
2016-02-21 22:12:59,790 mod_sftp/0.9.9[50309]: user 'user1' authenticated via 'publickey' method

PS

Skonfigurowana ścieżka do pliku zawierającego autoryzowane klucze ( SFTPAuthorizedUserKeys ) może korzystać ze zmiennej % u , która będzie interpolowana z nazwą uwierzytelnionego użytkownika. Ta funkcja obsługuje pliki autoryzowanych kluczy dla każdego użytkownika, które znajdują się w centralnej lokalizacji, zamiast wymagać (lub zezwalać) użytkownikom na zarządzanie własnymi autoryzowanymi kluczami. Na przykład:

SFTPAuthorizedUserKeys file:/etc/sftp/authorized_keys/%u

Chcę, aby kilku klientów mogło przechowywać pliki na moim serwerze. Każdy klient nie powinien widzieć plików innych klientów. Nie chcę zaśmiecać mojego serwera dziesiątkami kont użytkowników, dlatego chciałbym, aby klienci mogli łatwo zarządzać udostępnianiem konta użytkownika i nadal nie mieli dostępu do plików innych osób.

z ProFTPD jest to również możliwe. Wystarczy trochę zmodyfikować moją początkową konfigurację

<VirtualHost sftp.example.net>
    ...   
    SFTPAuthorizedUserKeys file:/etc/proftpd/sftp_authorized_keys
    AuthUserFile /etc/proftpd/sftp_users.passwd

    CreateHome on 0700 dirmode 0700 uid 99 gid 99

    RewriteHome on
    RewriteEngine on
    RewriteLog /var/log/proftpd/rewrite.log
    RewriteCondition %m REWRITE_HOME
    RewriteRule (.*) /vhosts/backup/%u
</VirtualHost>

I utwórz jedno konto wirtualne

# ftpasswd --passwd --file /etc/proftpd/sftp_users.passwd --sha512 --gid 99 --uid 99 --shell /sbin/nologin --name user1 --home /vhosts/backup

To wszystko. Do każdego dodatkowego konta wystarczy dodać jego klucz publiczny do / etc / proftpd / sftp_authorized_keys

Uwaga: plik musi na końcu zawierać nowy wiersz! To ważne.

ALex_hha
źródło
Dziękuję za szczegółową odpowiedź. Nie rozumiem jednak, w jaki sposób pomogłoby mi to osiągnąć główny cel, jakim jest używanie tylko jednego konta użytkownika dla wielu klientów, którzy nie powinni widzieć plików innych. (I może być łatwo zarządzany przez skrypt.) Ponownie czytając moje oryginalne pytanie, przyznaję, że może nie było do końca oczywiste, co chciałem osiągnąć. Przepraszam za to.
Xykon42
Zaktualizowałem odpowiedź
ALex_hha
1
Dobra, z małą zmianą, to naprawdę działa ładnie, dzięki! Aby upewnić się, że użytkownicy nie mogą uzyskać dostępu do plików innych użytkowników poprzez odgadnięcie ich nazwy użytkownika (lub aby zalać mój serwer przez nieprawidłowe użycie funkcji CreateHome), plik autoryzowanych_kluczy musi być specyficzny dla użytkownika, na przykład /foo/authorized_keys.d/%u.
Xykon42,
6

chroot=...nie działa.

Nie, na stronie podręcznika nie ma czegoś takiego sshd, opisującego format authorized_keyspliku.

Jeśli wpiszesz chroot command=, nie będziesz mógł go używać internal-sftp, ponieważ jest to podstawienie wewnętrznego wywołania funkcji wewnątrz sshd.

Zalecanym sposobem jest skonfigurowanie większej liczby użytkowników, jeśli potrzebujesz separacji. Możesz także użyć argumentów internal-sftp, jeśli nie potrzebujesz ścisłej separacji (np. Po prostu różnych katalogów roboczych), takich jak

command="internal-sftp -d /backup/client-1/data" ssh-rsa (key1)

Możliwe jest również ograniczenie liczby żądań za pomocą -Popcji jak na stronie podręcznika dla sftp-server.

Jakuje
źródło
0

Tymczasem wymyśliłem inne proste rozwiązanie, które również działa dobrze, przynajmniej w moim przypadku użycia:

Każdy klient łączy się z serwerem za pomocą tego samego konta użytkownika i ewentualnie nawet tego samego klucza (nie ma znaczenia). Chroots OpenSSH do katalogu o następującej strukturze:

d--x--x---   dark-folder
drwxr-x---   |- verylongrandomfoldername1
drwxr-x---   |- verylongrandomfoldername2
drwxr-x---   `- ...

Wraz z poleceniem tworzenia kopii zapasowej serwer informuje klienta o nazwie folderu, w której powinien umieścić swoje pliki. Nazwy folderów to 64-bajtowe ciągi losowe, których praktycznie nie można odczytać, więc każdy klient może naprawdę uzyskać dostęp do własnego folderu, nawet jeśli inni są „gdzieś w ciemności”.

tryb d - x - x-- w ciemnym folderze zapewnia, że ​​każdy klient może wejść do folderu (i folderów poniżej), ale nie może wyświetlić jego zawartości ani utworzyć żadnych nowych wpisów.

Podfoldery są tworzone przez proces serwera kopii zapasowej, a połączenie między klientem a folderem jest przechowywane (między innymi) w db sqlite.

Xykon42
źródło