Información blog

Linux, tutoriales, noticias, sistemas, redes y seguridad informática, entre otras cosas.

Mostrando entradas con la etiqueta Ubuntu. Mostrar todas las entradas
Mostrando entradas con la etiqueta Ubuntu. Mostrar todas las entradas

martes, 12 de noviembre de 2019

Cómo evitar problemas en el arranque de arpwatch en Ubuntu en 16.04

Arpwatch es un servicio de Linux que puede dar muchos problemas en el arranque; especialmente cuando se trabajan con múltiples interfaces de red, pues es bastante exigente para comenzar en el proceso de arranque.  Generalmente a muchos nos les importa, ya que con arrancar el servicio a mano después el problema se solventa; pero en ocasiones queremos que el equipo arranque automáticamente dicho servicio; especialmente en servidores que queremos que funcionen de forma "autonoma" y que sean susceptibles de reinicios inesperados.

arpwatch_portada

Es por ello que siempre es interesante saber cómo hacer que el servicio arranque de forma automática. Cosa que afortunadamente es sencillo, ya que arpwatch se enfrenta solamente a dos obstaculos para arrancar correctamente.

El primero es que al tener dos interfaces de red, con sus respectivas puertas de enlace, al servicio "networking" no le gustan las puertas de enlace estandard, sino que requieren de una métrica. Esto se solventa modificando el fichero /etc/network/interfaces y realizando el siguiente cambio; poniendo como ejemplo las puerta de enlace 192.168.1.1 y 172.16.1.1

Antes:
iface eth0 inet static
address 192.168.1.2
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1

iface eth1 inet static
address 172.16.1.2
netmask 255.255.0.0
network 172.16.0.0
broadcast 172.16.255.255
gateway 172.16.1.1

Despues:
iface eth0 inet static
address 192.168.1.2
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
post-up route add default gw 192.168.1.1
pre-down route del default gw 192.168.1.1

iface eth1 inet static
address 172.16.1.2
netmask 255.255.0.0
network 172.16.0.0
broadcast 172.16.255.255
post-up route add default gw 172.16.1.1
pre-down route del default gw 172.16.1.1

Con esta parte solventada, sería necesario forzar la ejecución de arpwatch como root, ya que como arpwatch no permite hacerlo bien durante el arranque. Para ello editaremos el fichero /etc/default/arpwatch; dentro del cual veremos una línea llamada RUNAS; la cual tendrá como valor arpwatch... Esto significa que el servicio sería ejecutado por el usuario arpwatch, pero al sistema no es algo que le guste, al menos durante el arranque, ya que el servicio en sí no arrancaría  correctamente por defecto y requeriría reiniciarlo para que funcione. Para que funcione durante el arranque, habría que hacer que el servicio sea ejecutado como root, con lo que sería necesario realizar el siguiente cambio:

Antes:
RUNAS="arpwatch"

Despues:
RUNAS="root"

Con estas pequeñas modificaciones, tras nuestro próximo reinicio, nuestro servicio arpwatch funcionaría adecuadamente, evitando así problemas con dicho servicio en caso de que el equipo fuese reiniciado de forma no controlada.

Espero que os haya resultado útil.

Saludos.

martes, 29 de octubre de 2019

Cómo realizar pruebas de carga en nuestro servidor Web

Una de las labores más importantes a la hora de montar un servidor web, es la dimensionarlo correctamente para poder realizar sus labores de forma efectiva. Generalmente a la hora de realizar el dimensionamiento se suele tender a optimizar el servidor lo máximo posible, con los recursos disponibles, para poder soportar el máximo de conexiones posibles, pero aun así, siempre es importante intentar forzar dicho servidor por encima de su capacidad máxima con el fin de ver cómo reacciona... Esto puede ser una labor sencilla si el servidor soporta muy pocas conexiones, pero y si soportase 1000 conexiones simultáneas o más? Afortunadamente existen herramientas especializadas de Linux que nos pueden ayudar a realizar testear nuestro servidor web... Entre ellas hay dos especialmente conocidas: Apache Benchmark  y JMeter.

portada_pruebas_carga

Apache Benchmark

Si bien esta utilidad se puede considerar bastante inferior a JMeter, se trata de una utilidad que tiene la ventaja de que te permite realizar pruebas rápidas desde la consola sin tener la necesidad de tener una interfaz gráfica, cosa que evita el obligarnos a depender de un entorno de escritorio para poder utilizarla. La herramienta en sí es muy fácil de instalar, ya que es parte del conjunto de utilidades estándares de Apache2, llamada apache2-utils, con lo que lo podemos instalar de los repositorios tal que así:

apt-get install apache2-utils

Con esto instalado, podemos hacer pruebas de carga de forma muy rápida mediante el comando ab; donde la sintaxis sería:

ab -c concurrencias -n numero_de_peticiones -r URL

El parámetro -r sería importante, ya que evitaría que el comando se interrumpiese aún cuando hubiese algún error... Además es importante resaltar que la URL tiene que apuntar siempre a un fichero web... Por ejemplo si tenemos un servidor web con IP 127.0.0.1, no valdría con poner dicha IP como URL sino que habría que poner http://127.0.0.1/index.html pues en caso contrario Apache Benchmark pensaría que la URL es errónea.

En caso de querer hacer 1000 peticiones con 20 concurrencias a la URL atrás mencionada, haríamos:

ab -c 20 -n 1000 -r http://127.0.0.1/index.html

Esto nos daría como resultado una serie de líneas, entre las cuales se resaltarían las últimas donde se muestran el porcentaje de paquetes que ha tardado X milisegundos en tener respuesta:

prueba_carga_ab
Resultado prueba carga Apache Benchmark

Lo malo que tiene esta herramienta, es que carece de opciones de personalización a la hora de realizar las pruebas de carga; es decir, no puedes decir si las peticiones se van a hacer de forma controlada, o como un ataque DOS... Simplemente las realiza lo más rápido que puede y listo... Lo cual viene por un lado bien para saber cómo se comporta bajo cierta presión, pero que no emula entornos realistas. Es por eso que esta herramienta tienes sus pros y sus contras y es ahí donde JMeter marca la diferencia, ya que dicha herramienta sí que tiene un mayor abanico de opciones.

Apache JMeter

En este caso para poder siquiera instalar la aplicación es 100% necesario tener instalado un entorno de escritorio, pues instalar elementos gráficos. El entorno de escritorio en sí es indiferente, puede ser XFCE, KDE, Gnome... Al gusto de cada uno... Cumpliendo dicho requisito habría que escribir en la consola:

apt-get install jmeter

Esto preparará todo lo necesario para que Jmeter sea utilizable, si bien Jmeter tiene una peculiaridad. La configuración de los diferentes parámetros y planes de pruebas se realizan desde de la GUI, pero la ejecución del plan de pruebas es extremadamente recomendable hacerlo desde la consola; recomendación que es dada por los propios desarrolladores de la utilidad.

Con lo que teniendo esto claro, primero abriríamos la aplicación desde la GUI, aplicación que, desgraciadamente, al ser tan completa, puede ser algo intimidante inicialmente.

El primer paso que habría que ejecutar sería la creación de un Grupo de Hilos; dicho paso es vital pues marca el número de peticiones simultáneas que se harían, el intervalo entre éstos y el número de veces que se lanzarían peticiones (pudiendo ser infinito); las capturas de a continuación serían realizadas desde un Ubuntu 18.04, capturas en las que, en este caso mostraríamos 100 peticiones simultáneas realizadas cada segundo continuamente :

nuevo_grupo_hilos
Nuevo grupo hilos

configuracion_grupo_hilos
Configuración grupo hilos

Con esto tendríamos las peticiones preparadas; lo que habría que especificar sería qué peticiones se desean realizar... Aquí tenemos diferentes opciones, pero la más común y usada sería una petición HTTP; petición en la que únicamente sería necesario especificar que sería del tipo GET y la IP y puerto de destino de dichas peticiones; habría una serie de parámetros adicionales, pero todos ellos serían completamente optativos:

nueva_peticion_http
Petición HTTP


opciones_peticion_http
Opciones petición HTTP

Por último pero no por ello menos importante, tendríamos que crear un reporte de resumen, el cual nos servirá para conocer los resultados de nuestras pruebas. El cual se encontraría dentro de: Añadir --> Receptor --> Reporte Resumen.  El resumen se puede ver en texto plano desde la propia consola, pero desde la herramienta tendríamos el resultado mostrado de forma sintetizada, lo cual nos es ventajoso.

Ahora que tenemos todo preparado, guardaríamos el proyecto, el cual siempre es guardado en formato .jmx, por ejemplo plan_de_pruebas.jmx. Solamente sería necesario ejecutar dicho plan, ejecución que aunque se puede hacer desde la GUI, tal y como he comentado antes es recomendable hacerlo desde la consola. El comando para ejecutarlo sería:

jmeter -n -t plan_de_pruebas.jmx -l Resumen.jtl

El parámetro -l seguido del fichero jtl sería importante, pues estaríamos especificando donde guardar los resultados de las pruebas realizadas; pruebas que siempre se guardan en ficheros en formato .jtl, si bien se puede leer de forma "normal" haciendo un simple cat sobre dicho fichero.

Gracias a dicho comando estaríamos ejecutando el plan de pruebas, que se estaría ejecutando de forma continua a menos que se pulsase la combinación de teclas CTRL + C, debido a que se trata de una prueba infinita. Esto estaría haciendo una prueba de carga "infinita" sobre el servidor de destino, prueba sobre la que tendríamos más control que mediante Apache Benchmark.

El informe de salida lo podríamos leer dirigiéndonos al `Reporte resumen` antes creado y clickando en navegar para seleccionar el informe generado por nuestras pruebas; en nuestro caso Resumen.jtl... A continuación una pequeña muestra de dicho informe:

reporte_resumen
Informe Jmeter


Como se puede observar, la aplicación JMeter ofrece una amplia gama de posibilidades; estas son solo algunas de ellas, pero las mostradas serían las más "comunes" y usadas. Eso no implica que Apache Benchmark no sea útil; cada una ofrece una serie de características, la cuestión está en saber qué aplicación se adapta mejora nuestras necesidades, al igual que también no siempre se puede contar con una interfaz gráfica, y ahí es donde JMeter flaquea, pues dicho entorno es un requisito para la propia instalación.

Espero que os haya resultado útil.

Saludos.

martes, 2 de enero de 2018

Cómo controlar el runlevel en Linux con systemd

La tecnología va evolucionando de forma inexorable con el paso de los años, haciendo que algunos conceptos que se han mantenido intocables con el paso de los años, cambien; cosa inevitable. Esto hace que, nos guste o no, tengamos que adaptarnos a dichos cambios. Uno de los cambios más polémicos que han tenido los entornos de GNU/Linux, es sin lugar a dudas la implantación de systemd, que se ha aplicado a la mayoría de sistemas operativos actuales, con algunas excepciones tales como Devuan. Dicho cambio supone la obligación del aprendizaje de nuevos conceptos, pues aunque en algunos sistemas como Debian o Ubuntu, existen varios enlaces simbólicos para algunas funciones con el fin de que la curva de aprendizaje sea mucho más suave, existen algunas funcionalidades que estamos obligados a aprendernos sí o sí. Uno de dichos conceptos sería el manejo del runlevel del sistema.

systemd_portada

Ya se ha hablado de dicho concepto con anterioridad en este blog; pero en dicho caso se trató el concepto con un init de System V; init que ,para bien o para mal, va a tender a desaparecer o perder relevancia progresivamente. En este caso trataremos el el manejo del runlevel, o nivel de ejecución, en un entorno con un init systemd.

Para ello lo primero que tenemos que tener en cuenta es que para hacer referencia a dichos niveles de ejecución, no se hace numéricamente como antes (0, apagado, 1 modo monousuario, etc...), sino que se hace mediante descripciones más técnicas; descripciones a las que luego se hacen referencia mediante enlaces simbólicos, cuyos nombres son parecidos a los usados en System V (runlevel0.target, runlevel1.target...) pero que no dejan de ser enlaces simbólicos, con lo que es mejor tener claros los nombres reales de los niveles de ejecución en systemd. He aquí una pequeña tabla con los runlevels de System V, los nombre "intuitivos" usados en systemd, y los nombres reales utilizados en systemd:

tabla_runlevel
Tabla nombre runlevels

Teniendo claros dichos conceptos, nosotros nos vamos a centrar en los nombres "reales" usados en systemd, sin uso de alias, pues dichos alias puede que en un futuro desaparezcan y es mejor intentar no crear posibles malos hábitos.

Para adivinar el runlevel usado por defecto por el sistema podemos recurrir a la herramienta principal de systemd: systemctl. En concreto habría que recurrir al siguiente comando:

root@debian:~# systemctl get-default
graphical.target

Por defecto, lo más común sería que viésemos el resultado mostrado arriba; es decir el runlevel graphical.target; o lo que sería lo mismo, el runlevel5 en System V. Además, si bien lo más común es que coincidan, podemos ver el runlevel actual de diferentes formas:

La primera, y menos recomendada debido a que con el tiempo la obsoletarán, será mediante el comando usado siempre en sistemas system V; es decir mediante el comando runlevel:

root@debian:~# runlevel
5

Otra forma de conocer el runlevel, es mediante systemctl, el cual ofrece un resultado más preciso pero que desgraciadamente no muestra un valor único; veréis, si os fijas bien todos los nombres acaban en "target", y es debido a que ahora muchos conceptos son denominados así, con lo que si listamos todos los targets cargados por el sistema, tendremos que ver entre dicho listado nuestro runlevel actual; el problema es que si bien la información es fidedigna, requiere o bien poner muchos greps para mostrar únicamente una línea, o fijarse entre las líneas mostradas en aquella que hace referencia al runlevel; he aquí el comando y el resultado mostrado por este:

systemctl list-units --type target |grep loaded

target_list

Teniendo en mano la información deseada, ahora podemos proceder a cambiar el runlevel, cambio que se puede hacer de dos formas diferentes.

El primero y el más "sólido" sería cambiando el runlevel por defecto usado por el sistema. Esto haría que a partir del siguiente reinicio siempre se usase dicho runlevel; lo cual en algunos casos puede ser útil aunque habría que ser muy cuidadoso, ya que en dicho caso nunca podríamos usar los "targets" poweroff.target ni reboot.target, pues en caso contrario no podríamos arrancar con normalidad a menos que editasemos el runlevel en el propio GRUB para dicho arranque en cuestión. Dicho cambio se haría mediante el comando systemctl tal que así:

systemctl set-default nombre_target

Por ejemplo:
systemctl set-default rescue.target

Esta acción cambiará el runlevel que cargaremos por defecto y si nos fijamos bien veremos que en realidad lo que realiza es un enlace simbólico desde /lib/systemd/system/nombre_target/etc/systemd/system/default.target, con lo que en caso de no sentirnos cómodos usando la herramienta systemctl, podemos optar por cambiar el runlevel por defecto de la siguiente forma:

rm /etc/systemd/system/default.target
ln -s /lib/systemd/system/rescue.target \
/etc/systemd/system/default.target

Si en cambio quisiésemos cambiar el runlevel del sistema únicamente para la sesión actual, habría que optar por otro comando de systemctl; en concreto sería:

systemctl isolate nombre_target

Por ejemplo:
systemctl isolate rescue.target


Como veis, la manipulación del runlevel mantiene las mismas bases que en system V, con la diferencia de que se usan herramientas y nomenclaturas distintas; lo más importante dentro de los runlevels de systemd no sería el conocimiento de la herramienta de systemctl, sino la comprensión de las nuevas nomenclaturas de éstos, nomenclaturas que ahora sería "targets" y que estarían estrechamente ligadas a la definición de cada nivel de ejecución.

Espero que os haya resultado útil.

Saludos.

viernes, 3 de febrero de 2017

Memoria RAM en Linux; una valiosa fuente de información

La memoria RAM (Random Access Memory) es indispensable para el uso de cualquier tecnología, ya sea para dispositivos pequeños como para super-ordenadores; memoria que es usada todos los días por todo tipo de personas: personas que juegan con el móvil, gente que realiza tareas cotidianas en su ordenador, etc... Lo que muchos no tienen en cuenta es que esta memoria es exactamente eso: Una memoria, valga la redundancia; y como tal almacena mucha información; información que muchos no tienen en cuenta pero que puede resultar muy valiosa y/o peligrosa, dependiendo del caso.

Portada_RAM

Las pruebas que he realizado han sido sobre sistemas Debian y Ubuntu, pero perfectamente sería aplicable para equipos basados en Red Hat, con un par de modificaciones. Lo primero que necesitamos hacer para leer el contenido de la memoria RAM, es realizar un volcado de ésta en un fichero, para luego leer éste a placer. A lo largo del tiempo han habido diferentes métodos para volcar la memoria RAM, pero el más usado a día de hoy es el uso de LiME (Linux Memory Extractor); principalmente debido a que trabaja a nivel de Kernel y puede usarse para realizar un volcado de la memoria RAM de todo sistema que trabaje con un Kernel Linux, incluidos los móviles Android.

Dependiendo de la distribución que tengamos y de la versión de ésta, podemos vernos obligados por instalar LiME a mano, pero generalmente, las últimas versiones de la mayoría de las distribuciones nos permiten instalar la herramienta desde los repositorios; cosa altamente recomendable, ya que el instalarla a mano nos puede dar problemas debido a que suele requerir de ciertas dependencias externas. Para instalar la herramienta desde los repositorios basados en Debian, junto con una serie de dependencias que son importantes tener instaladas, habría que escribir el siguiente comando:

apt-get install make build-essential lime-forensics-dkms

La instalación es automática y a primera vista, no apreciaremos ningún cambio; es más, no veremos ningún comando que haga referencia a LiME. Esto es debido a que LiMe trabaja como si se tratase de un módulo del Kernel; un módulo que tendría que ser cargado a mano, ya que dicho módulo tiene la función de volcar la memoria, y es un módulo que no funciona de la misma forma que el resto. Aún así vayamos por pasos... ¿Donde se halla dicho módulo? Para no andar volviéndonos locos buscando éste, nuestra mejor opción es recurrir al comando modinfo:

modinfo lime

Gracias a este comando, lograríamos ver la información de dicho módulo, esté o no cargado en el kernel, cosa interesante, ya seas para conocer la ubicación de este módulo como la de cualquier otro. Este módulo en concreto tendría la siguiente ubicación (válida para cualquier Kernel): /lib/modules/$(uname -r)/updates/dkms/lime.ko.

A sabiendas de donde tenemos dicho módulo, tendríamos que cargarlo en el kernel; si bien el método para cargarlo es ligeramente diferente al habitual. La forma para cargar el módulo y, al mismo tiempo, realizar el volcado de la memoria RAM, sería:

insmod /lib/modules/$(uname -r)/updates/dkms/lime.ko "path=/tmp/RAM.lime format=lime"

El proceso tardaría desde unos segundos a varios minutos, dependiendo de la cantidad de RAM a volcar. Es importante tener en cuenta que tras terminar el proceso de volcado, el módulo lime quedaría cargado, pero no estaría continuando volcando memoria; es decir que tras cargar el módulo lime, tendríamos un volcado completo de la RAM.

Si deseasemos optar por un volcado desde un equipo remoto, tendríamos que cargar el módulo de la siguiente forma:

insmod /lib/modules/$(uname -r)/updates/dkms/lime.ko "path=tcp:4444 format=lime"

Para después desde un equipo remoto obtener el volcado de memoria. Imaginemos que hemos realizado el volcado de memoria de esta forma en un equipo con IP: 192.168.1.2; para obtener remotamente dicho volcado, el otro equipo tendría que tener netcat instalado y poder acceder a dicha IP y puerto (4444). Cumpliendo dichos requisitos, desde el otro equipo haríamos:

192.168.1.2 4444 > /tmp/RAM.lime


Como veis la obtención de la información de la memoria RAM no es difícil, si bien obviamente dicho volcado no es "legible"; es decir que no es un volcado en texto plano, sino que requiere de herramientas especiales que tengan la capacidad de leer la información existente en el archivo. Para este punto la mejor alternativa sería recurrir a la herramienta de lectura de volcados de memoria más famosa en Linux: Volatility.

Esta herramienta es famosa por ser Open Source y estar preparada para leer volcados de memoria extraídos tanto de Windows, Linux y Mac; siendo una herramienta de lo más versátil. Dicha utilidad puede ser descargada desde GitHub, pero al igual que con LiME, yo recomiendo que a ser posible se descargue desde los repositorios, ya que te descarga todas las librerías necesarias para ser plenamente operativa; cosa recomendable para evitarnos posibles problemas. La instalación de esta herramienta es muy sencilla, y debe de ir acompañada de otra utilidad que trabaja estrechamente con ésta, llamada dwardump; con lo que para instalar ambas herramientas juntas haríamos:

apt-get install dwarfdump volatility

Ahora bien, con tener esto instalado no basta; ya que Volatility trabaja con perfiles para leer la memoria; con lo que ésta tiene que tener un perfil que sea compatible con el volcado de memoria que se quiere leer. Un perfil sería un archivo, comprimido en formato zip, que contiene tanto la estructura como la información de un kernel, haciendo que Volatility sepa donde y cómo buscar la información en la RAM; sin dicho perfil Volatility no sabría qué buscar ni donde hacerlo. Volatility incluye perfiles Windows por defecto, pero por desgracia no tiene ni un solo perfil de Linux incluido por defecto con lo que tenemos dos opciones:

  • Descargarnos un perfil "preconstruido" desde: 

  • Crearnos nuestro propio perfil; cosa que generalmente se recomienda, ya que los perfiles que hay online son genéricos y se han creado bajo una versión de kernel y una CPU que no tiene por qué ser compatible con lo que nosotros tenemos. 

Es importante tener en cuenta que el perfil tiene que ser del mismo "tipo" que del sistema del que hemos extraído el volcado de memoria, ya que en caso contrario volatility será incapaz de leer el volcado de memoria. Por ejemplo si hemos hecho una extracción desde un Fedora; un perfil Debian no sería válido para leerlo.  

En este caso en concreto esa posible incompatibilidad no se va a dar ya que vamos a hacer un perfil propio nosotros mismos y al querer leer una captura de memoria RAM realizada en nuestro propio equipo, la compatibilidad va a ser del 100%.

Para crear el perfil, lo primero que tendremos que hacer será crear un módulo dwarf especialmente diseñado para nuestro sistema. Dicho módulo se encargaría de leer la información del sistema y hacerla legible para la herramienta, y es uno de los componentes del perfil que necesitamos crear para la lectura de la memoria. Para ello haremos lo siguiente:

  1. cd /usr/src/volatility-tools/linux/
  2. make

En caso de no habernos dado ningún mensaje de error, debería de haber creado dentro de la carpeta /usr/src/volatility-tools/linux, el fichero module.dwarf.

Ahora que tenemos el fichero creado, es hora de crear nuestro perfil, que se trata de un archivo comprimido que contiene el fichero que hemos creado y nuestro System.map. Dicho perfil se almacena dentro de /usr/lib/python2.7/dist-packages/volatility/plugins/overlays/linux (siempre y cuando lo hayamos instalado desde los repositorios) y para crearlo realizaríamos el siguiente comando:

  1. zip /usr/lib/python2.7/dist-packages/volatility/plugins/overlays/linux/Perfil.zip \
  2. /usr/src/volatility-tools/linux/module.dwarf /boot/System.map-$(uname -r)

