Como recuperar el password de root en GNU/Linux

Cuando has perdido el password de root de tu máquina GNU/Linux y no sabes como recuperarlo estas en problemas. Aquí tienes una pequeña guía sobre que puedes hacer para hacerte con el control de tu máquina.

En ella explico diversas métodos que podrías emplear. Como sabes muchas cosas pueden ir mal debido a las enormes posibilidades de configuración que ofrece este sistema operativo. No te desesperes si al emplear alguno no te funciona pasa al siguiente método. Si todo sigue sin funcionar escribe un comentario en esta entrada, quizás podamos ayudarte.

La forma más sencilla sería entrar en los gestores de arranque para forzar un arranque en modo single. Si empleas LILO bastaría con pulsar Ctrl-X y escribir en el prompt:

linux single

Si empleas GRUB generalmente sólo tendrás que pulsar “p” e introducir el password de GRUB si lo tienes configurado, sino evita este paso. Cuidado pues en algunas configuraciones debes primero pulsar ESC para que aparezca el menu de GRUB. Una vez en el menú debes buscar la linea con el kernel con el que quieras arrancar, selecciona esta linea y pulsar “e” para editarla. Al final de la linea que comienza por “kernel” introduce la palabra “single” y presiona ENTER para salir del modo de edición. De vuelta en el menú sólo debes arrancar con el kernel que acabas de modificar pulsando “b” (boot).

Atención: Es posible que tanto en LILO como en GRUB ya tengas una opción disponible para arrancar el sistema en modo single. Compruébalo antes de nada (modo rescue, single-user mode pueden ser sus nombres).

Ejemplo linea antes de editarla:

kernel /boot/vmlinuz-x.x.xx-x-xxx root=/dev/sda1 ro

Tras la edición

kernel /boot/vmlinuz-x.x.xx-x-xxx root=/dev/sda1 ro single

Si esto no te ha funcionado otro método sería descargarte alguna distro Live de GNU/linux

Debian Live
Knoppix

Arranca tu sistema con este sistema live. Posiblemente tengas que acceder a la Setup de la BIOS de tu equipo para cambiar la secuencia de arranque.

Después de arrancar el nuevo sistema accede a una terminal en modo root. Monta la partición de tu disco duro que contenga la carpeta /etc/

Por ejemplo si /etc se hallaba en la partición /dev/sda1 ejecuta:

# mount /dev/sda1 /mnt

accede al directorio donde has montado la partición

# cd /mnt

Verifica que aquí tienes tu sistema correctamente montado y con todo lo necesario y ejecuta chroot

# chroot /mnt

Ahora sólo tienes que ejecutar

# passwd

Y cambiar el password al que quieras

Si por cualquier motivo no puedes emplear chroot

Puedes directamente alterar los ficheros de passwords sin necesidad de chroot

vi /mnt/etc/passwd

o si empleas shadow passwords

vi /mnt/etc/shadow

En la entrada de root en el lugar donde aparece el password encriptado debes dejarlo vacío. Por ejemplo:

root:dhfuieb$5454I$$&$&6:14180:0:99999:7:::

Debería quedar así:

root::14180:0:99999:7:::

Arranca el sistema con normalidad, quitando el arranque live (CD,DVD, USB o lo que venga en el futuro) y cuando se te pida el password de root pulsa simplemente ENTER.

Si todo esto falla vuelve a arrancar con la distro live y monta ahora la partición donde tengas tu gestor de arranque /boot/ ahora ya es posible modificar los archivos de configuración de tu gestor de arranque GRUB o LILO para entrar en modo “single” antes de reiniciar el equipo. Busca la linea que comienza con kernel y añádele al final la palabra “single” de manera análoga a como lo hicimos antes a través del menú de GRUB

Como cambiar la zona horaria de mysql por conexión

