Commit 8d4eb519 authored by jaime's avatar jaime
Browse files

cometida inicial

parents
# Instalación de sftp_sshfs_share
## Instalar paquetes dependencias
Es necesario instalar open_ssh_server y sshfs en el servidor
root@debian:~# apt-get install openssh-server sshfs
Este script también depende de systemd versión 230 o mayor. En debian jessie es necesario habilitar el repositorio de jessie-backports para actualizar systemd.
root@debian:~# apt-get install -t jessie-backports systemd
## Configuración de servidor ssh
Edita /etc/ssh/sshd_config haciendo lo siguientes cambios
Cambia la directiva Subsystem sftp
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
Al final del archivo agrega las siguientas lineas
Match Group sftponly
PasswordAuthentication no
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
Match Group localsftp Address 127.0.0.1
PasswordAuthentication no
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
Reinicia el servidor ssh para aplicar los cambios
systemctl restart ssh
## Instalación de archivos
Clonar este repositorio dentro del directorio /opt
root@debian:/opt# git clone https://soporte.tierracomun.org/desarrollo/sftp_sshfs_share.git
Crear ligas simbólicas a los scripts dentro de /usr/local/bin
root@debian:~# ln -s /opt/sftp_sshfs_share/sftp_sshfs_share /usr/local/bin/
root@debian:~# ln -s /opt/sftp_sshfs_share/wrapper_functions_sftp_sshfs_share /usr/local/bin/
root@debian:~# ln -s /opt/sftp_sshfs_share/create_systemd_sshfs_mount_point /usr/local/bin/
Crear liga simbólica al directorio de templates dentro de /usr/local/share/
root@debian:~# ln -s /opt/sftp_sshfs_share/systemd_sshfs_mount_unit_file_templates /usr/local/share/
## Introducción
[Instalación](INSTALL.md)
Uso:
sftp_sshfs_share nombre_de_usuario nombre_de_grupo
Coloca llave pública ssh del usuario en /home/nombre_de_usuario/.ssh/authorized_keys
#!/bin/bash
#format
#remoteuser@host:shared_folder /home/localuser/mount localuser /home/localuser/.ssh/sshfs_mount
REMOTEPATH="$1"
LOCALMOUNT="$2"
LOCALUSER="$3"
SSHKEY="$4"
MOUNT_TEMPLATE=/usr/local/share/systemd_sshfs_mount_unit_file_templates/template.mount
AUTOMOUNT_TEMPLATE=/usr/local/share/systemd_sshfs_mount_unit_file_templates/template.automount
DESCRIPTION="sshfs mount $REMOTEPATH to $LOCALMOUNT for $LOCALUSER"
REMOTEUSER=$(echo $REMOTEPATH | cut -f1 -d'@')
HOST=$(echo $REMOTEPATH | cut -f2 -d'@' | cut -f1 -d':')
SHAREDFOLDER=$(echo $REMOTEPATH | cut -f2 -d'@' | cut -f2 -d':')
HOMEDIR=$(getent passwd $LOCALUSER | cut -f6 -d:)
USERID=$(getent passwd $LOCALUSER | cut -f3 -d:)
MOUNTPOINT="$LOCALMOUNT"
ESCMOUNTPOINT=$(echo $MOUNTPOINT | cut -f2- -d'/' | sed -e 's/\//-/g')
#echo -e "$DESCRIPTION \n $HOMEDIR $MOUNTPOINT $ESCMOUNTPOINT $SSHKEY $USERID $REMOTEUSER $HOST $SHAREDFOLDER"
# escape slashes
#escaped="${escaped//\//\\/}"
# escape full stops
#escaped="${escaped//./\\.}"
exp="<<DESCRIPTION>>"
var="${DESCRIPTION//\//\\/}"
args+="s/$exp/${var}/g;"
exp="<<ESCMOUNTPOINT>>"
var=${ESCMOUNTPOINT}
args+="s/$exp/${var}/g;"
exp="<<HOMEDIR>>"
var="${HOMEDIR//\//\\/}"
args+="s/$exp/${var}/g;"
exp="<<MOUNTPOINT>>"
var="${MOUNTPOINT//\//\\/}"
args+="s/$exp/${var}/g;"
sed -e "${args[@]}" $AUTOMOUNT_TEMPLATE > /etc/systemd/system/${ESCMOUNTPOINT}.automount
exp="<<REMOTEUSER>>"
var=${REMOTEUSER}
args+="s/$exp/${var}/g;"
exp="<<HOST>>"
var="${HOST//./\\.}"
args+="s/$exp/${var}/g;"
exp="<<SHAREDFOLDER>>"
var="${SHAREDFOLDER//\//\\/}"
args+="s/$exp/${var}/g;"
exp="<<SSHKEY>>"
SSHKEY="${SSHKEY//\//\\/}"
var="${SSHKEY//./\\.}"
args+="s/$exp/${var}/g;"
exp="<<USERID>>"
var=${USERID}
args+="s/$exp/${var}/g;"
sed -e "${args[@]}" $MOUNT_TEMPLATE > /etc/systemd/system/${ESCMOUNTPOINT}.mount
#enable and start automount unit file
systemctl --quiet enable --now ${ESCMOUNTPOINT}.automount
#enable mount unit file
systemctl --quiet enable ${ESCMOUNTPOINT}.mount
en1=$(systemctl --quiet is-enabled ${ESCMOUNTPOINT}.automount)
en2=$(systemctl --quiet is-enabled ${ESCMOUNTPOINT}.mount)
[[ en1 -ne 0 ]] || [[ en2 -ne 0 ]] && exit 1;
exit 0
###sftpchroot
El servidor openssh nos permite crear un chroot o "jaula chroot" para usuarios de ssh. El chroot asigna a estos usuarios una nueva *raiz virtual*. Los usuarios "enjaulados" a su propio home por ejemplo solo pueden acceder al sistema de ficheros que desciende desde su home.
Utilzaremos el grupo *sftpusers* para controlar cuales usuarios serán enjaulados. Este grupo no existe por defecto en debian. Podemos crearla con el comando *groupadd*. en este caso utilizaremos la opción *-g 2000* para asignar un numero id al grupo fuera del rango de usuarios normales. Finalmente agregamos un usuario al grupo con el comando *adduser*.
sudo groupadd -g 2000 sftpusers
sudo adduser jaime sftpusers
Como medida de seguridad deberíamos asegurar que el [[shell de entrada|shell]] de los usuarios del grupo sftpusers es asignada a /bin/false para asegurar que no podrán ejecutar comandos. Ojo! No cambias el shell ni agregas a sftpusers un usuario que usas para administrar el sistema.
Aquí es un ejemplo de como crear un nuevo usuario sin acceso shell y automáticamente agregarle al grupo sftpusers con el comando useradd.
sudo useradd --home-dir /home/jaime --skel /dev/null --create-home \
--shell /bin/false --comment "jaime@tierracomun.org" --groups "sftpusers" jaime
sudo usermod -s /bin/false jaime
Es necesario que *root* sea el dueño del directorio chroot antes de activarla. Ejemplo:
chown root:root /home/jaime
Por consecuencia usuarios con sftp_chroot no podrán modificar o crear nuevo directorios directamente en su home. Una forma de resolver esto es crear un nuevo directorio "archivos" cuyos contenidos pueden modificar libremente.
sudo mkdir /home/jaime/archivos && sudo chown jaime:jaime /home/jaime/archivos
Para activar el sftp chroot editamos /etc/ssh/sshd_config y cambiamos el sftp subsystem
#Subsystem sftp /usr/libexec/openssh/sftp-server
Subsystem sftp internal-sftp
Ahora al final del sshd_config agregamos un bloque *Match* que a todos los usuarios del grupo *sftpusers* les asigna el directorio para la jaula chroot a su propio home.
Match Group sftpusers
ChrootDirectory %h
ForceCommand internal-sftp
PasswordAuthentication yes
AllowTcpForwarding no
X11Forwarding no
Las opciones adicionales arriba permiten acceso con contraseña y prohiben forwardear puertos tcp y X11 a traves de esta conexión. En algunos casos cambiaremos *PasswordAuthentication* a *no* para controlar el acceso [[utilizando llaves ssh]]. Para que los cambios en /etc/ssh/sshd_config toman efecto hay que reiniciar el servidor ssh
sudo service ssh restart
*S*ecure *SH*ell *F*ile*S*ystem (*SSHFS*) es un sistema de archivos para Linux que opera sobre archivos en una computadora remota a través del protocolo ssh.
Los efectos prácticos de esto es que el usuario puede interactuar con archivos remotos, viéndolos como si estuvieran en el sistema local.
### Instalar sshfs en debian
sudo aptitude install sshfs
### Utilizando sshfs
Montando un directorio remoto de sshfs es sencillo,siguiendo el siguente formato ficticio.
sshfs usuarioremoto@servidorremoto:/carpeta/remoto /directorio/local -o opciones_de_ssh
Aquí es un ejemplo con datos reales.
mkdir /home/jaime/tierracomun
sshfs tierracomun@192.168.0.4:/home/tierracomun /home/jaime/tierracomun -o idmap=user,uid=1000,gid=1000,IdentityFile=/home/jaime/.ssh/id_rsa
En el ejemplo arriba se montaría el directorio remoto /home/tierracomun del usuario tierracomun en el directorio local /home/jaime/tierracomun
El directorio local debe existir antes de intentar montar el sistema remoto y debe estar vacia. Las opciones *idmap=user,uid=1000,gid=1000* mapean los permisos del usuario remoto al usuario local con uid y gid "1000" lo cual corresponde al usuario jaime en este caso. Puedes revisar el numero id del usuario y grupo de cualquier cuenta con el comando *id*. ejemplo:
id --user jaime
id --group jaime
El efecto de las opciones *idmap=user,uid=1000,gid=1000* es que los archivos en /home/jaime/tierracomun aparecen como el usuario y grupo *jaime* localmente y jaime puede editarlos pero en el servidor remoto los mismos archivos retienen su usuario y grupo original de *tierracomun*.
El opción *IdentityFile=/home/jaime/.ssh/id_rsa* especifica que utilizaremos la llave privada de jaime para autentificar la conexión. La llave publica */home/jaime/.ssh/id_rsa.pub* debe haber sido copiado antemano a los authorized_keys de la cuenta tierracomun en el servidor remoto. Revisa [[utilizando llaves ssh]] para más información.
### Debug sshfs
Si tenemos problemas para montar con sshfs podemos agregar las opciónes * -o debug,sshfs_debug,loglevel=DEBUG * al final de comando para obtener mas datos sobre la falla en la conexión.
### Desmontar
Al final para desmontar el directorio remoto montado en /home/jaime/tierracomun ejecutamos
fusermount -u /home/jaime/tierracomun
#!/bin/bash
(( `id -u` )) && echo -e "\e[00;31mEs necesario correr este script con privilegios de root\e[00m" && exit 1
source wrapper_functions_sftp_sshfs_share
USER=$1
REMOTEUSER=$2
DEFAULT_DIRS="privado respaldos"
#this folder will contain other shared mount points
MASTER_SHARED_FOLDER="compartido"
SPECIAL_KEYNAME="sshfs_mount"
REMOTE_HOST="127.0.0.1"
REMOTE_SHAREDFOLDER="compartido"
DEFAULT_SFTPGROUP="sftponly"
LOCAL_SFTPGROUP="localsftp"
create_special_group $DEFAULT_SFTPGROUP $(get_next_gid);
[[ $? -ne 0 ]] && echo "error creando grupo $DEFAULT_SFTPGROUP" && exit;
create_sftp_user $USER "" $DEFAULT_SFTPGROUP
[[ $? -ne 0 ]] && echo "error creando usuario $USER" && exit 1;
HOMEDIR=$(getent passwd $USER | cut -f6 -d:)
SSHKEY=${HOMEDIR}/.ssh/${SPECIAL_KEYNAME}
#create default dirs for local user
for DIR in $DEFAULT_DIRS; do
mkdir ${HOMEDIR}/${DIR} 2> /dev/null
#must be owned by user to alow writing by user
chown $USER:$USER ${HOMEDIR}/${DIR} 2>/dev/null
done
#create master_shared_folder owned by root
mkdir ${HOMEDIR}/${MASTER_SHARED_FOLDER} 2> /dev/null
create_special_key $USER $SPECIAL_KEYNAME
[[ $? -ne 0 ]] && echo "error creando llave $SPECIAL_KEYNAME" && exit 1;
[[ -z $REMOTEUSER ]] && exit 0;
MOUNTPOINT=${HOMEDIR}/${MASTER_SHARED_FOLDER}/${REMOTEUSER}
create_special_group $LOCAL_SFTPGROUP $(get_next_gid);
[[ $? -ne 0 ]] && echo "error creando grupo $LOCAL_SFTPGROUP" && exit 1;
create_sftp_user $REMOTEUSER "-" $LOCAL_SFTPGROUP $(get_next_gid)
[[ $? -ne 0 ]] && echo "error creando user $REMOTEUSER" && exit 1;
REMOTEHOMEDIR=$(getent passwd $REMOTEUSER | cut -f6 -d:)
mkdir -p ${REMOTEHOMEDIR}/${REMOTE_SHAREDFOLDER}
chown $REMOTEUSER:$REMOTEUSER ${REMOTEHOMEDIR}/${REMOTE_SHAREDFOLDER}
cat ${SSHKEY}.pub >> ${REMOTEHOMEDIR}/.ssh/authorized_keys
create_systemd_sshfs_mount_point "${REMOTEUSER}@${REMOTE_HOST}:${REMOTE_SHAREDFOLDER}" "$MOUNTPOINT" "$USER" "$SSHKEY"
[[ $? -ne 0 ]] && echo "error creando systemd mount unit-files" && exit 1;
exit 0
[Unit]
Description=<<DESCRIPTION>>
Requires=-.mount
Conflicts=umount.target
Before=remote-fs.target <<ESCMOUNTPOINT>>.mount umount.target
After=-.mount
RequiresMountsFor=<<HOMEDIR>>
[Automount]
Where=<<MOUNTPOINT>>
TimeoutIdleSec=300
[Install]
RequiredBy=-.mount
[Unit]
Description=<<DESCRIPTION>>
Conflicts=umount.target
Before=umount.target
After=<<ESCMOUNTPOINT>>.automount systemd-journald.socket remote-fs-pre.target -.mount
OnFailureJobMode=replace
IgnoreOnIsolate=yes
RequiresMountsFor=<<HOMEDIR>>
[Mount]
What=<<REMOTEUSER>>@<<HOST>>:<<SHAREDFOLDER>>
Where=<<MOUNTPOINT>>
Type=fuse.sshfs
Options=noauto,_netdev,users,idmap=user,uid=<<USERID>>,gid=<<USERID>>,IdentityFile=<<SSHKEY>>,allow_other,reconnect
#!/bin/bash
function get_next_gid {
##get next available gid in specific range
##hardcode range x=STARTGID;x<=ENGID
##awk -F: '{gid[$3]=1}END{for(x=STARTGID; x<=ENDGID; x++) {if(gid[x] != ""){}else{print x; exit;}}}' /etc/group
awk -F: '{gid[$3]=1}END{for(x=10000; x<=11000; x++) {if(gid[x] != ""){}else{print x; exit;}}}' /etc/group
}
function create_special_group {
local grupo="$1"
local gid="$2"
if [[ -z "$grupo" ]] ; then echo -e "\e[00;31m Error: Nombre de grupo es requerido\e[00m" ; return 1 ; fi
getent group $grupo &> /dev/null
[[ $? -eq 0 ]] && return 0; #grupo ya existe
[[ ! -z $gid ]] && local gid_arg="--gid $gid";
addgroup $gid_arg $grupo &> /dev/null
if [[ $? -ne 0 ]]; then #error creando grupo
echo -e "\e[00;31m Error: Nombre de grupo inválido\e[00m" ;
return 1 ;
fi
#grupo creado con éxito
return 0
}
function create_special_key {
local user=$1
local keyname=$2
local result=$(getent passwd $user)
[[ $? -ne 0 ]] && return 1; #usuario no existe
local homedir=$(echo $result | cut -f6 -d:)
local keydir=${homedir}/.ssh
[[ ! -d "$keydir" ]] && mkdir $keydir;
[[ $? -ne 1 ]] && echo "error with keydir path" && return 1;
[[ -z $keyname ]] && keyname=id_rsa;
local sshkey=${keydir}/$keyname
[[ -f "$sshkey" ]] && [[ -f "$sshkey.pub" ]] && return 0; #llave ya existe
ssh-keygen -q -b 2048 -t rsa -N '' -C "$user@${HOSTNAME}" -f $sshkey
[[ $? -ne 0 ]] && echo "error creando llave" && return 1;
return 0;
}
function create_sftp_user {
local sftpuser="$1"
local mail="$2"
local sftpgroup="$3"
local uid="$4"
if [[ -z "$sftpuser" ]] ; #usuario no definido
then read -e -p " Ingresa nombre para nuevo usuario: " sftpuser ;
fi
# cancela script si ingresa usuario nulo
if [[ -z "$sftpuser" ]] ; then
echo " Nombre de usuario es requerido"
return 1
fi
getent passwd $sftpuser &> /dev/null
[[ $? -eq 0 ]] && return 0; #usuario ya existe
[[ -z "$mail" ]] && read -p " Ingresa un correo de contacto para el nuevo usuario: " mail
if [[ ! -z $uid ]] ; then
#crear usuario con uid especial
local uid_arg="--uid ${uid}";
else
#crear usuario en rango normal
#---esto es hardcoded, hay que buscar otra solución
uid_arg="-K UID_MIN=1000 -K UID_MAX=9999";
fi
[[ ! -z $sftpgroup ]] && local group_arg="--groups ${sftpgroup}";
useradd --home-dir /home/${sftpuser} --no-create-home $uid_arg\
--shell /bin/false --comment $mail --user-group $group_arg $sftpuser
if [[ $? -ne 0 ]] ; then
echo " Error creando usuario"
return 1
fi
#home del usuario sftp debe pertenecer a root
#asume que umask es 022
mkdir /home/${sftpuser}
mkdir /home/${sftpuser}/.ssh
touch /home/${sftpuser}/.ssh/authorized_keys
return 0
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment