Etiquetas

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 »

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 »

martes, 25 de febrero de 2014

Proyecto de fin de semana: Leds de status para Raspberry Pi

Cuando la Raspberry Pi se usa como servidor, o simplemente headless (sin monitor) resulta útil tener algunos indicadores de su status de funcionamiento. Este proyectito tiene una parte de hard muy simple (un driver de corriente e inversores) y de soft, para colocar en 1 los pines adecuados del GPIO.
El que quiera trabajar con GPIO debe hacerlo con sumo cuidado, así que corre por su propia cuenta y riesgo.

Esta necesidad surgió primero de un pedido de un amigo, que necesitaba un gabinete que alojara una Raspberry Pi y un HD de 2.5" que funcionarían 24/7 como servidor web, y que se encontraría en un IDC (Internet Data Center). Como los leds internos de la Raspberry suelen quedar ocultos en la mayoría de los gabinetes y este no era la excepción, quería agregar un par de leds que indicaran:

1) "Power On", la raspberry tiene conectada la alimentación, pero no concluyó el boot. (Led en Rojo)
2) "Ready", la raspberry concluyó satisfactoriamente el boot (led verde).

1 y 2) es un led bicolor de 5 mm.

3) "ethernet": un segundo led (ambar 5 mm) se pone en ON cuando la ethernet está activa, se apaga si no hay portadora.

Si alguna vez la Raspberry tuviera un problema el resposable de operaciones del IDC tendría un primer indicador a través de los leds. Se puede ver en la primera foto.

El circuito del driver de corriente e inversor sigue a continuación:


Se usó un CI 40106 que contiene 5 inversores lógicos, por la siguiente razón: como driver de corriente, es decir para no cargar directamente el GPIO de la raspberry. Es totalmente cierto que un par de leds podrían conectarse directamente, pero hay que tener en cuenta siempre que si conectamos otras "cosas" al GPIO la corriente total es la sumatoria de todas. Por eso, la utilización del driver ayudaría a la estabilidad general de la RasPi.

Tanto el código como los binarios empaquetados para instalar en la RasPi se pueden encontrar aquí:

https://github.com/retux/raspileds_status

$ git clone https://github.com/retux/raspileds_status --depth 0

Más info sobre interfaces de corriente para GPIO se puede ver aquí: http://elinux.org/RPi_GPIO_Interface_Circuits

RaspiLed-status requiere usar dos pines del GPIO configurados como salida. Como se podrá ver en las notas del código se eligieron los pines GPIO4 (para el status ethernet, led ambar) y el GPIO17 para status de la CPU (power=>rojo, ready=>verde).
El circuito funciona muy simple: cuando el GPIO17 está en cero el primer inversor tendrá a su salida un 1, encendiendo el led en rojo. Esa lógica se invierte cuando ponemos un 1 a la salida del GPIO17.
Dos scripts SysV se encargan de iniciar los dos programas al inicio (/etc/init.d/readyled y /etc/init.d/raspiledsts). si se quisiera cambiar el pin GPIO17 por otro es en readyled donde habrá que editarlo:

### BEGIN INIT INFO
# Provides: readyled
# Required-Start: $locale_fs $syslog
# Required-Stop: $locale_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Turn raspiled ready on/off at boot time
# Description: RaspiLed ready (GPIO pin 17) indicates system has finished boot process.
### END INIT INFO

#!/bin/sh

case "$1" in
start)
echo "Turning on ready LED "
/usr/bin/gpiopinctrl 17 1
;;
stop)
echo "Turning off ready LED"
/usr/bin/gpiopinctrl 17 0
;;
*)
echo "Usage: /etc/init.d/raspiledsts {start|stop}"
exit 1
;;
esac
exit 0