Mysql tiene asociadas dos horas horarias, una es global y otra por conexión. Su valor por defecto coincide con la zona horaria del servidor donde mysql esté en ejecución. Esto se corresponde con el valor de timezone SYSTEM. Para poder saber el valor de zonas horarias en una conexión basta con lanzar esta consulta:

mysql> SELECT @@global.time_zone,@@session.time_zone,NOW();

La primera columna es el time_zone de nuestro servidor y el segundo el de nuestra conexión. La tercera columna de la fecha y hora actuales de acuerdo con el valor de timezone de nuestra conexión (si, la 2ª columna)

Para poder modificarla según el manual online de mysql basta con ejecutar:

mysql> SET time_zone = timezone;

Siendo timezone una cadena que se debe corresponder con una zona horaria instalada en nuestro sistema. Sin embargo si ejecutas esta consulta es muy probable que te de un error, diciendo que desconoce esta zona horaria.

Por ejemplo

mysql> SET time_zone = ‘UTC’;
1298 Unknown or incorrect time zone: ‘UTC’

Como es esto posible, ¿mysql no sabe nada sobre esta zona horaria universal?. En mi sistema GNU/Linux (Debian). Las zonas horarias están a modo de archivo (filosofía UNIX) en /usr/share/zoneinfo. Y de un rápido vistazo se puede ver que, como no, UTC es una de las zonas horarias definidas.

Esto es porque a pesar de lo que dice el manual de mysql debemos introducir la zonas horarias que hay instaladas en nuestro sistema en mysql. Para hacer esto tenemos que ir a una shell y ejecutar:

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

¡Además sería preciso ejecutar periódicamente esta instrucción pues las zonas horarias pueden sufrir modificaciones!

Después de hacer esto ya podriamos ejecutar

mysql> SET time_zone = ‘UTC’;
Query OK, 0 rows affected (0.00 sec)

Ahora si que podemos ejecutar

mysql> SELECT @@global.time_zone,@@session.time_zone,NOW()\G

*************************** 1. row ***************************

@@global.time_zone: SYSTEM

@@session.time_zone: UTC

NOW(): 2010-05-24 15:24:31

1 row in set (0.00 sec)

Y podemos comprobar que la hora se ha modificado con la zona horaria seleccionada. Recuerda que esto es por conexión o sea que cuando vuelvas a conectarte a tu servidor mysql verás nuevamente la hora de la zona horaria del sistema

Para cambiar esto y tener de manera global esta configuración de zona horaria habría que arrancar el servidor mysql con la opción –default_timezone=timezone_name de mysqld_safe.

El servidor mysql también almacena además de las dos zonas horarias que comentamos (global y por conexión) la zona horaria del servidor donde se aloja. Lo almacena en la variable system_time_zone. También puedes modificar esto con la opción –timezone=timezone_name de mysqld_safe o con la variable de entorno TZ antes de lanzar el servidor myql. O en el archivo de configuración de mysql introducir la siguiente linea:

default-time-zone=’timezone’

Ya en tiempo de ejecución puedes modificar la zona horaria global del servidor. Pero si reinicias el servidor perdería estos cambios. Basta ejecutar con el usuario root la siguiente consulta:

mysql> SET GLOBAL time_zone = timezone;

Instalar linux desde un USB

Hoy en día la instalación de una distro de linux a través de un USB con las BIOS actuales es bastante sencilla. Existen herramientas que te ayudan a hacerlo de manera automática o semi-automática como portable linux,live USB creator o unetbootin. Algunos de estos programas tiene versiones para windows. Existen tutoriales aquí y allá por internet con instrucciones de como hacer esta instalación. Por ejemplo el que nos encontramos en ubuntu sobre instalación a través de usb.

Para hacerlo de una manera más casera y controlada y sobre todo por si todos los método anteriores os han fallado probad esto. Es un ejemplo de una instalación de debian a través de usb (recordad que.. debian rules!):

