Etiquetas

jueves, 24 de diciembre de 2015

Access Point / Repetidor Wi-Fi con raspberry PI y dongle RTL8192CU

A veces cuando viajamos queremos tener internet en varios dispositivos: notebooks, smartphones, etc y dependemos de un punto de acceso Wi-Fi distante que no tiene buena cobertura entonces contar con un repetidor que enrute el tráfico entre una interfaz (dongle RTL8192CU por ejemplo) y otra interfaz conectada a al wi-fi remota puede ser útil.
Esta entrada en el blog es más bien un paso a paso en español de información que está disponible en ingles. La primera parada en este camino es crear un AP Wi-Fi que enrutee a una red cableada. Luego modificaremos la configuración para hacer bridge a otra interfaz wireless y que la raspberry pi sirva como repetidor Wi-Fi. Para esto utilizaremos hostapd y eventualmente dnsmasq si hay necesidad de que el router (Rpi) asigne direcciones IP.


Antes de comenzar, unas breves palabras sobre el rendimiento de este dispositivo. La raspberry Pi no es el dispositivo ideal si buscamos un router de alto rendimiento. Inevitablemente, el rendimiento será algo menor que un dispositivo dedicado y diseñado para esa función. Dicho esto, invertir tiempo y algo de dinero en este proyecto de fin de semana tiene varias motivaciones: divertirnos en el proceso (habrá que compilar varios softs si usamos un dongle basado en el chipset RTL8192CU) y quizá dispongamos de alguna Raspberry Pi por ahí disponible para la diversión. Dicho sea de paso, siempre se aprende algo sobre networking con estos proyectos, así sean "just for fun".

Primero, crear un router wi-fi y red cableada. Manos a la obra

Para esta primera etapa, que nos servirá para probaer que hayamos configurado correctamente hostapd lo que haremos será: una interfaz wi-fi (ej wlan0) servirá como Access Point al cual se conectarán "clientes" usando encriptación WPA2 y autenticación basada en password. Muy similar a un router comercial convencional.

Primero, siguen las fuentes que me sirvieron para el paso a paso:

http://wannabe-nerd.tweakblogs.net/blog/10870/wifi-access-point-using-a-realtek-8192cu-based-usb-wifi-dongle-with-a-raspberry-pi.html

https://bogeskov.dk/UsbAccessPoint.html

Y especialmente este post me fue de suma utilidad, para mantener las cosas simples:

https://www.raspberrypi.org/forums/viewtopic.php?f=91&t=29752&start=75


Como dije, en mi caso debía usar un dongle marca TP-LINK modelo TL-WN823N, que está basado en el chipset RTL8192CU.

# lsusb
Bus 001 Device 004: ID 0bda:8178 Realtek Semiconductor Corp. RTL8192CU 802.11n WLAN Adapter

Este chipset tiene la particularidad de que el módulo que viene con el kernel no soporta el modo AP. Por lo que es necesario compilar el módulo.
Antes que nada, el "router" precisará que se establezca un bridge (dispositivo de capa 2 similar a un switch) que creará un puente entre dos interfaces. En esta primera etapa, entre wlan0 y eth0.

Instalamos las herramientas para bridges:
# apt-get install bridge-utils

Luego, configuramos la interfaz eth0 y el puente, editando /etc/network/interfaces:

# The loopback network interface
auto lo
iface lo inet loopback


# Setup bridge con bridge
allow-hotplug eth0
iface eth0 inet manual

auto br0
iface br0 inet static
bridge_ports wlan0 eth0
address 192.168.1.19
netmask 255.255.255.0
network 192.168.1.0
## isp router ip, 192.168.1.1 also runs DHCPD ##
gateway 192.168.1.1
dns-nameservers 192.168.1.1

En esta configuración estamos utilizando una dirección fija para la interfaz eth0 y otro dispositivo en la red (con dir 192.168.1.1) será el gateway hacia internet. También ese otro dispositivo se encargará de correr un servidor dhcp, que será el encargado de otorgar direcciones IP a los dispositos que se conecten al router (Raspberry Pi). Si fuera necesario correr el servidor dhcp en le propia raspberry habría que agregar dnsmasq, por ejemplo.

Compilar el modulo adecuado para el 8192CU

Debemos instalar la misma versión de gcc que se haya usado para compilar el kernel, en este caso podemos verla con:

$ cat /proc/version
Linux version 4.1.13+ (dc4@dc4-XPS13-9333) (gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 - Linaro GCC 2014.03) ) #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015

Instalamos la versión adecuada:

# apt-get update
# apt-get install -y gcc-4.8 g++-4.8

Si este no es la versión default de gcc podemos alterar el symlink de /usr/bin/gcc

Siguiente instalamos rpi-source que es la herramienta que facilita la descarga del código fuente del kernel a nuestro dir home. Véase que mejor usar un usuario sin privilegios:

$ cd ~
$ sudo wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source -O /usr/bin/rpi-source && sudo chmod +x /usr/bin/rpi-source && /usr/bin/rpi-source -q --tag-update

Acto seguido descargamos el source code del kernel

$ rpi-source

En nuestro directorio home, tendremos un directorio con un nombre linux-hash...blah creamos un symlink:

$ cd ~
$ ln -s linux-bc1669c846b629cface0aaa367afb2b9c6226faf linux

Ahora, compilamos el módulo:

cd linux
make mrproper

# config del kernel .config
zcat /proc/config.gz > .config
make modules_prepare

# compilar modulo 8192cu

cd ~/rt8192cu
CONFIG_RTL8192CU=m make -C /home/pi/linux M=`pwd`

Si todo fue bien, instalar el módulo:

sudo install -p -m 644 8192cu.ko /lib/modules/4.1.13+/kernel/net/wireless/
sudo insmod /lib/modules/4.1.13+/kernel/net/wireless/8188eu.ko
sudo depmod -a

Lógicamente ajustar la versión del kernel a tu medida. Este es sin dudas el punto más dificil, que va a requerir insistir si alguna dependencia está faltando.

Compilar hostapd

Como dijimos, el encargado de la magia será hostapd. Este es un daemon de user space para Linux y BSDs que implementa todas las funcionalidades de un AP wifi tales como AP management IEEE 802.11, IEEE 802.1X/WPA/WPA2/EAP Authenticators, cliente RADIUS, EAP server, etc.
Como vamos a usar este dongle basado en 8192CU, tendremos que compilar un hostapd modificado, y no usar el que está disponible vía gestor de paquetes. Para eso, descargamos los drivers del fabricante desde aquí Realtek el que indica linuxLinux Kernel 2.6.18~3.9.

Vamos a compilar simplemente la parte de hostapd, de esta forma

$ unzip RTL8192xC_USB_linux_*.zip
$ tar zxvf RTL8188C_8192C_USB_linux_*/wpa_supplicant_hostapd/wpa_supplicant_hostapd-0.8_rtw_*.tar.gz
$ cd wpa_supplicant_hostapd-0.8_*/hostapd/
$ make
$ sudo cp hostapd hostapd_cli /usr/local/sbin/

Ahora creamos la configuración para hostapd, en /etc/hostapd/hostapd.conf:

interface=wlan0
bridge=br0
driver=rtl871xdrv
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=roadconn
country_code=AR
hw_mode=g
channel=6
beacon_int=100
dtim_period=2
max_num_sta=255
rts_threshold=2347
fragm_threshold=2346
macaddr_acl=0
auth_algs=3
ignore_broadcast_ssid=0
wmm_enabled=1
wmm_ac_bk_cwmin=4
wmm_ac_bk_cwmax=10
wmm_ac_bk_aifs=7
wmm_ac_bk_txop_limit=0
wmm_ac_bk_acm=0
wmm_ac_be_aifs=3
wmm_ac_be_cwmin=4
wmm_ac_be_cwmax=10
wmm_ac_be_txop_limit=0
wmm_ac_be_acm=0
wmm_ac_vi_aifs=2
wmm_ac_vi_cwmin=3
wmm_ac_vi_cwmax=4
wmm_ac_vi_txop_limit=94
wmm_ac_vi_acm=0
wmm_ac_vo_aifs=2
wmm_ac_vo_cwmin=2
wmm_ac_vo_cwmax=3
wmm_ac_vo_txop_limit=47
wmm_ac_vo_acm=0
eapol_key_index_workaround=0
eap_server=0
own_ip_addr=127.0.0.1
wpa=2
wpa_passphrase=supersecreta
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Fíjense los parámetros driver=rtl871xdrv que es donde especificamos el driver a usar, ssid= donde definimos el nombre del ssid y wpa_passphrase donde definimos la autenticación.