Con el fichero comprimido alojado en la ubicación correcta, pasaríamos  a usar Volatility. Lo primero que deberíamos hace sería mirar que, efectivamente,  el perfil está preparado para ser usado. La mejor forma de saberlo sería con el comando de a continuación:

volatility --info |grep Linux

Perfil_Volatility

En este caso, veremos un perfil con nombre LinuxDebianx64 en cuya descripción dice claramente el tipo de perfil que es. Si os fijáis bien, el nombre que se ha puesto al perfil no importa (en mi caso he puesto antes como nombre Perfil.zip) ya que lo que le importa a Volatility es el contenido de dicho fichero zip. A sabiendas que tenemos un perfil válido, leeríamos el volcado de memoria, si bien antes de nada hay que tener en cuenta que la sintaxis de Volatility para leer un volcado es la siguiente:

volatility -f fichero.lime --profile nombre_perfil acción

Por ejemplo:

volatility -f /tmp/RAM.lime --profile LinuxDebianx64 linux_bash

Con este comando en concreto lo que haríamos sería obtener el historial de los últimos comandos realizados; una información que a primera vista puede parecer inofensiva, pero que puede ser muy valiosa... Pero no solo podemos obtener el historial; dependiendo de la acción que elijamos podemos obtener datos de lo más curiosos; hay muchísimas acciones pero las más útiles serían:

  • linux_pstree: Lista los procesos que estaban corriendo en el sistema cuando se realizó el volcado de la memoria.
  • linux_lsmod: Lista los módulos que estaban cargados en el kernel en el momento que se extrajo la memoria.
  • linux_netstat: Muy útil; con este se conocen los puertos abiertos en el equipo; una información muy valiosa y al mismo peligrosa.
  • linux_arp: Muestra la tabla ARP del equipo del que se ha realizado el volcado... Dicha información puede parecer inofensiva, pero recordad que la tabla ARP muestra la IP y la MAC de los "vecinos" de aquel equipo.
  • linux_ifconfig: La RAM también almacena la IP del equipo, con lo que obviamente es una información que puede extraerse de ésta.

Existen muchas más acciones que las que he mencionado, pero estas son mi opinión las más interesantes; ya que ofrecen una información de lo más curiosa... Y valiosa. 


Con este artículo no quiero dar a entender que la memoria RAM sea más o menos vulnerable que otros elementos de un equipo, pero sí que creo que es útil conocer lo valiosa que puede resultar como fuente de información dicha memoria; un factor que muchas veces no se tiene en cuenta.

Espero que os haya resultado útil.

Saludos.

miércoles, 14 de diciembre de 2016

Cómo personalizar la apariencia de GRUB2

En el día de hoy quiero traeros algo que si bien no se puede considerar como algo "útil" o "práctico", sin duda puede ser calificado como interesante; especialmente para aquellos amantes de la personalización de sus entornos GNU Linux. A muchos les gusta darle un toque único a su escritorio con el fin de que sea todo un espectáculo a nivel visual; cosa que está muy bien, pero que puede llevarse un paso más allá personalizando la apariencia de GRUB2.

GRUB2_Portada

Está personalización es bastante sencilla, más aún cuando se está familiarizado con algunos aspectos del GRUB2, pero sí que conviene tener algunos puntos claros para evitar andar realizando configuraciones a base de "prueba y error".  El primero de todos, sería tener claro donde y cómo realizar la configuración en cuestión... Aquí dependiendo del sistema operativo que se esté usando, el fichero de configuración puede variar, pero lo mejor sería crear uno personalizado que, hasta el momento, jamás me ha dado problemas, al menos en Debian y en Ubuntu. El fichero de configuración se llamaría custom.cfg y lo crearíamos como root dentro del directorio /boot/grub.

En este fichero podríamos añadir cualquiera de los siguientes cuatro parámetros:
  • set color_nomal: Este parámetro especificaría el color de las letras que se encuentran fuera del menú de opciones del GRUB2. Es decir que colorearía el título y el texto que rodea el recuadro de selección de sistema operativo.
  • set color_highlight: Este parámetro especifica el color de las letras que se encuentren resaltadas debido a que han sido seleccionadas. Este parámetro no incluye la opción seleccionada dentro del menú de selección de sistema operativo.
  • set menu_color_nomal: Aquí seleccionaríamos los colores del texto del menú de selección de sistema operativo. Estos colores únicamente afectarían a las líneas no seleccionadas del menú.
  • set menu_color_highlight: Está opción sería la inversa a la anterior, es decir que afectaría únicamente al elemento seleccionado en el menú.

Obviamente tendríamos que saber qué valores asignar a estos parámetros; valores que son realmente simples, pues siempre tendrán la misma estructura: Parámetro=fgcolor/bgcolor. Fgcolor haría referencia al "foreground color", es decir al color de las letras, mientras que bgcolor haría referencia al "background" color que sería el color que aparecería detrás de las letras. Ahora la pregunta sería muy obvia: ¿Qué colores podemos usar? Obviamente no podemos usar cualquier color, sino uno de los que GRUB2 nos permite introducir. Los colores disponibles serían:

colores_GRUB2

Aquí habría que hacer un pequeño inciso, que sería que el color negro (black) es especial, ya que especificamos dicho color como bgcolor (background color), éste sería transparente y no negro. Siguiendo estas indicaciones, podríamos rellenar el fichero custom.cfg tal que así:

  1. set menu_color_highlight=green/black
  2. set menu_color_normal=blue/black
  3. set color_normal=cyan/black

Con esta configuración guardada únicamente habría que actualizar la configuración del GRUB2, lo que sería tan sencillo como escribir el comando:

update-grub

