"Después del juego es antes del juego"
Sepp Herberger

martes, 28 de marzo de 2017

Hacer WOL desde el DLink DIR-860L

En la entrada anterior usábamos el punto de acceso DLink DIR-860L para hacer NAT y aislar el aula de la red del centro.

Después de hacerlo funcionar me dí cuenta de que había un problema: es tradicional que los ordenadores de los profesores se enciendan automáticamente mediante un WOL (Wake On Lan) a primera hora de la mañana, de manera que puedan iniciarse las clases sin contratiempos ni esperas. Este WOL se realiza mediante un script que utiliza el comando etherwake/wakeonlan y se ejecuta desde el servidor principal del IES con un crontab. Al aislar todo el aula en una red interna el ordenador del profesor quedaba fuera del alcance de esos paquetes WOL (hasta ahora, como el PC del profesor hacía el NAT tenia un pie en la red interna y otro en la del centro, por lo que si le llegaban los paquetes de WOL) y no despertaba como estamos acostumbrados. Que no cunda el pánco.

La primera opción es permitir al tráfico WOL traspasar el punto de acceso hacia la red interna del aula, haciendo un port forwarding . En teoría se puede, pero yo no lo he logrado.

La segunda opción es delegar en el DLink el despertar el PC del profesor de su aula. El comando en el sistema operativo DD-WRT para despertar por WOL es (ojo, hay que ponerlo con el path completo, si no se ejecuta otra cosa):
# /sbin/wol  -i 192.168.0.255  50:65:F3:1F:A7:AA
Siendo 192.168.0.255 la dirección de red de la red interna del aula (así sabrá el DD-WRT por que interface -lan o wan- debe enviar el paquete WOL) y 50:65:F3:1F:A7:AA la MAC del PC a despertar. Este comando debemos programarlo en el crontab del DD-WRT, usando su interface web, en la opción Administration/Management/Cron:



La línea que despierta el PC del profesor cada día lectivo a las 8:00 es:
00 8 * * 1-5 root   /usr/sbin/wol -i 192.168.0.255 50:65:f3:1f:a7:aa
Tampoco debemos olvidar poner en hora correcta el DLink activando el cliente NTP en la pestaña Setup del interfaz Web de configuración y poniendo como server NTP la IP del servidor principal del centro, que ofrece esa funcionalidad.

Para asegurarnos de que todo está en orden vamos a la querida línea de comandos del DD-WRT:
# nvram show | grep cron
cron_jobs=00 8 * * 1-5 root   /usr/sbin/wol -i 192.168.0.255 50:65:f3:1f:a7:aa
cron_enable=1

# nvram show | grep ntp
ntp_enable=1
ntp_server=172.55.213.2
ntp_mode=auto
Pues nada, ya tendremos a nuestro D-Link despertando al PC del profesor de buena mañana. De igual manera podemos meter mas líneas en el crontab para que despierte otras cosas tanto hacia la red del aula como hacia la red del centro, faltaría mas.

Hasta la próxima.

lunes, 27 de marzo de 2017

Uso de DLink DIR-860L para hacer NAT dentro del aula.

Normalmente por facilidad de gestión de los ordenadores de los alumnos y por no malgastar direcciones IP, dentro de las aulas tenemos una VLAN con un direccionamiento IP privado dentro del rango 192.168.0.X.

Los puestos de los alumnos reciben ip 192.168.0.201, .202, ... (si damos de alta el puesto del alumno en la rama DHCP Config del servidor ldap podemos incluso hacer que el PC del alumno reciba siempre una IP fija, lo cual facilita aún mas su gestión) y el puesto del profesor tiene la IP fija 192.168.0.254.

Es el PC del profesor con sus dos tarjetas de red el que hace la NAT entre la red del centro y la del aula.

Con la llegada de los puntos de acceso de DLink DIR-860L tenemos un elemento nuevo dentro del aula. Normalmente lo usaremos como punto de acceso wifi para portátiles y dispositivos móviles desde su dirección 192.168.0.1, pero al disponer de un puerto WAN y un switch con 4 puertos LAN podemos usarlo para liberar al PC del profesor de hacer NAT. Además, debemos tener en cuenta que los PC para los infolab que nos han mandado solo tienen una tarjeta de red que para más inri da bastantes problemas para hacer el NAT ya que su driver no soporta muy bien (por decirlo de foma suave) el tráfico del aula.

El punto Dlink lo estoy guardando en la mesa del profesor, dentro del cajón donde está el PC. El esquema del cableado que hacemos es el siguiente:

  1. Toma de 100Mb del suelo de la mesa del profesor. Está conectada directamente a la red del centro en el patch panel. La conectamos al puerto WAN (amarillo) del punto de acceso.
  2. El puerto LAN4 del punto de acceso se conecta con un cable directo a la única tarjeta de red del PC del profesor, la que trae en la placa base.
  3. Toma de 1Gb del suelo (etiquetada normalmente como "enlace profesor"). Va conectada a un puerto de switch el patch panel, incluido dentro de la VLAN interna del aula. Se conectará al puerto LAN1 del punto de acceso.
Antes de seguir con la configuración de red debemos aclarar que hay dos enfoques para este escenario, determinados por quién hace de servidor DHCP dentro del aula.
  • Si queremos que el mismo punto de acceso haga de servidor DHCP y gestione las IP que se van dando a los PC de los alumnos.
  • Si queremos que siga siendo el PC de profesor el servidor DHCP dentro de la red del aula.
En el primer caso, las ventajas son dos: el PC del profesor queda liberado de esa tarea y cada cosa sigue con la IP que hemos tenido hasta ahora: el PC del profesor con 192.168.0.254, el punto de acceso con 192.168.0.1 y los PC de los alumnos con 192.168.0.2XX. La desventaja es que los PC de los alumnos no podrán recibir IP fijas configuradas en el servidor ldap.

En el segundo caso la ventaja es que los PC de los alumnos reciben las IP fijas definidas en ldap (lo cual facilita su gestión e identificación desde Aulalinex, Squid, Sarg, etc). Otra ventaja es que si el PC del profesor está apagado, nadie da IP en la subred y los alumnos no podrán navegar. La desventaja es que hay que cambiar las IP de punto de acceso y PC del profesor para que funcione la cosa.

Yo me he decantado por el segundo caso, ya que estoy acostumbrado a tener los alumnos con IP fija y me parece un paso atrás renunciar a eso. Para configurar la red entramos en el punto de acceso por su interfaz web (https://192.168.0.1) y lo quedamos así:


El puerto WAN del router se configura con una IP 172.XX.YY.ZZ de la red del centro, poniendo la máscara, puerta de enlace y DNS como siempre. El puerto LAN tiene originalmente 192.168.0.1 pero como vemos la hemos cambiado a 192.168.0.254. La causa es que los PC de los alumnos están configurados para usar como gateway de su subred la IP 192.168.0.254, que es donde se hace NAT (recordemos que es el DLink el que hace el NAT ahora), y es mas fácil eso que cambiar la configuración DHCP de los clientes en ldap para usar un nuevo gateway. 

En el PC del profesor, cambiamos la IP fija que tiene en 192.168.0.254 por otra, por ejemplo 192.168.0.100, ya que él ahora no hace el NAT y esa IP está cogida por el DLink. No hay que olvidar cambiar la configuración de los clientes aulalinex de los alumnos para decirles que el profesor tiene ahora una nueva IP, lo cual por puppet es una tarea sencilla de realizar. Por último, el servidor DHCP se deja desactivado en la configuración Web del DLink. La configuración de red del profesor sería:
~# cat /etc/network/interfaces
auto lo eth0
iface lo inet loopback

iface eth0 inet static
        address 192.168.0.100
        gateway 192.168.0.254
        dns-nameservers 172.19.231.3
        dns-search vguadalupe
        netmask 255.255.255.0
        broadcast 192.168.0.255
Si tenemos algún script o servicio de NAT, como /etc/init.d/enable-nat o /etc/init.d/activa-nat habría que desinstalarlo, ya que no procede. En cuanto a aulalinex en el puesto del profesor:
~# cat /var/lib/aulalinex-profesor/aulalinex-profesor.conf
.....
[Profesor]
mesa profesor=192.168.0.100
.....
[Servidor]
IP=192.168.0.254
.....
[Punto Acceso]
IP=192.168.0.254
.....
Y en los alumnos:
~# cat /etc/aulalinex-red.conf
.....
[Profesor]
IP Profesor=192.168.0.100
.....
En el caso de querer optar por la primera opción propuesta activaríamos el servidor DHCP indicando un rango para repartir IP, el puerto LAN del punto de acceso se quedaría con 192.168.0.1 y el PC del profesor con IP 192.168.0.254. Adicionalmente habria que apagar el servicio DHCP del PC del profesor, para evitar que haya dos servidores DHCP en competencia en la red interna del aula. 

Sea cual sea la opción elegida, con esto tenemos el DLink haciendo NAT. 

Si además queremos controlar su wifi desde el PC del profesor podemos usar la aplicación controlwifi que hace que sea trivial para el profesor encender y apagar la wifi, así como indicar la clave a los alumnos.

Venga, nos vamos.

Añadido 30/05/2017. Tras varias pruebas con mi compañera Montse, ampliaré un poco algunos puntos que habían quedado sin tocar o poco claros.

Como el punto de acceso enruta entre 2 redes, debe permitir conexiones tanto https como ssh desde ambas. El tener activado por defecto el firewall es un problema aquí, por eso es conveniente detenerlo:


Luego, hay que activar el servicio ssh para permitir la conexión manual o de aplicaciones como controlwifi:




Por último, la gestión remota quedará así:



Para conectar por ssh al ordenador del profesor desde fuera hay que hacerlo pasando por el punto de acceso, en dos saltos:

~$ ssh root@aulax-ap
root@aulax-ap's password: 
==========================================================
 
     ___  ___     _      _____  ______       ____  ___ 
    / _ \/ _ \___| | /| / / _ \/_  __/ _  __|_  / / _ \
   / // / // /___/ |/ |/ / , _/ / /   | |/ //_ <_/ // /
  /____/____/    |__/|__/_/|_| /_/    |___/____(_)___/ 
                                                     
                       DD-WRT v3.0
                   http://www.dd-wrt.com
 
==========================================================


BusyBox v1.24.1 (2016-02-23 13:45:33 CET) built-in shell (ash)

root@AULAX-AP:~# ssh root@192.168.0.100
root@192.168.0.100's password: 
Welcome to Ubuntu 14.04.5 LTS (GNU/Linux 3.19.0-73-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

0 packages can be updated.
0 updates are security updates.

Last login: Mon May 29 10:51:05 2017 from 192.168.0.254
root@A0X-PRO:~# 


Bueno, creo que ahora queda mas claro.


domingo, 12 de marzo de 2017

No a la obsolescencia programada: cambiando la batería de un ebook.

Me ha llegado un ebook "averiado" para tirar a reciclaje o para hacer lo que quisiese con él. El dispositivo en cuestión es este:



Y el síntoma es que no se encendía, estaba como muerto. Tras consultar en Internet veo que lo mas seguro es que la batería se haya estropeado y como no tengo nada que perder, me decido a abrirlo para verle las tripas.

Una vez abierto observo que la batería que tiene es una batería de polímeros de litio (es blanda, como de arcilla, y tiene una pequeña circuitería de carga en un lateral, donde entran los cables) de 3.7V, como las baterías de cualquier móvil. Luce como esta sacada al azar de Aliexpress:



Está pegada con un adhesivo a la placa base y unida a ésta por los dos típicos cables rojo(+) y negro(-). Corto los cables que entran en la batería y la saco de la placa. Tengo varias baterías de móviles viejo dando vueltas por ahí en un cajón...¿cargo una y la pongo a ver si da el pego?. Vamos allá: la cargo en su propio móvil y luego la sueldo respetando la polaridad y la coloco donde estaba la original. Queda así:



Una panorámica de la placa con la batería vieja al lado:



Hecho esto, doy al botón de encendido y ¡voilá!:



El ebook funciona, simplemente estaba muerta su batería. Si pruebo a conectar el conector USB que tiene a un cargador de móvil verifico que empieza a cargarse. No me fío mucho de que la circuitería de la batería del móvil (que ya tiene mas de 10 años y estaba bastante fastidiada) no vaya a permitir cargar bien. Pero bueno, ya sé que por 6 euros puedo comprar una batería específica para ebooks en Aliexpress y soldarla. Otro aparato recuperado y tomo nota para cuando me dejen de ir los 2 ebooks que tengo en casa, un Kindle y un venerable Sony PRS-505.

Ahora mi editorial: es vergonzoso que los lectores de libros electrónicos usen este tipo de baterías díficiles de reemplazar cuando llegan al final de su vida útil. ¿Tan difícil es poner un compartimento con baterías intercambiables como las de un móvil o una cámara?.

La causa es sencilla: un ebook es un aparato que, a diferencia de la mayoria de chismes tecnológicos que nos ofrece el capitalismo terminal, nunca va a quedar obsoleto en funcionalidad o va a ir tan lento que haya que comprar otro para ponerse al día. A fin de cuentas se basa en un sistema que ha funcionado desde las tabillas de arcilla de Ur: marcas permanentes sobre una superficie.

Por tanto la solución pasa por entorpecer al máximo su durabilidad, como ya vimos en este blog con los lápices de la pizarra Interwrite, y yo por mi cuenta veo yo cuando desmonto un cepillo de dientes eléctrico "averiado" y compruebo que tiene una batería patatera de NiMh (a estas alturas del baile andan con baterías de NiMh, carajo, si al menos fueran de NiFe) soldada al motor y enclaustrada, de tal manera que es bastante complicado cambiarla sin romper nada. En el caso de los ebooks esto empieza por poner una batería soldada a la placa difícil de reemplazar para un comprador habitual.

Al final un ebook bien cuidado y con baterías intercambiables fácilmente pordía durar decenios. Si le añades un cargador USB solar además te haces independiente de las eléctricas y sus secuaces del gobierno. Todo esto suena muy subversivo, que mundo mas raro.

Addenda 13/5/2017: comprada batería por menos de 6 euros en Aliexpress, soldada y dejado el ebook funcionando al 100%:

jueves, 9 de marzo de 2017

La suma hash difiere, 406 not acceptable o index failed to download al hacer "apt-get update"

Finalmente lo tengo que apuntar aquí porque cada vez que me pasa me tiro un rato hasta que me acuerdo la solución. Al hacer apt-get update o pkgsync en algunos equipos aparece este enigmático mensaje:
W: Imposible obtener http://blablabla/archive/ubuntu/dists/trusty-backports/main/binary-amd64/Packages  La suma hash difiere
W: Imposible obtener http://blablabla/archive/archive/ubuntu/dists/trusty-backports/main/binary-i386/Packages  La suma hash difiere
O
100% [Trabajando]W: Se produjo un fallo al descargar http://blablaba/desarrollo/pizarras/wheezy/dists/wheezy/linex/binary-amd64/Packages: 406  Not Acceptable
W: Se produjo un fallo al descargar http://blablaba/desarrollo/pizarras/wheezy/dists/wheezy/linex/binary-i386/Packages: 406  Not Acceptable
E: Some index files failed to download. They have been ignored, or old ones used instead.
E: No se pudo reconstruir el almacén de paquetes
Evidentemente esto impide la instalación o actualización de paquetes, ya que hay algo corrupto en el sistema local de paquetes que le impide seguir. La solución nos la dió nuestro compañero Paco hace ya meses y paso a reflejarla aquí:
# cd /var/lib/apt/lists
# rm -rf *
Con esto se borra todo el contenido, incluyendo el subdirectorio "partial". Con esto queda limpio de polvo y paja y ya se puede actualizar todo bien.

martes, 7 de marzo de 2017

2x1: multiseat en las aulas (Parte III)

Bueno, tenía que llegar tarde o temprano al tema del sonido en multiseat. Tras montar el multiseat aquí y aquí hace varios días me pidieron hacer funcionar el sonido de forma autónoma en cada seat.

1. Configuracion del seat.

En la entrada anterior le dediqué un apartado al tema y concluí que si usamos homes montados sobre NFS había que poner 2 tarjetas de sonido físicas, ya que pulseaudio no funcionaba bien por separado en cada seat compartiendo una única tarjeta. Así que he pinchado una tarjeta PCI de sonido normalita sacada de algún desguace de PC de los 90. El lspci me muestra esa tarjeta de audio adicional:
# lspci | grep -i audio
00:1b.0 Audio device: Intel Corporation 82801JI (ICH10 Family) HD Audio Controller
06:00.0 Multimedia audio controller: Ensoniq ES1370 [AudioPCI]
Como siempre, por defecto ambas tarjetas están vinculadas al seat0, veámoslo:
# loginctl seat-status seat0 | grep sound

          ├─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0
          │ sound:card0 "Intel"
          │ ├─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input10
          │ ├─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input11
          │ ├─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input12
          │ ├─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input13
          │ ├─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input14
          │ ├─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input15
          │ ├─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input16
          │ └─/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input17
          ├─/sys/devices/pci0000:00/0000:00:1e.0/0000:06:00.0/sound/card2
          │ sound:card2 "AudioPCI"
          ................
          ................
Ahora vinculamos la tarjeta nueva, como ya vimos en las anteriores entradas, al seat-1:
# loginctl attach seat-1 "/sys/devices/pci0000:00/0000:00:1e.0/0000:06:00.0/sound/card2"
¿Estará ya en seat-1?. Como dicen en las Vegas Altas, vela ahíla:
# loginctl seat-status seat-1
seat-1
        Sessions: *c2
         Devices:
                  ├─/sys/devices/pci0000:00/0000:00:06.0/0000:02:00.0/drm/card0
                  │ drm:card0
                  ├─/sys/devices/pci0000:00/0000:00:06.0/0000:02:00.0/drm/renderD128
                  │ drm:renderD128
                  ├─/sys/devices/pci0000:00/0000:00:06.0/0000:02:00.0/graphics/fb0
                  │ [MASTER] graphics:fb0 "nouveaufb"
                  ├─/sys/devices/pci0000:00/0000:00:1d.7/usb2/2-2
                  │ usb:2-2
                  │ ├─/sys/devices/pci0000:00/0000:00:1d.7/usb2/2-2/2-2.1/2-2.1:1.0/0003:046D:C050.0001/input/input5
                  │ │ input:input5 "Logitech USB-PS/2 Optical Mouse"
                  │ └─/sys/devices/pci0000:00/0000:00:1d.7/usb2/2-2/2-2.2/2-2.2:1.0/0003:046D:C312.0002/input/input6
                  │   input:input6 "LITEON Technology USB Multimedia Keyboard"
                  └─/sys/devices/pci0000:00/0000:00:1e.0/0000:06:00.0/sound/card2
                    sound:card2 "AudioPCI"
Al reiniciar e iniciar sesión, podemos ver con un "ps aux" que pulseaudio se ejecuta en 3 instancias: una para lightdm y otra para cada una de las 2 sesiones en sendos seat.

El chasco viene cuando descubrimos que ambos seat reproducen el sonido por la tarjeta de audio Intel, ignorando la Ensoniq... ¿qué pasa aquí?. Si miramos la configuración de audio con pavucontrol en cualquiera de los seat vemos:
Horror de horrores: ambos seat ven las dos tarjetas de audio. Esto no es lo que me habían contado. Cada pulseaudio debería ver solo la tarjeta asociada a su seat, como sucede con los teclados, ratones y VGA. Esto tiene toda la pinta de ser un bug de pulseaudio que no maneja bien el tag ID_SEAT definido en su rules.d, pero no sé como arreglarlo en ese nivel.

2. El truco para activar una u otra tarjeta de sonido según el seat.

Lo que si me doy cuenta en la imagen anterior es que yo puedo, en cada combo, seleccionar el perfil "Desactivado" en una u otra tarjeta y conseguir que el sonido salga por la Intel o la Ensoniq, ignorando la otra. Eso es una rendija por la que colarse: si puedo hacerlo a mano...¿podria hacerlo al iniciar sesión en función del seat?. Dicho de otra manera...¿puedo controlar pulseaudio con comandos?. Pues si, encuentro en esta entrada que existe el comando "pacmd" que permite controlar todos y cada uno de los parámetros de una instancia de pulseaudio, incluyendo hacer copias de seguridad y restaurarlas. Con:
 ~$ pacmd help
Available commands:
    help                      Show this help
    list-modules              List loaded modules
    list-cards                List cards
    list-sinks                List loaded sinks
    list-sources              List loaded sources
    list-clients              List loaded clients
    list-sink-inputs          List sink inputs
    list-source-outputs       List source outputs
    ......
    play-file                 Play a sound file (args: filename, sink|index)
    dump                      Dump daemon configuration
    dump-volumes              Debug: Show the state of all volumes
    shared                    Debug: Show shared properties
    exit                      Terminate the daemon
Vemos todos los posibles comandos para obtener o fijar los parámetros de configuración. Con "pacmd dump > config.txt" haríamos una copia de seguridad, que podríamos restaurar con "pacmd < config.txt". Profundicemos: realmente la configuración de pulseaudio se guarda en:
 ~$ ls -1 ~/.config/pulse
cookie
e8418e23c6b647548fea260c81d4742b-card-database.tdb
e8418e23c6b647548fea260c81d4742b-default-sink
e8418e23c6b647548fea260c81d4742b-default-source
e8418e23c6b647548fea260c81d4742b-device-volumes.tdb
e8418e23c6b647548fea260c81d4742b-stream-volumes.tdb
Siendo los .tdb un tipo de BBDD bastante simple basado en pares "clave/datos binarios" usados principalmente en Samba. Son bastante crípticos incluso con la herramienta tdbtool, ya que guardan la información en formato binario, así que los ignoraremos y usaremos pacmd que es menos huraño.

Una curiosidad es el prefijo "e8418e23c6b647548fea260c81d4742b" de cada fichero. Es un UUID que sospecho que va asociado a la máquina, aunque no he podido averiguar de donde sale, y que permite tener configuraciones separadas de pulseaudio en función de la máquina en la que inicia sesión el usario, lo cual es muy útil cuando nuestros usuarios tienen un home centralizado en un servidor NFS.

Bueno, vamos al lío: tenemos que activar una u otra tarjeta al iniciar sesión en función del seat. Esto lo enfocaré como un parche temporal ya que según dice la parte contratante de la primera parte cada instancia de pulseaudio debería asociarse a la tarjeta de sonido vinculada seat correspondiente y santaspascuas. Hasta que esto sea cierto usaremos estos scripts para hacer funcionar el sistema:
# cat /usr/bin/multiseat-sound
#!/bin/bash
if [ "$XDG_SEAT" = "seat0" ]
then
   pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo
   pacmd set-card-profile 1 off
else
   pacmd set-card-profile 0 off
   pacmd set-card-profile 1 output:analog-stereo+input:analog-stereo
fi
Sencillo: si estamos en seat0 la tarjeta 0 se activa y la 1 se desactiva. Si es seat-1 se realiza la acción opuesta. Los valores output:analog-stereo+input:analog-stereo y off los he obtenido cambiando en pavucontrol a golpe de ratón y luego husmeando con "pacmd dump". Como queremos que esto se ejecute en cada inicio de sesión, metemos un .desktop en xdg/autostart:
# cat /etc/xdg/autostart/multiseat-sound.desktop
[Desktop Entry]
Type=Application
Name=Multiseat-Sound
Comment=Configura sonido por multiseat
Exec=/usr/bin/multiseat-sound
Terminal=false


3. Limpiando la casa.

Por último, si queremos quedar todo en recogido y en orden al salir de sesión debemos configurar un script de salida en lightdm:
 # cat /etc/lightdm/lightdm.conf.d/14-logout.conf
[SeatDefaults]
session-cleanup-script=/usr/bin/multiseat-sound-off
Siendo
# cat /usr/bin/multiseat-sound-off
#!/bin/bash
pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo
pacmd set-card-profile 1 output:analog-stereo+input:analog-stereo
Y con esto ya podemos tocar duetos con nuestros multiseat. Hasta podemos lanzar un duelo de guitarras haciendo salir por una a Joe Satriani y por otra a Yngwie Malmsteen y así alcanzamos el Nirvana en dobleplusestéreo.



jueves, 2 de marzo de 2017

Configuración de OpenWrt como routed client (Parte I)

Cuando tenemos nuestro router con OpenWrt y lo queremos usar como dispositivo wifi (suponiendo que el chipset esté soportado por OpenWrt, ĺo cual no siempre sucede) hay tres escenarios posibles:

  • Usarlo como repetidor para extender una wifi preexistente, creando una red wifi con un ESSID nuevo que amplía el alcance de la anterior.
  • Usarlo para crear un punto de acceso con una red wifi nueva, a partir de una conexión que ya nos trae acceso a internet cableada por ethernet. Lo que los chicos de OpenWrt llaman "Dumb AP".
  • Usarlo para conectar como cliente a una red wifi preexistente y luego permitir conexión de dispositivos adicionales usando los puertos ethernet del router, enrutando el tráfico entre ambas tarjetas de red (wifi y ethernet) usando NAT. (Nota: hay otras soluciones aparte de NAT, como usar rutas estáticas o relayd, pero se explicarán en entradas futuras)

Bueno, pues esta última es la opción que he tenido que configurar en los recientes días para acceder a la red wifi y conectar la Raspberry Pi a ella mediante un cable ethernet (es una Pi sin wifi y los pinchos USB que probé no tenían unos drivers muy estables y/o eficientes). El esquema (cogido de la web de OpenWrt) sería:


Las IP Azules son de la red preexistente y las rojas de la red nueva que creamos. Veamos como configurar los distintos ficheros para llegar hasta aquí.

El router usado ha sido, una vez más, un indestructible Astoria gris de ya.com, el ARV4518PW modelo R01A. Esta vez he ido más allá y le he metido el ultimísimo firmware lede-lantiq-xway_legacy-ARV4518PWR01A-squashfs-sysupgrade.bin, del proyecto LEDE que es una escisión de OpenWrt. Como diría Joseph Stalin, los proyectos de SW libre están llenos de trotskistas.

Recordemos que el router tiene una memoria NAND de 4Mb de la cual solo se puede usar 3.6Mb (si pasamos de ahí se sobreescriben los datos de calibración de la wifi), así que cabe la imagen y poco más. Si queremos instalar paquetes adicionales deberíamos usar otro router o bien pinchar un pendrive USB y configurarlo para instalar aplicaciones allí. Si no es así no podermos añadir paquetes nuevos, aunque realmente para este caso que nos ocupa no hacen falta. El espacio en disco tras la instalación es:
# root@ASTORIA:/etc/config# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root                 2304      2304         0 100% /rom
tmpfs                    30040        48     29992   0% /tmp
/dev/mtdblock5             320       264        56  83% /overlay
overlayfs:/overlay         320       264        56  83% /
tmpfs                      512         0       512   0% /dev
El banner de login es:
    /        /\      _    ___ ___  ___
   /  LE    /  \    | |  | __|   \| __|
  /    DE  /    \   | |__| _|| |) | _|
 /________/  LE  \  |____|___|___/|___|                      lede-project.org
 \        \   DE /
  \    LE  \    /  -----------------------------------------------------------
   \  DE    \  /    Reboot (SNAPSHOT, r3598-eb09d79)
    \________\/    -----------------------------------------------------------
La carga del sistema nuevo la he hecho desde el OpenWrt Barrier Breaker que tenia previamente, conectando por ssh, descargando el fichero .bin desde mi pc (192.168.0.100) a /tmp y luego ejecutando sysupgrade:
# cd /tmp
# wget http://192.168.0.100/lede-lantiq-xway_legacy-ARV4518PWR01A-squashfs-sysupgrade.bin
# sysupgrade -v lede-lantiq-xway_legacy-ARV4518PWR01A-squashfs-sysupgrade.bin
Una vez hecho el sysupgrade el router reinicia manteniendo la configuracion IP y de telnet/ssh que tenia antes. Por tanto para configurarlo conectamos por telnet o ssh y procedemos a editar los ficheros de configuración tal como describimos a partir de ahora.

Empezamos con la configuracion de tarjetas de red, la red ethernet con ip fija 192.168.1.1 en la red 192.168.1.X. La red wifi recibirá su IP por dhcp del otro router wifi al que nos conectemos (que suponemos en la red 192.168.0.X):
# cat /etc/config/network
config interface 'loopback'
    option ifname 'lo'
    option proto 'static'
    option ipaddr '127.0.0.1'
    option netmask '255.0.0.0'

config interface 'lan'
    option ifname 'eth0'
    option type 'bridge'
        option proto 'static'
    option ipaddr '192.168.1.1'
    option netmask '255.255.255.0'

config 'interface' 'wan'
        option 'proto'      'dhcp'
Aquí configuramos la tarjeta wifi como cliente de la red wifi remota (clave WPA2/PSK) :
# cat /etc/config/wireless
config wifi-device  radio0
    option type     mac80211
    option channel  11
    option macaddr    00:13:fe:e9:2a:5a
    option hwmode    11g

    # REMOVE THIS LINE TO ENABLE WIFI:
    option disabled 0

config wifi-iface
    option device 'radio0'
    option mode 'sta'
    option network 'wan'
    option ssid 'MI_WIFI'
    option encryption 'psk2'
    option key 'MI_PASSWORD'
 
Configuración del servidor DHCP para que reparta IP por la red ethernet (lan). Aunque es aconsejable poner IP fijas de forma manual en los dispositivos de esa red, para que tengan su dirección nada mas arrancar y agilizar la conexión:
# cat /etc/config/dhcp
config dnsmasq
    option domainneeded '1'
    option boguspriv '1'
    option filterwin2k '0'
    option localise_queries '1'
    option rebind_protection '1'
    option rebind_localhost '1'
    option local '/lan/'
    option domain 'lan'
    option expandhosts '1'
    option nonegcache '0'
    option authoritative '1'
    option readethers '1'
    option leasefile '/tmp/dhcp.leases'
    option resolvfile '/tmp/resolv.conf.auto'

config dhcp 'lan'
    option interface 'lan'
    option start '100'
    option limit '150'
    option leasetime '12h'
    option ignore '0'
    option dhcpv6 'server'
    option ra 'server'

config dhcp 'wan'
    option interface 'wan'
    option ignore '1'

config odhcpd 'odhcpd'
    option maindhcp '0'
    option leasefile '/tmp/hosts/odhcpd'
    option leasetrigger '/usr/sbin/odhcpd-update'

Configuramos el servicio ssh con dos instancias para que se permita el acceso remoto a router desde ambas redes. Por la wifi se entrará por el puerto 22 y por la ethernet por el puerto 443:
# cat /etc/config/dropbear
config dropbear
    option PasswordAuth 'on'
    option RootPasswordAuth 'on'
    option Port         '22'
    option Interface    'wan'

config dropbear
        option PasswordAuth 'on'
        option RootPasswordAuth 'on'
        option Port         '443'
        option Interface    'lan'
En el fichero firewall definimos el NAT entre lan (ethernet) y wan (wifi):
# cat /etc/config/firewall
config defaults
    option syn_flood    1
    option input        ACCEPT
    option output        ACCEPT
    option forward        REJECT
# Uncomment this line to disable ipv6 rules
#    option disable_ipv6    1

config zone
    option name        lan
    option network        'lan'
    option input        ACCEPT
    option output        ACCEPT
    option forward          REJECT       

config zone
    option name        wan
    option network        'wan'
    option input        ACCEPT
    option output        ACCEPT
    option forward        ACCEPT
    option masq        1
    option mtu_fix        1

config forwarding
    option src        lan
    option dest        wan

# We need to accept udp packets on port 68,
# see https://dev.openwrt.org/ticket/4108
config rule
    option name        Allow-DHCP-Renew
    option src        wan
    option proto        udp
    option dest_port    68
    option target        ACCEPT
    option family        ipv4

# Allow IPv4 ping
config rule
    option name        Allow-Ping
    option src        wan
    option proto        icmp
    option icmp_type    echo-request
    option family        ipv4
    option target        ACCEPT

# Allow DHCPv6 replies
# see https://dev.openwrt.org/ticket/10381
config rule
    option name        Allow-DHCPv6
    option src        wan
    option proto        udp
    option src_ip        fe80::/10
    option src_port        547
    option dest_ip        fe80::/10
    option dest_port    546
    option family        ipv6
    option target        ACCEPT

# Allow essential incoming IPv6 ICMP traffic
config rule
    option name        Allow-ICMPv6-Input
    option src        wan
    option proto    icmp
    list icmp_type        echo-request
    list icmp_type        echo-reply
    list icmp_type        destination-unreachable
    list icmp_type        packet-too-big
    list icmp_type        time-exceeded
    list icmp_type        bad-header
    list icmp_type        unknown-header-type
    list icmp_type        router-solicitation
    list icmp_type        neighbour-solicitation
    list icmp_type        router-advertisement
    list icmp_type        neighbour-advertisement
    option limit        1000/sec
    option family        ipv6
    option target        ACCEPT

# Allow essential forwarded IPv6 ICMP traffic
config rule
    option name        Allow-ICMPv6-Forward
    option src        wan
    option dest        *
    option proto        icmp
    list icmp_type        echo-request
    list icmp_type        echo-reply
    list icmp_type        destination-unreachable
    list icmp_type        packet-too-big
    list icmp_type        time-exceeded
    list icmp_type        bad-header
    list icmp_type        unknown-header-type
    option limit        1000/sec
    option family        ipv6
    option target        ACCEPT

# include a file with users custom iptables rules
config include
    option path /etc/firewall.user

Y ya está, con esto conectamos remotamente a la wifi, enchufamos la Raspberry Pi al router y podemos hacer cosas interesantes, como ver películas con nuestro Kodi/Osmc o controlar el riego del huerto, como hace mi hermano.

See you soon.

domingo, 19 de febrero de 2017

Flash y libros digitales de las editoriales

Bueno, mis problemas con Flash han sido debido a los libros digitales que mandan las editoriales, en este caso de la editorial Oxford. Muchas editoriales siguen viviendo de las rentas con contenidos hechos en Flash, como si no se hubiesen enterado de que:


Lo malo del problema no es solo que dependan de una tecnología viejuna cada vez peor soportada como Flash, que lleva el camino de Java. Lo realmente malo es que dependan de una versión concreta del plugin, de tal forma que las nuevas actualizaciones (muchas de ellas de seguridad) del mismo hagan fallar el libro digital y para hacerlo funcionar nos obligue a tener en el sistema un Flash obsoleto.

Mi problema era con el libro "Oxford University Press/Key to Bachillerato iPack": necesita el Flash 11.2.202.394, cuando ahora vamos por la versión 24. Al abrir el libro directamente se quejaba de que no estaba instalado su Flash e invitaba a ponerlo ofreciendo un enlace. Descargar la versión de 32 o 64 bits es sencillo desde este enlace.

Claro que si lo descargamos, cogemos el libflashplayer.so de dentro y lo ponemos en la ruta /usr/lib/mozilla/plugins no habrá problemas: quedamos todo el sistema con un Flash antiguo, pero el Oxford iPack funcionará. Cuando haya alguna actualización no controlada del plugin habrá que volver a meter nuestro libflashplayer.so viejuno y así iremos tirando, pero tendremos páginas web modernas que no se vean o fallen con el Flash antiguo y las consiguientes quejas de los usuarios.

Esto no me satisfacía, así que me puse a investigar. Primeramente, me doy cuenta de que la aplicación de Oxford usa la tecnología de Mozilla llamada XUL, que se usaba para construir plugins para el navegador y, esta faceta no es muy conocida, para crear aplicaciones que son de escritorio pero internamente se basan en tecnologías Web, usando HTML, plugins, DOM, Javascript y una serie de ficheros XML. La idea es correr una aplicación web sin usar el navegador, como aplicación de escritorio.

Bueno, pues me dije: si Oxford iPack usa XULRunner (y efectivamente, en sus directorios se encuentra un libxul.so privado), internamente se basa en Mozilla-Firefox y por tanto buscará los plugins en la misma secuencia en que los busca el navegador. Esto es:
  • Directorio indicado por la variable de entorno MOZ_PLUGIN_PATH.
  • Directorio ~/.mozilla/plugins.
  • /usr/lib/mozilla/plugins, o quizá /usr/lib64/mozilla/plugins.
  • [Directorio de Perfil]/plugins, siendo normalmente el directorio de perfil ~/.mozilla/firefox/xxxx.default/.
Entonces, si antes de abrir la aplicación de Oxford hago que MOZ_PLUGIN_PATH apunte a un directorio donde está el libflashplayer.so que necesita para funcionar, esto no interferirá con el plugin instalado a nivel de sistema en /usr/lib/mozilla/plugins. Pues ciertamente es así, mi aplicación de Oxford se abría con esta ruta:
$ /home/compartido/Ingles/Oxford\ University\ Press/Key\ to\ Bachillerato\ iPack\ 1/linux/oup
siendo el ejecutable "oup" el que lanza la aplicacion XUL. Si antes de ejecutarla hago:
$ cp libflasplayer.so /home/compartido/Ingles/Oxford\ University\ Press/Key\ to\ Bachillerato\ iPack\ 1/linux/
$ export MOZ_PLUGIN_PATH=/home/compartido/Ingles/Oxford\ University\ Press/Key\ to\ Bachillerato\ iPack\ 1/linux/
$ /home/compartido/Ingles/Oxford\ University\ Press/Key\ to\ Bachillerato\ iPack\ 1/linux/oup
Ahora la aplicacion de Oxford usará la versión de libflashplayer.so que hemos metido previamente en el mismo directorio (será la 11.2, claro) y dejará tranquila la versión que hay en /urs/lib/mozilla/plugins, que seguirá siendo la 24.

Para hacer esto transparente al usuario simplemente hay que crear un script con las 2 últimas líneas y desde el fichero .desktop del escritorio que lanza el programa invocar a ese script en lugar de a "oup" directamente, modificando su línea "Exec=".

Et voilá, ya tenemos para aguantar una temporada más a Oxford y sus Flash obsoletos.

Nota: es importante que el libflashplayer.so que pongamos coincida en arquitectura con el ejecutable oup que usemos. Ambos deben ser de 32 bits o de 64 bits, no se pueden mezclar. Para saber de que arquitectura son usamos el comando "file *archivo*".


Otro problema que me relatan mis compañeros también con Oxford es que hay además libros que si aceptan el Flash 24, pero cuando van a reproducir los vídeos se queda la ventana en blanco. Parece ser que es un problema de permisos de Flash al acceder a directorios locales y se soluciona:
  • Buscando en un navegador "panel de control Adobe Flash" y pinchando el primer resultado. Nos llevará seguramente a esta página.
  • Pinchamos en "Parámetros de seguridad global".
  • Marcamos "Permitir siempre".
  • Pinchamos en Editar--> Agregar--> buscar carpeta. Le damos la ruta donde esta instalado el iPack y marcamos la carpeta "Oxford University Press" (En mi caso la ruta es "/home/compartido/Ingles/Oxford\ University\ Press").
  • Aceptamos y probamos.
Bueno, creo que con esto se resuelve la casuística que nos ha aparecido. Seguiremos informando.

viernes, 17 de febrero de 2017

Aparente bloqueo en el arranque de Ubuntu.

Es increíble, me ha pasado una vez más. Había clonado un equipo con una nueva imagen y en el arranque, tras unos cuantos mensajes, se paraba con la pantalla en negro sin mostrar ni siquiera la pantalla de login. Lo último que veía era:
Unable to determine destination address
Unable to determine destination address
Unable to determine destination address
Y, tonto de mí, otra vez he pensado que esos mensajes estaban relacionados con el "bloqueo". Nada más lejos de la realidad, esos mensajes son lo último que vemos antes de que empiece a fallar, pero la causa es normalmente otra. Como usualmente tenemos habilitado el arranque para que sea en modo gráfico y silencioso nos perdemos toda la ristra de mensajes de inicio, incluidos los que nos informan de los errores que paran el proceso de inicio.

Lo verdaderamente gracioso es que eso lo hacemos para intentar conseguir un arranque mas bonito y agradable para el usuario, con alguna animación o similar, pero la mayoría de las veces el resultado es una pantalla negra interminable hasta que sale de pronto la petición de credenciales de login. Intuyo que esa pantalla negra tiene algo que ver con el intento no conseguido de activar potentes modos gráficos durante el inicio y que el modo VESA 800x600 para mostrar una triste animación de inicio está infravalorado, motivo por el cual sólo vemos una pantalla negra. Como decía mi padre, "por querer alcanzar la gloria nos quedamos sin cielo".

Volvamos al hilo de la cuestión. ¿Cómo mostrar qué está pasando detrás del telón?. Pues editando el GRUB en el arranque:

1) Si vemos el GRUB al inicio, normalmente pulsando ESC se nos muestra.

