Kerberos es un protocolo de autenticación, originariamente desarrollado por el MIT en los años '90. Fue concebido ofrecer servicio de autenticación de manera segura (basado en criptografía de clave simétrica (secret-shared). En la mitología griega Kerberos era el demonio del pozo, un perro de tres cabezas que vigilaba que los muertos no pudieran salir del Hades y que los vivos no entraran.
Hablando sobre el protocolo Kerberos puede pensarse como un tercero, que con una cabeza verifica la identidad de un primero: el cliente, con otra la del segundo: el servidor.
Esta entrada no pretende ser un tutorial completo, es más bien una guía y un recordatorio propio sobre la documentación necesaria y algo de troubleshooting para poner a funcionar NFS4 con autenticación kerberos.
Siempre existe una limitación en las recetas paso-a-paso o en los tutoriales "quick and dirty": cuando ocurre algún problema y se requiere hacer troubleshooting seguramente tendremos que hacernos del conocimiento más profundo que es el de una documentación oficial por ejemplo. En realidad un problema es trivial o no dependiendo del grado de conocimiento del observador/analista.
Espero sirva para otros que sigan el mismo camino y si se acercan al Hades, cuidado con el perro.
¿Por qué ponerse un poco paranoico? Redes LAN del hogar bajo fuego
Las redes LAN de los hogares, en donde existe Access Points wi-fi son relativamente seguras utilizando WPA2 WPA-PSK (Pre-shared Key) con todo, siempre pueden ser objeto de algunas vulnerabilidades.
Más allá de ataques de diccionarios, lo más común es que por el simple hecho de mantener la misma clave, la passphrase va a pasar por muchas manos. Más tiempo la red se mantenga, inalterada mayor el numero de usuarios que hayan usado esa red y que por tanto, tengan conocimiento de la passphrase.
En las redes lan de nuestras casas, salvo que hayamos agregado alguna capa de seguridad extra, los hosts que se conectan por wi-fi comparten el mismo segmento de red que los hosts conectados a la red cableada (ej 192.168.1.0/24).
Un usuario que conozca la passphrase de acceso wi-fi no solamente podría utilizar el acceso a internet sino que en servicios con seguridad basada en host (como históricamente fue nfs) podría hacer spoofing y cambiar la dirección ip. Supongamos que nuestro fileserver NFS restringe el acceso de rw para el host 192.168.1.12, con mala intención, alguien que hubiera obtenido acceso wi-fi podría "hacerse pasar por ese host", que tiene derecho de acceso al fileserver, para hacer sus backups. Eso sin dudas constituye un vector de vulnerabilidad.
El caso descripto para una red hogareña, podría tener su equivalente si alguien con acceso físico a la oficina conecta su la ehternet de su laptop a la red. Para evitar que esa persona no autorizada tuviera acceso a datos o servicios de la intranet puede usarse Kerberos.
El perro vigilante: Kerberos
Kerberos fue desarrollado originariamente en el MIT, y como es un estándar abierto descripto en varias RFCs, existen diversas implementaciones además de la del MIT, entre otros: Heimdal un derivado de la del MIT, GNU Shisi de la Free Software Foundation y Microsoft AD que entre sus servicios incluye kerberos.
Las líneas que siguen describen brevemente el funcionamiento del protocolo y fueron tomadas del documento The MIT Kerberos Administrator’s How-to Guide de Jean-Yves Migeon.
Kerberos fue desarrollado con foco en la autenticación y no en el manejo de cuentas (por ejemplo, Kerberos no guarda UIDs, GIDs u otras informaciones sobre las cuentas de usuario). Tarea como esa es el objeto de otros servicios de directorio, como LDAP.
El funcionamiento del protocolo se basa en el intercambio de tickets criptográficos que permiten autenticar tanto a servidores que ofrezcan servicios "kerberizados" ej NFS, ssh, etc y a sus clientes.
La comunicación de Kerberos se basa en el protocolo Needham-Shroeder (conocido como protocolo NS) que fue diseñado por esos autores en 1978 como una solución para un sistema de autenticación distribuido basado en claves criptográficas secretas.
Esas claves criptográficas las comparten los dos extremos de una conexión Kerberos. Se trata del modelo de criptografía simétrica (pre-shared key), que se diferencia de los métodos asimétricos o de "Clave pública" utilizados por ssl, IPSec, etc.
Para el usuario, la clave secreta es su password entreverada criptográficamente en un único sentido (léase "one-way hashed") que normalmente se almacena en el KDC (Key Distribution Center, un componente central del servidor Kerberos). Para un servicio "kerberizado" normalmente la clave secreta es una secuencia aleatoria que actúa como password y que también se guarda en el KDC, como también en un archivo llamado keytab que irá en la máquina que corra el servicio kerberizado.
Para que esto funcione clientes y servicios deben confiar en un tercer servicio (el servidor Kerberos) que es responsable de otorgar las claves que se le demanden.
En un ambiente corporativo la mejor práctica es que el servidor Kerberos esté aislado de internet.
La comunicación en Kerberos se basa en tickets. Estos son una suerte esquema de datos encriptados que se transmite a través de la red y almacenado del lado del cliente. Dónde se almacena depende de la implementación del kerberos y del SO. En el caso del MIT Kerberos se almacena en un archivo en el directorio /tmp.
La parte principal de una red Kerberos es el KDC (Key Distribution Center), que consiste de tres partes:
• Un Authentication Server (Servidor de Autenticación), el cual responde solicitudes de autenticación iniciadas por los clientes. Estos intercambios son los mensajes de desafío (challenge) AS_REQUEST y AS_REPLY, en los que el cliente obtiene un TGT: Ticket Granting Ticket.
• La segunda parte del KDC es el Ticket Granting Server el cual otorga los TGS (Ticket Granting Service) esta es la parte del intercambio con los mensajes TGS_REQUEST y TGS_REPLY, en la que el cliente obtiene un TGS que le permite autenticarse ante un servicio disponible en red.
• Una base de datos que guarda todas las claves secretas (las de los clientes y la de los servicios) (Migeon, 2008).
Siguen esquemas tomados del libro de Migeon sobre el proceso de intercambio de tickets:
Proceso de Autenticación - TGT :
Mecanismo de uso de Servicio - TGS (Ticket Granting Service):
El primer paso, descripto en le primera figura es el proceso de autenticación, que culmina con el otorgamiento de un TGT.
Una vez que el cliente cuenta con un TGT (es decir, completó el proceso de auth) y si quiere acceder a un cierto servicio de red (ej. servidor web, servidor de archivos, etc) debe requerir un TGS: Ticket Granting Service. Ese es el proceso mostrado por Migeon en la segunda figura.
Una vez que el cliente obtuvo su TGS, tendrá que autenticarse a sí mismo directamente con el servicio a utilizar (ej NFS, ssh, etc). Este proceso varía según cuál sea el servicio en cuestión.
A rasgos generales, el servicio (ej NFS4) tiene acceso al archivo keytab un archivo que guarda su clave a largo plazo. Esta clave le permitirá al servicio desencriptar el TGS que le envíe el cliente y las demás informaciones para identificar el usuario y crear el contexto seguro.
No vamos reproducir aquí el contenido del libro de Migeon, si no más bien recordar algunos puntos esenciales para que la autenticación vía kerberos funcione sin problemas.
En resumen, según Migeon el protocolo Kerberos se puede dividir en tres pasos:
1. Proceso de autenticación, en el que el usuario y el host obtienen un TGT (Ticket Granting Ticket).
2. Proceso de solicitud de servicio, en el que el usuario obtiene un TGS (Ticket Granting Service) para acceder a un servicio.
3. Acceso al servicio propiamente dicho, en el que el usuario (y host) usan su TGS para autenticarse a sí mismos ante un cierto servicio (ej: ssh, nfs, etc).
Hay que recordar que en la jerga de Kerberos, el equivalente a una cuenta de usuario se denomina principal.
Instalación y configuración de Kerberos
El sabor de kerberos elegido fue el del MIT, bajo Debian Linux/GNU.
Un howto completo, que utilicé como guía fue el de Debian Administration - MIT Kerberos Installation on Debian
NFSv4 con Kerberos
NFSv4 con Kerberos depende de la resolución de nombres. Por lo tanto si lo usamos en un ambiente pequeño debemos usar /etc/hosts o bien dnsmasq. Para ambientes de más escala se justificará usar bind u otro servidor DNS.
El servicio es sumamente sensible a la resolución de nombres directa y reversa.
En un ambiente hogareño, el servicio implementado contiene el servidor KDC (Kerberos Distribution Center) el servidor Kadmin y el NFS en un mismo host (en mi caso una Raspberry Pi con un HD para storage de NFS).
Pero en un ambiente empresarial lo adecuado es que estos tres componentes estén aislados en hosts individuales. Especialmente, como se mencionó arriba, deben ser hosts que no tengan acceso a internet.
En el servidor NFS (+KDC+KADMIN) /etc/hosts debe contener las entradas de los hosts, por ejemplo:
192.168.51.107 krb1.equiscentrico.com.ar
192.168.51.106 matuxntbk.equiscentrico.com.ar
En mi caso, krb1.equiscentrico.com.ar será el servidor y matuxntbk.equiscentrico.com.ar será una estación, capaz de montar el recurso NFS autenticando con krb5.
La estación (matuxntbk.equiscentrico.com.ar) debe tener correctamente configurado su hostname y la resolución de nombres:
Para ello, /etc/hostname debe contener solo el nombre de host (matuxntbk en este caso):
~$ hostname
matuxntbk
## Y:
~$ hostname -f
matuxntbk.equiscentrico.com.ar
Y /etc/hosts debe contener el dominio para formar el FQDN:
127.0.0.1 localhost
127.0.1.1 matuxntbk.equiscentrico.com.ar matuxntbk
192.168.51.107 krb1.equiscentrico.com.ar krb1
Me detuve en este punto porque el problema de la resolución de nombres suele ser el principal problema que nos encontramos en el troubleshooting cuando algo falla.
Lo que podemos hacer, como siempre, es descomponer el problema en sus partes más simple: primero podemos configurar NFSv4 (sin auth vía kerberos), probar que todo funcione, es decir que desde las workstations podamos
montar el recurso exportado y si todo va bien entonces seguir con Kerberos.
En el servidor NFS precisaremos los siguientes paquetes:
# apt-get install nfs-kernel-server nfs-common
NFSv4 ya no utiliza el protocolo rpc.mountd, que se usaba en NFSv2 y 3, por lo tanto el montaje del file systems ha cambiado: un cliente NFSv4 tiene ahora la posibilidad de ver todos los exports servidos por el servidor NFSv4 como un único FS, llamado pseudo-file system NFSv4 (se puede ver más información al respecto en este link: https://www.centos.org/docs/5/html/5.1/Deployment_Guide/s3-nfs-server-config-exportfs-nfsv4.html.
Para preparar los exports se puede hacer una vez, usando --bind o bien dejarlo persistente en /etc/fstab. En mi caso, el pseudo FS quedó de la siguiente forma:
$ cat /etc/fstab
#
UUID=493641ad-bf73-45b2-93f0-e63fd63f384f /mnt/bighd ext4 defaults,errors=remount-ro 0 3
/mnt/bighd/data /mnt/bighd/nfs4exports/data none bind,rw,_netdev 0 0
La primera partición, identificada por su UUID es la partición física de un hd, cuyo punto de montaje fue /mnt/bighd. La segunda es la encargada de crear el pseudo-FS para NFSv4. Los sucesivos exports formarán parte de ese pseudo FS.
Si deseamos probar primero el funcionamiento de NFSv4 sin kerberos podemos entonces crear los exports de esta forma en /etc/exports:
# Sin kerberos:
/mnt/bighd/nfs4exports 192.168.1.0/24(ro,sync,insecure,no_subtree_check,fsid=0)
/mnt/bighd/nfs4exports/data 192.168.1.0/24(rw,nohide,sync,insecure,no_subtree_check)
Podremos entonces probar montar el export desde una estación.
El perro entra en escena
En el host que funcionará como KDC y/o krb5-admin deberemos instalar los siguientes paquetes (en este caso usaremos la variante Kerberos de MIT):
# apt-get install krb5-admin-server krb5-kdc krb5-user libgssapi-krb5 libpam-krb5
Mientras que las workstation que serán "clientes" NFS4 y Kerberos deberán tener los siguientes paquetes:
# apt-get install krb5-config krb5-user libgssapi-krb5-2 libkrb5-3 libpam-krb5 nfs-common
(el ultimo paquete es el que brinda soporte para nfs, mientra que el resto es para Kerberos.
En el servidor NFS debemos configurar el servicio para que soporte auth por kerberos, en /etc/default/nfs-kernel-server:
# Number of servers to start up
RPCNFSDCOUNT=8
# Runtime priority of server (see nice(1))
RPCNFSDPRIORITY=0
# Options for rpc.mountd.
# If you have a port-based firewall, you might want to set up
# a fixed port here using the --port option. For more information,
# see rpc.mountd(8) or http://wiki.debian.org/SecuringNFS
# To disable NFSv4 on the server, specify '--no-nfs-version 4' here
RPCMOUNTDOPTS="--manage-gids --debug all"
# Do you want to start the svcgssd daemon? It is only required for Kerberos
# exports. Valid alternatives are "yes" and "no"; the default is "no".
NEED_SVCGSSD=yes
# Options for rpc.svcgssd.
#RPCSVCGSSDOPTS=
RPCSVCGSSDOPTS=-vvvvvvvvv
Tanto en el servidor NFS como en los clientes debe también editarse /etc/default/nfs-common:
# If you do not set values for the NEED_ options, they will be attempted
# autodetected; this should be sufficient for most people. Valid alternatives
# for the NEED_ options are "yes" and "no".
# Do you want to start the statd daemon? It is not needed for NFSv4.
NEED_STATD=
# Options for rpc.statd.
# Should rpc.statd listen on a specific port? This is especially useful
# when you have a port-based firewall. To use a fixed port, set this
# this variable to a statd argument like: "--port 4000 --outgoing-port 4001".
# For more information, see rpc.statd(8) or http://wiki.debian.org/SecuringNFS
STATDOPTS=
# Do you want to start the idmapd daemon? It is only needed for NFSv4.
NEED_IDMAPD=YES
# Do you want to start the gssd daemon? It is required for Kerberos mounts.
NEED_GSSD=YES
Cuando NFS se utiliza con Kerberos el KDC le da acceso solamente a los usuarios que tenga un ticket kerberos, por eso la seguridad ya no depende de algún atributo del cliente (ej. su dirección IP). Por lo tanto, en la jerga de kerberos, se precisa un Principal en tu Realm Kerberos para cada uno de los usuarios que vaya a acceder a un recurso NFSv4.
Una vez que tenemos los paquetes y los componentes del servidor kerberos
root@krb1:/tmp# /etc/init.d/krb5-admin-server status
[ ok ] kadmind is running.
root@krb1:/tmp# /etc/init.d/krb5-kdc status
[ ok ] krb5kdc is running.
# Aquí se pueden ver los dos demonios (kdc y krb5-admin-server corriendo)
Como dijimos más arriba, se está usando la variante MIT de Kerberos. Tanto en el servidor como en los clientes NFS precisaremos estos paquetes:
# apt-get install krb5-user
# apt-get install libpam-krb5
Verificar que el siguiente módulo del kernel está cargado en memoria tanto en el servidor Kerberos como en los clientes NFS:
# lsmod | grep gss
rpcsec_gss_krb5
Caso contrario, cargarlo o agregarlo a /etc/modules para que se cargue automáticamente.
# modprobe rpcsec_gss_krb5
Crear y distribuir las credenciales
Para que la autenticación por kerberos funcione para nfs(v4) se precisará un principal en nuestro Realm por cada usuario que vaya a usar un share NFS.
NFSv4 requiere credenciales (principals en la jerga kerberos) para el server y para cada cliente que quiera usar las características de seguridad de NFSv4.
Se deben crear las credenciales para el servidor nfs y para todos los clientes en el servidor Kerberos (KDC) y distribuir las keys vía scp a cada cliente.
Podemos verificar que estas entradas se hayan creado ejecutando # klist -e -k /etc/krb5.keytab.
Desde el servidor KDC nos autenticamos directamente usando:
# kadmin.local
# En este caso no nos pedirá passphrase.
O desde un cliente del "Realm" podremos también hacer:
# kadmin krb1.equiscentrico.com.ar
Donde krb1.equiscentrico.com.ar es el FQDN del servidor kerberos. En este caso se solicitará la passphrase que hayamos configurado al momento de configurar el servicio de kerberos.
Entonces, para registrar los principals del servidor y cada cliente sería:
En este caso: krb1.equiscentrico.com.ar es el servidor. Mientras que nfs-client.equiscentrico.com.ar
$ kinit admin/admin
$ kadmin -q "addprinc -randkey nfs/krb1.equiscentrico.com.ar"
$ kadmin -q "addprinc -randkey nfs/nfs-client.equiscentrico.com.ar"
Esto mismo podría hacerse de esta forma:
# kadmin.local
$ addprinc -randkey nfs/krb1.equiscentrico.com.ar
$ addprinc -randkey nfs/nfs-client.equiscentrico.com.ar
Ahora se debe agregar estas al archivo keytab en el servidor NFS y en los clientes. Loguearse a krb1.equiscentrico.com.ar (reemplace con el que corresponda) e inicializar el administrador kerberos como antes:
Ahora se debe agregar al los keytab-files del servidor NFS y de los clientes.
root@krb1.equiscentrico # kadmin -p admin/admin -q "ktadd nfs/krb1.equiscentrico.com.ar"
Y agregar al archivo keytab del cliente:
root@nfs-client.equiscentrico.com.ar# kadmin -p admin/admin -q "ktadd nfs/nfs-client.equiscentrico.com.ar"
Nota: para que esto funcione previamente tendremos que haber creado un "principal" admin/admin en el servidor, de esta forma:
kadmin.local
Authenticating as principal matias/admin@EQUISCENTRICO.COM.AR with password.
kadmin.local: addprinc admin/admin
WARNING: no policy specified for admin/admin@EQUISCENTRICO.COM.AR; defaulting to no policy
Enter password for principal "admin/admin@EQUISCENTRICO.COM.AR":
Re-enter password for principal "admin/admin@EQUISCENTRICO.COM.AR":
Principal "admin/admin@EQUISCENTRICO.COM.AR" created.
kadmin.local: quit
O bien:
nfs-client.equiscentrico.com.ar# kadmin
(pedirá la passphrase del admin kerberos)
kadmin: ktadd nfs/nfs-client.equiscentrico.com.ar
Luego podemos verificar que la entrada se haya agregado a al keyfile del cliente
# cat /etc/krb5.keytab
Se puede verificar que las entradas en los archivos keytab se puede verificar tanto en el servidor como en los clientes de esta forma:
# klist -e -k /etc/krb5.keytab
En este punto, se puede probar la autenticación de kerberos previamente a utilizarlo con NFSv4. De esta forma podremos verificar que la capa de kerberos funcione bien:
# kinit -k -t /etc/krb5.keytab nfs/nfs-client.equiscentrico.com.ar
Con esto lo que habremos hecho es solicitar un ticket al servidor kerberos usando la entrada en nuestro keytab para el host nfs-client.equiscentrico.com.ar. Si la autenticación fue exitosa, no obtendremos mensaje alguno, pero podemos ver los detalles del ticket que nos otorgó:
# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: nfs/nfs-client.equiscentrico.com.ar@EQUISCENTRICO.COM.AR
Valid starting Expires Service principal
27/03/16 18:17:11 28/03/16 04:17:11 krbtgt/EQUISCENTRICO.COM.AR@EQUISCENTRICO.COM.AR
renew until 28/03/16 18:17:11
Con:
# kdestroy
Con eso habremos borrado el ticket que nos había sido otorgado.
Ahora podríamos (finalmente!) montar los exports NFS usando kerberos:
# mount -t nfs4 -o sec=krb5 krb1.equiscentrico.com.ar:/ /mnt
Voilà! NFS y Kerberos están andando. Para crear una entrada en /etc/fstab podría ser:
# NFSv4 kerberos
krb1.equiscentrico.com.ar:/ /mnt/nfs4 nfs4 _netdev,noauto,sec=krb5 0 0
Nótese las opciones: _netdev para que el montaje ocurra después de que los servicios de red estén activos, noauto si deseamos que no se monte automáticamente y sec=krb5 para auth vía kerberos.
Conclusiones:
El camino para utilizar kerberos fue largo. Algunos problemas que en el camino pueden ocurrir tuvieron con:
- Verificar siempre resolución de nombres adecuada. El servicio depende de eso.
- En algunas versiones de Debian, notablemente en la testing actual (stretch) me encontré que en los clientes servicios necesarios para nfs con kerberos no levantaban solos. Para hacerlo hay que reiniciar el servicio nfs-common (service nfs-common restart):
# ps aux | grep rpc
root 2353 0.0 0.1 6608 3400 ? Ss 13:09 0:00 /sbin/rpcbind -f -w
statd 2355 0.0 0.1 4576 2124 ? Ss 13:09 0:00 /sbin/rpc.statd
root 2370 0.0 0.0 2920 1328 ? Ss 13:09 0:00 /usr/sbin/rpc.idmapd
root 2374 0.0 0.1 4796 3764 ? Ss 13:09 0:00 /usr/sbin/rpc.gssd -v
Aquí se ven todos los demonios corriendo.
Para troubleshooting siempre se puede ver el log /var/log/daemon.log
De esta forma quedó la implementación final, con una Raspberry Pi y un HD de 500Gb en este case:
Nota: si se necesita incluir kinit en algún script para automatizar el otorgamiento del ticket se puede crear un keytab de usuario siguiendo este procedimiento: crear keytab de usuario.
Referencias:
https://help.ubuntu.com/community/NFSv4Howto
The MIT's Kerberos Administrator How-To