Etiquetas

lunes, 8 de abril de 2013

Servidor ftp seguro con una instancia independiente de ssh

Como SysAdmins, en muchas ocasiones precisamos ofrecer servicio de acceso sftp (secure ftp) en un host conectado a internet. En un principio, el problema que se plante es que como sftp utiliza ssh, si ya estamos usando ssh para administración remota y otros servicios administrativos utilizar la misma instancia para acceso sftp a usuarios externos podría plantear una brecha de seguridad. Por eso, utilizar otra instancia de sshd, independiente de la "principal" (administrativa) puede suponer un agregado de seguridad extra, porque vamos a "limitar" los permisos que daremos a los usuarios que accedan vía sftp.

sftp, conocido como "ftp seguro" utiliza el protocolo ssh ("secure shell") para encriptar todo el tráfico de red envuelto en este tipo de comunicación o transferencias de archivos. De esta forma, mejora el protocolo ftp clásico, en el cual credenciales de acceso como archivos se envían sin cifrado, lo que los hace visibles para ojos de malvivientes.

Lo que nos proponemos con este acercamiento es crear una instancia adicional de sshd, es decir, correr otro deminio (servidor) ssh que será el encargado de prestar el servicio para sftp, en otro puerto diferente al estándar (puerto 22). Partiendo de ese punto limitaremos los usuarios solo a usuarios definidos para usar sftp como también limitaremos las opciones del shell del usuario.

Manos a la obra

1) Crear configuracion para nuevo demonio:

Aquí copiaremos el archivo original de configuración del servidor sshd para que nos sirva de punto de partida.

cd /etc/ssh
cp -p sshd_config sshd_config-sftp


2) Modificaciones en sshd_config-sftp (Alterar puerto, bindings, etc):
OBS. Importante: es clave definir el PID file para este nuevo demonio o instancia.
Este nuevo servicio sshd escuchará conexiones en el puerto 2222, definido en el archivo sshd-config-sftp.

# BOF Modificaciones para segundo demonio
# Port modificado
Port 2222
# Agregado PID para este demonio
PidFile /var/run/sshd-sftp.pid

3)Seguridad: no permitir acceso root y limitar usuarios: Permitiremos acceso a esta instancia de sshd solo a los usuarios listados en AllowUsers o a los pertenecientes al grupo AllowGroups

# Authentication:
LoginGraceTime 120
PermitRootLogin no
StrictModes yes
AllowUsers ptolomeo alberto # Usuarios permitidos para acceso sftp
AllowGroups sftp # Grupo permitido

4) Crear symlink para diferenciar el demonio del principal:

# cd /usr/sbin
# ln -s /usr/sbin/sshd /usr/sbin/sshd-sftp
# ls -l sshd-sftp
lrwxrwxrwx 1 root root 14 mar 28 11:10 sshd-sftp -> /usr/sbin/sshd

5) Si se usa PAM, como es default en Debian:

# cd /etc/pam.d/
# ln -s sshd sshd-sftp

6) Modificar el script SysV para inicio y parada:

# cd /etc/init.d/
# cp -p ssh ssh-sftp

7) Alterar script de inicio ssh-sftp para definir las config de la nueva instancia (ver abajo en Anexo I el script completo).

8) Creacion de usuario y grupo para acceso restringido:

# useradd -m -c "usuario acceso sftp limitado" -s /bin/bash ptolomeo
# passwd ptolomeo
Introduzca la nueva contraseña de UNIX:
Vuelva a escribir la nueva contraseña de UNIX:
passwd: contraseña actualizada correctamente

