Etiquetas

Mostrando las entradas con la etiqueta TIps. Mostrar todas las entradas
Mostrando las entradas con la etiqueta TIps. Mostrar todas las entradas

jueves, 3 de febrero de 2022

Optimizando el kernel de Linux para el escritorio (desktop) con xanmod

compilar kernelEn ocasiones customizar y compilar el kernel de Linux/GNU puede ser una tarea que lleve mucho tiempo, no siempre invertir ese tiempo se justifica.
Eso se aplica si el hardware de tu PC es actual o si no querés sumergirte un poco en cómo el sistema funciona "bajo el capot".
Para quienes deseen exprimir su hardware al máximo y optimizar el comportamiento del sistema operativo para ciertos usos, por ejemplo optimizarlo para funcionar con aplicaciones "de escritorio" este post puede resultarles útil.
Hoy en día compilar el kernel del Linux es mucho más fácil de lo que acostumbraba ser. Xanmod o Liquorix ofrecen una serie de parches y optimizaciones que se aplican por sobre el kernel "vainilla" de Linux y que procuran optimizar el kernel para diferentes casos de uso.


Respecto de utilizar un kernel "de stock" provisto por nuestra distribución favorita, compilar el kernel nosotros mismos es una tarea que requiere invertir de cierto tiempo. Requiere al menos familiarizarse con el hardware en donde vamos a ejecutar ese kernel. Mi modesto consejo es configurá tu kernel si:

  • Estás buscando optimizarlo para ciertos casos de uso.
  • Si tu hardware es raro y requiere soporte que no estuviera ya presente en el kernel de tu distribución.
  • Si por ejemplo un sistema embebido tiene relativamente pocos recursos y hay que reducir la "pisada" del sistema.

En mi caso más o menos recientemente solo necesité compilar el kernel cuando utilizo hardware antiguo. Por ejemplo si quisiéramos utilizar una unidad floppy o una interfaz ide un kernel estándar actual nos va a dejar a pie. Tengo una máquina que ya tiene cerca de doce años, es una pequeña netbook de las que el Gobierno de la Ciudad entregó a los alumnos de las escuelas primarias. Ya mis hijos no la utilizaban, porque quedó bastante rezagada para correr soft actual.
A mí me gusta por su diseño y su robustez. Puedo usarla a la intemperie, en cualquier clima. Y con Linux tiene una vida algo extendida, de otro modo ya habría ido a parar al callejón del olvido. Si bien el teclado no es cómodo, usé esa máquina para transcribir mi libro ("Piensa Abierto") de mis cuadernos manuscritos a archivos markdown, que fueron la base para su composición tipográfica. Demás está decir que navegar la web no es una experiencia llevadera en esa máquina, pero para escribir con visual studio o codear algunos script o aplicación simple resulta utilizable. Por eso me propuse hace unos días tratar de optimizarle algunos pocos ciclos de cpu a ver si podía reducir la latencia de ciertas aplicaciones. Pese a tener solo 1GB de ram, utilizo allí debian con enlightenment como gestor de escritorio, lo que hace al desktop elegante y liviano. El principal cuello de botella de la máquina es sin dudas su CPU, un antiguo Atom de Intel.

Xanmod y la optimización del kernel


Xanmod es una distribución de software, en este caso una distribución del kernel Linux que incluye varios parches y mejoras, algunas de las cuales no se incluyen en el kernel estándar. En general el fuerte de Linux/GNU desde su edad temprana ha sido correr en el servidor. Es por ello que con cierto grado de solución de compromiso, el kernel suele incluir una configuración que resulte estable para el servidor, pero no necesariamente está optimizada del todo para software de escritorio. Entre otros usos xanmod procura facilitar esos ajustes y "tweaks" para que uno pueda optimizar el kernel para el escritorio. Otra distribución alternativa es Liquorix . Estas distribuciones suelen incluir binarios ya compilados del kernel, empaquetados en paquetes .deb, por ejemplo utilizables en Debian o Ubuntu. Además existen paquetes para Arch, Fedora, etc. Un problema es que ya es raro que se incluyan binarios 32bits en estos builds, y el Atom de mi vieja netbook no es 64 bits. Compilar el kernel tenía entonces algo más de sentido. Además podría incluir algunos ajustes más para reducir la latencia, en particular me interesaba ajustar la "preferencia" del kernel (en inglés "preemption" para intentar reducir en algo la latencia del escritorio). Además podría seleccionar schedulers alternativos para controlar la Entrada/Salida de disco (este fierro viejo tiene hdd).

Compilando el kernel (usando el código fuente de xanmod) a la manera de Debian

Para comenzar, obviamente se requiere descargar el código fuente del kernel, en la distribución provista por xanmod. Como he descripto en una entrada en este blog hace ya varios años atrás voy a compilar el kernel a la Debian, eso quiere decir que los artefactos que resulten del build serán un puñado de archivos .deb (el kernel en sí, sus headers y al librería de C). De esa forma uno puede distribuir esa versión de su kernel "custom" de forma fácil. La manera en como se compila a la Debian ha cambiado hace un tiempo y hoy es incluso más fácil. Manos a la obra. Por supuesto no iba a compilar mi kernel en la vieja netbook, porque allí demoraría días, o quizá semanas. De forma que es mejor utilizar el hardware más potente que tengamos a mano. En mi caso, la PC de mi escritorio tiene un procesador AMD de 64 bits, de modo que es necesario hacer un cross-compiling para que los binarios resultantes sean de 32 bits. Pero eso no es más que pasarle un parámetro al compilador.
Si uno quiere empezar a jugar con la configuración y no invertir horas de prueba y error, lo más seguro es partir de una configuración conocida. En el directorio /boot tenemos la configuración del kernel que estamos utilizando y podemos partir de esa configuración para empezar a hacerle algunos cambios.

1) Instalar dependencias, si es la primera vez que vamos a compilar el kernel necesitaremos las herramientas de desarrollo:
$ sudop apt-get install build-essential bison flex

2) Para partir de una configuración "conocida", desde dentro del directorio de las fuentes de xanmod:
$ make localmodconfig
Con esto lo que haremos es crear el archivo de configuración del kernel (.config) a partir de la configuración del kernel actual y de los módulos que éste contiene.

3) Luego, copiar el directorio de xanmod a la máquina (más potente quizá) que utilizaremos para la compilación.