Se puede probar hostapd con el siguiente comando:

# hostapd -dd /etc/hostapd/hostapd.conf

Si todo va bien podemos crear el script de inicio sysv:

#!/bin/bash
# /etc/init.d/hostapd

### BEGIN INIT INFO
# Provides: hostapd
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Managing hostapd
# Description: This service is used to manage hostapd (WiFi Access Point)
### END INIT INFO


case "$1" in
start)
echo
echo "Starting hostapd..."
echo
if [ ! -d /var/run/hostapd ]; then
rm -rf /var/run/hostapd
mkdir /var/run/hostapd
fi

/usr/local/sbin/hostapd -B -P /var/run/hostapd/wlan0.pid /etc/hostapd/hostapd.conf
;;
stop)
echo
echo "Stopping hostapd..."
echo
if [ -e /var/run/hostapd/wlan0.pid ]; then
read pid < /var/run/hostapd/wlan0.pid if [ x$pid != x ]; then kill $pid fi fi ;; restart) echo echo "Restarting hostapd..." echo if [ -e /var/run/hostapd/wlan0.pid ]; then read pid < /var/run/hostapd/wlan0.pid if [ x$pid != x ]; then kill $pid fi fi if [ ! -d /var/run/hostapd ]; then rm -rf /var/run/hostapd mkdir /var/run/hostapd fi /usr/local/sbin/hostapd -B -P /var/run/hostapd/wlan0.pid /etc/hostapd/hostapd.conf ;; *) echo echo "Usage: /etc/init.d/hostapd start|stop|restart" echo exit 1 ;; esac exit 0


Proximo paso, brevemente es convertir el dispositivo a un repetidor wi-fi, haciendo bridge a una segunda interfaz wifi.
Continuar »

domingo, 3 de mayo de 2015

Unprivileged LXC en Debian Jessie

Linux Containers, o más conocidos como LXC son una joya relativamente reciente -hacen uso de los control groups o cgroups del kernel Linux- que permite correr un sistema operativo Linux dentro de los límites de un contenedor.
Correrlos como root suele ser directo, pero lo más recomendable es ejecutar todo el contenedor como un usuario sin privilegios. Dicha tarea no requiere demasiados esfuerzos en Ubuntu porque esa fue ajustada en detalle. En cambio, en Debian requiere bastante esfuerzo. Varios días, prueba y error compilando paquetes hasta poder conseguirlo ejecutar mis primeros contenedores sin privilegios en Debian. Estas son unas notas sobre el proceso, aún un work-in-progress.


Esta entrada no pretende ser un paso a paso sobre cómo crear contenedores unprivileged, sino más bien listar los prerequisitos necesarios para poder crearlos en Debian Jessie.
Uno de los mejores tutoriales es el de Stéphane Graber en este link: https://www.stgraber.org/2014/01/17/lxc-1-0-unprivileged-containers/
Lo que ocurre es que para poder ejecutar contenedores en Debian debemos realizar algunos ajustes previos:

1) Kernel con las features necesarias

- Un kernel custom con las features necesarios. En este caso compilé un kernel 3.16.6 basandome en la configuración usada por Ubuntu. El archivo config puede encontrarse aquí: config-3.16.0-23-generic

Aquellos que busquen una guía para el build puede encontrarse una aquí: http://www.equiscentrico.com.ar/2012/07/compilar-un-kernel-la-debian.html

También una versión para i386 de esa configuración puede descargarse de: https://www.dropbox.com/s/wazs1fhgru2hyly/linux-image-3.16.6-lxc-rtx_3.16.6-lxc-rtx-10.00.Custom_i386.deb?dl=0

Y los headers pueden encontrarse: https://www.dropbox.com/s/z5udb1stt3q9gor/linux-headers-3.16.6-lxc-rtx_3.16.6-lxc-rtx-10.00.Custom_i386.deb?dl=0

2) systemd parchado para lxc "unprivileged"

Para que el usuario tenga control sobre los cgroups del lxc se requiere una versión bien reciente de systemd, 217-2 en adelante. Yo usé la versión 219, tomandola de la rama experimental de Debian:

Agregar los repo experimantal a APT (/etc/apt/sources.list):
deb http://ftp.debian.org/debian experimental main

Y luego instalar el paquete:

# apt-get update && apt-get -t experimental install systemd

Otro paquete importante es libpam-systemd. Los paquetes instalados pueden verse:

$ dpkg -l | grep systemd
ii libpam-systemd:i386 219-8 i386 system and service manager - PAM module
ii libsystemd0:i386 219-8 i386 systemd utility library
ii systemd 219-8 i386 system and service manager
ii systemd-sysv 219-8 i386 system and service manager - SysV links

3) Versión apropiada de LXC

En este punto es importante hacer notar lo siguiente: debe usarse una versión de LXC de los repos de Debian y no una compilada por uno mismo. Porque se incluyen en la de Debian algunos parches para que LXC se lleve bien con systemd, como puede verse abajo:


dpkg-source: información: extrayendo lxc en lxc-1.0.7
dpkg-source: información: desempaquetando lxc_1.0.7.orig.tar.xz
dpkg-source: información: desempaquetando lxc_1.0.7-3.debian.tar.xz
dpkg-source: información: aplicando «0001-lxcinitdir.patch»
dpkg-source: información: aplicando «0002-sysvinit-directory.patch»
dpkg-source: información: aplicando «0003-sysvinit-lsb-headers.patch»
dpkg-source: información: aplicando «0004-sysvinit-lsb-functions.patch»
dpkg-source: información: aplicando «0005-sysvinit-lsb-lock.patch»
dpkg-source: información: aplicando «0006-lxc-attach-sigint.patch»
dpkg-source: información: aplicando «0007-lxc-patch-shebang.patch»
dpkg-source: información: aplicando «0008-lxc-debian-fuse.patch»
dpkg-source: información: aplicando «0009-lxc-debian-openssh-server.patch»
dpkg-source: información: aplicando «0010-lxc-debian-root-password.patch»
dpkg-source: información: aplicando «0011-lxc-debian-systemd.patch»
dpkg-source: información: aplicando «0012-lxc-debian-sysfs.patch»

Como se ve, esos parches son fundamentales. Pasé mucho tiempo rompiéndome la cabeza con unos deb compilados a partir del upstream de lxc. Esos parches están para eso. Entonces, con la versión que Jessie tiene en sus repos de LXC: 1.0.6 va bien. Lo ideal sería poder usar una un poco más nueva, como 1.0.7 (fuentes de sid), eso voy a intentar dentro de poco.

4) Instalar cgmanager y verificar que esté demonizado

$ dpkg -l cgmanager
ii cgmanager 0.36-1 all

Para cgmanager estoy usando la versión 0.36, que creo que hasta este momento es la más reciente. El DEB que preparé está aquí: https://www.dropbox.com/s/dvkg8sugcpqdc72/cgmanager_0.36-1_all.deb?dl=0

Luego de instalarlo, asegurarse de que quede activado en los scripts de inicio:

c$ systemctl status cgmanager
● cgmanager.service - Cgroup management daemon
Loaded: loaded (/usr/lib/systemd/system/cgmanager.service; enabled; vendor preset: enabled)
Active: active (running) since dom 2015-05-03 20:12:15 ART; 2h 22min ago
Main PID: 814 (cgmanager)
CGroup: /system.slice/cgmanager.service
‣ 814 /usr/sbin/cgmanager -m name=systemd
matias@matuxntbk:~/RamosLinux/lxc$ ps aux | grep cgmanager
root 814 0.0 0.2 2912 2072 ? Ss 20:12 0:00 /usr/sbin/cgmanager -m name=systemd

5) script de inicio y configuración de red lxc-net

También en el dropbox guardé una copia del script de configuración de red, lxc-net que es el encargado de iniciar dnsmasq con la configuración necesaria para utilizar una red tipo "nat", en la que cada contenedor "guest" tendrá una interfaz virtual con una red "interna" que hará nat a la dirección IP del host.

https://www.dropbox.com/s/s4yl5jn30w1apot/lxc-net.tar.gz?dl=0

Luego copiar los archivos, iniciar el script:

# systemctl start lxc-net

Y verificar con bridge utils que la interfaz tipo bridge se haya creado:

matias@matuxntbk:~/RamosLinux/lxc$ /sbin/brctl show
bridge name bridge id STP enabled interfaces
lxcbr0 8000.000000000000 no

6) Preparar el ambiente, siguiendo el tutorial de Stéphane (https://www.stgraber.org/2014/01/17/lxc-1-0-unprivileged-containers/)

6.1) Conviene agregar al usuario que usaremos para los containers al archivo sudoers para que pueda ejecutar cgm:

# /etc/sudoers o visudo
lxcuser ALL=NOPASSWD:/usr/bin/cgm

6.2) preparar los permisos:

$ sudo cgm create all foo
$ sudo cgm chown all foo $(id -u) $(id -g)
$ cgm modepid all foo $$

Aqui utilizamos cgm (cgroup manager) para crear el cgroup foo, y mover a él el pid del running shell. Eso permitirá que los procesos susecuentes se ejecuten bajo ese cgroup.

Notas finales: este es un borrador de un trabajo aún en progresos. Hay que señalar que las versiones que se necesitan por ejemplo de systemd son realmente bleeding-edge. Siendo systemd un proceso crítico (de él depende toda la estabilidad del sistema) conviene probar en profundidad esta configuración antes de aventurarse a hacer un deploy a producción.

Continuar »

martes, 17 de febrero de 2015

En los *nix, los pipelines son un caño

Parte de la "filosofía" de Unix (o de la programación para sistemas *nix) puede resumirse según el principio "escribí programas que hagan una cosa, y que la hagan bien".
Los pipelines, "pipes" son el mecanismo que permite extender este principio combinando y comunicando distintos procesos, para que cada uno haga su tarea, de la mejor forma posible.
En esta entrada, la historia de la noche febril en que Ken Thompson escribió la llamada al sistema pipe() y un par de breves y mundanos ejemplos de uso de pipes en bash.


Una febril noche de 1973 y una orgía de one-liners

Dice Wikipedia ( Pipeline_(Unix) ) que el concepto de pipeline (el paso de la salida de un programa a la entrada de otro) fue inventado por Douglas McIlroy, uno de los autores de los primeros shells. McIlroy notó que buena parte del tiempo estaban dirigiendo la salida de un programa a la entrada de otro.
Sus ideas las implementó Ken Thopson en una "noche febril" de 1973, cuando agregó la llamada al sistema pipe() y el mecanismo de "pipe" | a shell, junto con varias utilitarios en la versión 3 de Unix. Al día siguiente surgieron los "one-liners" (entradas de una líneas que encadenaban varios programas): dice McIlroy "vi una orgía inolvidable de one-liners en la medida que cada uno se sumaba a la diversión de meter todo en un caño".

Comunicar procesos en Bash

Los "pipes" o "pipelines" son una de las formas más simples y básicas de comunicar procesos (IPC: "Inter Process Communication"). Una de las grandes ventajas de los shells *nix es la posibilidad de crear one-liners que son combinaciones de programas, que juntos hacen una tarea en la que cada uno contribuye.
Solo un ejemplo, tomado de www.bashoneliners.com:

$ /usr/bin/printf 'GET / \n' | nc yahoo.com.ar 80

En este ejemplo se puede grabar el html de yahoo.com.ar usando netcat como cliente. Esa era la orgía a la que McIlroy se refería.

Existen pipelines con nombre y pipelines sin nombre, los primeros son básicamente un tipo de archivo especial en el File System al cual cierto/s proceso/s pueden escribir y otros leer. Los pipeline sin nombre son los que más usamos en la cli, cuando se usa para dirigir la salida de un comando a la entrada de otro con el caracter '|'.
Un pipe funciona, oh sorpresa, como un archivo y puede leerse de la misma forma.
Sigue abajo un ejemplo con el que me divertí un rato y con la esperanza que le pueda servir al sr. @esturniolo:

#!/usr/bin/env bash
#### Script for testing porpouses. Showing unnamed pipes in bash
#### imagemagick must be installed, so: # aptitude install imagemagick.


function printUsage {
    echo >&2 'Error: no argument supplied.'
    echo >&2 "Usage $0 "
    echo >&2 "$0 will start looking for image files starting at the initial directory you supply"
exit 1

}

