Com muntar accessos SFTP

De GiLUG
Dreceres ràpides: navegació, cerca

Català - Castellano - English


SFTP és el sistema de transferència de fitxers que, a diferència del FTP tradicional, passa per una connexió segura SSH, amb la qual tota la comunicació és xifrada i es comprova l'autenticitat del servidor. Muntar un accés a un directori remot implica poder accedir les carpetes i fitxers d'aquell ordinador remot de forma plenament integrada al nostre ordinador, com si aquella carpeta estigués al nostre ordinador local.

Amb els detalls d'aquesta guia, també l'administrador de servidors-web pot substituir completament el servei FTP per SFTP en el manteniment de continguts-web. El tutorial ha estat provat amb distribucions Debian, però amb poca diferència pot servir per altres GNU/Linux i Unix que utilitzin el mateix programari.

Equip servidor

El servidor és el sistema/ordinador que conté les carpetes i fitxers a servir, és a dir, el magatzem accessible des d'altres ordinadors.

  • Almenys s'hi ha de tenir instal·lat el paquet openssh-server, i també el paquet libpam-umask o libpam-modules
  • Al fitxer /etc/pam.d/sshd cal afegir (no cal reiniciar cap servei):
# Default umask mask for SSH/SFTP sessions
# Shell sessions: Settings in /etc/profile or ~/.bashrc or ~/.profile will replace this
session optional        pam_umask.so umask=0000

La qual cosa estableix una màscara al servidor sobre la màscara del client a l'hora de crear fitxers i directoris. Això vol dir que si per exemple al servidor-pam hi ha umask=0077 i el client fa servir umask=0227 , els elements seran creats amb umask=0277 (el servidor tapa el client), sense perjudici de què el client canvii després els atributs (chmod). En resum: és per a què es puguin crear carpetes i documents amb permisos per nosaltres i els demés.

Si al sistema no tenim un fitxer /etc/pam.d/sshd aleshores podem escriure les opcions al genèric /etc/pam.conf

  • Nota1: Obrint del tot la màscara del servidor-pam (umask=0000), els elements es creen de forma transparent amb els permisos de l'usuari-client (el seu umask local), així que és a l'equip-client on millor es poden configurar.
  • Nota2: Arreu trobareu documentat el truc de reemplaçar al fitxer /etc/ssh/sshd_config del servidor la crida a sftp-server o internal-sftp per un script, que primer executi umask i després faci la crida a sftp-server, però això no pot funcionar amb SFTP engabiat on no s'habilita Shell que pugui executar scripts.

SFTP engabiat

Connectant per SFTP a un servidor tal qual, es poden explorar els directoris del sistema com si estiguessim en una sessió local o per terminal SSH. Per a què això no passi, hem d'establir un directori en concret que el client veurà com si fos l'arrel del servidor (/), i impedir les sessions de terminal/consola.

  • Requisit: OpenSSH server versió 4.8 o superior.
  • Establim un grup d'usuaris que només tindran accés per SFTP (sense Shell), i el directori per les seves rutes d'accés:
groupadd sftponly
mkdir /etc/sftp-roots.d
  • Al fitxer /etc/ssh/sshd_config deshabilitar la línia "Subsystem sftp ..." existent (inserint # com a primer caràcter), i afegir al final del fitxer:
Subsystem       sftp    internal-sftp
Match Group sftponly
	# Variables per ChrootDirectory: %h ($HOME) %u ($USERNAME)
	ChrootDirectory /etc/sftp-roots.d/%u
	ForceCommand internal-sftp
	AllowTcpForwarding no
	X11Forwarding no
  • Reiniciem el servei SSH per a què funcionin els canvis (no es tallen les sessions SSH obertes):
service ssh restart

Crear usuaris i directoris engabiats

Els comptes d'usuari creats amb les següents instruccions seran els afectats pel sistema d'engabiat. No se'ls crea un perfil/directori propi a /home (opcional) ni se'ls permet accedir via terminal/SSH (restricció necessària). En aquest exemple l'usuari es dirà "narcis" i quan connecti accedirà a la carpeta /mnt/dades :

NouUsuari="narcis"
Destinacio="/mnt/dades"
ln -s $Destinacio /etc/sftp-roots.d/$NouUsuari
adduser  --gecos "" --no-create-home --home /etc/sftp-roots.d/$NouUsuari --ingroup sftponly $NouUsuari
usermod -s /bin/false $NouUsuari
chown root $Destinacio
chmod go-w $Destinacio

Vegeu que el directori d'accés (a l'exemple /mnt/dades) ha d'estar protegit pel superusuari (root), i allà mateix l'usuari extern (a l'exemple "narcis") no podrà crear ni modificar res. Se li poden donar permisos d'escriptura a un subdirectori, com per exemple "escola":

CarpetaModificable="/mnt/dades/escola"
mkdir $CarpetaModificable
chown $NouUsuari:sftponly $CarpetaModificable
chmod ug+rwX $CarpetaModificable

Crear usuaris i directoris normals

No està de més ensenyar la fórumla simple sense engabiar i amb perfil propi a /home , de manera que determinats usuaris puguin accedir a qualsevol directori com un usuari local (sense privilegis d'administració), i amb la possibilitat d'entrar via terminal SSH.

NouUsuari="narcis"
adduser  --gecos "" --add_extra_groups $NouUsuari

En aquest cas se li crea un típic directori d'usuari a /home/narcis , on anirà a parar si es connecta per terminal SSH. Per SFTP l'arrel (/) és la mateixa que el servidor, així que per a muntar des de l'equip client caldria especificar /home/narcis

  • Nota: Els usuaris normals també poden iniciar sessió local, és a dir, que poden iniciar una sessió utilitzant físicament la pantalla i el teclat del servidor. Si és un ordinador d'escriptori el que fa de servidor, potser és millor crear els usuaris amb l'eina de l'entorn gràfic.

Equip client

El client és el programari/ordinador que accedirà a les carpetes i fitxers de la xarxa, és a dir, el que no té les dades i es vol connectar al servidor. Sempre es podria connectar de forma senzilla amb un programa-client de FTP com gFTP, FileZilla o similar, però aquesta guia és per a tenir-ho muntat i integrat per totes les aplicacions.

  • Almenys s'hi ha de tenir instal·lat el paquet sshfs
  • Cal habilitar l'opcio user_allow_other al fitxer /etc/fuse.conf per a permetre que l'usuari normal munti per sí mateix la connexió.
Normalment trobarem aquesta opció deshabilitada amb una marca de comentari (#) al davant:
#user_allow_other
que hem de treure per a deixar:
user_allow_other
  • Crear un fitxer /usr/local/bin/sshfs-mount.sh amb aquest contingut que he elaborat:
#!/bin/sh
# Connectar un punt de muntatge SFTP
# Versio 2010.12.28
# Copyright (GNU GPL) Narcis Garcia

RutaLocal="$1"
ContrasenyaRemota="$2"
RestringirAUsuari="$3"

Connectar ()
{
	Result=0
	JaMuntat="$(mount | grep " $RutaLocal ")"
	if [ "$JaMuntat" = "" ] ; then
		if [ "$(which sshfs)" = "" ] ; then
			apt-get install -qq -y sshfs
		fi
		if [ "$(which mount.fuse.sshfs)" = "" ] ; then
			ln -s $(which mount.fuse) /sbin/mount.fuse.sshfs
		fi
		if [ ! -d "$RutaLocal" ] ; then  # Crear el punt de muntatge amb permisos
			mkdir -p "$RutaLocal"
			if [ "$RestringirAUsuari" = "" ] ; then
				chmod ugo=rwX "$RutaLocal"
			else
				GrupLocal="$(id -ng $RestringirAUsuari)"
				chown $RestringirAUsuari:$GrupLocal "$RutaLocal"
				chmod u=rwX,g=rX,o= "$RutaLocal"
			fi
		fi
		
		echo "$ContrasenyaRemota" | mount "$RutaLocal" -o password_stdin,allow_other,StrictHostKeyChecking=no
		Result=$?
		if [ $Result -eq 0 ] ; then
			echo "	Correcte"
		else
			echo "($Result) La instruccio era:"
			echo "echo \"\$ContrasenyaRemota\" | mount \"$RutaLocal\" -o password_stdin,allow_other,StrictHostKeyChecking=no"
		fi
	else
		echo "El directori ja estava muntat a $(RetornaParaula () { echo $3; }; RetornaParaula $JaMuntat)"
		Result=1
	fi
	return $Result
}
BitacolaTemp="/tmp/sshfs_$(echo "$RutaLocal" | tr -s "/" "-" | tr -s " " "_").log"
MissatgeInicial="Connectant $RutaLocal al servidor$(if [ -f $BitacolaTemp ] ; then echo " (s'havia interromput) " ; fi)... "
printf "$MissatgeInicial"
Linia1Log="$(date +'%Y-%m-%d %H:%M:%S') $MissatgeInicial"
Connectar > $BitacolaTemp 2>&1
cat $BitacolaTemp
if [ $(id -g) -eq 0 ] ; then
	echo "$Linia1Log$(cat $BitacolaTemp)" >>/var/log/sshfs.log
fi
rm $BitacolaTemp
  • Donar permisos d'execució al nou fitxer:
chmod a+x /usr/local/bin/sshfs-mount.sh
  • Crear un fitxer /etc/network/if-down.d/sshfs-umounts (sense extensió .sh) amb aquest contingut que he elaborat:
#!/bin/sh
# Desconectar tots els punts de muntatge SFTP
# Versio 2010.10.10
# Copyright (GNU GPL) Narcis Garcia
# Nota: Nomes funciona amb rutes remotes i locals sense espais

Desconnectar ()
{
	local RutaLocal="$1"
	umount "$RutaLocal"
	Result=$?
	if [ $Result -eq 0 ] ; then
		echo "	Correcte"
	else
		echo "($Result)"
	fi
	return $Result
}

TextActual="$(date +'%Y-%m-%d %H:%M:%S') Es desconnectaran els accessos SFTP:"
echo "$TextActual"
if [ $(id -g) -eq 0 ] ; then
	echo "$TextActual" >>/var/log/sshfs.log
fi
LlistaMuntats="$(mount | grep -e " fuse\.sshfs ")"
if [ "$LlistaMuntats" != "" ] ; then
	IFS=$(printf "\n\b") ; for LiniaActual in $LlistaMuntats ; do unset IFS
		RutaLocal="$(RetornaParaula () { echo $3; }; RetornaParaula $LiniaActual)"
		BitacolaTemp="/tmp/sshfs_$(echo "$RutaLocal" | tr -s "/" "-" | tr -s " " "_").log"
		MissatgeInicial="Desconectant $RutaLocal del servidor $(if [ -f $BitacolaTemp ] ; then echo "(s'havia interromput)" ; fi)... "
		printf "$MissatgeInicial"
		Linia1Log="$(date +'%Y-%m-%d %H:%M:%S') $MissatgeInicial"
		Desconnectar "$RutaLocal" > $BitacolaTemp 2>&1
		cat $BitacolaTemp
		if [ $(id -g) -eq 0 ] ; then
			echo "$Linia1Log$(cat $BitacolaTemp)" >>/var/log/sshfs.log
		fi
		rm $BitacolaTemp
	done
else
	TextActual="No hi havia punts SFTP muntats."
	echo "$TextActual"
	if [ $(id -g) -eq 0 ] ; then
		echo "$TextActual" >>/var/log/sshfs.log
	fi
fi
  • Donar permisos d'execució al nou fitxer:
chmod a+x /etc/network/if-down.d/sshfs-umounts

Crear accessos per usuari

Amb aquesta recepta preparem el muntatge d'una unitat per a què l'utilitzi un usuari de l'equip client.

  • Comprovem el número d'usuari (uid) i el número de grup (gid) de l'usuari que utilitzarà l'accés:
id usuarilocal

Podem obtenir per exemple:

uid=1000(ngarcia) gid=1000(grupgarcia) grups=24(cdrom),46(plugdev),1000(grupgarcia)

d'on obtenim el número d'usuari (1000) i el número de grup principal (1000)

  • L'usuari i contrasenya que utilitzarem per connectar han d'existir al servidor. Afegim l'entrada corresponent al fitxer /etc/fstab , suposant a l'exemple que el servidor es troba a 192.168.1.5 i que ho muntarem a la carpeta /home/ngarcia/Documents/escola de l'ordinador-client.
# escola-ngarcia
narcis@192.168.1.5:/escola /home/ngarcia/Documents/escola fuse.sshfs uid=1000,gid=1000,port=22,ConnectionAttempts=3,ServerAliveInterval=15,ServerAliveCountMax=5760,noauto,user,idmap=user,default_permissions,intr,transform_symlinks,follow_symlinks 0 0
  • Crear un fitxer /etc/network/if-up.d/sshfs-mounts (sense extensió .sh) amb un contingut així:
#!/bin/sh
# Sintaxi de les entrades: sshfs-mount.sh "ruta local" "contrasenyaremota" "restringir a usuari?"

sshfs-mount.sh "/home/ngarcia/Documents/escola" "1234" "ngarcia"

Nota: Si volem muntar més carpetes, només hem d'afegir entrades a aquest mateix fitxer.

  • Mesures de seguretat, per amagar una mica la contrasenya i per restringir l'accés des d'altres usuaris:
chown root:root /etc/network/if-up.d/sshfs-mounts /etc/network/if-down.d/sshfs-umounts
chmod u=rwx,go=  /etc/network/if-up.d/sshfs-mounts /etc/network/if-down.d/sshfs-umounts
mkdir /home/ngarcia/Documents/escola
chown ngarcia:grupgarcia /home/ngarcia/Documents/escola
chmod u=rwX,g=rX,o= /home/ngarcia/Documents/escola

Tot i amb això, un usuari de l'ordinador amb permisos d'administració (o des d'un Live-CD) pot veure el cotingut de /etc/network/if-up.d/ , amb les contrasenyes que hi hagi escrites. La manera de blindar això és que el sistema-client estigui en una partició encriptada, o separa aquesta dada en un volum encriptat.

  • Preparació de permisos predeterminats de l'usuari-client
    • Quan es prepara un accés SFTP per un(s) usuari(s), s'estableix umask a ~/.bashrc i ~/.profile - Senzillament al final de cada fitxer s'afegeix/reemplaça una línia amb una instrucció tal com:
umask 0027
~/.bashrc és específic pels terminals/scripts Shell interpretats per Bash en una sessió d'usuari.
~/.profile és pels terminals/scripts Shell d'altres intèrprets com Dash (no-Bash), en una sessió d'usuari.
      • Si vols saber quin intèrpret utilitza el sistema de forma predeterminada (per exemple amb scripts), executa en un terminal: ls -l /bin/sh
      • Si vols saber quin intèrpret utilitzen les sessions de terminal/consola, executa en un terminal: echo $SHELL
    • Quan es prepara un accés SFTP per tothom del sistema, s'estableix umask a /etc/profile
La configuració de /etc/profile val de forma predeterminada per les sessions Shell (de terminal/consola i de tots els scripts del sistema). Senzillament al final del fitxer s'afegeix/reemplaça una línia amb una instrucció tal com:
umask 0027
    • Per ambdós tipus d'accés, establir-ho als diferents fitxers de configuració esmentats.

Nota per navegants: A /etc/login.defs hi ha un paràmetre UMASK, però només val per les sessions no-shell (per exemple connexions PPP des de fora). Les sessions gràfiques i SFTP es consideren cridades des de Shell-script.

  • Per a què tots els canvis s'apliquin correctament (bàsicament umask), cal reiniciar el sistema.
Alternativa: no muntar automàticament

Si no volem que la connexió es munti automàticament en engegar l'ordinador i tenir xarxa, símplement hem d'ometre l'entrada al fitxer /etc/network/if-up.d/sshfs-mounts i podrem muntar de dues maneres:

1. Amb la instrucció:
mount /home/ngarcia/Documents/escola
2. O bé mitjançant l'explorador de carpetes. A escriptoris com Gnome o KDE solen aparèixer les unitats sense muntar de /etc/fstab , i anant a aquests Llocs, és a dir, obrint els accessos que ens mostra l'entorn gràfic, ens demanarà la contrasenya remota i ens muntarà la carpeta.

Opcions de FUSE/SSHFS (annex de referència)

Aquí una taula explicativa sobre algunes opcions subministrades a l'entrada de muntatge i comanda de connexió:

user (per investigar)
noauto Específica de /etc/fstab per a què mount no munti automàticament, sinó que esperi la instrucció d'usuari.
L'alternativa seria "auto", però amb les decoracions d'inici segurament no es podria subministrar la contrasenya.
ConnectionAttempts=3 Número d'intents de connexió. Per una xarxa local (cablejada o inalàmbrica) n'hi ha prou amb 3. Pot convenir incrementar-ho per enllaços a través d'internet o amb equips lents.
ServerAliveInterval=15 Interval d'enviament del senyal "keep alive" al servidor per a què no talli la connexió durant la manca d'activitat. En segons.
ServerAliveCountMax=5760 Número total d'enviaments de "keep alive" que es faran. Després es deixaria morir la connexió si no hi ha activitat.
idmap=user Habilitar la traducció del UID emprat entre client i servidor: si per exemple el vostre ID d'usuari local en ús és 1034 però el ID d'usuari remot de la connexió és 1002, aleshores tots els fitxers pertanyents remotament a 1002 seran vistos localment pertanyents a 1034. No hi ha traducció/comparació de noms. Per defecte és deshabilitat (idmap=none).
  • No utilitzeu idmap=user si voleu veure o obtenir fitxers remots estrictament amb el número de ID propietari:grup original.
uid=1000 Identificador d'usuari del sistema-client a traduir per l'identificador de l'usuari remot
Amb la versió provada (SSHFS 2.2 FUSE 2.8.1), qualsevol usuari remot (propietari) es veu com si fos l'usuari especificat.
Actua com una disfressa per la lectura (servidor->client), i una traducció per l'escriptura (client->servidor).
  • Tot i la disfressa, el servidor aplica els seus permisos de forma realista; el petit inconvenient des del client pot ser que no sembli coherent una restricció si es veu tot de la seva propietat.
  • No utilitzeu aquesta opció si voleu veure o obtenir fitxers remots amb el propietari original. De tota manera no hi ha traducció/comparació de noms, doncs un propietari remot 1234 (UID remot per jordi) pot ser vist aquí com a 1234 (UID local per miquel).
gid=1000 Identificador de grup al sistema-client a traduir per l'identificador de grup d'usuari remot.
Amb la versió provada (SSHFS 2.2 FUSE 2.8.1), qualsevol grup remot es veu com si fos el grup especificat.
Actua com una disfressa per la lectura (servidor->client), i una traducció per l'escriptura (client->servidor).
  • Tot i la disfressa, el servidor aplica els seus permisos de forma realista; el petit inconvenient des del client pot ser que no sembli coherent una restricció si es veu tot del seu mateix grup.
  • No utilitzeu aquesta opció si voleu veure o obtenir fitxers remots amb el grup original. De tota manera no hi ha traducció/comparació de noms, igual com passa amb UID.
umask=0027 Màscara de permisos per fitxers i subdirectoris
Amb la versió provada (SSHFS 2.2 FUSE 2.8.1), fa que el client vegi disfressats tots els elements com si portessin aquests permisos (0027 -> rw-r-----).
Per a veure els permisos tal com són al servidor, cal ometre aquest paràmetre.
Nota: tot i la disfressa, el servidor aplica els seus permisos de forma realista; l'inconvenient des del client no sembli coherent una restricció si es veuen permisos favorables.
default_permissions Habilita el control de permisos (no d'usuaris-propietaris) des del sistema-client, en comptes de mostrar atributs desactualitzats i esperar respostes d'error del servidor (R/W)
intr Permet que les peticions siguin interrompudes
transform_symlinks Traduir els enllaços absoluts al servidor per enllaços relatius que funcionin des del client
follow_symlinks (relacionat amb transform_symlinks)
port=22 Port TCP de connexió al servidor SSH (per defecte 22)
password_stdin Esperar la contrasenya via stdin:
echo "contrasenya" | mount /mnt/punt -o password_stdin

És la manera d'enviar automàticament la contrasenya des d'un programet-script. Convé utilitzar-ho només amb la crida d'instrucció; si es posa a fstab pot ser problemàtic muntant mitjançant entorn gràfic.

allow_other Permetre l'accés al contingut muntat a usuaris normals (no root)
Convé utilitzar-ho només a la crida d'instrucció; posar-ho a fstab és incompatible amb què ho munti l'usuari normal.
StrictHostKeyChecking=no Assumir com a bona la primera clau RSA que retorni el servidor.
Convé utilitzar-ho només a la crida d'instrucció, per a poder gestionar millor un error de RSA diferent.

Més informació amb:

man sshfs
man ssh_config

Funcionament general de umask

És una màscara-plantilla. És com l'invers de chmod, ja que serveix per tapar els permisos a establir en la creació de fitxers i subdirectoris. Com més alt és el valor octal, més restrictiu (a nivell binari un bit 1 tapa un atribut i un bit 0 el permet).

0 permet rwX
1 permet rw-
2 permet r-X
3 permet r--
4 permet -wX
5 permet -w-
6 permet --X
7 permet ---
  • Exemples:
Aleshores amb umask 0022 es creen fitxers amb permisos rw-r--r-- i subdirectoris amb rwxr-xr-x
amb umask 0007 es creen fitxers amb permisos rw-rw---- i subdirectoris amb rwxrwx---
amb umask 0027 es creen fitxers amb permisos rw-r----- i subdirectoris amb rwxr-x---
  • El zero inicial es posa per indicar que està escrit en octal (0022 en comptes de 022)
  • Tot això sense perjudici de que es poden canviar després els atributs (chmod)

Sincronització, còpies de seguretat

Notes:

  • La única manera de preservar les pertanyences de propietari i al mateix temps que coincideixin els noms remots amb els locals, és tenir els mateixos IDs numèrics al sistema local que al servidor remot. Això s'aconsegueix efectivament quan es té idèntic contingut en aquests fitxers:
/etc/passwd
/etc/group

Veure també

Pendent de documentar

  • Desenvolupar més sshfs-mount.sh per a què també munti carpetes que no tenen entrada a "fstab" (això evitaria l'aparició d'unitats de disc als exploradors de carpetes, o facilitaria tenir una eina-script portable)
  • "transform_symlinks" no sembla funcionar, i aleshores no es pot comprovar l'eficàcia de "follow_symlinks"
  • Està per veure la utilitat de l'opció "user"
  • Tenir en compte que els programets a /etc/network/if-up.d i /etc/network/if-down.d són executats per cada interfície de xarxa.