lunes, 24 de marzo de 2008

Configurando protocolo ed2k en Opera con MLDonkey

Vamos a ver como configurar Opera corriendo sobre Linux para que cuando clickeemos sobre una URL de la forma ed2k:// el download correspondiente se agregue a la núcleo MLDonkey que está corriendo en el sistema (o en algún sistema remoto).

Para esto cerramos Opera y editamos el archivo $HOME/.opera/opera6.ini agregando bajo la sección [User Prefs] la línea TrustedExternalURLProtocols=ed2k. Si esta entrada ya existe es posible agregar protocolos adicionales separando los identificadores por comas simples. Guardamos los cambios, cerramos el archivo y reabrimos Opera.

Luego vamos a Tools -> Preferences, luego el tab Advanced y por último la sección Programs. Ahí clickeamos el botón 'Add...', escribimos 'ed2k' en el campo Protocol, seleccionamos Open with other application y escribimos la ruta al siguiente script, que tenemos que guardar a disco y dar permisos de ejecución:

#!/bin/bash

USER='admin'        # u otro usuario en caso de haberlo configurado
PASS='password'     # el password de la cuenta
HOST='localhost'    # el host donde corre el núcleo MLDonkey
PORT='4000'         # el puerto en el que corre

STDOUT=`( sleep 0.1 ;
          echo "auth $USER $PASS" ;
          sleep 0.1 ; echo "dllink $1" ;
          sleep 0.1 ;
          echo "q") | telnet $HOST $PORT 2>&1`

if [[ "$STDOUT" =~ 'Unable to connect to remote host' ]]; then
    kdialog --error "Unable to connect to MLDonkey server"
elif [[ "$STDOUT" =~ 'Unable to match URL' ]]; then
    kdialog --error "Unable to match URL:\n$1"
elif [[ "$STDOUT" =~ 'Added link' ]]; then
    kdialog --msgbox "Added link:\n$1"
else
    kdialog --error "Error:\n$STDOUT"
fi



El script utiliza telnet para acceder al núcleo (habilitado por defecto en MLDonkey), por lo que es bueno verificar que que esta conexión esté funcionando (telnet localhost 4000). En caso de estar utilizando la cuenta admin sin password, el primer sleep y el auth no serían necesarios. Como se puede ver el script concatena la salida estándar de un conjunto de comandos y la conecta a la entrada estándar de una llamada a telnet, almacenando la salida estándar de este último en una variable. Luego examina la salida almacenada y utiliza kdialog para generar un mensaje de éxito o error, según corresponda.

Ahora con simplemente clickear en un link con url de la forma ed2k://... la descarga se agrega al MLDonkey e inicia automáticamente.

martes, 11 de marzo de 2008

Utilizando xinetd para levantar el túnel SSL 'on demand'

Como vimos en la entrada anterior, una de las opciones para evitarnos crear el túnel SSL a mano cada vez que queremos arrancar KNode es utilizar xinetd para que escuche el puerto local al que se conecta KNode, y cuando detecta una conexión entrante (proveniente de KNode) forkee un stunnel para atenderla.

Para hacer esto, creamos el archivo /etc/xinet.d/knode-ssl con el siguiente contenido:

# Begin /etc/xinetd.d/knode-ssl
# default: on
# SSL Tunnel para KNode

service knode-ssl
{
    port = PUERTO_LOCAL
    socket_type = stream
    protocol = tcp
    wait = no
    disable = no
    user = root
    only_from = 127.0.0.1
    server = /usr/bin/stunnel
    server_args = -c -r HOST_REMOTO:PUERTO_REMOTO
}

# End /etc/xinetd.d/knode-ssl



Con esto indicamos a xinetd el proceso a forkear (y los parámetros) para atender la conexión entrante, que queremos que en principio sólo sea originada en la propia PC. Vale notar que a diferencia que con la ejecución manual del túnel, no se utiliza el parámetro -d PUERTO_LOCAL dado que la conexión ya fue aceptada por xinetd, y cuando stunnel se ejecute pasará directamente a atenderla.

Luego debemos agregar la siguiente línea al final de /etc/services, especificando el mapeo entre el identificador utilizado en la configuración de xinetd y el puerto y tipo de protocolo del servicio de internet a configurar:

knode-ssl LOCAL_PORT/tcp



Por último le enviamos una señal a xinetd para que recargue el archivo de configuración mediante:

sudo killall -HUP xinetd