Con este cambio y reiniciando el sistema, lograríamos cambiar los colores de los diferentes elementos del GRUB2, exceptuando del fondo de pantalla que se mantendría igual, tal y como podemos ver a continuación.

grub_color

Si esto no nos bastase y quisiéramos también personalizar el fondo de pantalla del gestor de arranque, podemos hacerlo de dos formas. La primera sería usando una imagen a nuestro gusto que cumpliese los siguientes requisitos, que, si bien pueden parecer sencillos, hay que tenerlos presentes:

  • Tienen que estar en formato JPG,PNG o TGA.
  • Tienen que ser de 8 bits (256 colores).
  • La imagen tiene que ser RGB.

La mejor forma de asegurarnos de ello sería usando la herramienta GIMP, ya que nos da la libertad suficiente sobre las imágenes como para controlar estos puntos. Si en cambio preferimos optar por la alternativa más cómoda, podemos instalarnos el paquete grub2-splashimages, que nos descarga una serie de imágenes TGA que cumplen todos los requisitos, aunque obviamente esta "galería" sería limitada y no tiene que tener imágenes que sean 100% de nuestro gusto. Al ser un paquete integrado en los repositorios oficiales podemos hacer:

apt-get install grub2-splashimages

A sabiendas de la imagen que queremos usar, pasaríamos a personalizar el fondo de GRUB2, para lo cual habría que editar el fichero /etc/default/grub y añadirle una línea con la estructura:

GRUB_BACKGROUND="ruta_imagen"

En mi caso por ejemplo sería:

GRUB_BACKGROUND="/home/ivan/tux_bytelearning.png"

Con esta línea añadida guardaríamos los cambios y, una vez más, los aplicaríamos mediante el comando update-grub, de nuevo. Ahora únicamente tendríamos que reiniciar el sistema y podríamos disponer de un gestor de arranque completamente personalizado como el de a continuación:

GRUB2_Personalizado

Como veis, la personalización del GRUB2 no es especialmente complicada. Simplemente requiere de manejar unos pocos pequeños y de algo de tiempo en caso de querer poner un fondo completamente personalizado, lo cual con herramientas como GIMP no es especialmente complicado aún sin conocimientos sobre esta herramienta.

Espero que os haya resultado útil.

Saludos.

martes, 6 de septiembre de 2016

Cómo solventar problemas de resolución en una shell Linux

La instalación de un sistema operativo, se cual sea, en una máquina nueva, siempre conlleva sus riesgos a nivel de compatibilidad. Generalmente pensamos que no debería haber problemas y que simplemente se trata de instalar el sistema operativo y listo; pero la realidad no siempre corresponde con nuestras expectativas. Drivers no compatibles, discos duros problemáticos, problemas de red... Los problemas pueden venir por doquier, y aún cuando logramos instalar el sistema base exitosamente, podemos descubrir que no todo acaba allí... Podemos vernos en la situación de que, al instalar un sistema operativo Linux sin entorno gráfico (es decir, un sistema operativo con solamente la consola), esta es completamente ilegible. Más de uno puede pensar que puede haber un problema de drivers o que se ha realizado un paso incorrecto durante la instalación del sistema operativo, pero no es así: Se trata de un problema de resolución de pantalla.

pantalla_borrosa

Este problema, si bien no impide que el equipo actué con normalidad, es increíblemente molesto a nivel de gestión, pues es prácticamente imposible distinguir nada en la pantalla y tienes que escribir a tientas con la esperanza de que el comando introducido se haya escrito correctamente, lo cual no es nada práctico. Es por eso que es importante encontrar alguna solución que nos ayude a evitar este inconveniente... En concreto habrían dos acciones que se podrían tomar:

La primera es esperar a que “aparezca” la pantalla de login; loguearnos e instalar openssh-server a tientas para luego poder gestionar remotamente vía SSH al equipo, pues remotamente la legibilidad es plena. Esto tiene como problema que en caso de tener algún problema durante el arranque, nos quedaremos a ciegas con lo que no es del todo práctico y no sería otra cosa que un "parche" que esquivaría el problema; pero el problema seguiría allí. Aún así, es un parche válido y simplemente requiere escribir:

apt-get install openssh-server

La segunda vía es modificar la resolución de la Shell. Para ello comenzaríamos primero con una medida de carácter temporal; se trata de editar el GRUB, tal y como hemos hecho en alguna ocasión anterior, pulsando la tecla e sobre la primera opción del menú. Allí veremos todos los parámetros editables del GRUB y varias líneas referentes al sistema operativo que arranca; entre estas líneas, se encuentra el sistema que desea arrancar, seguido de los caracteres ro; A dicha línea sería necesario añadirle el parámetro vga=720 tal y como podemos ver a continuación en este GRUB de Ubuntu:

Grub_editado

Para aplicar dicho cambio al arranque actual simplemente habría que pulsar ctrl-x o F10, con lo cual se podría ver la terminal con una resolución adecuada hasta el próximo arranque que, a menos que no se haga nada, requerirá repetir el mismo procedimiento.

Aprovechando que podemos manejar adecuadamente el sistema operativo, llegaría el turno de hacer que el cambio de resolución sea persistente para no tener que entrar en el GRUB en cada arranque... Esto se consigue editando el fichero /etc/default/grub y añadiendo las dos siguientes líneas (La resolución puesta es una genérica que a mí, personalmente, me ha valido, pero puede variar dependiendo de la pantalla):

  1. GRUB_GFXMODE=1024x768
  2. GRUB_GFXPAYLOAD_LINUX=1024x768

Aún con los cambios realizados; estos de por sí no son suficientes, pues el GRUB necesita entender que se han aplicado los susodichos. Esto requiere que ejecutemos dos comandos que harán que el GRUB cargue la nueva configuración introducida:

  1. grub-mkconfig
  2. update-grub

Gracias a este cambio en los próximos reinicios podremos disfrutar de la Shell del sistema sin sufrir problemas de resolución, lo cual nos servirá para evitar tener que recurrir a "parches", tales como la gestión remota del equipo vía SSH.