4) En este punto, previo a la compilación es cuando -si queremos- podemos hacer algunos ajustes. A mí me interesaba, como comenté antes, cambiar la preferencia del scheduler del kernel:

$ make menuconfig

Ese comando abrirá una interfaz ncurses para navegar las diferentes secciones de la configuración del kernel.
En la sección "Preemption Model", selecciné "Preemptible Kernel (Low-Latency Desktop)". Una nota sobre esto ¿De qué se trata el model de preferencia? Dicho en pocas palabras, define el modo en que el kernel elige entre las diferentes procesos o tareas que deben correrse en un sistema operativo multi-tasking (como todos los actuales). El modo seleccionado procura que las aplicaciones de escritorio puedan correr sin muchos contratiempos, aún cuando el sistema esté bajo una carga pesada, como suele ser el caso de mi netbook. Por otro lado quería experimentar también con el scheduler de Entrada/Salida, por ello agregué algunos schedulers que no suelen ser tan estándar:
Me interesó el scheduler BFQ. En este caso agregué el scheduler como módulo, de modo que si no lo quiero utilizar luego no ocupe más memoria en la imagen del kernel.

5) Finalmente (en una máquina más o menos "potente") hacer el build:
$ make ARCH=i386 -j 8 deb-pkg LOCALVERSION=-retux

Aquí con ARCH= indicamos la arquitectura target, que es i386 ya que se trata de un procesdor Atom de Intel. Con -j N podemos asignar un cierto número de núcleos de CPU disponibles para paralelizar la compilación.

6) Instalar en la máquina de destino, que usará este kernel instalar los .deb.
$ sudo dpkg -i *.deb

7) En la configuración del kernel, en los parámetros que grub le pasa en tiempo de boot, se puede seleccionar el scheduler BFQ y deshabilitar watchdog (que en una máquina de escritorio o laptop no es indispensable):
elevator=bfq nowatchdog


Con justicia, ustedes me preguntarán ¿Y los resultados? ¿Vale la pena el esfuerzo? Algunos mejoras en la netbook, en lo que hace a la latencia fueron perceptibles. No es el día y la noche, solo con esto no vamos a hacer de una pc de 13 o 14 años, pero en algo podemos extenderle la vida. Además puede ser el comienzo de otras experimentaciones para el que le interese.
Existe una analogía entre algo del "hacking" con la práctica de los radioficionados. Entre estos existe una práctica denominada transmisión QRP, que consiste en transmitir con la menor potencia en antena. De esa forma, lo que se procura es optimizar el rendimiento (de la línea de transmisión, de la antena, etc) para obtener el mejor resultado posible. De esa forma, un comunicado QRP tiene otra satisfacción diferente a la de poner 100W en antena.
Espacio para mejoras, siempre suele haber, por pequeño que este sea. Si puedo hacer algunos benchmarks prometo publicarlos próximamente.
Continuar »

sábado, 20 de octubre de 2018

Meeprommer, grabador de EEPROMs. Notas sobre el troubleshooting.

Desde que era chico y tuve mi primera compu tuve curiosidad por cómo funcionaban los "cartuchos" con memoria de lecturá solamente, como los que también usaban, además de las primeras computadoras personales (msx, atari, commodore, etc) las consolas de videojuegos de segunda y tercera generación.
Los años pasan y por alguna profunda u oscura razones nos siguen gustando juguetes parecidos, a veces quizá algo más caro. Aunque los precios de la electrónica, con el tiempo fueron reduciéndose exponencialmente.
Aquí comento brevemente la construcción -y sobre todo el troubleshooting- de un grabador -diseñado por Mario Keller- de eeprom para aquellas computadoras de 8 bits.

Tiempo atrás, cartuchos como los mencionados solían utilizar EPROMs como la 2764 o 27256. Aquellas EPROMs requerían de exposición a una fuente de luz UV para su borrado. Normalmente se ponía un pequeño tubo UV en una caja estanca y se las exponía por un cierto tiempo, en general 10-15 minutos.
Posteriormente se desarrollaron las "Electrically Erasable Programmable Read Only Memory", que ya no tienen en su encapsulado la ventana para el ingreso de luz UV, porque se pueden borrar eléctricamente.
Hay EEPROMs con distinto tipo de buses, pero las de bus paralelo, como la 28C256 presentan un pinout retrocompatibles con las EPROMs de bus paralelo de generaciones previas, como la 27256.

Para que estas EEPROMs/EPROM puedan servir, por ejemplo para algún proyecto con algún microprocesador de 8 bits (z80,6809, etc) o para programar un cartucho para la Commodore 64 por ejemplo, es necesario usar un grabador. Hoy en día, los grabadores para EEPROMs de bus paralelo pueden ser relativamente costosos.

MEEPROMMER

MEEPROMMER es el nombre de un diseño de Mario Keller basado en un Arduino, publicado bajo licencia open source (MIT): https://github.com/mkeller0815/MEEPROMMER. El autor también desarrolló una aplicación Java que sirve para interactuar con el grabador, para grabar o leer datos desde la memoria, comparar la imagen con el contenido de la memoria, etc. El esquemático puede verse a continuación:



Aquí se puede ver el circuito montado, ya funcionando:

Para llegar a esto, fue necesario un troubleshooting bastante laborioso.

Sobre el troubleshooting

En varios aspectos un montaje electrónico se parece a cualquier otra artesanía: en general una vez montado el circuito en un prototipo o no, siempre es necesario dedicar tiempo al troubleshooting. Por errores humanos u otros factores, siempre algo puede fallar, algo habrá que mejorar o depurar. Estas notas son la historia de este troubleshooting, supongo que quizá le sean de utilidad a otros o posiblemente a mí mismo, cuando me haya olvidado de lo que tuve que hacer para detectar la falla.
Además de el proyecto en github, me fue muy útil para el troubleshooting la información disponible en este site en español: https://8bit65.wordpress.com/2014/09/04/programando-la-eeprom/
También los consejos de foros y de mi amigo el Bocha me fueron de gran utilidad.
Como en un troubleshooting de cualquier cosa, la técnica que me resulta más eficaz es dividir el problema en partes más pequeñas, hasta identificar las fallas.
El diseño de Mario se basa en dos shift registers (los chips 74HC595) que sirven para resolver el problema de la cantidad de pines I/O necesarios para el bus de direcciones (15) más el bus de datos (8) y pines de control de la memoria. Por supuesto, los pines de un arduino nano no serían suficientes. El registro de desplazamiento permite controlar 8 salidas al mismo tiempo, mientras solo se utilizan unos pocos pines del microcontrotrolados. Una buena explicación acerca del principio de funcionamiento puede leerse en: https://www.arduino.cc/en/Tutorial/ShiftOut