2) Una vez en el menú, vamos a la opción que carga por defecto (normalmente la primera) y pulsamos "E" para editarla.

3) Nos salen todas las opciones y parámetros, entre los cuales estará seguramente "quiet splash". Esos dos parámetros son los culpables de que no veamos nada. Nos movemos hasta ellos con el cursor y los borramos. Puede que haya algún "vga=XX" que también interfiera, pero no lo tocaremos a no ser que esto funcione.

4) Pulsamos F10 para realizar el arranque con el GRUB modificado. Este cambio no es permanente, solo vale para el arranque actual.

Ahora sí se muestra todo el proceso y podemos ver donde se para. En mi caso era en el montaje de varias particiones que no había clonado bien, con lo cual simplemente reclonando esas particiones se ha solucionado el problema. Los mensajes mencionados antes no tenían nada que ver.

Espero que esto no me vuelva a suceder.

martes, 14 de febrero de 2017

Obtener la versión de un fichero libflashplayer.so

Estos días he estado liado con Flash Player para hacer funcionar un libro digital de Oxford, de esos que necesitan una versión concreta en una ubicación concreta para tirar sin problemas.

Llega un momento en que tienes varios libflashplayer.so de distintos orígenes dando vueltas y no sabes la versión y arquitectura de cada cual. Podemos meterlos uno a uno en el directorio /usr/lib/mozilla/plugins o similar, abrir firefox e irnos a about:plugins para saber la versión, pero es un poco tedioso.

