bash – przesłanie pliku przez SFTP

Jeśli istnieje potrzeba, aby w bezpieczny sposób przesłać np. kopię zapasową w inne miejsce, i zrobić to automatycznie, to warto pomyśleć o zaprzęgnięciu bezpieczniejszego FTP oraz skryptu BASH uruchamianego przez CRON. Np do serwera z sFTP takim jak opisane tutaj.

Sprawdzam w terminalu:

wiks@dellwiks:~$ sftp -oPort=59999 sftp@11.22.33.44 <<EOF
put /home/wiks/Dokumenty/plik.txt ftp/plik.txt
EOF
sftp@11.22.33.44's password: 
Connected to 11.22.33.44.
sftp> put /home/wiks/Dokumenty/plik.txt ftp/plik.txt
Uploading /home/wiks/Dokumenty/plik.txt to /ftp/plik.txt
/home/wiks/Dokumenty/plik.txt                100%  200   100.3KB/s   00:00    

W terminalu padło pytanie o hasło. W automatyzacji nie przejdzie. Zerkam, jak to wygląda gdy program sftp poprosimy o bycie bardziej wylewnym (opcja -v):

wiks@dellwiks:~$ sftp -v -P 59999 sftp@11.22.33.44 <<EOF
put /home/wiks/Dokumenty/plik.txt ftp/plik.txt
EOF
OpenSSH_8.2p1 Ubuntu-4ubuntu0.1, OpenSSL 1.1.1f  31 Mar 2020
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files
debug1: /etc/ssh/ssh_config line 21: Applying options for *
debug1: Connecting to 11.22.33.44 [11.22.33.44] port 59999.
debug1: Connection established.
debug1: identity file /home/wiks/.ssh/id_rsa type -1
debug1: identity file /home/wiks/.ssh/id_rsa-cert type -1
debug1: identity file /home/wiks/.ssh/id_dsa type -1
debug1: identity file /home/wiks/.ssh/id_dsa-cert type -1
debug1: identity file /home/wiks/.ssh/id_ecdsa type -1
debug1: identity file /home/wiks/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/wiks/.ssh/id_ecdsa_sk type -1
debug1: identity file /home/wiks/.ssh/id_ecdsa_sk-cert type -1
debug1: identity file /home/wiks/.ssh/id_ed25519 type -1
debug1: identity file /home/wiks/.ssh/id_ed25519-cert type -1
debug1: identity file /home/wiks/.ssh/id_ed25519_sk type -1
debug1: identity file /home/wiks/.ssh/id_ed25519_sk-cert type -1
debug1: identity file /home/wiks/.ssh/id_xmss type -1
debug1: identity file /home/wiks/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.4p1 Debian-10+deb9u7
debug1: match: OpenSSH_7.4p1 Debian-10+deb9u7 pat OpenSSH_7.0*,OpenSSH_7.1*,OpenSSH_7.2*,OpenSSH_7.3*,OpenSSH_7.4*,OpenSSH_7.5*,OpenSSH_7.6*,OpenSSH_7.7* compat 0x04000002
debug1: Authenticating to 11.22.33.44:59999 as 'sftp'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:36Rk47+HzfscI65Mq33Qg1+zo7E+MIef+xwOyqnS8gQ
debug1: Host '[11.22.33.44]:59999' is known and matches the ECDSA host key.
debug1: Found key in /home/wiks/.ssh/known_hosts:8
debug1: rekey out after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey in after 134217728 blocks
debug1: Will attempt key: /home/wiks/.ssh/id_rsa 
debug1: Will attempt key: /home/wiks/.ssh/id_dsa 
debug1: Will attempt key: /home/wiks/.ssh/id_ecdsa 
debug1: Will attempt key: /home/wiks/.ssh/id_ecdsa_sk 
debug1: Will attempt key: /home/wiks/.ssh/id_ed25519 
debug1: Will attempt key: /home/wiks/.ssh/id_ed25519_sk 
debug1: Will attempt key: /home/wiks/.ssh/id_xmss 
debug1: SSH2_MSG_EXT_INFO received
debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Trying private key: /home/wiks/.ssh/id_rsa
debug1: Trying private key: /home/wiks/.ssh/id_dsa
debug1: Trying private key: /home/wiks/.ssh/id_ecdsa
debug1: Trying private key: /home/wiks/.ssh/id_ecdsa_sk
debug1: Trying private key: /home/wiks/.ssh/id_ed25519
debug1: Trying private key: /home/wiks/.ssh/id_ed25519_sk
debug1: Trying private key: /home/wiks/.ssh/id_xmss
debug1: Next authentication method: password
sftp@11.22.33.44's password: 
debug1: Authentication succeeded (password).
Authenticated to 11.22.33.44 ([11.22.33.44]:59999).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: network
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Sending environment.
debug1: Sending env LANG = pl_PL.UTF-8
debug1: Sending subsystem: sftp
Connected to 11.22.33.44.
sftp> put /home/wiks/Dokumenty/plik.txt ftp/plik.txt
debug1: Couldn't stat remote file: No such file or directory
Uploading /home/wiks/Dokumenty/plik.txt to /ftp/plik.txt
/home/wiks/Dokumenty/plik.txt                100%  200    78.3KB/s   00:00    
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
Transferred: sent 2556, received 2640 bytes, in 0.0 seconds
Bytes per second: sent 100595.1, received 103901.0
debug1: Exit status 0