Luego de que las primeras pruebas indicaran que algo estaba fallando, para el troubleshooting del circuito seguí el siguiente orden:

1) Testeado del cableado en la placa experimental.

2) Se puede utilizar el monitor serie de arduino IDE o cualquier programa de comunicaciones serie, funcionando a 115200 bps para interactuar con el circuito, utilizando el protocolo que el autor implementó. Pasando un caracter 'V' nos mostrará los comandos disponibles y también se pueden ver con más detalle aquí: https://8bit65.wordpress.com/2014/09/04/programando-la-eeprom/

3) Prueba del bus de direcciones (salida de ambos shift registers). El código original de Keller tiene un comando muy útil para el troubleshooting: A,ADDRESS. Pasándole la dirección en hexadecimal, el bus de direcciones tendrá que asumir el valor dado. Así se encuentra documentado en el código:

// Set the address bus to an arbitrary value.
// Useful for debugging shift-register wiring, byte-order.
// e.g. A,00FF

Entonces el comando A,00FF habrá de poner los primeros 8 bits del bus de direcciones en 1.

Con un array de leds probé el bus de direcciones:

Con esto descubrí que había un problema con mi cableado del bus de direcciones que no había detectado en (1)
Corregido el cableado ahora el bus de direcciones comenzó a funcionar al 100%, pero por algún otro motivo la grabación de datos continuaba fallando.

4) Prueba de lectura: Para las pruebas también me ayudó bastante haber encontrado guardada una RAM estática, memoria que se graba y accede de una forma muy similar a estas eeproms.
Como puede consultarse en su hoja de datos, para concluir cada ciclo de escritura -ya sea de un byte, o de una página de 64 bytes- se lleva a cabo un proceso de "data polling". Se lee la salida del bus de datos, y una vez que esta coincide con el byte que se quería almacenar, concluye el ciclo de escritura.
Seguí el consejo de mi amigo el Bocha y uní algunas líneas del bus de direcciones con el bus de datos. De esta manera, podría setear una dirección arbitraria y leer un byte del bus. Si los datos coincidían la lectura estaría funcionando correctamente.
Agregué una función corta al código para esas pruebas y los datos concidieron. Las cosas empezaban a mejorar, direcciones y lectura funcionaban ok. Como para escritura se utiliza el mismo bus de datos, tenía certeza de que esas líneas estaban ok. Fue necesario además, poner unas resistencias de unos 10K entre los pines del bus de datos que no se usaban y masa, para evitar que en la lectura dichos pines quedara en estado indefinido.

5) El siguiente paso era intentar escribir apenas un byte en una dirección de la memoria y leerlo para ver si el valor conicidía. Para ello una breve función de tests:

void run_tests(void) {
//void fast_write(unsigned int address, byte data)
Serial.println("\nWriting \'c\' char to addr 0000...");
fast_write(0000,'c');
delay(100);
Serial.println("\nReading from addr 0000. Should get ascii 99 ...");
byte data = read_byte(0000);
Serial.print(" ");
Serial.print(data);
}

Esta prueba, con la SRAM tenía éxito, pero con la eeprom no. A esas alturas ya estaba bastante claro que el circuito se encontraba funcionando, pero algo fallaba en la interacción con la memoria eeprom.
La falla resultó ser bastante rara. Pero no solo me había ocurrido a mí. La eeprom tiene un código de bloqueo, que si uno desea establecerlo bloquea la eeprom. No se pueden borrar los datos, si no se envía antes el código de desbloqueo que el fabricante especifica.
Aparentemente, la EEPROM 28C256 que tenía (la única por el momento) había venido bloqueada.
Luego de envíar el código de desbloqueo el circuito empezó a funcionar correctamente.

No me queda más que agradecer a Mario Keller por compartir su diseño, a Marcel Van Kervinck
https://github.com/kervinck (su versión del código me ayudó para el desbloqueo), otros del foro 6502.org y a mi amigo el Bocha. Ahora solo queda darle algún uso interesante al grabador, para divertirse un rato con retro computing.
Continuar »

miércoles, 21 de febrero de 2018

SELinux ¿De forma fácil?

SELinux es una de las alternativas disponibles en Linux para MAC (Mandatory Access Control), que es una segunda y potentísima barrera de contención por encima de DAC o Discrecionay Access Control, es decir el sistema clásico de permisos en derivados de Unix.
SELinux tiene fama de resultar complejo y dificil para el recién llegado. Este artículo viene por una parte a confirmar esa percepción, pero con la esperanza de que con horas de trabajo el aprendizaje se irá completando.




SELinux fue desarrollado por la NSA junto a otras empresas como Red Hat y Mc Afee que contribuyeron mucho al proyecto. Fue incluído desde las ramas 2.6 del kernel Linux.

SELinux ¿Por qué importa usarlo?

Un kernel linux con política de MAC (Control de Acceso Obligatorio) sirve para confinar programas de usuario y servidores (demonios), como también acceso a archivos y recursos de red. De esta forma es posible aplicar tan solo el menor privilegio requerido para que una aplicación dada funcione, lo que reduce enormemente la exposición a fallas, errores de configuración o buffers overflows. Como SELinux es una forma de implementar RBAC (Role Based Access Control) su uso es altamente recomendado en aplicaciones de la industria financiera o en organizaciones donde hay que reducir al mínimo la exposición de información.
Este confinamiento de aplicaciones, usuario y recursos no reconoce el concepto de "roor" o super-
usuario y no comparte características del control de acceso discrecional como setuid/setgid.
En tiempos de Spectre y Meltdown, cualquier implementación de MAC que contribuya a ofrecer un cierto grado de seguridad adicional resulta valiosa.

Él está ahí, no lo deshabilites