Primero debes tener un sistema GNU/linux completamente funcional. Un live CD de knoppix es más que suficiente. Ahora basta con descargarte una imagen boot.img.gz, para arrancar tu usb. Puedes buscar otros arranques para otras versiones debian navegando en los mirros de debian, por ejemplo http://http.us.debian.org/debian/dists/

A continuación debes introducir tu USB (tiene que tener al menos 256 Mb de capacidad). Si tu kernel actual reconoce el dispositivo debes de buscar que nombre le ha asignado (tipo /dev/sda, /dev/sdb, /dev/sdc /dev/sdd etc). Usualmente empleando dmesg

$ dmesg | tail

o simplemente revisando la salida de mount (muchos sitemas actual montan automáticamente los discos usb en cuanto los conectas)

$ mount

Ahora debes grabar el arranque en tu usb ejecutando como root la siguiente instrucción (debes sustituir /dev/sdX por el nombre de dispositivo que acabas de encontrar)

# zcat boot.img.gz > /dev/sdX

Esto creará una nueva particion/estructura de tu usb. Es mejor que retires y lo vuelvas a insertar para que tu sistema sea capaz de reconocerla bien. Después de volver a insertarla (cuidado el nombre del dispositivo puedo haber cambiado, vuelve a utilizar dmesg o mount para averiguarlo).

Si no tienes el dispositivo montado hazlo ejecutando:

# mount /dev/sdX /mnt

El USB no tiene ahora número de partición, no es necesario montar /dev/sdX1 o /dev/sdX2. Basicamente el USB ahora no tiene particiones y se comporta como un disco.

Ahora sólo tienes que grabar una imagen iso de la distribución que quieras en el USB por ejemplo una de debian 😉

instalación en red de debian

Emplea la adecuada para tu arquitectura (i386 si no sabes de que estoy hablando)

Descargate la iso y grabala en el raiz del usb. Instrucciones completas:

# umount /dev/sdX
# mount /dev/sdX /mnt
# cp /mnt
# umount /dev/sdX

Ahora ya puedes retirar el usb. Reiniciar/enceder el equipo en donde quieras instalar tu nuevo linux. Arrancar la BIOS y configurandola para que inicia la secuencia de Boot con USB. Introducir tu USB. Y ejecutar de nuevo el arranque del equipo. El proceso de instalación que debes tener ahora en tu equipo es el mismo que el del CD de instalación.

nmap, herramienta de seguridad

Nmap es una aplicación que sirve para explorar y auditar una red. Nmap lanza paquetes IP a la red para averiguar que servidores están disponibles en la red, que servicios (aplicaciones y versión) están ofreciendo estos servidores, que sistema operativo ejecutan, que tipo de cortafuegos están utilizando y otras muchas características.

Nmap tiene una utilidad gráfica que facilitará la tarea para aquellos menos avezados en la línea de comandos, su nombre es zenmap.

nmap es gratuito y open source bajo licencia GNU GPL versión 2

sshfs, el sistema de ficheros ssh

Con la llegada de fuse (file system userspace), que nos permite crear completos sistemas de archivos a través de programas en el espacio de usuario estaba claro que muchos desarrolladores iban a sacar buen provecho de esta herramienta para crear utilidades realmente interesantes. Cosas como un repositorio de subversión, cvs, git o mercurial como sistema de archivos o sistemas de archivos ad-hoc por ejemplo. En fin FUSE ofrece muchas posibilidades. Aunque ciertamente muchas de estas aplicaciones parecen estar bastante verdes y no será por falta de ports a diferentes lenguajes porque FUSE está disponible para C, C++, Java, C#, Haskell, TCL, Python, Perl, Ruby, Lua, Erlang o incluso PHP.