Widać tutaj, że serwer negocjuje z klientem sposób, w jaki mógłby go uwierzytelnić, dopiero gdy to się nie powiedzie – pyta o hasło. Co zatem musiałoby się stać, aby negocjacje uwierzytelnienia powiodły się i nie padło pytanie o hasło? Logiczna, nasuwająca się odpowiedź jest taka, że serwer musiałby znać klienta, i mieć do niego zaufanie. Zatem…

Zatem klient musi podzielić się z serwerem swoim kluczem publicznym, zaś serwer musi traktować ten klucz jako zaufany. Zaczynamy.

Należy dla klienta wygenerować parę kluczy (jeśli ich jeszcze nie ma), można to zrobić np. tak:

wiks@dellwiks:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/wiks/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/wiks/.ssh/id_rsa
Your public key has been saved in /home/wiks/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:si3xbE2ndMvOumSNa+QFvnBrYI8TmuCBLfcfJzQrqRw wiks@dellwiks
The key's randomart image is:
+---[RSA 3072]----+
|                 |
|                 |
|                 |
|          .      |
|   o  o S.o.o    |
|  o =  X=*+B..   |
|   +E+=+OXB++    |
|   ..o++o*B+     |
|    o  ..++oo    |
+----[SHA256]-----+

Klucze są w folderze domowym użytkownika, w ukrytym podfolderze .ssh/id_rsa . Export – import klucza, wygląda zaś tak:

wiks@dellwiks:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub 11.22.33.44 -p 59999
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/wiks/.ssh/id_rsa.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
wiks@11.22.33.44's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -p '59999' '11.22.33.44'"
and check to make sure that only the key(s) you wanted were added.

Po tym klucz znajduje się na serwerze i użytkownik wiks może logować się bez hasła.

Inaczej jednak jest dla użytkownika, którego utworzyłem jako dedykowanego dla obsługi sFTP.

Ponieważ jest on 'zarezerwowany’ do połaczeń SFTP via SSH i niejako uwięziony w chroocie, nie jest możliwe zalogowanie się do niego poprzez SSH. Pozostaje zatem zalogować się jako wiks – poprzez SSH i skopiować zaimportowany już klucz do katalogu /.ssh/ i pliku authorized_keys użytkownika sftp:

Z poziomu SSH i terminala loguję się jako wiks:

wiks@qrgo:/$ cd /home/sftp/
wiks@qrgo:/home/sftp$ ls
ftp
wiks@qrgo:/home/sftp$ sudo mkdir .ssh              #tworzę katalog .ssh
[sudo] hasło użytkownika wiks: 
wiks@qrgo:/home/sftp$ sudo chown sftp:sftp .ssh    #ale ownerem ma być sftp
wiks@qrgo:/home/sftp$ cd .ssh
wiks@qrgo:/home/sftp/.ssh$ sudo touch authorized_keys  #tworze plik 
wiks@qrgo:/home/sftp/.ssh$ sudo nano authorized_keys   #kopiuję do niego 
                                                       #zawartość z 
                                                       #/home/wiks/.ssh
wiks@qrgo:/home/sftp/.ssh$ sudo chown sftp:sftp authorized_keys  #owner

Sprawdzenie (przy okazji zmiana uprawnień do pliku przesłanego, tak aby mógł go oglądać tylko właściciel):

wiks@dellwiks:~$ sftp -oPort=59999 sftp@11.22.33.44 <<EOF
put /home/wiks/Dokumenty/plik.txt ftp/plik.txt
chmod 700 ftp/plik.txt
EOF
Connected to 11.22.33.44.
sftp> put /home/wiks/Dokumenty/plik.txt ftp/plik.txt
Uploading /home/wiks/Dokumenty/plik.txt to /ftp/plik.txt
/home/wiks/Dokumenty/plik.txt                100%  200   108.6KB/s   00:00    

działa! Hola hola… to dopiero z terminala działa, teraz jeszcze pora na wpisanie tego w skrypcie BASH…

Zerknę jednak jeszcze, jak ta negocjacja i wymiana kluczy wygląda z opcją -v :