Espero que os haya resultado útil.

Saludos.

jueves, 30 de junio de 2016

Cómo crear un honeypot SSH en Linux

En el mundo de la seguridad informática hay una regla primordial: Cualquier cosa que esté expuesta en el exterior, va a sufrir cyber ataques... Esto es así nos guste o no y se acabará haciendo realidad tarde o temprano, cosa que se puede aprender por las buenas o por las malas... Generalmente siempre querremos intentar hacer que los atacantes no entren, pero a veces podemos "satisfacer" la curiosidad de nuestros atacantes mediante el uso de "tarros de miel" que les haga creer que han logrado entrar, aunque en realidad no sea así; tarros de miel que son conocidos mundialmente como honeypots. Un honeypot no es ni más ni menos que un entorno ficticio con información ficticia que hace de señuelo para que los atacantes no vayan a por la información real; dicho entorno ficticio deja que el atacante "juegue" con él a su libre albedrío pero en realidad no hace otra cosa que hacer perder el tiempo al criminal y evitar que consiga el verdadero objetivo de su ataque... Existen diversos honeypots: FTP, HTTP/HTTPs, SIP... Pero hoy nos centraremos en el tarro de miel más "goloso" de todos: El orientado al protocolo SSH.

Honeypot_ssh

Para crear nuestro tarro, recurriremos a una herramienta desarrollada en Python llamada Kippo, una herramienta especializada en la creación de honeypots orientados a ssh que nos creará un entorno ficticio para todos los curiosos que quieran entrar al puerto 22 de nuestro servidor. Para ello lo primero que haremos será cambiar el puerto de escucha de nuestro servidor ssh (si es que no lo tenemos cambiado de antes) a un puerto distinto; queremos que el puerto 22 sea el que usen para entrar el honeypot con lo que tendremos que hacer que el ssh real se realice a través de otro puerto... A modo de recomendación personal evitaría usar el puerto 2222 o 22000, pues dichos puertos son conocidos por ser usados como puertos alternativos al 22. Para cambiar el puerto de escucha editaremos el fichero /etc/ssh/sshd_config y cambiaremos el valor de Port a uno menos conocido como podría ser el 10000 (por ejemplo). Si quisiésemos hacerlo directamente desde la línea de comandos al mismo tiempo que aplicamos los cambios, podríamos hacerlo de la siguiente forma:

sed -i 's/Port 22/Port 10000/g' /etc/ssh/sshd_config && /etc/init.d/ssh restart

Esta línea estaría compuesta por una sustitución de la línea "Port 22" por "Port 10000" en el fichero sshd_config, seguido del reinicio del servicio ssh para aplicar los cambios.

Con este pequeño requisito cumplido, tocaría comenzar instalando los preparativos; es decir los paquetes necesarios para que Kippo funcione. Kippo no puede ser instalado desde los repositorios oficiales, pero este programa posee dependencias que sí que pueden ser instalados desde éstos, con lo que comencemos instalándolos. En este caso me he centrado en un entorno Debian, pero el proceso en entornos Red Hat no debería diferir mucho más allá del gestor de paquetes:

apt-get install python-dev openssl python-openssl python-pyasn1 python-twisted authbind

La mayoría de los paquetes están basados en python, a excepción del paquete authbind que se encarga de permitir que usuarios que no sean root, puedan trabajar con puertos menores 1024, pues queremos que el honeypot NO sea ejecutado por root. 

Ahora crearemos un usuario especialmente preparado para ejecutar el honeypot, un usuario que, valga la originalidad, llamaremos kippo y que pertenecerá al grupo sudo.

useradd -m kippo -g sudo

Dicho usuario podrá manipular/usar el puerto 22, un privilegio que única y exclusivamente tendrá él, si bien con lo que hemos hecho no basta, sino que también necesitamos preparar authbind para ello. Esto es tan sencillo como crear un fichero llamado 22 dentro del directorio /etc/authbind/byport/ y darle los permisos adecuados para que únicamente kippo pueda tener acceso a éste; lo cual se resumiría tal que así:

  1. touch /etc/authbind/byport/22
  2. chown kippo /etc/authbind/byport/22
  3. chmod 700 /etc/authbind/byport/22

Ahora que hemos preparado tanto el puerto como el usuario, llegaría el turno de movernos a la carpeta /home de kippo y descargarnos el fichero kippo; fichero que, tal y como he comentado antes, no está disponible desde los repositorios, pero sí desde github con lo que tras movernos a la carpeta, descargaríamos y descomprimiríamos la aplicación. A modo de recomendación, sería bueno crear una carpeta dentro del directorio home que guarde todo lo relacionado con la aplicación.

  1. su kippo
  2. cd /home/kippo
  3. mkdir kippo_DIR
  4. cd kippo_DIR
  5. wget https://github.com/desaster/kippo/archive/v0.9.tar.gz
  6. tar -xzf v0.9.tar.gz

Por fin tenemos kippo descargado, si bien eso no significa que esté operativo... Por un lado es importante tener en cuenta que, a diferencia de muchos programas descargados desde github, este programa no requiere ser compilado/instalado para funcionar y además requiere realizar algunos ajustes para ser del todo operativo... Para empezar, el fichero de configuración que existe ahí, está a modo de plantilla y ni siquiera se encuentra correctamente nombrado para evitar que pueda usarse... Esta plantilla tendría se llama kippo.cfg.dist y además está configurada para trabajar por defecto con el puerto 2222, cosa que nosotros no queremos pues queremos usar el puerto 22 para emular un puerto ssh "real". Es por eso que primero renombraremos el fichero de configuración y después cambiaremos el puerto de escucha del 2222 al 22 mediante el comando sed de forma parecida a como hemos hecho antes con el fichero sshd_config.

  1. cd /home/kippo/kippo-DIR/kippo-0.9/
  2. mv kippo.cfg.dist kippo.cfg
  3. sed -i '/ssh_port = 2222/ssh_port = 22/g' kippo.cfg