Cualquier salida de error que esto pueda provocar (por ejemplo por un mal formato del archivo knode-ssl) se puede ver en /var/log/syslog.

De esta manera es suficiente con ejecutar KNode para lograr una conexión SSL con el servidor de noticias utilizado.

Salú!

Utilizando stunnel para dar soporte SSL a KNode

Rescatando a brain_back-up del abandono, hoy vamos a ver como hacer para que el lector de noticias KNode de KDE3 pueda conectarse a servidores configurados para utilizar conexiones SSL. Esta opción está presente en muchos otros lectores de noticias, pero no ha aparecido en KNode sino hasta la versión proporcionada con KDE4.

La necesidad de SSL frente a conexiones TCP normales surge para evitar que la información de autorización (para los servidores que la requieren) viaje sin encriptar a través de internet. La herramienta auxiliar que vamos a utilizar es stunnel, que nos va a permitir crear un túnel SSL entre nuestra máquina y el servidor remoto.

La idea es poner a stunnel a escuchar conexiones en un PUERTO_LOCAL de nuestra PC para hacer que las encripte y redirija hacia un HOST_REMOTO y un PUERTO_REMOTO. Al correr KNode, vamos configurarlo de modo que en lugar de conectarse al servidor remoto, se conecte a localhost:PUERTO_LOCAL.

Para establecer el túnel, llamamos:

sudo stunnel -c -d PUERTO_LOCAL -r HOST_REMOTO:PUERTO_REMOTO -f



La opción -c indica que es el servidor remoto el que pretende utilizar SSL. La opción -f evita que stunnel libere la terminal y ejecute como demonio, con el fin de desplegar la información de log en pantalla y poder cerrar el túnel con un simple Ctrl + C.

Tras hacer esto, vamos a ver una salida como la siguiente indicando que el túnel se creó con éxito:

2008.03.11 11:33:25 LOG5[9199:3082761904]: Using 'HOST_REMOTO.PUERTO_REMOTO' as tcpwrapper service name
2008.03.11 11:33:25 LOG5[9199:3082761904]: stunnel 3.26 on i486-pc-linux-gnu PTHREAD+LIBWRAP with OpenSSL 0.9.8e 23 Feb 2007
2008.03.11 11:33:25 LOG5[9199:3082761904]: FD_SETSIZE=1024, file ulimit=1024 -> 500 clients allowed



Luego abrimos KNode y vemos como ahora puede conectarse sin problemas.

Hacer esto cada vez que queremos leer noticias puede ser medio tedioso, por lo que podemos por ejemplo utilizar un script para que cree el túnel, ejecute KNode y luego lo destruya al terminar. Para esto puede ser útil utilizar sudoers, para evitar tener que introducir el password cada vez que queremos iniciar KNode.
Otra opción es iniciar el túnel como un servicio, agregando un script a /etc/init.d para que abra el túnel cuando se inicia el sistema y lo cierre al finalizar.
La última y más eficiente es configurar xinetd para que escuche el PUERTO_LOCAL y al recibir una conexión entrante forkee un stunnel para que la atienda. De esta manera cuando la conexión es finalizada, stunnel termina e xinetd vuelve a escuchar el puerto.

Esto ya queda medio obsoleto con la nueva versión de KNode de KDE4, pero es bueno saber que existe y entender como funciona por si lo volvemos a necesitar en otro caso. Saludos!

domingo, 16 de septiembre de 2007

Autologin con cuenta root en sistema de consola

Resulta que necesitaba intentar re-compilar el kernel con unos pocos cambios para una materia de la facultad. Para no arriesgar mi instalación de Kubuntu cree una máquina virtual con VMware e instalé un Ubuntu Edgy que venía con Kernel 2.6.17-10, cercano al que teníamos que utilizar. Hice una instalación sin entorno gráfico, ni KDE ni Gnome, con la opción "Install a command-line system" utilizando el LiveCD de Edgy.

Después de reiniciar la máquina virtual setecientas veces cada vez que recompilaba e instalaba el nuevo kernel, me aburrí de loguearme como el usuario por defecto y tener que usar sudo para ejecutar cada comando privilegiado entrando el password cada vez. Así que me puse a investigar un poco.

Los pasos necesarios para activar la cuenta root (desactivada por defecto en *ubuntu), eliminar el usuario normal y hacer que se loguee con la cuenta de administrador por defecto son los siguientes:

Activamos la cuenta root para que se pueda hacer login con ella:

sudo passwd root