wiks@dellwiks:~$ sftp -v -oPort=59999 sftp@11.22.33.44 <<EOF
put /home/wiks/Dokumenty/BURPEES.txt ftp/plik.txt
chmod 700 ftp/plik.txt
EOF
OpenSSH_8.2p1 Ubuntu-4ubuntu0.1, OpenSSL 1.1.1f  31 Mar 2020
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files
debug1: /etc/ssh/ssh_config line 21: Applying options for *
debug1: Connecting to 11.22.33.44 [11.22.33.44] port 59999.
debug1: Connection established.
debug1: identity file /home/wiks/.ssh/id_rsa type 0
debug1: identity file /home/wiks/.ssh/id_rsa-cert type -1
debug1: identity file /home/wiks/.ssh/id_dsa type -1
debug1: identity file /home/wiks/.ssh/id_dsa-cert type -1
debug1: identity file /home/wiks/.ssh/id_ecdsa type -1
debug1: identity file /home/wiks/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/wiks/.ssh/id_ecdsa_sk type -1
debug1: identity file /home/wiks/.ssh/id_ecdsa_sk-cert type -1
debug1: identity file /home/wiks/.ssh/id_ed25519 type -1
debug1: identity file /home/wiks/.ssh/id_ed25519-cert type -1
debug1: identity file /home/wiks/.ssh/id_ed25519_sk type -1
debug1: identity file /home/wiks/.ssh/id_ed25519_sk-cert type -1
debug1: identity file /home/wiks/.ssh/id_xmss type -1
debug1: identity file /home/wiks/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.4p1 Debian-10+deb9u7
debug1: match: OpenSSH_7.4p1 Debian-10+deb9u7 pat OpenSSH_7.0*,OpenSSH_7.1*,OpenSSH_7.2*,OpenSSH_7.3*,OpenSSH_7.4*,OpenSSH_7.5*,OpenSSH_7.6*,OpenSSH_7.7* compat 0x04000002
debug1: Authenticating to 11.22.33.44:59999 as 'sftp'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:36Rk47+HzfscI65Mq33Qg1+zo7E+MIef+xwOyqnS8gQ
debug1: Host '[11.22.33.44]:59999' is known and matches the ECDSA host key.
debug1: Found key in /home/wiks/.ssh/known_hosts:8
debug1: rekey out after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey in after 134217728 blocks
debug1: Will attempt key: /home/wiks/.ssh/id_rsa RSA SHA256:si3xbE2ndMvOumSNa+QFvnBrYI8TmuCBLfcfJzQrqRw agent
debug1: Will attempt key: /home/wiks/.ssh/id_dsa 
debug1: Will attempt key: /home/wiks/.ssh/id_ecdsa 
debug1: Will attempt key: /home/wiks/.ssh/id_ecdsa_sk 
debug1: Will attempt key: /home/wiks/.ssh/id_ed25519 
debug1: Will attempt key: /home/wiks/.ssh/id_ed25519_sk 
debug1: Will attempt key: /home/wiks/.ssh/id_xmss 
debug1: SSH2_MSG_EXT_INFO received
debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Offering public key: /home/wiks/.ssh/id_rsa RSA SHA256:si3xbE2ndMvOumSNa+QFvnBrYI8TmuCBLfcfJzQrqRw agent
debug1: Server accepts key: /home/wiks/.ssh/id_rsa RSA SHA256:si3xbE2ndMvOumSNa+QFvnBrYI8TmuCBLfcfJzQrqRw agent
debug1: Authentication succeeded (publickey).
Authenticated to 11.22.33.44 ([11.22.33.44]:59999).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: network
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Sending environment.
debug1: Sending env LANG = pl_PL.UTF-8
debug1: Sending subsystem: sftp
Connected to 11.22.33.44.
sftp> put /home/wiks/Dokumenty/plik.txt ftp/plik.txt
debug1: Couldn't stat remote file: No such file or directory
Uploading /home/wiks/Dokumenty/plik.txt to /ftp/plik.txt
/home/wiks/Dokumenty/plik.txt                100%  200   109.6KB/s   00:00    
sftp> chmod 700 ftp/plik.txt
Changing mode on /ftp/plik.txt
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
Transferred: sent 3836, received 3152 bytes, in 0.1 seconds
Bytes per second: sent 50717.8, received 41674.3
debug1: Exit status 0

Ok. teraz w skrypcie bash. Tworzę skrypt, nazwę go test_sftp.sh z zawartością jak niżej. Czyli prześlę plik jako użytkownik sftp uwierzytelniając się swoim kluczem publicznym jako zaufanym dla serwera. Następnie prześlę plik i zmienie jego uprawnienia w ten sposób, aby nikt nie mógł go otwierać:

#!/bin/bash

echo 'czy dziala'

sftp -oPort=59999 sftp@11.22.33.44 <<EOF
put /home/wiks/Dokumenty/plik.txt ftp/plik.txt
chmod 700 ftp/plik.txt
EOF

echo 'koniec'

uruchamiam: bash test_sftp.sh , sprawdzam poprzez SSH jako wiks , w folderze użytkownika sftp :

wiks@qrgo:/home/sftp/ftp$ ls -al
razem 28
drwxrwxrwx 3 root root 4096 sty 22 00:24 .
drwxr-xr-x 4 root root 4096 sty 21 17:56 ..
-rwx------ 1 sftp sftp  200 sty 22 00:25 plik.txt
drwxr-xr-x 2 sftp sftp 4096 sty 16 18:17 Nowy folder
wiks@qrgo:/home/sftp/ftp$

Ok. Działa.

Łącząc teraz automatyczną codzienną archiwizację bazy danych, logów z szyfrowaniem powstałej paczki oraz przesłaniem w bezpieczny sposób na oddalony serwer – uzyskam dość bezpieczny i trwały sposób zachowania i możliwości odtworzenia bazy danych, oraz działań świata zewnętrznego na wystawionym serwerze www. 🙂

Linki: FTP, SSH, archiwizacjaDB .

Dodaj komentarz

Translate »