Recordé que en Debian había un script llamado /usr/sbin/update-flashplugin-nonfree, que actualizaba libflashplayer.so si la versión de la web de Adobe era superior a la instalada. Lo he localizado en packages.debian.org y he podido localizar dentro el fragmento de código que extrae la versión de Adobe Flash del fichero .so:
# strings libflashplayer.so 2> /dev/null | grep LNX | cut -d ' ' -f 2 | sed -e "s/,/./g"
24.0.0.194
Sencillo: con "strings" se sacan todos los strings (cadenas ASCII) legibles contenidos en el fichero .so, luego buscamos una línea con el trigrama LNX y detrás está el número de versión de Flash.
Por último, ¿cómo sabemos si es de 64 o 32 bits?. Esta es más sencilla si cabe:
# file libflashplayer.so 
ELF 32-bit LSB.... | ELF 64-bit LSB....
Aprovechando el Grammy a Megadeth pongamos un vídeo suyo para rematar:



Venga, vale, no troleemos al buenazo de Mustaine:

viernes, 3 de febrero de 2017

Cerrar sesiones inactivas de usuario en Linux y en Windows.

Un problema frecuente que tenemos con los ordenadores compartidos es el de usuarios que se dejan su sesión abierta al alcance de todo el mundo. Además del evidente problema de seguridad esto lleva a malentendidos de todo tipo, ya que si se sienta otro usuario despistado y se pone a trabajar en la sesión de anterior, manipulando y guardando ficheros, cuando se va al final no sabemos fácilmente en que sesión ha trabajado y la pregunta "¿dónde están mis datos?" irrumpirá en nuestra tranquilidad de sysadmin.