Ya lo tenemos casi preparado, solo faltan un par de detalles más. Por un lado, tenemos que saber que los usuarios ficticios del honeypot se encuentran dentro del fichero userdb.txt, el cual se encuentra dentro del directorio data que a su vez se encuentra dentro de la carpeta de la aplicación de kippo. Cada usuario existente dentro de dicho fichero tiene la siguiente estructura:

usuario:0:contraseña

He aquí un fichero de ejemplo:

  1. root:0:123456
  2. root:0:test
  3. ivan:0:ivan


Por otro lado, dentro del directorio de la aplicación de kippo, tenemos un fichero llamado start.sh, fichero encargado de arrancar kippo; dicho fichero tiene que ser modificado, pues ahora mismo no está preparado para trabajar con authbind. Éste tendría que ser editado para ofrecer este aspecto:

  1. #!/bin/sh
  2. echo -n "Starting kippo in background..."
  3. #twistd -y kippo.tac -l log/kippo.log --pidfile kippo.pid
  4. DIR=/home/kippo/kippo-DIR/kippo-0.9
  5. cd ${DIR}
  6. authbind --deep twistd -y kippo.tac -l log/kippo.log --pidfile kippo.pid

A base de prueba y error, he visto que esto no basta y que es necesario que creemos dos directorios nuevos, pues en caso contrario, la aplicación no funcionará correctamente... El primero es un directorio llamado log, que se crearía dentro de la carpeta de la aplicación, mientras que el otro se llamaría tty. Obviamente ambas carpetas tendrían que pertenecer al usuario kippo.

  1. mkdir /home/kippo/kippo-DIR/kippo-0.9/log
  2. mkdir /home/kippo/kippo-DIR/kippo-0.9/log/tty
  3. chown kippo /home/kippo/kippo-DIR/kippo-0.9/log
  4. chown kippo /home/kippo/kippo-DIR/kippo-0.9/log/tty

Con esto ya tendríamos todo preparado y si ejecutásemos el script start.sh podríamos arrancar kippo, pero en mi opinión dicho script no es demasiado funcional pues no puede ser ejecutado en el arranque y no te ofrece ninguna posibilidad de pararlo de una forma cómoda. Es por ello que he añadido un pequeño script en /etc/init.d / para poder manejar el servicio con más comodidad. Dicho script sería el de a continuación y se denominaría kippo.sh.

  1. #!/bin/bash
  2. #
  3. # preload init.d script
  4. ### BEGIN INIT INFO
  5. # Provides:          start.sh
  6. # Required-Start:    $local_fs $remote_fs $time
  7. # Required-Stop:     $local_fs $remote_fs $time
  8. # Default-Start:     2 3 4 5
  9. # Default-Stop:      0 1 6
  10. # Short-Description: Kipoo starter
  11. # Description:  Kippo automatic starter. It starts during the boot
  12. ### END INIT INFO
  13. PIDFILE=/home/kippo/kippo-DIR/kippo-0.9/kippo.pid
  14. NOMBRE="Kippo"
  15. SRV="twistd"
  16. function status()
  17. if [ -f ${PIDFILE} ];
  18. then
  19.         echo "${NOMBRE}  esta en marcha"
  20. else
  21.         echo "${NOMBRE} esta parado"
  22. fi
  23. function start(){
  24.  echo -n $"Iniciando servicio ${NOMBRE}: "
  25.  su - kippo -c "/home/kippo/kippo-DIR/kippo-0.9/start.sh" >/dev/null 2>&1
  26.  RETVAL=$?
  27.  echo $! > $PIDFILE
  28.  if [ ${RETVAL} -eq 0 ];
  29.  then
  30.         echo "Se ha iniciado ${NOMBRE}"
  31.  else
  32.         echo "No se ha podido iniciar ${NOMBRE}"
  33.  fi
  34.  echo
  35. }
  36. function stop(){
  37.  echo -n $"Parando servicio ${NOMBRE}... "
  38.  SERV=$(ps -e |grep ${SRV} |awk '{print $1}')
  39.  kill -9 ${SERV}
  40.  echo "Servicio detenido"
  41. }
  42. function restart(){
  43.  stop
  44.  sleep 10
  45.  start
  46. }
  47. case "$1" in
  48. start)
  49.  start
  50.  ;;
  51. stop)
  52.  stop
  53.  ;;
  54. restart)
  55.  restart
  56.  ;;
  57. status)
  58. status
  59. ;;
  60. *)
  61.  echo $"Usar: $0 {status|start|stop|restart}"
  62.  exit 1
  63. esac
  64. exit 0

Obviamente sobre dicho script tendríamos que ejecutar dos comandos más; uno que haga que sea ejecutable, y otro que haga que se arranque en el inicio con el fin de que en caso de apagar el servidor. no se pierda nuestro querido tarro de miel.

  1. chmod 755 /etc/init.d/kippo.sh
  2. insserv kippo.sh

Ahora cualquier que acceda al puerto 22 por ssh, en vez de acceder a nuestro entorno real, accederá al honeypot en cuestión, honeypot en el que en caso de acertar sus credenciales (por defecto está diseñado para tener un único usuario que sería root con contraseña 123456) accederíamos. Obviamente dicho honeypot estaría aislado del verdadero sistema y siempre nos estaría dando datos ficticios, desde la ip hasta los ficheros presentes.

Una evidencia de que no estamos accediendo al servidor de siempre, más allá de la información existente dentro de éste, sería el hecho de que el ssh fingerprinting del servidor ha cambiado, pues en realidad estaríamos accediendo a un entorno diferente al real.

Gracias a este sencillo pero útil procedimiento, lograríamos alejar a gran parte de los curiosos de nuestro servidor ssh, haciendo que los atacantes malgasten su tiempo en un entorno ficticio y evitando que centren su atención en el puerto ssh real.

Espero que os haya resultado útil.

Saludos.