Bueno, volviendo al tema en cuestión una de las aplicaciones más interesantes que emplean FUSE es SSHFS. Como su nombre indica se trata de acceder por ssh a un equipo remoto como si fuera un punto de montaje más dentro de nuestro sistema de ficheros local. Es realmente sencillo de instalar (está en las fuentes de debian: # apt-get install sshfs) y de configurar.

Una vez correctamente instalado ya deberíamos tener la aplicación sshfs en nuestro path, ahora basta con ejecutar (mejor como usuario sin privilegios)

$ sshfs hostname: mountpoint

A continuación se te preguntará el password de acceso para la máquina hostname (con el usuario igual al de la sesión actual). Si quieres especificar un usuario diferente utiliza la sintaxis [email protected] delante del nombre de host:

sshfs [[email protected]]host:[dir] mountpoint [options]

Por ejemplo:

$ sshfs [email protected] /mnt /

$ sshfs -h

o

$ man sshf

Te da toda la información que necesitas sobre las opciones disponibles.

Para desmontar el sistema de archivos basta con ejecutar

$ fusermount -u mountpoint

Puedes descargar sshfs en sourceforge y también fuse.

Para más información esta es la página principal de sshfs

Redis, un nuevo modelo de base de datos ligero

Redis es una base de datos que asocia a una clave un determinado valor. Es similar a memcache pero con un conjunto de datos persistente (no volátiles).

Para ser lo más rápida posible y a la vez no volátil redis tiene todo el conjunto de datos en memoria y de vez en cuando o cuando el número de registros cambiados llega a cierto valor estos son escritos asincronamente en disco. Podrían perderse un pequeño número de valores que es aceptable para la mayoría de las aplicaciones pero es tan rápido como una base de datos en memoria.

Redis está escrito en ANSI C y funciona en la mayoría de sistemas POSIX como Linux, BSD, Mac OS X. Redis es software libre bajo licencia BSD.

Empleando git y subversion

Emplear dos sistemas de control de versiones parece algo fuera de lugar a la hora de llevar un proyecto. Sin embargo muchas pueden ser las causas en las que emplear subversion y git puede ser muy provechoso. Por ejemplo en el caso de estos dos escenarios el empleo de ambos sistemas de versionado esta justificado:

– Repositorio central con subversion y posibilidad de trabajar offline con git en máquina local. Cuando el desarrollador vuelva a estar online puede comitear los cambios al repositorio central de subversion. Con tu copia de trabajo puedes trabajar offline puedes decir. Si pero no tienes ninguna de las capacidades de un control de versiones disponible.

– Repositorio central con subversion donde no se desea aumentar el número de ramas. Los desarrolladores pueden hacerse con el código en git y hacer ramas y otros repositorios clonados mientras dure el desarrollo de una característica específica luego se reúne el código y se comitea a subversión.

Veamos como puedes mezclar lo mejor de los dos mundos.

Para poder empezar debemos tener instalado subversion git y git-svn. En distros tipos debian/ubuntu podemos ejecutar:

$ sudo apt-get install subversion git git-svn

Para conocer un poco de subversion sigue la serie de artículos sobre subversion.

Para conocer un poco de git visita este tutorial introductorio sobre git

Ok pues partimos de que tenemos la rama principal de desarrollo (trunk) con un repositorio central subversion en esta url

http://svn.midominio.com/miproyecto/trunk

creamos un directorio para nuestra copia de trabajo y entramos en ella

$ mkdir working-copy
$ cd working-copy

A continuación para inicializar el repositorio git ejecutamos:

$ git-svn init http://svn.midominio.com/miproyecto/trunk

Para traernos el código de la revisión HEAD:

$ git-svn fetch -rHEAD

Trabajamos con normalidad con git y comiteamos los cambios primero en este repositorio:

$ git commit -m “Cambios en git”

Si queremos actualizar el repositorio gitr respecto a posibles cambios en el repositorio central ejecutamos

$ git-svn rebase

Y si queremos comitear a subversion

$ git-svn dcommit

Si encontramos un conflicto debemos resolverlo de la siguiente manera

Tras comitear en git

$ git commit -m “Tal vez encontremos conflictos”

Pedimos actualización (si primero ejecutamos un git-svn dcommit nos dará error ‘Transaction is out of date’):

$ git-svn rebase

Esto nos informará de los ficheros con conflictos. Editamos el/los ficheros con conflictos hasta resolverlos. Luego comiteamos en git estos cambios con:

$ git add .

y luego

$ git rebase –continue

para finalmente ejecutar:

$ git-svn dcommit

Que llevará los cambios al repositorio central de subversion.

Instalar las claves GPG de launchpad

Hay bastante gente que anda incluyendo las fuentes de launchpad para poder descargarse algunos paquetes no oficiales para Ubuntu. También hay gente que tiene problemas con la validación de los paquetes porque no tienen instalado la clave gpg adecuada para launchpad. Los síntomas del problema son los siguientes:

Abren una consola de root y ejecutan:

# apt-get update

Y tras algunos mensajes relacionados con la descarga de las últimas listas de paquetes actualizados le aparece por consola algo tal que así

W: GPG error: http://ppa.launchpad.net intrepid Release: The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 28A8205077558DD0

Y te sugiere que vuelvas a darle al apt-get update para solucionar el problema. La solución no esta ahí. En su lugar hay que ver el hash que aparece justo al final del mensaje de aviso en concreto en sus últimos 8 caracteres. En el ejemplo serían 77558DD0 pero en tu caso podrían ser otros (consulta la salida de tu apt-get update)

Para añadir las claves basta con ejecutar lo siguiente pero sustituyendo $key por esos 8 caracteres:

# gpg –keyserver subkeys.pgp.net –recv-key $key && gpg -a –export $key | sudo apt-key add –

El problema/molestia habrá desaparecido

Grabar el historial de la shell sincronamente

A todos los que utilizamos una shell de linux más o menos habitualmente nos ha pasado que hemos perdido información valiosa que creíamos que teníamos a buen recaudo en el historial.

Con el tiempo nos damos cuenta que el histórico de comandos que se graba en ~/.bash_history se actualiza cada vez que cerramos nuestra sesión (logout). Esto trae muchos problemas cuando tenemos abiertas varias sesiones simultáneamente ya que lo que grabamos en una al cerrar sesión se pierde cuando posteriormente cerramos otras sesiones. Las posibilidades de perder la información del histórico son muy grandes. Es raro que no se haya pensado en esto pues es algo muy común. Pues estamos equivocados nuevamente porque el problema se puede solucionar rápidamente con opciones de shell.

Basta con ejecutar

$ shopt -s histappend

Para que cuando se cierren una sesión de shell se añadan los comandos ejecutados en esta sesión al fichero de historial en lugar de sobrescribir su contenido.

Además también podemos hacer que los comandos se graben en el histórico justo después de ser ejecutados y no cuando se cierra la sesión. Basta con fijar esta variable de esta manera:

PROMPT_COMMAND=’history -a’

Hay que tener cuidado aquí si PROMPT_COMMAND ya ha sido inicializada y tiene algún valor podemos perderlo y es mejor hacer esto:

PROMPT_COMMAND=”history -a;$PROMPT_COMMAND”

Por su puesto podemos añadir estas dos lineas

shopt -s histappend
PROMPT_COMMAND=”history -a;$PROMPT_COMMAND”

a nuestro fichero ~/.bashrc para que se activen automáticamente estas opciones al inicio de la sesión. Y si tenemos acceso al root de la máquina y queremos que todos los usuarios tengan las mismas opciones activas podemos escribir las dos líneas en el fichero /etc/bash.bashrc

Bueno creo que este blog se esta convirtiendo poco a poco en un pequeño libro de recetas sobre pequeños problemas que van surgiendo al utilizar linux. Espero que sean de utilidad.

Globbing

La shell bash no es capaz por si sola ni de reconocer ni de analizar expresiones regulares. Sin embargo tiene un proceso para descubrir/detectar nombres de fichero de una manera más o menos automatizada conocida con el nombre de expansión de nombre de fichero o también globbing.

Mediante el globbing y empleando caracteres especiales como \*, ?, ^, -, comas paréntesis, llaves y corchetes; bash puede analizar expresiones que le permiten sustituir dicha expresión por el conjunto de ficheros que verifican dicha expresión.

Veamos cual es el significado de cada uno de estos caracteres y como funcionan con varios ejemplos:

\* Sirve para sustituir cualquier conjunto de caracteres, incluso un conjunto vacío que este presente en el nombre de los ficheros a detectar. No detectará implicitamente ficheros que comiencen por punto

Ejemplos:

$ echo \*
Todos los ficheros que no empiecen por punto

$ echo .\*
Todos los ficheros que empiecen por punto

$ echo a\*
Todos los ficheros que empiecen por ‘a’

$ echo \*a\*
Todos los ficheros que contengan al menos una ‘a’

? Sirve para sustituir 1 caracter de cualquier tipo (excepto el punto al comienzo del nombre del fichero como en el caso del asterisco).

$ echo ???
Todos los ficheros que tengan 3 caracteres por nombre

$ echo ?a\*
Todos los ficheros cuyo segundo caracter sea una ‘a’

[] Para rangos de caracteres separados por guión o un conjunto de caracteres
Ejemplos:

$ echo [a-z]\*
Todos los ficheros que empiecen por una letra minúscula del alfabeto inglés

$ echo \*[0-9]
Todos los ficheros que terminen con un número

$ echo \*[abc]\*
Todos los ficheros que contengan una a, una b o una c minúscula

{} lista separada con comas de expansiones válidas. Permite combinar aditivamente varios expresiones de globbing

Ejemplo:
$ echo {\*[abc]\*,\*[0-9],hola,???}

^ Negación de un rango de caracteres

Ejemplo:
$ echo [^0-9]\*
Ficheros que no comienzan por numero

Globbing admite un modo extendido que habilita mas wildcards y posibilidades. Para tenerlo disponible debemos ejecutar:

$ shopt -s extglob

+, !, @ estarían ahora disponibles como wildcards

Un interesante y sutil punto a tener en cuenta es que el globbing lo realiza directamente el interprete bash y no los programas que lancemos a través de él ni el sistema operativo. Esto quiere decir que el globbing lo realizará el bash antes de ejecutar el programa al que sólo le llegarán los nombres de ficheros que hayan sido detectados correctamente mediante globbing. En la inmensa mayoría de los casos esto carece de importancia pero en otros si que la tiene. Por ejemplo, cuando ejecutamos programas a través de exec() o su familia de funciones amigas. Si no ejecutamos el programa a través de bash no tendremos disponible la expansión de nombre de ficheros.

Existe otro caso bien conocido en el que esta característica se vuelve importante. Imaginemos una carpeta que contiene cientos de miles de ficheros digamos más de cien mil (en realidad con tener más de 65535 nos llega). Por algún motivo (que bien podría ser este) queremos borrar estos ficheros. Entramos en este directorio y escribimos

$ rm -rf \*

Pero rm se niega a ejecutarlo dando este mensaje de error

-bash: /bin/rm: Argument list too long

¿Que es lo que pasa?

Pues que bash ha pasado al programa rm una lista con más de 65535 argumentos que es más de los permitidos para que rm (o cualquier otro programa de bash) pueda ejecutar a causa del globbing. Para solucionar esto podemos ejecutar por ejemplo:

find -type f -exec rm -f {} \;

Cuidado esta instrucción no es equivalente a la anterior aunque si es válida en este escenario. La diferencia radica en que la instrucción con find también borrará ficheros que comiencen por punto que estén en el directorio actual. Sin embargo rm -rf * no los borrará (aunque si los ficheros que comiencen con punto incluidos en subdirectorios del directorio actual).