Lo ideal es colocar un temporizador que cierre las sesiones inactivas pasado un tiempo, mitigando en menor o mayor medida el problema descrito. Veremos soluciones para nuestros clientes Windows y Linux.

1. Soluciones para Linux.

A lo largo de los años hemos encontrado varias soluciones al problema de cerrar la sesión cuando ha pasado un tiempo sin actividad. Repasemos algunas de ellas:

  • Evanescent: es un software específico para esta tarea. Por desgracia parece abandonado y no sabemos si funcionará ahora. Código para descargar y capturas de pantalla.
  • Creando un protector de pantalla ad-hoc para salir de sesión, mediante un script y seleccionando dicho salvapantallas en la lista que podemos ver con xscreen-saver-demo o la utilidad que tengamos para seleccionar screensaver. Aquí cuentan como sería. Al ser un protector de pantalla "falso" simplemente hay que configurar el tiempo y cuando le toque saltar lo que hará será cerrar la sesión en lugar de hacer dibujitos en la pantalla.
  • Usando xprintidle. Es una utilidad que muestra el tiempo que lleva una sesión ociosa, sin interacción del usuario. Combinado con idlekiller tendremos un programa que se ejecuta como un servicio y cierra sesiones que lleven más de cierto tiempo inactivas. Otra opción es usarlo con un script arrancado desde crontab, como muestran aquí o aquí.
  • Usando xautolock. Este método me lo ha revelado mi compañero Camilo, ¡gracias!. xautolock es una utilidad que se arranca en el inicio de sesión, desde /etc/xdg/autostart/xxxx.desktop y permite configurar un programa a ejecutar cuando la sesión del usuario lleve un tiempo ociosa. En nuestro caso, el programa a ejecutar ser xfce4-session-logout (evidentemente cambiará según el escritorio usado). Este es el fichero .desktop que Camilo usa, que lanza el cierre de sesión a los 55 minutos de inactividad:
    # cat /etc/xdg/autostart/xautolock.desktop
    [Desktop Entry]
    Type=Application
    Name=xautolock
    Comment=Lock the screen after a certain time automagically
    Exec=xautolock -time 55 -locker "xfce4-session-logout"
    OnlyShowIn=XFCE;
    NoDisplay=true
    