En muchas oportunidades nos encontramos con algún tutorial o incluso con el vendor de alguna aplicación que diga "La aplicación X requiere deshabilitar SELinux". Eso siempre es lo último que hay que hacer. En realidad lo que eso quiere decir el vendor Y no tiene idea acerca de cómo hacer que su app funcione con SELinux.
¿Por qué deshabilitarlo es la peor idea? Porque por defecto las distribuciones actuales que utilizan SELinux (puede ser Centos o RH pero también Debian) vienen con una política ya configurada que permite que cuando ejecutamos aplicaciones como nginx o apache estas ya corran "confinadas" en un dominio SELinux. Deshabilitar SELinux globalment supone perder esa ventaja.
Pero SELinux tiene una fama bien ganada de tener una curva de aprendizaje lenta, de ser complicado por demás. Hay que decirlo también, puede ser complicado pero ofrece una solución sumamente potente para MAC.
Este artículo, breve es el resultado de haber dedicado unas cuantas horas a entender algo sobre SELinux y a escribir un módulo para ejecutar confinada una aplicación web simple. Por defecto, en un sistema con SELinux una apliación que no está descrita en la "policy" correra en modo no-confinado, es decir, como si SELinux no estuviera corriendo.
Es cierto que actualmente SELinux es mucho más sencillo de lo que acostumbraba debido a que vienen incluidas con él un set de herramientas que hacen las cosas bastante más fáciles.
Más que nada el artículo tiene por objeto describir cuál fue el proceso para escribir un módulo, lo que implicó un arduo trabajo de iteracioes prueba/error, hasta que finalmente la aplicación quedó funcionando confinada.
Antiguamente la policy de SELinux solía ser monolítica, pero actualmente se pueden escribir módulos (de alguna forma similares a los del kernel linux) que permiten escribir políticas modulares por cada aplicación. De hecho si en un sistema SELinux hacemos # semodule -l veremos todos los módulos que componen la policy, identificados en general por la aplicación que confinan.

Algo concreto con SELinux

Para esta PoC utilicé una aplicación web muy simple que suele la que uso para probar algunas cosas. Es una versión web del clásico Fortune (escrita con el micro framework flask en python). La misma, junto con la policy SELinux se puede encontrar aquí: https://github.com/retux/flask-web-fortune

La vamos a configurar con un nginx que actuará como reverse proxy:


I N T E R N E T ⇒ NGINX:80 => localhost:5000



Para escribir nuestro módulo CentOS se requieren los siguientes paquetes:

setools-console
policycoreutils-python-2.5-17.1.el7 // Este último provee el binario para /usr/sbin/semanage
policycoreutils-devel // este provee los pkg de desarrollo para escribir policies.


Con web-fortune escuchando en el puerto 5000 la aplicación correrá como unconfined:

# ps auxZ | grep web
system_u:system_r:unconfined_service_t:s0 rtxapps 12430 0.0 1.6 223476 17064 ? Ss 15:08 0:00 /usr/local/share/venvs/flask-web-fortune/bin/python /usr/local/share/applications/web-fortune/app.py

Una vez que hayamos configurado el reverse proxy para que conecte a localhost:5000 seguramente nos entraremos con una barrera que nos pone SELinux. En el audit.log veremos mensajes como este:

type=AVC msg=audit(1519064697.245:443): avc: denied { name_connect } for pid=12674 comm="nginx" dest=5000 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:commplex_main_port_t:s0 tclass=tcp_socket
type=AVC msg=audit(1519064697.246:444): avc: denied { name_connect } for pid=12674 comm="nginx" dest=5000 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:commplex_main_port_t:s0 tclass=tcp_socket

audit2allow es LA herramienta SELinux que servirá para todo el camino, en general siempre va a darnos alguna pista acerca de lo que hay que hacer, pero debemos tener cuidado de no seguir todo al pie de la letra.

# tail -n30 /var/log/audit/audit.log | grep avc | audit2allow


#============= httpd_t ==============

#!!!! This avc can be allowed using the boolean 'httpd_can_network_connect'
allow httpd_t commplex_main_port_t:tcp_socket name_connect;

nginx no consigue conectar al puerto TCP 5000 porque la policy no lo permite.
Como indica audit2allow, tenemos dos alternativas:

La primera utilizar booleans (httpd_can_network_connect), con este boolean vamos a habilitar varias cosas, por ejemplo que el servidor web (en este caso nginx pueda conectar diversos puertos, smtp, el 5000 como requerimos acá).

# getsebool httpd_can_network_connect
httpd_can_network_connect --> off

# setsebool httpd_can_network_connect on

Si funciona de la manera esperada lo podemos setear como Persistente (con el modificador -P)

# setsebool -P httpd_can_network_connect on

Los booleans de SELinux son como interruptores que permiten cambiar algún aspecto de la policy al vuelo. Habilitando este boolean permitieremos que las aplicaciones que corran en el dominio httpd_t puedan conectar a un puerto TCP. Este puede ser el 5000 de nuestra app o el 25 para un MTA local por ejemplo, con lo cual este boolean tiende a ser bastante utilizado.
Cabe destacar que bajo ningún concepto SELinux reemplaza a otras herramientas como iptables o firewall en general. SELinux es una capa más en el camino de la seguridad que se complementa con muchas otras.
Habilitado el boolean y con web-flask-fortune corriendo en modo no-confinado tendremos las cosas funcionando. Pero siempre hay más, siga leyendo lector.


Creando un módulo de SELinux policy "from scratch" para confinar fortune

Si por ejemplo queremos confinar una aplicación, en mi caso una web app flask que escucha en localhost:5000 y que tiene un nginx río arriba.

El comando sepolicy generate sirve para crear los archivos iniciales necesarios para compilar un módulo, o sea los .te, .fc y .if.

Ejemplo:

sepolicy generate --init -n web-fortune /home/rtxapps/.venvs/flask-web-fortune/bin/python

Nótese que el path a python es el binario con el que va a correr la app python, en este caso la versión del venv. En general el path al archivo que inicia el demonio lo podríamos tomar de ExecStart del unit file de systemd.

Después de ejecutar el .sh que provee tendremos que tener el módulo compilado e insertado en la policy de SELinux:

# semodule -l | grep web-fortune

Y después de un restart del servicio podremos ver que en contexto (más que nada el tipo) con el que corre el script ha cambiado:

# ps auxZ | grep fortune | grep -v grep
system_u:system_r:web-fortune_t:s0 rtxapps 15081 0.0 1.6 223476 17068 ? Ss 19:55 0:00 /usr/local/share/venvs/flask-web-fortune/bin/python /usr/local/share/applications/web-fortune/app.py

Puede decirse que ahora la aplicación está corriendo confinada.

Podemos ver también que SELinux etiquetó el “binario” python que inicia nuestro script:

# semanage fcontext -l | grep "fortune"
/usr/local/share/venvs/flask-web-fortune/bin/python regular file system_u:object_r:web-fortune_exec_t:s0

Este era el contexto original de fortune.txt:

ls -lZ /usr/local/share/applications/web-fortune/fortune.txt
-rwxrwxr-x. rtxapps rtxapps unconfined_u:object_r:usr_t:s0 /usr/local/share/applications/web-fortune/fortune.txt


De seguro, la app habrá quedado funcionando sin problemas porque el type web-fortune-t está corriendo en modo permissive:

# semanage permissive -l

Customized Permissive Types
Builtin Permissive Types

web-fortune_t


Por defecto en el archivo .te que nos haya generado sepolicy generate incluye una línea:

permissive web-fortune_t;

“Builtin permissive” se refiere a módulos que fueron construidos con ese tag en su archivo .te.
Esto es MUY interesante, porque indica cuál es el flujo de trabajo cuando trabajamos para “confinar” los privilegios de una app con SELinux. El modo permissive permite que una vez que hayamos insertado nuestro módulo éste haga que SELinux escriba las AVC que violen las reglas, pero eso es precisamente para que la aplicación corra sin restricciones, va a loguear los problemas y podremos ajustar el módulo para ajustarlo a la necesidad.

Hay que tener en cuenta que un módulo que corra en modo permissive no lo podremos deshabilitar, de esta forma:

# semanage -d web-fortune_t
libsemanage.semanage_direct_remove_key: Unable to remove module permissive_web-fortune_t at priority 400. (No such file or directory).
OSError: No such file or directory
Source: http://danwalsh.livejournal.com/42394.html

Para que podamos cambiar un "tipo" o app de modo permisivo o no debemos comentar en esa línea en el .te.
Pero esto define el flujo de trabajo para el desarrollo del módulo de la app. En modo permisivo la app va a funcionar sin bloqueos, pero logueando las violaciones a las reglas de la policy. Con dichas violaciones en el log (audit.log o messages) usaremos audit2allow para depurar el código. Este es un arduo camino. Nadie dijo que era fácil.

¿Qué hacer cuando lo sacamos de modo permissive y la app no anda y aparecen AVCs en el log?

El trabajo es recursivo, prueba y error. Una forma en que audit2allow nos puede ayudar -y mucho- es la siguiente:

audit2allow -a -l

O bien:

audit2allow -a -l -M nombre-modulo

Este último generará los cambios que necesitamos en un módulo (.pp) podemos ir agregando las indicaciones que nos de audit2allow a nuestros .te. El modificador -l nos dará una indicación de las AVCs ocurridas desde la última carga de la policy (o de módulo).
En el caso de este módulo, fue central agregar el contenido de la sección require:


require {
type commplex_main_port_t;
type net_conf_t;
type ldconfig_exec_t;
type bin_t;
type proc_t;
type node_t;
type shell_exec_t;
type web-fortune_t;
type cert_t;
type usr_t;
type lib_t;
type user_home_dir_t;
class tcp_socket { accept bind name_bind node_bind shutdown };
class file { execute execute_no_trans getattr open read };
}

Queda para otro artículo la comparación y la misma implementación usando otra herramienta para confinamiento, como puede ser apparmor.

Fuentes:

https://mgrepl.wordpress.com/2015/05/20/how-to-create-a-new-initial-policy-using-sepolicy-generate-tool/

Dan Walsh es la autoridad de SELinux, la mejor doc es de su autoría. Todos sus posts son más que útiles: https://danwalsh.livejournal.com/

Continuar »

viernes, 16 de febrero de 2018

Infra como codigo: manejar containers LXD con terraform

No hace falta argumentar las ventajas del uso de Infraestructura como Código, sea cuál fuere el destino, plataformas de cloud como aws, google o muchas más. Pero también es una herramienta muy práctica para gestionar como código la creación de containers de docker o lxc. En este caso me ocupo de algunos ejemplos simples para uso con LXD.

Terraform es una herramienta para construir, cambiar y versionar infraestructura de manera segura y eficiente.



Terraform y sus providers

Terraform tiene la enorme ventaja de manejar sos providers como plugins instalables, separados del binario principal. Esta es una forma de modularizar la aplicación como también de hacerla más fácilmente extensible.
Existen providers no solo para las principales plataformas de cloud (SaaS, PaaS, IaaS). Una lista de los plugins oficiales puede encontrarse en el site de terraform: https://www.terraform.io/docs/providers/
Pero también la comunidad crea otros providers, en este caso el plugin para manejar containers de LXD es: https://github.com/sl1pm4t/terraform-provider-lxd
Una vez instalado el plugin como indica la doc, en el directorio .terraform/plugins/linux_amd64/, relativo a donde tengamos nuestro "código" de terraform, podremos listar los providers:

$ terraform providers
.
├── provider.lxd

Con eso listo ya podemos crear los containers codificándolos, sigue un ejemplo simple:

providers.tf
provider "lxd" {
alias = "unix"
}

profiles.tf
resource "lxd_profile" "ssh-access" {
name = "ssh-access"

config {
limits.cpu = 1
}
}


container.tf
resource "lxd_container" "test1" {
name = "test1"
provider = "lxd.unix"
image = "images:debian/stretch/amd64"
ephemeral = false
profiles = ["default", "ssh-access"]
depends_on = ["lxd_profile.ssh-access"]


provisioner "local-exec" {
command = "lxc exec test1 -- /bin/sh -c 'apt-get update && apt-get install openssh-server -y'"
}

}

Y con terraform plan / apply ya tendremos nuestro primer container creado.
Para un aprovisionamiento simple terraform utiliza ssh, como la mayoría de las imágenes de lxd vienen sin openssh-server instalado, deberemos aprovisionarlo con el recurso local-exec.
Continuar »

martes, 31 de enero de 2017

conky se integra cada vez mejor con KDE Plasma

Desde que usaba fluxbox como window manager en una vieja notebook Pentium III durante los primeros años 2000 siempre me gustó conky o su antecesor, torsmo.
En la mayoría de los ambientes de escritorio conky se integraba sin problemas. Con KDE lo hacía interfiriendo un poco con los widgets nativos y modificando un poco el comportamiento general del escritorio. Creo que esos días pasaron para siempre. Por lo menos ahora estoy super conforme con cómo conky se integró con Plasma.