# addgroup sftp
Añadiendo el grupo `sftp' (GID 1005) ...
Hecho.

# usermod -aG sftp ptolomeo
# groups ptolomeo
ptolomeo : ptolomeo sftp

9) OPCIONAL: ambiente chroot para el acceso sftp

Si bien, se recomiendan, los pasos descriptos en esta sección (9) son opcionales. Describen cómo configurar un ambiente chroot para que los usuarios sftp se encuentren limitados únicamente a su directorio de usuario ($HOME). De esa forma no podrán acceder a lectura de otros archivos del sistema operativo, por ejemplo.

# chown root:sftp /home/ptolomeo/
# chmod 755 /home/ptolomeo/

9.1) Alterar estas líneas de /etc/ssh/sshd_config-sftp

# Comentado para acceso chroot (ver abajo)
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp

9.2) Agregar al final de /etc/ssh/sshd_config-sftp:

###################################################
## OPT. (RECOMENDADO): ###
## Para acessos sftp ambiente chroot ###
## Requiere OpenSSH>= 4.8 ###
## Este bloque debe estar al final del archivo ###
## sshd_config-sftp ###
###################################################
Match User ptolomeo
ChrootDirectory /home/ptolomeo
#ForceCommand internal-ftp
# Restringir todavia mas las posibilidades (+ paranoia)
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no

Esta última configuración establece que cuando el usuario coincida com ptolomeo, que fue el que se definió para acceso sftp el mismo quede en una jaula chroot en su directorio home. También la misma directiva condicional se puede aplicar al grupo sftp, lo que sería mejor en caso de que tengamos que dar acceso sftp a múltiples usuarios , lo que suele ser lo habitual.


Anexo I

Script llamado ssh-sftp tipo SysV de inicio para la instancia, que fue modificado a partir del original /etc/init.d/ssh, que queda inalterado.

#! /bin/sh

### BEGIN INIT INFO
# Provides: sshd-sftp
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: OpenBSD Secure Shell server
### END INIT INFO

set -e

# /etc/init.d/ssh-sftp: start and stop the OpenBSD "secure shell(tm)" daemon

test -x /usr/sbin/sshd-sftp || exit 0
( /usr/sbin/sshd-sftp -\? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0

umask 022

if test -f /etc/default/ssh; then
. /etc/default/ssh
fi

. /lib/lsb/init-functions

if [ -n "$2" ]; then
SSHD_OPTS="$SSHD_OPTS $2"
fi

# Are we running from init?
run_by_init() {
([ "$previous" ] && [ "$runlevel" ]) || [ "$runlevel" = S ]
}

check_for_no_start() {
# forget it if we're trying to start, and /etc/ssh/sshd_not_to_be_run exists
if [ -e /etc/ssh/sshd_not_to_be_run ]; then
if [ "$1" = log_end_msg ]; then
log_end_msg 0
fi
if ! run_by_init; then
log_action_msg "OpenBSD Secure Shell server not in use (/etc/ssh/sshd_not_to_be_run)"
fi
exit 0
fi
}

check_dev_null() {
if [ ! -c /dev/null ]; then
if [ "$1" = log_end_msg ]; then
log_end_msg 1 || true
fi
if ! run_by_init; then
log_action_msg "/dev/null is not a character device!"
fi
exit 1
fi
}


check_privsep_dir() {
# Create the PrivSep empty dir if necessary
if [ ! -d /var/run/sshd-sftp ]; then
mkdir /var/run/sshd-sftp
chmod 0755 /var/run/sshd-sftp
fi
}

check_config() {
if [ ! -e /etc/ssh/sshd_not_to_be_run ]; then
/usr/sbin/sshd-sftp $SSHD_OPTS -t || exit 1
fi
}

export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"

case "$1" in
start)
check_privsep_dir
check_for_no_start
check_dev_null
log_daemon_msg "Starting OpenBSD Secure Shell server" "sshd"
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd-sftp.pid --exec /usr/sbin/sshd-sftp -- -f /etc/ssh/sshd_config-sftp $SSHD_OPTS; then
log_end_msg 0
else
log_end_msg 1
fi
;;
stop)
log_daemon_msg "Stopping OpenBSD Secure Shell server" "sshd"
if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd-sftp.pid; then
log_end_msg 0
else
log_end_msg 1
fi
;;

reload|force-reload)
check_for_no_start
check_config
log_daemon_msg "Reloading OpenBSD Secure Shell server's configuration" "sshd"
if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile /var/run/sshd-sftp.pid --exec /usr/sbin/sshd-sftp; then
log_end_msg 0
else
log_end_msg 1
fi
;;

restart)
check_privsep_dir
check_config
log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"
start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sshd-sftp.pid
check_for_no_start log_end_msg
check_dev_null log_end_msg
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd-sftp.pid --exec /usr/sbin/sshd-sftp -- -f /etc/ssh/sshd_config-sftp $SSHD_OPTS; then
log_end_msg 0
else
log_end_msg 1
fi
;;
try-restart)
check_privsep_dir
check_config
log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"
set +e
start-stop-daemon --stop --quiet --retry 30 --pidfile /var/run/sshd-sftp.pid
RET="$?"
set -e
case $RET in
0)
# old daemon stopped
check_for_no_start log_end_msg
check_dev_null log_end_msg
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd-sftp.pid --exec /usr/sbin/sshd-sftp -- -f /etc/ssh/sshd_config-sftp $SSHD_OPTS; then
log_end_msg 0
else
log_end_msg 1
fi
;;
1)
# daemon not running
log_progress_msg "(not running)"
log_end_msg 0
;;
*)
# failed to stop
log_progress_msg "(failed to stop)"
log_end_msg 1
;;
esac
;;

status)
status_of_proc -p /var/run/sshd-sftp.pid /usr/sbin/sshd-sftp sshd && exit 0 || exit $?
;;

*)
log_action_msg "Usage: /etc/init.d/ssh-sftp {start|stop|reload|force-reload|restart|try-restart|status}"
exit 1
esac

exit 0

No hay comentarios.:

Publicar un comentario