Y con esto acaban los sistemas en Linux, como vemos hay de sobra donde elegir.

2. Solución para Windows.

En el caso de los Windows la cosa se complica y se hace mas necesaria ya que por motivos diversos tengo habilitado el cambio rápido de usuario. Esto hace que un usuario pueda abrir sesión sin cerrar la del anterior, de tal forma que al final del día hay una pila de sesiones abiertas chupando recursos. Da igual que digas a los usuarios que cierren sesión abierta antes de entrar con la suya. No lo hacen. Por eso es importante cerrarlas de forma forzada si no registran actividad.

La forma mas sencilla de hacerlo que he podido encontrar es usando la utilidad gratuita IdleLogoff. Sencillamente le dices un tiempo en segundos y una acción (logoff, lock o shutdown) y al pasar dentro de las sesión esos segundos inactivos se ejecuta dicha acción.

La segunda parte es meterla en un script que lo lance, por ejemplo a los 1800 segundos. Una vez descargado el ejecutable y puesto en c:\windows creamos también allí el fichero .bat:
c:\> type c:\windows\IdleLogoff.bat
Echo off
start c:\Windows\IdleLogoff.exe 1800 logoff 
La tercera y última parte es la más peliaguda: que se inicie una instancia del IdleLogoff con cada usuario que inicie sesión en la máquina, para poder cerrarlas si se quedan ociosas en primer o segundo plano.