Una vez que el sistema concluya el boot se pondrá en verde el led de status, una vez que demos "shutdown" como el script pasará a stop, se pondrá rojo, indicando que queda con la tensión conectada, pero apagada.
El programa netifledwatch es el encargado de sensar el status de ethernet, es un demonio que a intervalos regulares (1/2 segundo) lee el archivo carrier del pseudo FS /sys. (ej. si la interfaz es eth0 y la portadora ethernet está activa aparecerá un 1 en el archivo, como se ve aquí:

$ cat /sys/class/net/eth0/carrier
1

Con esa lectura el programa lo único que hace es poner en 1 o 0 segun corresponda el GPIO4.

RaspiLeds-status en otro gabinete.

Matías Gutiérrez Reto (retux)
Continuar »

viernes, 7 de febrero de 2014

Crear un paquete DEB a partir de código fuente "upstream"

Siempre lo dije y lo seguiré sosteniendo: una de las cosas que mejor resumen la idea de belleza y eficiencia es el sistema de empaquetamiento de Debian, que así en español no suena del todo bien, hablamos del Debian Package Management System.
Sigue un tip muy breve sobre cómo crear un .deb instalable a partir de un tarball de código fuente "upstream".


Uno de los aspectos de la belleza de DPKG, la base del Debian Management System es la manutención y actualización de los paquetes. Tener idea de los paquetes que tenemos instalados en un servidor o en una estación es rápido y simple, mucho más rápido que tener que hacer find por directorios como /usr/local, /opt.
Por eso siempre es recomendable, de ser posible, usar el sistema de empaquetamiento antes que instalar soft, por ejemplo usando make install (el paso culminante de la compilación de soft con Make: configure, make, make install).
Unas razones por las que es mejor el sistema de empaquetamiento es simple. Si quisiéramos desinstalar el paquete es simplemente dpkg -r, o apt-get remove... y el sistema de gestión de paquetes se va a encargar de borrar los archivos necesarios, y listo.

En otro tip vimos cómo compilar y crear un deb fácilmente cuando el código fuente está en los repositorios Debian
http://www.equiscentrico.com.ar/2011/06/como-crear-paquetes-deb-partir-de.html

¿Y si solo tenemos un .tar.[gb]z ?

A no desesperar. dh_make es el dueño de la magia. Este programa forma parte del paquete debhelper, que es el juego de herramientas para la creación de debs.

Para ejemplificar voy a usar el código fuente de piklab, que es un IDE para el desarrollo en Microcontroladores PIC, que no encontraba en los repositorios de wheezy. Su código fuente se puede encontrar aquí http://sourceforge.net/projects/piklab/files/
Una vez que lo descargamos, y descomprimimos:

$ bzip2 -dc piklab-0.16.2.tar.bz2 | tar xvf -

dh_make va a hacer la magia:

$ cd piklab-0.16.2
$ dh_make -f ../piklab-0.16.2.tar.bz2

dh_make va a crear todos los archivos para la debianización.

Opcionalmente, antes de hacerlo se pueden fijar algunas variables del entorno, para que los datos del "mantainer" como correo y nombre queden ok. En este ejemplo estamos creando un deb para uso propio o distribución en una empresa. Si el paquete fuera a formar parte de los repositorios Debian debe cumplir toda una serie de requisitos extra.
Una vez que dh_make hizo su magia, ahora sí, compilamos (desde dentro del dir del fuente):

$ dpkg-buildpackage -us -uc

A tomar algo y luego obtendremos el .deb (atenti con todas las dependencias que requiera el soft):

dpkg-deb: construyendo el paquete `piklab' en `../piklab_0.16.2-1_i386.deb'.
dpkg-genchanges >../piklab_0.16.2-1_i386.changes
dpkg-genchanges: incluyendo el código fuente completo en la subida
dpkg-source --after-build piklab-0.16.2
dpkg-buildpackage: subida completa (se incluye la fuente original)

Podemos instalarlo:

# dpkg -i piklab_0.16.2-1_i386.deb
Seleccionando el paquete piklab previamente no seleccionado.
(Leyendo la base de datos ... 311105 ficheros o directorios instalados actualmente.)
Desempaquetando piklab (de piklab_0.16.2-1_i386.deb) ...
Configurando piklab (0.16.2-1) ...
Procesando disparadores para man-db ...
Procesando disparadores para hicolor-icon-theme ...
Procesando disparadores para shared-mime-info ...
Unknown media type in type 'all/all'
Unknown media type in type 'all/allfiles'
Unknown media type in type 'uri/mms'
Unknown media type in type 'uri/mmst'
Unknown media type in type 'uri/mmsu'
Unknown media type in type 'uri/pnm'
Unknown media type in type 'uri/rtspt'
Unknown media type in type 'uri/rtspu'
Procesando disparadores para desktop-file-utils ...

Para aquel que todavía no lo crea: Ain't it nice?


Matías Gutiérrez Reto (retux)
Continuar »

miércoles, 1 de enero de 2014

go-mtp para conectar smartphone android a Linux usando mtp

En los actuales smartphones basados en Android fue triste la decisión de abandonar el soporte como "almacenamiento masivo" para transferencia de archivos entre un pc y el móvil para reemplazarlo por mtp (Media Transfer Protocol), desarrollado originariamente por Microsoft.


Me llevó varias horas de trabajo. Compilar libmtp a la versión 1.1.6. Para hacerlo fácil, en Debian puede seguirse el procedimiento descripto en esta entrada de equiscentrico: http://www.equiscentrico.com.ar/2011/06/como-crear-paquetes-deb-partir-de.html sólo bastará reemplazar el nombre del paquete de ejemplo (era midori en aquel caso) por libmtp.

Después probé varias alternativas: kio-mtp, mtpfs... ambos compilados a sus versiones más recientes en los repositorios de fuentes de Sid. En un Samsung S2 el funcionamiento era estable, pero en un Samsung Trend (supongo que debe tener un Android algo más nuevo (?) no había caso.

go-mtp fue el camino

Conviene asegurarse que nuestro usuario pertenezca a los grupos "plugdev" y "fuse":

$ groups
retux dialout cdrom audio video plugdev fuse wireshark

Instalar go-mtp

En el gitHub del proyecto se puede bajar el paquete https://github.com/hanwen/go-mtpfs y como indica la documentación, la compilación del programa es sencilla:

1) Instalación de go-mtp:

# apt-get install golang-go
# apt-get install libusb-1.0-0-dev

$ mkdir /tmp/go
$ export GOPATH=/tmp/go
$ go get github.com/hanwen/go-mtpfs

En el directorio /tmp/go/bin/go-mtpfs tendremos el binario.

Podemos copiarlo a un directorio permanente:

# cp /tmp/go/bin/go-mtpfs /usr/local/bin



2) Usando go-mtp

2.1) Creamos un directorio como punto de montaje

# mkdir /media/samsung
# chown retux /media/samsung

Obviamente, reemplazando "retux" por el nombre de usuario que corresponda.

La magia de go-mtp (conectando el teléfono al usb previamente, claro):

$ go-mtp /media/samsung &
2014/01/01 15:35:00 starting FUSE.

Véase el mensage que indica el inicio de FUSE. Si aparece, ya tendremos accesible el sistema de archivos del teléfono vía mtp:

$ ls /media/samsung/Phone/
Alarms data-app gameloft GoLocker_in GOWeatherEX Music Podcasts TalkingFriends
Android DCIM GOLauncherEX GoStore media Notifications Pou WhatsApp
AppGame Download golocker GoTheme Movies Pictures Ringtones

Una vez que lo hayamos usado, solo basta desmontarlo:

$ fusermount -u /media/samsung
Continuar »