Recientemente también conky cambió la forma en que la configuración (en general el archivo ~/.conkyrc) debe estar estructurada. La configuración que venía usando, que se puede ver en la imagen está disponible en este repo:

https://github.com/retux/conky-configs

Una breve guía sobre cómo instalarlo se puede leer en el README.

¿Cómo optimizar la configuració con Plasma?

La clave de esto la encontré por algún foro que ahora no puedo encontrar su url, pero se trata de lo siguiente:

Verán en el archivo de configuración la definición del tipo de ventana para conky es:

own_window_type = 'dock'

Bueno, esto hará la magia. Lo que debemos configurar es el comportamiento que deseamos para esa ventana, lo que en Plasma se hace de esta forma:


Fíjense que el nombre que le demos a la ventana, en este caso 'conky' es significativo. Con eso debe bastar, desde luego hay que ajustar las preferencias en la sección de texto del .conkyrc para que reflejen las características de su equipo.


Continuar »

lunes, 19 de septiembre de 2016

Configurar servidor LDAP con STARTTLS y SSSD

Un servidor LDAP es parte central de muchos deployments, sean en la nube o en infraestructura propia.
Aplicar los principios de security in depth, es decir procurar siempre aplicar diversos niveles de seguridad contribuye a que nuestros deployments sean más seguros. Por eso en esta entrada se describe cómo integrar un servidor LDAP usando openLDAP con STARTTLS para encriptación. Se usará además GOSA como interfaz gráfica de usuario para la configuración del directorio.
Usaremos además sssd (System Security Services Daemon) que es un approach más reciente y bastante conveniente.



Esta configuración la estoy probando con containers de LXD/LXC por eso quizá los nombres de hosts algo extraños. La ventaja es que con LXC podemos probar con containers la infra que después vamos a llevar la nube (aws, Azure, etc).
La idea centrar es usar el directorio LDAP para autenticación e identificación de usuarios, por eso, aún cuando el servidor LDAP no esté expuesto directamente a Internet vamos a configurar STARTTLS para que el tráfico entre clientes LDAP y el servidor sea encriptado. También llamada oportunistic TLS nos permite utilizar el puerto LDAP estándar (389).

En la máquina que usamos como nuestra CA interna firmaremos los certificados. Lo ideal es que nuestra CA tenga una entidad intermedia o subsidiaria que será la que efectivamente firme los certificados de nuestra organización y que no requieran sites o servicios públicos. Idealmente la máquina de la CA no debiera tener conexión a internet si nos ponemos el nivel de paranoia elevado /alto :

# cd /root/ca

# openssl genrsa -out intermediate/private/ldap02-debian.lxd.key.pem 2048

# chmod 400 intermediate/private/ldap02-debian.lxd.key.pem

2) Crear el csr:

# openssl req -config intermediate/openssl.cnf -key intermediate/private/ldap02-debian.lxd.key.pem -new -sha256 -out intermediate/csr/ldap02-debian.lxd.csr.pem

3) Create certificate:

# openssl ca -config intermediate/openssl.cnf -extensions server_cert -days 999 -notext -md sha256 -in intermediate/csr/ldap02-debian.lxd.csr.pem -out intermediate/certs/ldap02-debian.lxd.cert.pem

#mkdir -p /etc/ssl/{certs,private}