Se nos pide un nuevo password para esta cuenta, ya que el que usábamos era para la cuenta de usuario normal. Luego eliminamos la cuenta de usuario creada a la hora de la instalación junto con su directorio home (opción -r):

userdel -r nombre_usuario



Ahora vamos a necesitar mingetty, en lugar de getty, ya que éste permite hacer un login automático, evitando introducir el password. Editamos el archivo /etc/apt/sources.list (con sudo) descomentando los repositorios universe:

deb http://uy.archive.ubuntu.com/ubuntu/ edgy universe
deb-src http://uy.archive.ubuntu.com/ubuntu/ edgy universe



Y hacemos:

sudo apt-get update
sudo apt-get install mingetty



Con mingetty instalado, sólo nos queda editar el archivo /etc/event.d/tty1 (en el caso de que queramos que root se autologuee en esta terminal, aka Ctrl + Alt + F1), comentando la siguiente línea y agregando otra:

# respawn /sbin/getty 38400 tty1
respawn /sbin/mingetty --autologin root tty1



La proxima vez que reiniciemos, tendremos la sesión del usuario root ya iniciada.

Bueno, como verán cambié un poco la modalidad del blog con esta entrada, sin limitarme a escribir solamente sobre las cosas que entiendo... ;) Por otro lado se me hacía un estrés escribir ya que siempre intentaba explicar (y entender) cada paso que daba... Con suerte ahora pueden esperar entradas más seguido... :)

Saludos!

viernes, 14 de septiembre de 2007

Recuperando archivos corruptos

Muchas veces tenemos algún archivo en CD o DVD que no podemos copiar a disco porque cierta parte del mismo está corrupta. Tanto desde el escritorio en KDE como utilizando el comand cp en la consola el archivo se copia hasta el bloque en que no se puede leer y el resto se descarta.

No siempre que haya un defecto en el archivo éste queda inusable... en el caso de AVIs, MP3 y seguramente muchos otros el defecto simplemente se verá o se oirá por un instante y la reproducción continuará sin mayores problemas.

En Windows existen varios programas (ninguno libre, que yo sepa) que pueden recuperar estos archivos, obviamente rellenando las zonas que no se puedan leer. Estos procesos son generalmente poco configurables y muchas veces demoran demasiado por lo que uno termina aburriéndose y cancelándolos.

Resulta que googleando un pocó encontré que esto se puede hacer muy fácilmente con la añeja herramienta dd de Linux. Es muy fácil ajustar también el grado de recuperación/velocidad que se quiere usar.

El comando necesario es:

dd bs=2K if=ruta_archivo_entrada of=ruta_archivo_salida conv=noerror,sync



La herramienta dd se utiliza generalmente para hacer copias de dispositivos completos o también secciones importantes de éstos (como el MBR en el disco duro). En este caso vamos a utilizarla para copiar archivos reales de un sistema de archivos a otro. En realidad en Linux no hay diferencia: tanto un dispositivo como un archivo real en disco son en fin archivos en nuestro filesystem.

Este comando va a leer y escribir bloques de 2K = 2048 bytes de datos (si no se especifica bs se utiliza el valor por defecto de 512 bytes) desde el archivo origen (if) hacia el archivo destino (of). Sin opciones adicionales la copia se detiene al encontrar un error de lectura y el archivo queda truncado. Utlizando las opción conv=noerror,sync en la llamada se hace que cuando dd encuentra un error de lectura en un bloque particular el resto del bloque se rellene con carácteres nulos. Utilizando un tamaño de bloque más grande la copia se hace más rápidamente pero cada vez que se encuentra un error en un bloque, el resto del éste es ignorado. Bloques más pequeños minimizan la pérdida de datos, pero hacer la copia con un tamaño de bloque menor consume más tiempo.

Siempre que ocurra un error de lectura se imprime el mensaje de error correspondiente en stderr, junto con el estado actual del proceso. Por ejemplo:

dd: reading `/media/cdrom0/Se7en.1995.DVDRip.XviD-FreeGuy-CD1.avi': Input/output error
358586+704 records in
359290+0 records out
735825920 bytes (736 MB) copied, 532.963 seconds, 1.4 MB/s



El valor para 'records in' es la cantidad de bloques completos leidos con éxito seguida de la cantidad de bloques con error de lectura. El valor para 'records out', como ya suponen, es la cantidad de bloques escritos completos escritos exitosamente seguida de la cantidad de bloques en los que ocurrió un error de escritura. Estas cantidades corresponden con el tamaño de bloque bs especificado en la llamada al comando, como es fácil comprobar con la cantidad de bytes copiados desplegada.

También es posible hacer que dd imprima el estado actual (siempre en la salida estandar de error) en cualquier momento enviándole la señal SIGUSR1, de la siguiente manera:

$ kill -USR1 PID_DEL_PROCESO



Esto es útil para tener una idea sobre el avance de la copia si no han ocurrido errores.

Saludos!

domingo, 9 de septiembre de 2007

Renombramiento masivo de archivos

Sería interesante poder hacer un Find and Replace sobre los nombres de los archivos contenidos en un directorio, tan fácilmente como se hace por ejemplo desde KWrite. Para esto, podemos usar el siguiente comando:

for file in *; do mv $file `echo $file | \
           sed 's/TEX_ORIG/TEX_REEMP/g'`; done;



Lo que hace es iterar sobre los nombres de los archivos que matchean * (que podría ser también algo como *.avi o cualquier otra extensión) y ejecutar por cada uno de ellos una llamada a mv, renombrando el archivo de nombre $file (archivo actual de la iteración) por el resultado de hacer un reemplazo sobre el texto que lo compone utilizando sed.

También es posible el uso de expresiones regulares en general para hacer el reemplazo. De esta manera se puede matchear algún trozo de texto particular de $file y utilizarlo para formar el nombre de archivo destino. Por ejemplo:

$ ls
1.pdf 2.pdf 3.pdf 4.pdf 5.pdf 6.pdf 7.pdf 8.pdf 9.pdf

$ for file in *.pdf; do mv $file `echo $file | \
           sed 's/\^([0-9]*\).pdf/archivo-\1.pdf/g'`; done;

$ ls
archivo-1.pdf archivo-3.pdf archivo-5.pdf archivo-7.pdf archivo-9.pdf
archivo-2.pdf archivo-4.pdf archivo-6.pdf archivo-8.pdf



En este caso estamos utilizando grupos, delimitándolos con \( y \). De esta manera los nombres de archivo que consistan en una tira de dígitos (que es almacenada en \1) seguida por '.pdf', van a ser renombrados a 'archivo-' + tira_de_dígitos + '.pdf'.

Nótese que si el texto en $file no matchea la expresión regular, se estaría intentando mover un archivo con igual destino y origen (sed no modifica el texto de entrada), lo que causaría que se despliegue algo como 'mv: `X.pdf' and `X.pdf' are the same file' en pantalla. De todas formas, esto no afecta al renombramiento del resto de los archivos.

jueves, 6 de septiembre de 2007

Correr comando como root sin autenticarse

Si tenemos algún comando con permiso de ejecución exclusivo para root que ejecutemos muy a menudo o que se ejecute de forma automática (ej.: un theme de Superkaramba), podemos hacer que no se nos pida autenticarnos cada vez que queramos utilizarlo.

Es el caso del script de la entrada anterior, que necesitaba ejecutarse como sudo script.sh ya que éste utiliza la herramienta apt-get con argumento upgrade, para la cual sólo el usuario root tiene permisos de ejecución.

El comando sudo en las distros Debian/*ubuntu nos permite ejecutar un comando como otro usuario del sistema, en particular root, según los permisos en /etc/sudoers. Para esto puede estar configurado que se nos pida autenticarnos (introducir el password de nuestro usuario). Por defecto, en *ubuntu al menos, nuestro usuario tiene permiso para ejecutar cualquier comando como si fueramos root, siempre y cuando nos autentiquemos. Por esto vale aclarar que cuando hacemos sudo comando y escribimos la contraseña, estamos utilizando la contraseña de nuestro usuario y no la del usuario root (el login de root está desactivado por defecto, y por lo tanto no tiene contraseña).

Así, procedemos a editar /etc/sudoers utilizando el comando visudo (sin argumentos, pero como root), el cual chequeará la validez del archivo una vez terminada la edición. En nuestro caso, nos interesa agregar la siguiente línea al final del archivo:

usuario ALL = NOPASSWD: /ruta/al/comando



Con ella permitimos al usuario usuario ejecutar en cualquier host (útil sólo para sistemas distribuidos), sin que se le pida autenticarse, el comando /ruta/al/comando.

Para ejecutar el comando, el cual tiene permisos de ejecución para root solamente, debemos llamarlo con sudo y especificando la ruta al comando exactamente como la escribimos en /etc/sudoers. O sea:

sudo /ruta/al/comando



De esta forma la contraseña no nos será pedida y la ejecución del comando se hará instantáneamente.