function checkDep {
    type $1 > /dev/null 2>&1
    if [ "$?" -ne 0 ]
    then
     echo >&2 "Dependency $1 not met. Install it!"
    exit 1
    fi
}
function main {
    echo "inicial dir=" $1
    COMMAND="find $1 -iregex .*\.\(jpg\|gif\|png\|jpeg\)$ -type f"
    $COMMAND | while read i
    do
    # Here you do whatever you want with each lined passed throgh the pipe.
    # That's the unix magic.
      echo $i
      # in this test we grab some data from image file properties.
      identify -format "%wx%h %[EXIF:DateTime] " $i
    done
    echo
}

# Test user input: parameter $1, which must be the initial dir.
if [ "$#" -eq 0 ]; then
    printUsage
fi
if [ ! -d $1 ]; then
    echo >&2 "$1 is not a valid directory, so it's none of my bussiness fellow."
    exit 1
fi

# For checking dependency pass bin/script to be checked as checkDep parameter:
checkDep identify
main $1

A este script se le pasa como único parámetro un directorio inicial para que busque recursivamente en él archivos de imágenes:

find $1 -iregex .*\.\(jpg\|gif\|png\|jpeg\)$ -type f

Donde $1 es el primer parámetro que se le pasa al script. Ejemplo:

$ ./test_stu.sh /home/retux/fotos

La magia de pipe:

$COMMAND | while read i
do
    # Here you do whatever you want with each lined passed throgh the pipe.
     # That's the unix magic.
     echo $i
     # in this test we grab some data from image file properties.
     identify -format "%wx%h %[EXIF:DateTime] " $i
done

Cada línea que find en este caso devuelva por su stdout es redirigida por un pipe y almacenada en la var $i. Luego podemos hacer o que querramos, en este caso se llama al programa identify para que imprima algunos atributos de cada imagen, cuando se le pasa su ubicación, contenida en $i.
Continuar »

lunes, 16 de febrero de 2015

Mantener ssh más seguro. Hoy: ssh-agent

Como sysadmins en ambientes corporativos o en nuestras redes hogareñas openssh es el protocolo capaz de encriptar absolutamente todos el tráfico y permitirnos la administración remota de hosts o vps de forma segura.

Usar ssh de manera predeterminada con autenticación por password puede ser peligroso. Por eso, auth asimétrica con keys es la solución.

El desconfiao' puede hacer la prueba. Colocar un host en internet que acepte autenticación por password. En algunas horas los logs evidenciarán que el host fue objeto a algún ataque de diccionario. Si además la config de sshd permite ogin del usuario root (como suele ser el default: PermitRootLogin yes) las consecuencias pueden ser fatales. Si la contraseña es débil y el ataque tiene éxito los miscreants se habrán hecho de acceso al host y con el usuario con mayores privilegios del sistema.
Estas líneas asustadoras sólo pretenden exponer la gravedad. Un protocolo sumamente seguro como ssh versión 2 puede ser vulnerado solo por una configuración "permisiva" del usuario.

En otra entrada de este blog me ocupé sobre cómo usar criptografía asimétrica (par de claves pública/privada) para autenticar ssh:

Aquella vez, para mantener las cosas simples, al momento de crear las claves con ssh-keygen no se establecía una passphrase para el acceso a la clave privada. Eso efectivamente hace las cosas sencillas si se va a usar scp u otro programa en scripts. Pero qué pasa si alguien lograra tener acceso a la clave privada: como no hay passphrase podría tener acceso a los hosts que tienen su clave pública en el archvio authorized_keys.

Para hacer mejor las cosas existe ssh-agent.

Como su manpage explica el objeto de ssh-agent es

ssh-agent es un programa que guarda las llaves privadas que se usan para autentificación por llave pública. En general ssh-agent se inicia como demonio al principio de una sesión X. Otros programas funcionarán como clientes de ssh-agent cuando requieran acceder a otros hosts vía ssh.
Las aplicaciones pueden localizar a ssh-agent a través de dos variables del entorno:

SSH_AGENT_PID

SSH_AUTH_SOCK

Por ejemplo, en mi Debian, el entorno de escritorio Enlightenment inicia el ssh-agent.
Para usarlo con autenticación ssh por clave pública el procedimiento es similar al descripto en pero en el momento de crear las llaves, se debe registrar una contraseña fuerte (passphrase) para el acceso a la llave privada.
Luego, con ssh-add agregaremos la llave privada a la gestión de ssh-agent:

$ ssh-add /home/retux/.ssh/id_rsa

Luego, podremos listar las llaves que ssh-agent gestiona. Obtendremos algo así:

$ ssh-add -l
2048 04:07:3f:a8:28:ca:e7:11:22:33:55:.... .ssh/id_rsa (RSA)

Así las cosas, ssh-agent nos pedirá la primera vez que intentemos acceder a ese host ingresar las passphrase, pero el programa se encargará de gestionarla, y en lo sucesivo, mientras dure la sesión no nos la pedirá nuevamente.
El resultado es similar a no registrar passphrase al crear las llaves con ssh-keygen, pero con el enorme agregado en lo que hace a la seguridad. Si un malhechor se hace de la llave privada deberá conocer la passphrase para tener acceso.
Continuar »

viernes, 21 de marzo de 2014

PAM establecer horarios de uso del sistema, ejemplo para contron paternal

Un tip "quick and dirty" fácil rápido y directo para limitar los horarios en los que ciertos usuarios del sistema pueden loguearse.
En conjunto con otras utilidades sirve para configurar eso llamado "control paternal".


El Linux, como otras variantes de *nix trae implementado PAM (Pluggable Authentication Modules), que básicamente es una API para autenticación de usuarios, pero además como su nombre lo indica PAM incluye varios módulos que con sus "botones y perillas" (configurables en archivos de config, claro) que permiten por ejemplo limitar la asignación de recursos que el kernel provee a cada usuario (ej. RAM, tamaño de la pila, CPU, etc). En ese caso el archivo de config es /etc/pam.d/limits.conf (véase man limts.conf).
Pero el tip rápido y furioso de hoy se ocupa de otro módulo: pam_time.so que nos permite configurar los horarios en que ciertos usuarios podrán loguearse al sistema.

En una entrada previa en Equiscéntrico me ocupé sobre cómo configurar iptables para que algunos usuarios usaran selectivamente los servidores DNS de openDNS y de esa forma establecer un filtro básico de sites no convenientes para niños ver: (http://www.equiscentrico.com.ar/2010/09/filtrar-facilmente-contenido-web.html ).
En otras ocasiones queremos establecer horarios en que los pibes puedan usar las compus, para que no le resten demasiado tiempo a otras actividades. Ahí es donde el módulo pam_time.so viene a nuestra ayuda.
Rápidamente, para activarlo tenemos que incluir la siguiente línea en al archivo /etc/pam.d/login (esa es su ubicación en Debian, en otras distros o sabores *nix debe ser similar). Y también en /etc/pam.d/kdm o el gestor de logins que use nuestro ambiente de escritorio, en este caso es kde.

# BOF modulo para limites horarios
account requisite pam_time.so
# EOF limites horarios

Editando estos dos archivos se activará la verificación de horarios tanto al loguin GUI como a las consolas. Lo más probable es que nuestros hijos usan más el entorno gráfico pero si uno de ellos usara más las consolas, convendría dejarle la compu libre las 24 hs :)
Hablando en serio, si acaso también quisiéramos limitar el acesso por horarios vía ssh habrá que configurarlo en el archivo correspondiente: /etc/pam.d/sshd.
Ahora tendremos que configurar los usuarios a los que queremos aplicar las restricciones, eso se hace en /etc/security/time.conf

Ejemplo:
# usuario 1 (dinix)
*;*;dinix;!Wk1115-1910
*;*;dinix;Wd0000-2400
# Usuario 2 (ada)
*;*;ada;!Wk1115-1910
*;*;ada;Wd0000-2400

Aquí configuramos que de lu-vi tanto el usuario dinix como ada no puedan loguearse entre las 11:15 y las 19:10 !Wk1115-1910 pero que los fines de semana (Wd) puedan loguearse las 24 hs. Errores que cometamos durante la config se puede seguir en el syslog.

Más info se puede obterner con man time.conf·

Una cosita más. Si el usuario ya se encuntra logueado al momento en que comienza la franja horaria restringida no hay un mecanismo que lo desloguee automáticamente. Eso debe implementarse, por ejemplo desde un script disparado por crontab para complementar este módulo de PAM.
Este fue un tip "quick and dirty". Si hay errores, sugerencias, el feedback es siempre bienvenido.
Continuar »