(copiar los certificados de la CA (trust chain), certificado del servidor y la private key.

cp ldap02-debian.lxd.key.pem /etc/ssl/private
chown -R root:openldap /etc/ssl/private
chmod 440 /etc/ssl/private/ldap02-debian.lxd.key.pem

cp ldap02-debian.lxd.cert.pem /etc/ssl/certs
cp ca-chain.cert.pem /etc/ssl/certs

Configurar LDAP:

Configurar /etc/ldap/ldap.conf con los parametros requeridos (BASE y URI):

BASE dc=ldap02-debian,dc=lxd
URI ldap://ldap02-debian.lxd

#SIZELIMIT 12
#TIMELIMIT 15
#DEREF never

# TLS certificates
TLS_CACERT /etc/ssl/certs/ca-chain.cert.pem


Creamos el siguiente archivo ldif para configurar nuestro certificado ssl:

vim /root/certs.ldif

dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/ca-chain.cert.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap02-debian.lxd.cert.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap02-debian.lxd.key.pem

Y lo importamos al directorio LDAP:

ldapmodify -H ldapi:/// -Y EXTERNAL -f /root/certs.ldif
(si hay algun error revisar permisos y que la ruta a los certs sea la correcta)


Probar que starttls funcione, con el parámetro -ZZ

ldapwhoami -H ldap:// -x -ZZ

Si está todo bien debemos obtener:

anonymous

Forzar usar siempre starttls (opcional pero recomendado):

Creamos el siguiente archivo ldif:

cat /root/forcetls.ldif:
dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcSecurity
olcSecurity: tls=1

ldapmodify -H ldapi:/// -Y EXTERNAL -f /root/forcetls.ldif

Para probar podemos hacerlo con:

ldapsearch -H ldap:// -x -b "dc=ldap02-debian,dc=lxd" -LLL dn
Si la encriptación está activada obtendremos:

Confidentiality required (13)
Additional information: TLS confidentiality required


En cambio, si con la opción -ZZ forzamos el uso de starttls:

# ldapsearch -H ldap:// -x -b "dc=ldap02-debian,dc=lxd" -LLL -ZZ dn
dn: dc=ldap02-debian,dc=lxd

dn: cn=admin,dc=ldap02-debian,dc=lxd

Con esto último nos habremos asegurado que todas las solicitudes para LDAP se encripten usando STARTTLS.

Recordar: en la instalación de los clientes LDAP se deberá configurar el archivo /etc/ldap/ldap.conf de la misma manera que se indicó arriba. Asegurándose de haber deployado el certificado de la CA o chain trust y referenciarlo a la ubicación correcta.

Instalación de GOSA

Instalar los siguientes paquetes:

# apt-get install gosa gosa-plugin-sudo gosa-plugin-sudo-schema gosa-schema

La configuración básica de GOSA se hace a través de su UI. Es bastante directa. Lo importante es configurar para que use STARTTLS caso contrario no se podrá comunicar con LDAP. Para ello, luego de haber configurado GOSA por la UI debemos agregar en /etc/gosa/gosa.conf:

<location name="default"
ldapTLS="true"
config="ou=gosa,ou=configs,ou=systems,dc=ldap02-debian,dc=lxd">
<referral URI="ldap://localhost:389/dc=ldap02-debian,dc=lxd"
adminDn="cn=admin,dc=ldap02-debian,dc=lxd"
adminPassword="topsecret" />
</location>

Luego podremos ir creando nuestra base de usuarios en LDAP vía gosa:



Configurar sssd en los clientes para que autentifiquen vía LDAP

Lo que resta es configurar sssd en los clientes para que se autentifiquen vía LDAP:

Instalar paquetes para sssd:

ii sssd 1.13.4-3 System Security Services Daemon -- metapackage
ii sssd-ad 1.13.4-3 System Security Services Daemon -- Active Directory back end
ii sssd-ad-common 1.13.4-3 System Security Services Daemon -- PAC responder
ii sssd-common 1.13.4-3 System Security Services Daemon -- common files
ii sssd-ipa 1.13.4-3 System Security Services Daemon -- IPA back end
ii sssd-krb5 1.13.4-3 System Security Services Daemon -- Kerberos back end
ii sssd-krb5-common 1.13.4-3 System Security Services Daemon -- Kerberos helpers
ii sssd-ldap 1.13.4-3 System Security Services Daemon -- LDAP back end
ii sssd-proxy 1.13.4-3 System Security Services Daemon -- proxy back end
ii sssd-tools


Y la configuración de /etc/sssd/sssd.conf:

root@host01-debian:~# cat /etc/sssd/sssd.conf
[sssd]
services = nss,pam
config_file_version = 2
domains = ldap

[domain/ldap]
ldap_schema = rfc2307bis
ldap_search_base = dc=ldap02-debian,dc=lxd
id_provider = ldap
auth_provider = ldap
chpass_provider = ldap
ldap_uri = ldap://ldap02-debian.lxd:389
ldap_id_use_start_tls = True
cache_credentials = True
ldap_tls_cacertdir = /etc/ssl/certs
ldap_tls_cacert = /etc/ssl/certs/ca-chain.cert.pem


[nss]

[pam]

[sudo]

[autofs]

[ssh]

Verificar que la ubicación de los certificados de la CA sea correcta y que además el modo para el archivo config sea 0600:

# ls -l /etc/sssd/sssd.conf
-rw------- 1 root root 435 Sep 18 23:27 /etc/sssd/sssd.conf

Por último si deseamos que los directorios home de los usuarios (configurados en ldap) se creen automáticamente debemos configurar el módulo pam adecuado:

# cat /etc/pam.d/common-session
#
# /etc/pam.d/common-session - session-related modules common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of modules that define tasks to be performed
# at the start and end of sessions of *any* kind (both interactive and
# non-interactive).
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules. See
# pam-auth-update(8) for details.

# here are the per-package modules (the "Primary" block)
session [default=1] pam_permit.so
# here's the fallback if no module succeeds
session requisite pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
session required pam_permit.so
# and here are more per-package modules (the "Additional" block)
session required pam_unix.so
session optional pam_sss.so
session optional pam_systemd.so
# Added for creating homedir (line to be added):
session required pam_mkhomedir.so
# end of pam-auth-update config


Continuar »

miércoles, 10 de agosto de 2016

Hardening mailserver: configurar Postfix como smarthosts (sasl + TLS)

Como se comentaba en un post anterios sobre Kerberos, una red, hogareña pero con wi-fi es una red semi-abierta. Suponiendo que se haya usado WPA2 cuya encriptación no es trivial romper, todos aquellos con los que hayamos compartido la contraseña podrán seguir teniendo acceso a los servicios de la LAN. Por eso, no está demás configurar el servidor de correo (en este caso Postfix) con autenticación y TLS. De esa forma, ese servidor solo podrá ser "relay" de usuarios autenticados.

Un mismo principio simple acerca de la "seguridad" puede aplicarse prácticamente para cualquier cosa que haya de construise: una casa, una herramienta, un software o una serie de servicios de soft: las técnicas para hacer más seguro el objeto se aplican desde el principio o inevitablemente cuando querramos aplicarlo será demasiado tarde. Algo se habrá roto, alguien se habrá lastimado, un site web habrá sido desfigurado, la información de los clientes capturada, etc.
O la seguridad es una preocupación y ciertos principios se aplican desde el momento cero o después va a ser tarde.

Sea para un sistema de alertas o monitoración o para el envío de mail convencionales siempre es útil configurar nuestro servidor de correo dedicado (MTA). Para que un servidor de correo sea "full-blown" (que no solo entregue correo sino también que sea un receptor) es necesario tener un dominio público, registros DNS, etc. Como este servidor de ejemplo será mayoritariamente para enviar correo (alertas) vamos a configurarlo como un smarthost que en realidad le pase los mensajes a un servidor externo (gmail o cualquier otro) que será el que finalmente entregue el correo.
Supongamos el siguiente caso:


En esta configuración, los dispositivos que requieran enviar alertas o mensajes de correo en general tendrán un postfix configurado como smarthost es decir que no entregarán directamente el correo al servidor de destino sino que primero se lo pasarán al postfix instalado en la raspberry Pi, que hará las veces de "gateway". Este último a su vez será también un smarthost que dependerá de google para enviar el correo a sus destinatarios. En caso que contáramos con un dominio público y registros tipo A y MX en servidor DNS podría funcionar como servidor de correo "full-blown".

Los hosts que usen postfix tendrán en su archivo /etc/hosts una entrada para resolver el nombre del "gateway", en este caso pi1.equiscentrico.com.ar.
Un par de requisitos, que no voy a detallar acá para no extenderme demasiado es que como vamos a usar TLS precisaremos firmar los certificados ssl (con openssl) con nuestra propia CA interna. Tendremos tres archivos: la key privada, el certificado firmado por nuestra CA y por último la chain-trust, es decir el o los certificados de nuestra CA. Es chain-trust cuando la CA root delega la firma en otras CA intermedias. Esa suele ser una buena práctica cuando usamos una CA propia.
Vamos a la configuración del gateway (pi1.equiscentrico.com.ar). Donde ya están instalados los paquetes postfix, libsasl2 y sasl2-bin (en Debian y derivados tienen esos nombres):

Archivo config principal de postfix: /etc/postfix/main.cf:
Debian specific: Specifying a file name will cause the first
# line of that file to be used as the name. The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_key_file=/etc/postfix/pi1.equiscentrico.com.ar.key.pem
smtpd_tls_cert_file=/etc/postfix/pi1.equiscentrico.com.ar.cert.pem
smtp_tls_CAfile=/etc/postfix/cacert.pem
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = pi1.equiscentrico.com.ar
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = pi1@equiscentrico.com.ar, pi1.equiscentrico.com.ar, localhost.equiscentrico.com.ar, localhost
relayhost = [smtp.gmail.com]:587
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_use_tls = yes
smtpd_sasl_local_domain = $myhostname'
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

Principales parámetros:

mydestination = pi1@equiscentrico.com.ar, pi1.equiscentrico.com.ar, localhost.equiscentrico.com.ar, localhost
Lógicamente deberá adaptarse al nombre del host

relayhost = [smtp.gmail.com]:587
Acá especificamos que la entrega del correo se hará a través de gmail.

Con estos parámetros configuramos la autenticación de gmail:

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_use_tls = yes

En la sección TLS configuramos la ubicación del certificado, la private key y los certificados de la CA.

En la sección "smtpd" configuramos los parámetros del servidor propiamente dicho:

smtpd_sasl_local_domain = $myhostname'
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

Aquí configuramos para usar autenticación sasl y especialmente con permit_sasl_authenticated le especificamos que el servidor solo aceptará mensajes de usuarios autenticados.

El archivo /etc/postfix/sasl/sasl_passwd debe mapear la cuenta de google y la contraseña, por ejemplo:

[smtp.gmail.com]:587 cachocastanha@gmail.com:SuperSecreta

Donde "cachocastanha" y "SuperSecreta" son el usuario y contraseña respectivamente.

Luego creamos el hash file y damos permisos adecuados:

# chmod 400 /etc/postfix/sasl/sasl_passwd
# postmap /etc/postfix/sasl/sasl_passwd


En el archivo de config de sasl indicamos qué backend usaremos, en este caso la base "nativa" de sasl, pero soporta muchas otras opciones.

/etc/postfix/sasl/smtpd.conf
pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: plain login

Es posible que la primera vez Gmail requiera que autoricemos la nueva aplicación que está haciendo el envío.
Hecho eso podemos probar el envío desde el propio servidor:

$ echo "Test mail from postfix" | mail -s "Test Postfix" you@retux.com


Veamos la configuración de los hosts, que enviarán el correo a través del "gateway", aquí comento cada sección:

mtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters - con smtpd_use_tls=yes le indicamos que use TLS para establecer un canal seguro (ssl)
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated
myhostname = desktop01.equiscentrico.com.ar
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = $myhostname, desktop01.retux.com.ar, localhost.retux.com.ar, localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = loopback-only
inet_protocols = ipv4
# Config de mail relay a gateway Pi1
relayhost = [pi1.equiscentrico.com.ar]
# si hubiera un backup
#smtp_fallback_relay = [relaybackup.equiscentrico.com]
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/relay_passwd
smtp_sasl_security_options =
smtp_use_tls = yes
# force to use TLS
smtp_tls_security_level = encrypt
# Estos dos parámetros son importantes cuando usamos /etc/hosts para resolución de nombres
# le indican a postfix que use el orden establecido en nsswitch.conf, de otra manera va a usar
# primero el servidor dns que tenga configurado el host.
lmtp_host_lookup = native
smtp_host_lookup = native

De forma parecida, la autenticación sasl se debe configurar en /etc/postfix/relay_passwd

pi1.equiscentrico.com.ar retux:SuperSecretisima

# chmod 400 /etc/postfix/relay_passwd
# postmap /etc/postfix/relay_passwd

Donde "retux" y "SuperSecretisima" son el user y contraseña en la base sasl.

En el servidor "gateway" (pi1.equiscentrico.com.ar) deberá haberse creado el usuario:

saslpasswd2 -c -u `postconf -h mydomain` retux

Podemos listar los usuarios:

# sasldblistusers2
retux@pi1.equiscentrico.com.ar: userPassword

Hecho esto no queda más que probar el envío de correo desde los hosts "internos". Posiblemente las primeras veces haya que revisar los logs y
corregir algo.
Podemos además para asegurarnos de que se está usando TLS y las contraseñas no son enviadas en texto plano, hacer una captura con tcpdump y analizarla, con la GUI de wireshark o como prefiramos:



Como podemos ver, se está usando TLS 1.2 lo que nos garantiza que nuestras credenciales van a viajar encriptadas.

Notas finales: Esta configuración es útil para una red pequeña. Para redes mayores usar la base de sasl resulta en demasiado overhead, porque habrá que registrar una entrada por cada usuario. Por eso usar un servidor centralizado para eso como LDAP o quizá kerberos para autenticar sería la opción más adecuada.


Troubleshooting

Podemos utilizar la navaja suiza del email, swaks:

swaks --auth --server pi1.equiscentrico.com.ar --port 25 --au retux@pi1.equiscentrico.com.ar --ap secretisima --from maildeorigen@gmail.com --to destinatario@gmail.com --h-Subject: "Testing SMTP relay" --body 'Testing Postfix SASL relay'
O también openssl/telnet:
$ openssl s_client -starttls smtp -crlf -connect pi1.equiscentrico.com.ar:25
y utilizaremos el mecanismo AUTH LOGIN
read R BLOCK
ehlo retux.equiscentrico.com.ar
250-pi1.equiscentrico.com.ar
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING
AUTH LOGIN
334 VXNlcm5hbWU6
bWFzarFzQHBpMS5lcXVpbarlbnRyaWNvLmNvfoocg==
334 UGFzc3dvcmQ6
cJaFDADfx0ZXRl
235 2.7.0 Authentication successful
Nótese el "Authentication successful".

Otra herramienta útil para el troubleshooting es sasl2auth:

1) Levantar saslauthd:
$ sudo saslauthd -a sasldb -d -V

Y luego probamos:
$ testsaslauthd -f /run/saslauthd/mux -s"smtp" -r"pi1.equiscentrico.com.ar" -u"elUsuario" -p"lapasswordSecretísima"


Referencias:

https://wiki.debian.org/PostfixAndSASL https://serverfault.com/questions/1050452/postfix-sasldb-issue-solved-as-of-mar-2021
Continuar »

domingo, 27 de marzo de 2016

NFSv4 y Kerberos, la dupla para un fileserver seguro

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
Continuar »