La primera proposición es utilizar GPO (políticas de grupo), como cuentan aquí: se crea una GPO que ejecuta el script IdleLogoff.bat en el inicio de sesión de cada usuario. El problema que tengo con esto es que en nuestras redes no tenemos un Windows Server que nos distribuya las GPO. Desde arriba nos llenaron de Windows pero se les olvidó ese pequeño detalle: mejor tener un administrador informático apretando tuercas Windows a Windows que un servidor que los administre centralizadamente. Ya avisamos de ello.

Otra opción es definir una tarea programada que ejecute el script al inicio de sesión de cada usuario o quizá algo parecido a como se cuenta aquí. El problema que he encontrado con esto es que las tareas programadas asociadas a determinados eventos no van muy bien con Windows 8 y/i Windows 10. Si no fallan por una cosa fallan por otra, por lo que no son viables debido a fallos en su implementación. Con la úĺtima edición de Windows 10, por poner un ejemplo, han dejado de funcionar los eventos vinculados al establecimiento de conexión de la interfaz de red.

¿Qué opción nos queda a los pobres?. Pues la carpeta "Inicio" del Menú de Inicio de Windows de siempre. Ahora esa carpeta está en la ruta:
 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
antes estaba en c:\documents and settings\all users\... y luego en c:\users\public\..., Microsoft la mueve de vez en cuando para aumentar la entropía del Universo (y es que en Microsoft se lleva la Segunda Ley de la Termodinámica a rajatabla). Allí ponemos nuestro script IdleLogoff.bat para que se ejecute en el inicio de sesión de todos los usuarios. Como el /etc/xdg/autostart de toda la vida de Linux. ¿Funciona?. Si: cuando hay varios usuarios en el sistema hay un idlelogoff.exe por usuario y cuando expira su tiempo de inactividad la sesión desaparece y libera recursos. Misión cumplida.

Bueno, pues he dedicado un post conjunto a Windows y Linux. Para que luego no digáis que los linuxeros tenemos prejuicios cognitivos.