jueves, diciembre 31, 2015

¡Feliz año 2016!

Disfrutad en compañía de vuestra gente

No es oro todo lo que reluce,
ni toda la gente errante anda perdida;
a las raíces profundas no llega la escarcha,
el viejo vigoroso no se marchita.
De las cenizas subirá un fuego,
y una luz asomará en las sombras;
el descoronado será de nuevo rey,
forjarán otra vez la espada rota.

martes, diciembre 29, 2015

Baterías de litio en aviones

Multitud de aparatos electrónicos usan hoy en día baterías de ión de litio: Teléfonos inteligentes, cámaras fotográficas, tabletas o portátiles. Estas compactas baterías son capaces de almacenar en poco volumen una gran cantidad de energía. Por eso, cuando una batería de este tipo se daña debido a un golpe o un fallo en la circuitería de carga puede provocar un incendio grave y complicado de apagar. No digamos ya, si dicho incendio se produce dentro de un avión las consecuencias que puede tener. Por eso, las aerolíneas recomiendan que cualquier dispositivo que utilice una batería de este tipo nunca vaya en la bodega de carga del avión sino en el equipaje de mano, para poder actual rápidamente en caso de problemas.

Hoy en el The Aviation Herald han publicado el incidente ocurrido en un A321 de Air Berlin cuando una batería de respaldo empezó a arder: La tripulación tuvo que apagar la batería descargando un extintor, enfriarla y colocarla en una caja metálica ... mientras el avión se desviaba al aeropuerto más cercano.

Puede parecer una tontería, pero hay algunas compañías de carga aérea que se niegan a transportar cargas de baterías de este tipo. Hay sospechas que incendio de del vuelo UPS Flight 6 estuvo relacionado con la carga de baterías de ion de litio que transportaba.

martes, diciembre 22, 2015

Hackeando la PS4 (enlaces)

Ayer dando un repaso a Reddit.programming me encontré con una serie de artículos que describen como usar un fallo de seguridad en webkit, el núcleo del navegador web que usa la Playstation 4, junto con la técnica de ROP poder ejecutar código no firmado dentro de la Playstation 4:

El autor de los artículos ha realizado toda este análisis en una Playstation 4 con una versión antigua del firmware 1.7x. Actualmente, puede que algunos de los agujeros de seguridad que se han usado no funcionen. Sin embargo, es una lectura amena y muy bien explicada para aquellos a los que nos gusta la ingniería inversa.

martes, diciembre 15, 2015

nstat: Estadisticas de red en Linux

Todos los sistemas que implementan la pila de protocolos TCP/IP suelen tener unos contadores internos que almacenan estadísticas sobre el funcionamiento de la pila de procotolos: Paquetes recibidos, conexiones TCP abiertas, paquetes UDP, etc. Normalmente, esas estadísticas son las necesarias para poder implementar la MIB II que necesitan los agentes SNMP. A esta información se puede acceder desde Linux de manera sencilla con el comando nstat. Este comando forma parte del paquete iproute2 que debe estar instalado para poder hacer uso del mismo. Cuando se ejecuta nos muestra los valores de los contadores SNMP del kernel y de las interfaces de red.

root@menzoberrazan:~# nstat
#kernel
IpInReceives                    152295             0.0
IpForwDatagrams                 147066             0.0
IpInDelivers                    5228               0.0
IpOutRequests                   160352             0.0
IpFragFails                     1                  0.0
IcmpInErrors                    421                0.0
...

He cortado la salida del comando. Hay que tener en cuenta que:

  • Se muestran la diferencia entre ejecuciones del comando. Si se quiere saber los valores totales hay que usar la opción -a
  • No se muestra aquellos contadores cuyo valor es cero. Si se quieren mostrar hay que usar la opción -z
  • Si se quiere resetear esos contadorews usar la opción -r
  • Para que los datos estén en formato json y se pueda procesar por otras utilidades (como jq), cabe la posibilidad de usar la opción -j.
  • Si sólo queremos actualizar los acumulados y no imprimir resultados -n

Esta utilidad es de utilidad para ver cual es el rendimiento de nuestra pila TCP/IP y si hay errores. Por ejemplo los contadores UdpInErrors nos podría dar una pista de paquetes UDP que estamos recibiendo y que el sistema no está aceptando por carga o porque estamos bajo un situación de denegación de servicios. UdpRcvbufErrors nos puede indicar que el sistema está saturando la pila TCP/IP a mayor velocidad que la que esta puede procesar el tráfico entrante.

lunes, diciembre 14, 2015

La gran apuesta (The Big short), la película.

Hace algún tiempo escribí una pequeña reseña de la Gran Apuesta, el magnífico libro de Michael Lewis en el cual relata algunos de los mecanimos que llevaron a la crisis subprime en EEUU. Hace unos días me enteré que el libro se ha llevado al cine. Con guión de Adam McKay y Charles Randolph, dirigida por Adam McKay y protagonizada por Christian Bale, Steve Carell, Ryan Gosling y Brad Pitt, en Enero del 2016 tendremos en el cine La Gran Apuesta. Si es la mitad de buena que el libro de Lewis, será una gran película. Aquí os dejo el trailer.

sábado, diciembre 12, 2015

ElasticSearch: Algunos conceptos básicos

Estas últimas semanas estoy trabajando con el buscador Elasticsearch. Quiero recopilar algunas notas de los conceptos, terminología y uso básico del mismo.

Elasticsearch es un motor de almacenamiento y búsqueda de documentos en formato JSON. Estos documentos se organizan índices de acuerdo a nuestros requerimientos. Los índices internamente se dividen en shards los cuales pueden residir en diferentes nodos. Un esquema sencillo de esta relación es el siguiente:

La primera decisión importante cuando se despliega un proyecto sobre Elasticsearch es decidir cual va a ser el número de shards que va a tener cada uno de los índices que usemos. Esta es una de la primeras preguntas que nos debemos hacer. El número de shards determina como podemos distribuir el índice entre los diferentes nodos que forman el cluster. Además, cada shard es un índice de Lucene que ocupa los correspondientes recursos en el sistema. Además está el inconveniente de que no se puede cambiar los shards de un índice sin reindexar de nuevo todos los datos y es un parámetro fundamental a la hora de evaluar el rendimiento del cluster y los problemas de escalado que pudiera haber. Como todo, el número que se use es un conjunto de compromisos entre nuestra escalabidad y rendimiento

Otro concepto importante a la hora de manejar los índices de elasticsearch son aquellos shards que son réplicas. Estás se usan para implementar la redundacia a fallos. Si un nodo que tiene un shard primario cae, la réplica pasa a ser el shard primario y así el cluster puede seguir funcionando.

Los shards, tanto primarios como réplicas se distribuyen entre los diferenes nodos del cluster que forman Elasticsearch para conseguir un escalado horizontal entre varias máquinas. Un cluster lo forman varios nodos que tienen el mismo nombre. Éste se fija en el fichero de configuración elasticsearch.yml con la propiedad cluster.name:. En la arquitectura de Elasticsearch un nodo siempre es el master encargado de la gestión de los índices y coordinación de los diferentes nodos. Las peticiones de indexado y búsqueda que reciben los nodos son rutadas de manera adecuada a donde están los datos.

Para interactuar con Elasticsearch lo más sencillo es usar su interfaz REST que por defecto escucha en el puerto 9200 de la máquina donde se está ejectuando Elasticsearch. Es muy fácil usar software como curl para realizar dichas peticiones. Aparte del verbo http (GET, PUT, POST, DELETE) la información que necesita Elasticsearch viaja en el cuerpo de las peticiones codificado en formato JSON. La mayoría de las respuestas que da el servidor de Elasticsearch son también en este formato. Existe otro método para interactuar con el cluster de Elasticsearch y es el llamado API de transporte, donde el sistema cliente simula ser otro nodo del cluster. Hay multitud de librerías que encapsulan este acceso al servidor como Python Elasticsearch Client para Python. Para algunas cosas que hago en Python he usado bastante Requests montando las peticiones directamente.

Intereactuar con el API rest es bastante sencillo. Por ejemplo, esta simple petición nos devuelve un JSON con las propiedades del server. A continuación unos ejemplos de como crear un índice, introducir datos, devolverlos y borrar el índice.

baldurgate:~ terron$curl -XGET http://localhost:9200
{
  "name" : "Krang",
  "cluster_name" : "avos",
  "version" : {
    "number" : "2.0.0",
    "build_hash" : "de54438d6af8f9340d50c5c786151783ce7d6be5",
    "build_timestamp" : "2015-10-22T08:09:48Z",
    "build_snapshot" : false,
    "lucene_version" : "5.2.1"
  },
  "tagline" : "You Know, for Search"
}

Crear un índice y ver las propiedades del índice es muy sencillo. Se añade el parámetro pretty para que nos devuelva el JSON formateado para que su lectura sea sencilla

baldurgate:~ terron$curl -XPUT http://localhost:9200/prueba?pretty
{
  "acknowledged" : true
}
baldurgate:~ terron$curl -XGET http://localhost:9200/prueba?pretty
{
  "prueba" : {
    "aliases" : { },
    "mappings" : { },
    "settings" : {
      "index" : {
        "creation_date" : "1449933189870",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "wFT1ymODQCqsXIOkeCakVw",
        "version" : {
          "created" : "2000099"
        }
      }
    },
    "warmers" : { }
  }
}

Introducir datos en el índice se puede hacer con curl de manera sencilla. Voy a dejar, de momento el fundamental tema de los mapeos, dejando que sea el propio servidor el encargado de generarlos automáticamente. Por ejemplo, para crear dentro del índice prueba un tipo de datos llamado libro, introducimos un

baldurgate:~ terron$curl -XPOST http://localhost:9200/prueba/libro/?pretty \
  -d '{"autor": "Julio verne","titulo": "Veinte mil lenguas de viaje submarino"}'
{
  "_index" : "prueba",
  "_type" : "libro",
  "_id" : "AVGWzzLD6jhN-gT8oefN",
  "_version" : 1,
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : true
}

Y una búsqueda rápida que devuelva todo lo que tiene el índice

baldurgate:~ terron$curl -XGET http://localhost:9200/prueba/_search
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "prueba",
      "_type" : "libro",
      "_id" : "AVGWztnY6jhN-gT8oefM",
      "_score" : 1.0,
      "_source":{"autor": "Julio verne","titulo": "Veinte mil lenguas de viaje submarino"}
    }]
  }
}

Por último, se puede borrar todo el índice como un simple:

baldurgate:~ terron$curl -XDELETE http://localhost:9200/prueba {
  "acknowledged":true
}

viernes, diciembre 04, 2015

ssh-agent: Agente de autentificación de ssh

Aunque llevo casi dos décadas usando openssh para conectar a máquinas remotas1 no ha sido hasta estos dos últimos años cuando he dejado de usar la autentificación con contraseñas y he pasado a usar la autentificación basada en claves públicas y privadas. Y no ha sido hasta estos días cuando he empezado a usar el agente de autentificación ssh-agent

ssh-agent se encarga de gestionar nuestras claves privadas y pasar las mismas a los programas que la soliciten. ssh-agent se localiza en el sistema con ayuda de varibles de entorno. Estas variables le dice a los posibles clientes de ssh-agent como contactar con él para usar las claves privadas que almacena.

Normalmente el agent se arranca durante el inicio de sesión. La configuración que uso es la siguiente:

export SSH_AUTH_SOCK=~/.ssh/ssh-agent.$HOSTNAME.sock
ssh-add -l 2>/dev/null >/dev/null
if [ $? -ge 2 ]; then
  ssh-agent -a "$SSH_AUTH_SOCK" >/dev/null
fi

Estas líneas lo primero que establecen es la ruta hacia el socket Unix que se utilizará para comunicarnos con el agente. Luego usamos la aplicación encargada de añadir claves al agente para comprobar si está corriendo. Si se consulta la página de manual de ssh-add, vemos que la opción -l intenta listar las claves que tiene el agente. En caso de error, el valor de retorno será mayor que cero. Concretamente dos, si no puede contactar con el agente. El autor del script detecta ese valor de retorno para ejecutar el agente si éste está parado.

Para añadir una clave privada al agente basta con usar ssh-add:

ssh-add clave_privada

En caso de que la clave privada la hayamos creado protegida con una contraseña, nos la preguntará para poder desbloquarla y cargarla en el agente. Una vez realizado este paso, ssh consultará el agente buscando las claves privadas para poder hacer la autentificación.

El uso del agente y la autentificación con clave pública/privada es más seguro y permite olvidarse de estar tecleando claves constantemente.

Notas

  1. Incluyo en este tiempo el precursor, el ssh escrito por Tatu Ylönen del cual deriva en openssh

miércoles, diciembre 02, 2015

Mac OS X: Configurar paths y uso de path_helper

Estaba configurando algunos directorios en la ruta de búsqueda de ejecutables (PATH) de mi OS X y en principio recurrí a modificar mi $HOME/.profile - uso bash como shell - añadiendo las nuevass rutas a la variable PATH, si estas rutas no están añadidas con un código similar al siguiente:

DIRS=(/usr/local/java/maven/bin)
for d in ${DIRS[@]}; do
    if [[ !  ":$PATH:" == *":$d:"* ]]; then
       PATH=$PATH:$d
    fi
done
export PATH

Normalmente, si quería que ese PATH estuviera disponible en todo el sistema, solía modificar uno de los scripts en /etc que se ejecutan cuando el usuario hace login. Sin embargo, viendo el valor de la variable en mi OS X me di cuenta que había algunos directorios en el PATH que habían sido añadidos por alguno de los paquetes que he ido instalado en el sistema a lo largo del tiempo. He buscado qué mecanismo utiliza OS X para establecer esas ruta en la configuración, encontrando la respuesta en en esta entrada de StackOverflow: OS X utiliza un mecanismo llamado path_helper para configurar la variable PATH.

path_helper lee los directorios de búsqueda por defecto de ejecutables de /etc/paths y luego los ficheros que estén en /etc/paths.d y compondrá las rutas de búsquedas definidas en la variable PATH de acuerdo al contenido de los mismos.

Si se quiere añadir una ruta, por ejemplo /usr/local/java/maven/bin al sistema, basta con crear un fichero /etc/path.d/maven donde cada línea especifica una ruta donde se deben de buscar los ejecutables y path_helper se encargará del resto.

Este mecanismo también se usa para las rutas de las páginas de manual. Las rutas por defecto se definen en /etc/manpaths y se pueden añadir otras en el directorio /etc/manpaths.d

La ventaja de este tipo de mecanismos es que nos permite no tener que tocar scripts del sistema que pueden machacarse con posteriores actualizaciones.

lunes, noviembre 30, 2015

vim: registros y macros (I)

vim utiliza una serie de registros internos para manejar el texto que se está editando. Si consultamos la ayuda con :help registers veremos que hay nueve tipos distintos. En esta entrada me voy a centrar en los llamados registros con nombre, aquellos que se identifican con una letra del alfabeto (de la a a la z). Éstos sólo los usa vim cuando se referencia a los mismos de manera específica.

Hay varios comando que se le puede especifar el registro destino donde queremos que se almacene los resultados del mismo. Por ejemplo, si se quiere copiar las 4 primeras líneas de un fichero al registro a:

:1,4y a

Puede verse el contenido del registro a con los datos copiados con:

:register a

Si se quisiera insertar el contenido del registro a al final del fichero se podría hacer de la siguiente manera:

:$pu a

Esta no deja de ser una manera de usar el conjunto de registros con nombre de vim como una especie de block de notas donde podemos poner texto e ir pegando según nos convenga. Una propiedad interesante que tienen los registros es que su contenido puede ser interpretado como una secuencia de pulsaciones que son órdenes de vim, es decir, los registros se utilizan para definir macros.

Por ejemplo, supongamos que queremos usar el registro a de tal manera que cuando se ejecute la macro vim automáticamente realice los siguientes pasos:

  • Vaya a una nueva línea
  • Pase a modo de inserción
  • Inserte un texto.
  • Situe el cursor en una determinada posición en el texto insertado.

Para grabar una macro usamos la orden ql, introducimos las órdenes de vim que nos interese y cuando terminamos pulsamos q. Para ejecutar una macro se utiliza @l. En ambos casos l es el nombre del registro que queremos usar. Cuando vim está grabando una macro de esta manera, aparecerá la palabra recording en la línea de comando. Un ejemplo de una macro grabada esa manera es el siguiente:

$a^M<p style="text-indent: 30px;">^M^M</p>^[

El comando anterior sólo lo utilizo para que se vea lo que podemos hacer con vim en una macro. No está preparado para poder copiarse directamente a nuestro $HOME/.vimrc, ya que tiene caracteres de control que no están correctamente en el texto.

Lo interesante es poder mapea estas macros a secuencias de teclas, de tal manera que las mismas se ejecuten de manera automática al pulsarlas. Por ejemplo, si quiero que la macro anterior, grabada en el registro a se ejecute al pulsar F1, sólo en el modo normal del editor:

:nmap <F1> @a

La limitación más importante que tiene el mecanismo de registros es que son globales a vim, no están personalizados por cada buffer de texto que estemos editando, con lo cual las macros que hayamos grabado, serán iguales para todo vim. Esto, sin embargo, puede tener cierta solución usando los eventos de BufRead / BufEnter, para ir definiendo las macros de acuerdo a nuestros intereses en ciertos buffers de texto.

Referencias

viernes, noviembre 27, 2015

osquery(II): Configurar osqueryd

En el primera entrada sobre osquery estuve probando las posibilidades de osquery para obtener información del sistema desde la línea de comandos con osqueryi. Pero la fortaleza de una herramienta de este tipo es poder definir aquellas consultas que queramos y que el programa las vaya ejecutando cada cierto tiempo, almacenando el resultado de las mismas o los cambios que se han producido en las partes del sistema que estamos monitorizando.

El programa que se encarga de ejecutar las consultas programadas en osqueryd. Éste lee su fichero de configuración en el cual se definen las diferentes opciones, las consultas que ejecutará para obtener la información del sistema, los ficheros y directorios que monitorizará para detectar cambios y las opciones de salida. Por defecto, esta información la almacenará en una base de datos RocksDB y en un fichero de texto donde cada una de sus líneas es un objeto JSON con los datos o la modificación de los mismos. La primera vez que se ejecuta una consulta determinada almacenará todos los resultados en la base de datos RocksDB. A partir de entonces, solamente almacenará los cambios respecto a la última vez que se ejecutó la consulta.

Por defecto, el fichero de configuración en el caso de la instalación de OS X está en /var/osquery/osquery.conf o en los directorios /var/osquery/osquery.conf.d/*.conf. En caso de que esté en una ruta distinta puede pasarse el parámetro --config-path ruta especificando la ruta donde está dicho fichero. El formato del fichero de configuración es JSON. En casa una de las claves principales, se configura las opciones, las consultas que se quieren realizar, la comprobación de integridad de ficheros y los packs, que son conjuntos de consultas que permiten tener información del sistema que estamos monitorizando.

{
  "options": {
    ...
  },
  "schedule": {
    ...
  },
  "file_paths": {
    ...
  },
  "packs": {
    ...
  }
}

Bajo la clave options se definen varios parámetros de configuración de osqueryd. Todos estos parámetros de configuración tienen valores por defecto, por lo que en principio no sería necesario definirlos. Pero si estamos haciendo un despliegue en multitud de nodos usando alguna herramienta como Ansible o Puppet se querrá establecer algunos paramétros de configuración por defecto.

En la configuración por defecto, osqueryd leerá las consultas a realizar del fichero de los ficheros de configuración y almacenará los resultados de las mismas en un fichero en texto plano en el disco duro. Cada línea de dicho fichero es un objecto JSON. Una funcionalidad interesante que tiene osqueryd es que se puede crear un fichero de configuración mínima que utilice una conexión protegida por TLS para que baje la configuración y envié los resultados de las consultas que se hagan en el sistema a un punto central donde puedan consolidarse y analizarse. En los ejemplos que voy a utilizar en esta entrada toda la configuración y el registro se hará sobre el sistema de ficheros.

Un ejemplo de las opciones que se pueden configurar es el siguiente

{
  "options": {
    "host_identifier": "baldurgate",
    "schedule_splay_percent": 10,
    "config_plugin": "filesystem",
    "logger_plugin": "filesystem",
    "logger_path": "/var/osquery/logs"
  }
}

Configuramos algunas de las opciones que no nos interesa por defecto de osqueryd. El nombre del host (host_identifier), un tiempo que se añade a cada query para evitar lanzar varias a la vez en el mismo instante (schedule_splay_percent), el sistema que se va a usar para almacenar los registros (logger_plugin) y la ruta donde se van a almacenar, puesto que el logger_plugin es filesystem.

Pero la parte importante son las consultas que se quieren realizar sobre el sistema para que nos de la información que necesitamos monitorizar. La configuración normal hace que se ejecute la consulta la primera vez y luego sólo se almacene las diferencias de las mismas respecto a la ejecución anterior. Estas diferencias también son escritas a través del plugin de registro que se haya seleccionado. En la web del proyecto pueden verse las diferentes tablas que pueden consultarse. Cada clave que haya dentro de la sección schelude debe ser única, definiendo la consulta y cual debe ser la periodicidad con la cual se debe de ejecutar.

{
  "schedule": {
    "macosx_alf" :{
      "query": "SELECT * from alf",
      "interval": 60
    },
    "macosx_alf_excpetions": :{
      "query": "SELECt * from alf_exceptions",
      "interval": 60
    },
    "macosx_alf_explicit_auths": :{
      "query": "SELECT * from alf_explicit_auths",
      "interval": 60
    },
  }
}

Estas tres consultas obtienen información del sistema cada sesenta segundos. Es importante cuando se definen las consultas en osquery comprobar cual es el rendimiento que tienen la máquina, ya que podría ocurrir que se gastara demasiados recursos en las mismas, teniendo que modificar tanto la programación como el número de consultas para no ahogar la máquina.

El comportamiento por defecto del osqueryd es mandar al plugin de registro tanto las filas de la consulta que se han añadido como las que se han quitado. Sin embargo, hay consultas en las cuales dicho comportamiento no tiene sentido. Por ejemplo, consultas que devuelvan resultados relacionados con el tiempo o contadores de rendimiento. Puesto que osquery mandará la línea añadida y quitará la que no existe, se puede usar la clave removed a false para que esa información no se almacene. Por ejemplo

Por otro lado, si se quiere los datos en un punto determinado de tiempo de una consulta se puede hacer con snapshot a true, en vez de registrar las diferencias. Por ejemplo, la siguente consulta almacenaría la información de cada punto de montaje de manera periódica (mismo ejemplo que está en la documentación de osquery)

  "schedule": {
    "mounts": {
      "query": "select * from mounts",
      "interval": 3600,
      "snapshot": true
    }
  }

Una de las funcionalidades más interesantes incluidas en osquery es la posibilidad de actual como un host IDS, analizando los directorios y ficheros que se programen para avisar en caso de que exista algún cambio. Por ejemplo, si se desea monitorizar posibles cambios en todos los directorios bajo /etc se podría usar una configuración como la siguiente:

  "schedule": {
    "query": "select * from file_events;",
    "removed": false,
    "interval": 300
  },
  "file_paths": {
    "etc": [
      "/etc/%%"
    ]
  }

Los posibles eventos que se generen debido a las modificaciones que se produzcan en los ficheros y directorios especificados en file_paths se almacenarán en la tabla file_events, la cual se podrá consultar para ver las modificaciones que se han ido produciendo.

Por último hablar de los packs que no son más que conjuntos de consultas definidas para realizar una determinada labor (por ejemplo obtener una foto de la máquina en un momento dado o para gestión de vulnerabilidades). La instalación de OS X por defecto tiene cuatro packs que se instalan en /var/osquery/packs. Un ejemplo de como configurar uno de ellos es el siguiente:

  "packs": {
    "vuln_management": "/var/osquery/packs/vuln-management.conf"
  }

Esto es un primer vistazo a las posibilidades que tiene osquery para utilizarlo como herramienta de inventariado, monitorización y conformidas en máquinas Linux y OS X. Hay más opciones de las que no he hablado, como la posibilidad de usar reglas yara para detectar malware, la posibilidad de usar herramientas remotas para configurar osquery o centralizar los registros de los eventos que vaya creando el sistema.

miércoles, noviembre 25, 2015

Activar el menú depuración de las App Store de OS X

La App Store que utiliza las últimas versiones de OS X es una aplicación desarrollada con tecnologías HTML y Javascript que se ejecuta en un contenedor WebKit. A veces, puede ser necesario activar la depuración de la misma depurar errores que puedan estar ocurriendo. Para ello simplemente introducimos la siguiente línea en una shell:

defaults write com.apple.appstore ShowDebugMenu -bool true

Volvemos a reiniciar la aplicación de la App Store y tendremos el menú depuración:

Las opciones más interesante son Show Download Folder que nos abrirá una ventana del Finde en el directorio por defecto donde se descargan las aplicaciones, Clear Cookies que borrará las cookies que el sistema pudiese tener almacenadas y Reset Application que nos reseteará la aplicación.

sábado, noviembre 07, 2015

HyperScan: Librería de expresiones regulares de alto rendimiento de Intel

En la pasada Conferencia de Usuarios de Suricata,celebrada a principios de esta semana en Barcelona,Intel ha presentado HyperScan, una librería de expresiones regulares especializada en machear gran cantidad de las mismas contra bloques o flujos de datos a alta velocidad. Este librería comenzó como un producto de fuentes cerradas en el año 2008 hasta su publicación por Intel este año.

Los antivirus y sistemas de deteción de instrusiones de red (NIDS) suelen estar diseñados para usar un conjunto de reglas que usan expresiones regulares para intentar detectar patrones de datos que puedan ser una amenaza.

Las librería compila las expresiones regulares - que siguen el formato de expresiones regulares de la librería pcre - en una base de datos. El resultado de esta compilación depende del modo en que se vaya a usar las expresiones regulares - ya sea para buscar en un bloque o en un flujo de datos - y del procesador que se vaya a usar para realizar la operación de macheo, intentando usar todas las características que tenga cada CPU - como instrucciones SIMD - .La librería no usa backtraking con lo cual su consumo de recursos es reducido y apropiado para su uso en sistemas embebidos.

Ayer le pregunté a uno de los autores de Suricata sobre las pruebas que Intel había hecho con un Suricata modificado para usar dicha librería, ya que los datos de rendimiento del Suricata normal era un orden de magnitud menor que el Suricata que usaba HyperScan. Las pruebas las ha hecho Intel usando el conjunto de reglas http de emerging threads.

El código fuente de la librería está disponible en github bajo una licencia de tipo BSD.

martes, octubre 27, 2015

oss-webmail: Un viejo documento donde se explica como montar un pequeño servicio de correo.

Aunque ya hace bastantes años que publiqué en Como montar un servidor con qmail + vpopmail + squirrel sobre Linux, el documento oss-webmail que describe como montar un sistema de correos usando software de fuentes abiertas sobre una Debian o sobre una RedHat 7.3 - imaginad si ha llovido -, he decido subir de nuevo todas las fuentes a un repositorio de github oss-webmail para que estén fácilmente disponibles para aquellos que quieran usarlas o les pueda ser útil.

Si tengo ganas y tiempo, lo mismo me animo a actualizarlo para una distribución más moderna de Linux. Aunque, por desgracia, hoy en día Internet es un territorio hostil para aquellos que quieran usar sus servidores propios de correos y no depender de los grandes

lunes, octubre 26, 2015

Tunelizar UDP con ssh y socat

Tunelizar UDP con ssh y socat

Hoy me he encontrado con un pequeño problema: Quería mandar un syslog (UDP) sobre Internet a una máquina EC2 con la cual estaba haciendo pruebas en Amazon. Es cierto que podía montar una VPN con OpenVPN o usar stunnel, pero la verdad, no me apetecía estar montando certificados y quería algo rápido. La solución por la que opté fue usar socat para encapsular el tráfico UDP sobre TCP, un reenvío TCP sobre ssh para mandar los datos a la instancia EC2 en Amazon encriptados sobre el canal ssh y de nuevo socat para desencapsular los datos del flujo TCP y lanzarlos sobre el puerto UDP local.

El escenario del que parto es el siguiente:

  • Tengo configurado el daemon de syslog para que mande todo lo que recibe al puerto 5000 de la máquina a través de UDP
  • Voy a redirigir el puerto de la máquina local 4000 al puerto 4000 de la máquina en EC2 a través de un túnel ssh
  • En la máquina local, todo lo que se reciba con protocolo UDP al puerto 5000 se encapsular sobre un flujo TCP y se redirigirá a través del puerto 4000 que es donde está escuchando la redirección de puertos local.
  • En el extremo EC2 todo lo que reciba por el puerto TCP 4000, se dirigirá al puerto UDP 514, que es el syslog daemon local.
  • A modo de ejemplo, asumo que la IP de la máquina de Amazon remota es 10.11.12.13

Para que funcione correctamente hay que dar los siguientes pasos y en orden:

  1. Establecer el tunel TCP con el reenvio de puertos en la máquina local
    $ ssh -L 4000:localhost:4000 -i clave_secreta.pem -l root 10.11.12.13
  2. Realizar con socat la redirección del puerto 4000 TCP al puerto 514 UDP en el servidor EC2
    $ socat -4 TCP-LISTEN:4000 UDP:localhost:514
  3. Por último, en nuestra máquina local, mandar los datagramas UDP que recibimos por el puerto 5000 a través del túnel
    $ socat -4 UDP-LISTEN:5000 TCP:localhost:4000

Decir que en este caso concreto, syslog, podría simplemente no usar UDP y aprovechar las conexiones TCP que también soporta dicho daemon para tunelizar vía ssh directamente los datos, pero trataba de poner un ejemplo de esa encapsulación UDP sobre TCP con socat y ssh.

Otra manera de hacer esta redirección, suponiendo que tengamos credenciales de root en las dos máquinas es esta que me apunta sntg_boff: Se aprovecha las posibilidades de ssh para establecer el túnel TUN/TAP y mandar los datos sobre ssh.

sábado, octubre 24, 2015

ElasticSearch: Notas de instalación

Instalación

ElasticSearch es un sistema de almacenamiento distribuido orientado a documentos JSON construido sobre Apache Lucene. Su punto fuerte es la facilidad que permite crear clusteres de varias máquinas rápidamente. Su especialidad es el análisis y búsqueda de datos introducidos en índices y la potencia de búsqueda que da la librería Lucene sobre la que está construido.

Instalar ElasticSearch es sencillo. La versión estable cuando escribo esta entrada, 1.7.3, necesite al menos Java 7, siendo recomendable el uso de Java 8. En ambos casos es necesario el JDK. Una vez que lo tenemos instalado el proceso de instalación es tan sencillo como bajarse el zip con ElasticSearch, descomprimirlo y activarlo.

$ wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.3.tar.gz
$ wget -O elasticsearch-1.7.3.tar.gz.sha1  \
  https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.3.tar.gz.sha1.txt
$ # Verificamos la hash
$ sha1sum elasticsearch-1.7.3.tar.gz.sha1
$ # El comando anterior debe devolver OK
$ tar zxvf elasticsearch-1.7.3.tar.gz
$ cd elasticsearch-1.7.3
$ bin/elasticsearch

ElasticSearch exporta su funcionalidad a través de una potente interfaz REST que permite realizar todas las operaciones que se necesite. Por defecto, dicha interfaz escucha en el puerto 9200 en cualquier interfaz IP de la máquina. En caso de que dicho puerto esté ocupado, ElasticSearch intentará localizar uno libre desde el mismo, intentando abrir un puerto de manera consecutiva desde el 9200. Se puede comprobar que está el sistema funcionando con ayuda del comando curl

$ curl -XGET http://localhost:9200
{
"status" : 200,
"name" : "Yandroth",
"cluster_name" : "darkelf",
"version" : {
"number" : "1.7.2",
"build_hash" : "e43676b1385b8125d647f593f7202acbd816e8ec",
"build_timestamp" : "2015-09-14T09:49:53Z",
"build_snapshot" : false,
"lucene_version" : "4.10.4"
},
"tagline" : "You Know, for Search"
}

Personalmente, cuando uso ElasticSearch prefiero seguir una estructura que me permita cambiar entre versiones de manera fácil. ElasticSearch, en su configuración por defecto está autocontenido. Puede ejecutarse desde una cuenta de usuario normal sin necesidad de privilegios espaciales. Esto me permite usar enlaces simbólicos para activar la versión que me conviene de ElasticSearch:

lrwxr-xr-x   1 terron  staff    19 21 sep 19:19 elasticsearch -> elasticsearch-1.7.2
drwxr-xr-x+  8 terron  staff   272 16 dic  2014 elasticsearch-1.4.2
drwxr-xr-x+ 19 terron  staff   646 19 oct 18:50 elasticsearch-1.7.2
drwxr-xr-x+  8 terron  staff   272 23 oct 15:26 elasticsearch-1.7.3

Uso siempre rutas que incluyan el enlace simbólico y cambiando el mismo, puedo seleccionar una versión u otra sin alterar otras partes de la aplicación que haga referencias a las mismas.

Configuración mínima

Aunque sea fácil arrancar por defecto ElasticSearch hay que tener en mente algunos problemas de configuración que pueden presentarse. Voy a suponer que existe una variable de entorno $HOME_ES que apunta al directorio raíz donde se ha descomprimido ElasticSearh. El fichero de configuración es $HOME_ES/config/elasticsearch.yml, que utiliza el formato yaml. Además existen una serie de variables de entorno que utiliza el script de arranque para configurar el proceso y el fichero $HOME_ES/bin/elasticsearch.in.sh donde también se pueden configurar diversos aspectos de la aplicación. Si se usa el script de arranque $HOME_ES/bin/elasticsearch

Como mínimo sería interesante establecer el nombre del cluster y el nombre del nodo en el fichero $HOME_ES/config/elasticsearch.yml. Por defecto, gracias al mecanismo de multicast que tiene ElastiSearch, todos los nodos que utilicen el mismo nombre de cluster tratarán de unirse al mismo, creando un entorno distribuido.

cluster.name: avos
node.name: "Nodo 1"

También es intersante establecer la variable de entorno que controla el heap de Java. La variable que controla dicha cantidad es ES_HEAP_SIZE y por defecto es un 1 giga. Ojo, que hay ciertas reglas a tener en cuenta al establecer la memoria máxima que puede usar ElasticSearch.

lunes, octubre 19, 2015

Descripción del kernel de Linux

Siempre me ha interesado la programación de sistemas operativos y su diseño interno. He leído algunos libros sobre el tema, tanto del mundo Unix (el magnífico The Design of the UNIX Operating System), mundo Windows (la serie Windows Internal o a nivel teórico el libro de sistemas de operativos de Andrew Tanenbaum.

La disponibilidad del código fuente de Linux o de cualquiera de los BSD siempre me ha permitido curiosear sobre las tripas de los sistemas. Mucho ha cambiado desde finales de los 90 el hardware y estos sistemas, pero de vez en cuando leo algo sobre los mismos en entradas de blogs o en proyectos interesantes como este: el funcionamiento e implementación del kernel de Linux, donde el autor está creando una referencia a la implementación de Linux, desde el cargador de arranque, la inicialización del núcleo, gestión de memoria, interrupciones,...

Linux puede ser muy duro para empezar, así que dejo en esta entrada la referencia a The little book about OS development, un libro que describe como crearse un pequeño sistema operativo desde cero para x86.

¿Ha roto la NSA el intercambio de claves Diffie-Hellman para algunos números primos?

Diffie - Hellman es un método de intercambio de claves criptográficas sobre un canal público de manera segura. Utiliza un número primo con unas determinadas propiedades y extremadamente grande que se usa para realizar una serie de operaciones matemáticas que permitan compartir una clave común sobre el canal público entre dos extremos. Este número es común a los dos extremos que inician un intercambio Diffie-Hellman. Hace falta mucha potencia de cálculo para romper sólo uno de estos números primos usados durante este tipo de intercambios.

Pero, ¿Qué ocurre, si por cualquier razón, la elección de estos números primos se reduce a unos pocos?. Es más, ¿Qué ocurre si muchos de ellos son valores predefinidos?. Pues que sólo hay que utilizar ese ataque una vez contra esos valores, y posteriormente, desencriptar fácilmente esa negociación Diffie-Hellman. Hay sospechas que la NSA está utilizando este sistema para desencriptar tráfico VPN: Ellos tienen el músculo financierio para poder montar las estructura de supercomputación que sea capaz de romper uno de estos números primos. Una vez roto, se puede usar para la multitud de tráfico que los utilizan. Actualmente, el problema más grave se da en los intercambios de clave del protocolo IPSEC, seguido por el protocolo ssh y https. Las cifras pueden verse en WeakDH.

Si alguien tiene más curiosidad sobre este tema, puede leer el Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice.

viernes, octubre 09, 2015

osquery (I)

Hace unos días que he empezado a mirar el software de inventariado osquery. Ha sido desarrollado por Facebook para obtener datos de instrumentación del equipo en el que está instalado a través de consultas similares a SQL. Es el equivalente en el mundo Linux a los sevicios WMI de Window y a WQL. Se trata de software libre cuyo código puede encontrarse en repositorio de Facebook de github. Puede compilarse desde el código fuente o bien bajar algunos de los paquetes que ya están compilados para diversos sistemas operativos.

Instalarlo en caso de OS X (Mavericks) es bajarse el paquete e instalar el correspondiente pkg a través del cuadro de diálogo que nos presenta. Una cosa que me gusta poco es que no hay posibilidad de comprobar una huella o una firma digital de lo que te bajas.

Una vez instalado puede ejecutarse la interfaz en línea de comandos, que recuerda mucho a la de sqlite. Con .help se puede obtener ayuda y con .schema se puede ver las diferentes tablas que se usan para representar las distintas entidades dentro del sistema. Por ejemplo, para obtener los procesos que están corriendo en el sistema. Se pu

osquery> select * from processes;

Pero lo interesante es la potencia que da hacer este tipo de queries a través de un lenguaje similar a sql. Por ejemplo si se quiere obtener el pid, el nombre y el path cuyo nombre sea bash:

osquery> select * from processes where name='bash';

Si se quiere ver los campos que tiene cualquiera de las tablas que representan los conceptos del sistema operativo se puede hacer con .schema tabla. Por ejemplo, las últimas versiones de OS X tienen un mecanismo de protección de aplicaciones llamado sandboxes. Para ver los campos de dicha tabla:

osquery> .schema sandboxes
CREATE TABLE sandboxes(label TEXT, user TEXT, enabled INTEGER, build_id TEXT, bundle_path TEXT, path TEXT);

Cuando se ejecuta osquery de esta manera, sólo se tendrá acceso a aquella información a la que está autorizado a acceder el usuario que lo está ejecutando

En la web del proyecto se puede consultar todas las tablas, tanto las generales como aquellas que son específicas de cada sistema a las cuales se pueden hacer consultas. Como se ve de esta breve introducción es una herramienta muy potente para instrumentalizar sistemas y así poder recoger información sobre los mismos y consolidarla en sistemas de gestión.

miércoles, septiembre 30, 2015

Pasmo: un ensamblador cruzado para Amstrad CPC

Me he animado a continuar con una pequeña serie sobre algunas cosas que he probado con el emulador de Amstrad CPC, por pura diversión. Esta entrada está dedicada a la instalación y uso de pasmo un ensamblador de Z80 creado por Julian Albo que nos va a permitir generar programas para usar en cualquier emulador de Amstrad CPC. Se instala en cualquier Unix de manera sencilla:

$ wget http://pasmo.speccy.org/bin/pasmo-0.5.4.beta2.tgz
$ tar zxvf pasmo-0.5.4.beta2.tgz
$ cd pasmo-0.5.4.beta2
$ ./configure --prefix=/usr/local
$ make
$ su
# make install

pasmo es un macro ensamblador que nos permite generar ficheros de código máquina en multitud de formatos de antiguas máquinas de 8 bits. Su sintaxis es muy similar al clásico de los 80 GEN3 de Hisoft. Permite macros, definiciones o ensamblado condicional. La documentación está en el fichero HTML pasmodoc.html.

Ensamblar un fichero es muy sencillo. Luego lo podemos transferir a nuestra imagen de disco y montarla en el emulador para ejecutar el programa que hemos ensamblado.

$ pasmo --amsdos mode.asm mode.bin
$ cpmcp imagen.dsk 0:mode.bin

El contenido del fichero mode.asm es un sencillo programa que se carga en la dirección #A000 e imprime el mensaje esto es una prueba

org #A000
        LD HL, MENSAJE
LOOP:   LD A, (HL)
        OR A
        RET Z
        PUSH HL
        CALL #BB5A
        POP HL
        INC HL
        JP LOOP
MENSAJE: DEFM 'Esto es un mensaje de prueba',0
Para cargarlo desde BASIC
MEMORY &9FFF
LOAD "mode.bin",&A000
CALL &A000

Crear imágenes de disco de Amstrad

Más allá del hacking value o de cierta nostalgia de otros tiempos no tiene mucho sentido andar enredando con emuladores de máquinas con micros de 8 bits, que funcionaban a 4 Mhz y tenían 64 o 128 Kb de memoría de RAM, con suerte un disco de 3" o 3.5" y lo más normal un magnetófono de cintas de cassete como medio de almacenamiento. El Amstrad CPC 6128 fue el primer ordenador que tuve. Me lo compraron en las Navidades de 7º de EGB. Junto al mismo, mi padre - sin saber muy bien lo que hacía, sospecho - compró el libro de Código máquina para principiantes con Amstrad de Steve Kramer. Con los años fui aprendiendo, programé algunas cosillas con BASIC y ASM, desemsabléa las ROMs, aprendí algo (poco) sobre el hardware, enredé con CP/M y me divertí bastante con multitud de juegos de la plataforma - sacando también de quicio a mis padres por el camino -. Todo un cóctel que me llevaría a mi actual mundo profesional.

A mis más de cuarenta años, me gusta de vez en cuando, en vez de un partidad a la PS3 , un X-Plane o algún juego de rol online, lanzar el Arnold en el Mac y disfrutar de alguna partitida a algún viejo clásico. En ello estaba, cuando hace unos días pensé, ¿me acordaré de algo de ensamblador de Z80?. ¿De como se programaba la máquina?. Me animé a buscar información y lo primero que me planteé es, ¿se puede trabajar en "cruzado" con las herramientas corriendo nativas en el Mac y luego subiendo al CPC?. Pues la respuesta es sí, por un lado pasmo un ensamblador de Z80 capaz de generar ficheros ejecutables para múltiples plataformas y por otro libdsk y cpmtools que me iban a permitir generar las imágenes que necesito. Esta entrada la voy a centrar, precisamente, en la generación de imágenes. Para ellos necesitamos sólo libdsk y cpmtools. Se compila la primera, se compila la segunda y ya tenemos una serie de programas que nos permiten crear imágenes y acceder a la mismas.

El primer paso es compilar libdsk:

$ wget http://www.seasip.info/Unix/LibDsk/libdsk-1.2.2.tar.gz
$ tar zxvf libdsk-1.2.2.tar.gz
$ cd libdsk-1.2.2
$ ./configure --prefix=/usr/local
$ make
$ su
# make install
# exit

El siguiente paso es compilar cpmtools, pero le vamos a indicar que utilice las librería que hemos compilado en el paso anterior

$ wget http://www.moria.de/~michael/cpmtools/files/cpmtools-2.20.tar.gz
$ tar zxvf cpmtools-2.20.tar.gz
$ cd cpmtools-2.20
$ ./configure --prefix=/usr/local --with-libdsk --with-defformat=cpcdata
$ make
$ su
# make install
# exit

El Amstrad CPC 6128 podía manejar 3 formatos de datos: De sisytema CP/M 3.0, de sistemas CP/M 2.2 y de datos. La diferencia estaba en la reserva de dos pistas en cada cara del disco para el cargador de arranque del sistema y otras propiedades (CP/M 3.0) o para el propio sistema operativo (CP/M 2.2). Además, en el caso del Amstrad, los ficheros podían residir en diferentes areas de usuario, indentificadas por un entero entre 0 y 15 - esto es herencia directa de CP/M -. Decir que por defecto, el CPC sólo es capaz de usar una cara de un disco, aunque el controlador de disco que utilizaba , el NEC 765, el mismo que el de un PC, podía manejar unidades de dos caras simultáneamente sin problemas.

Para crear una imagen de disco de CPC lo único que tenemos es que usar el programa dskform de las libdsk para que nos cree el mismo. Si quiero usar el formato de datos, la orden para generarlo sería la siguiente.

dskform -format cpcdata imagen.dsk

cpmtools instala varias utilidades para manejar ficheros dentro de las imágenes que creemos. En nuestro caso nos interesa las siguientes.

cpmls
Muestra los ficheros que hay en la imagen.
cpmrm
Permite borrar ficheros de la imagen.
cpmcp
Permite copiar ficheros a la imagen.

Por defecto todas estas utilidades están compiladas para usar el formato de datos del Amstrad CPC. Si fuera necesario usar otro, todas admiten el parámetro -f para indicar el formato que se desea usar (usando --help a cualquiera de ellas muestra la lista de formatos soportados).

Copiar un fichero y posteriormente borrarlo se haría con las siguientes órdenes.

$ cpmcp imagen.dsk text.bin 0:text.bin
$ cpmrm imagen.dsk 0:text.bin

Es necesario especificar el área de usuario a la hora de copiar com cpmcp (la que usa el sistema por defecto siempre es la 0). cpmcp no sobreescribe archivos, es necesario borrarlo antes con comrm

lunes, septiembre 28, 2015

Las cuentas gestionadas de gmail y API de auditoría.

Uno de los servicios que ofrece Google para empresas es el correo electrónico. Este se lleva a cabo a través de las llamadas cuentas gestionadas de Google. El administrador de un dominio de este tipo tiene acceso a toda la información que existe en las cuentas que gestiona. Eso incluye acceso a todos los buzones de correo. Pero lo más curioso de todo este tema es que Google pone a disposición de los usuarios de estos servicios un API que permite auditar el correo. Un simple conjunto de llamadas permite obtener toda la información que se quiera de las mismas. Lo interesante es que este API permite establecer monitores que vayan analizando y almacenando los correos que se deseen durante el periodo que se programe.

Ojo, no vayamos a pensar que esto es exclusivo de este tipo de cuentas. Cualquier máquina Unix puedes hacer un grep sobre los ficheros almacenados de correo, en el tradicional /var/spool/mail o Exchange permiten al usuario administrador leer todo el correo del usuario que sea.

Esto no es más que un simple recordatorio de la privacidad que ofrecen todos los sistemas de correo

domingo, septiembre 27, 2015

Imaginando un cisne negro: El cierre repentino de Google

Con todo el escándalo organizado por el trucaje de las emisiones de lo coches diesel de Volkswagen y la pérdida de casi un tercio de su capitalización hasta el punto de poder poner en peligro la viavilidad de la compañía, me ha dado por hacer un poco de ciencia ficción y plantearme el siguiente escenario:

Google se ve envuelto en un gran escándalo - del tipo que sea - que hace que pierda su capitalización bursatil en apenas una semana, situándose financieramente al borde de la bancarrota en cuestión de días.

¿Es disparatado ese escenario?. Probabemente, pero después de ver lo que le pasó British Petroleum tras el accidente de su plataforma en el golfo de Méjico, donde en cuestión de dos meses perdió el 40% de su capitalización bursátil y tuvo que vender activos para poder obtener liquidez y hacer frente a todas las consecuencias del vertido.

Imaginad que a una semana vista, deja de funcionar Gmail, Youtube o el buscador de Google. Bien, me podéis decir que hay alternativas a todos esos servicios, con mayor o menor uso (Yahoo, Bing), pero sinceramente, no es lo más importante. Google se ha convertido en muchos aspectos en una utility, es decir una empresa que da servicios relativamente básicos a otros en Internet: Autentificación, Hosting, medidas de tráfico,... Y multitud de empresas han montado sus servicios entorno a Google, en especial en cosas tan críticas como la autentificación - ya que Google permite tener todo centralizado en una única cuenta. No es la primera vez que una empresa que monta su negocio usando ciertos servicios que daba Google se encuentra con la desagradable sorpresa de que el servicio cierra porque Google no es capaz de monetizarlo o no le interesa. Ahora, imaginad las consecuencias de un escenario donde se plantee el cierre de Google. ¿Esto no va a ocurrir nunca?. Probablemente jamás ocurra. Es un tail event, un cisne negro.

Aunque el futuro de los próximos años parece que será la nube, no dejemos de tener en cuenta dos ideas claves:

  • La nube no existe, existe el ordenador de otra empresa donde tenemos nuestra lógica de negocio.
  • Si dependemos de servicios de terceros para nuestros negocios, siempre tener pensando un posible plan B. No sólo tenemos que hacer copias de seguridad de nuestros datos, sino evaluar todos los riesgos de que nos pasaría si un proveedor fallara.

Si ocurriera, ¿deberían los gobiernos rescatar a Google o nacionalizarlo? .... Buena pregunta después de todo lo visto estos años con la crisis financiera, la banca y multitud de empresas.

miércoles, septiembre 23, 2015

Debian Jessie: Deshabilitar startpar

Una de las nuevas características de Debian Jessie es el uso del sistema de arranque systemd. Uno de los objetivos de systemd es > es paralelizar al máximo el arranque del sistema para que este sea lo más rápido posible1. Systemd es un conjunto de programas exclusivos de Linux ya que usan ciertas llamadas al sistema que sólo están disponibles en él.

La existencia de systemd no elimina la necesidad de scripts da arranque, ya sea de programas heredados o bien porque hay programas que prefieren usar estos scripts de arranque que facilitan la portabilidad entre sistemas Unix. En Jessie, los scripts de arranque siguen estando en /etc/init.d y el concepto de runlevels sigue existiendo, sólo que ahora lo maneja systemd. Para ejecutar de manera simultánea varios scripts de arranque existe la utilidad startpar. Se supone que los scripts se han escrito de acuerdo a las Linux Standard Base para que puedan declarase las dependencias de manera correcta y startpar pueda ejecutar los mismos paralelizando al máximo y sin problemas de interdepencias entre ellos.

Sin embargo, esto no siempre es así y puede que en un momento dado sea necesario desactivar esta capacidad de arranque en paralelo para corregir problemas que se presenten en el sistema. En Debian es muy fácil realizar desactivarlo creando un fichero:

touch /etc/init.d/.legacy-bootordering

Para volver a disponer del arranque en paralelo de los diferentes scripts, simplemente borramos el fichero anterior

rm /etc/init.d/.legacy-bootordering

Notas

  1. Una pequeña maldad: ¿De verdad la gente apaga y enciende el sistema, en especial portátiles y sistema de escritorio o simplemente lo hiberna?.

jueves, septiembre 17, 2015

Repositorio con el código fuente de Unix los últimos 44 años

Diomidis Spinellis ha realizado un inmenso trabajo de recopilación del código fuente de Unix desde su concepción y primera versión en 1972 en Bell Labs hasta el actual FreeBSD 10.x. Las versión está ordenadas en el proyecto Unix History Repository en github. Toda una delicia para aquellos que quieran estudiar el origen Unix. El autor del mismo ha publicado un artículo titulado A Repository with 44 Years of Unix Evolution describiendo el proceso de creación del mismo. Tiene un gráfico muy chulo donde se puede ver la relación de las diferentes versiones.

En este repo no está incluido Linux - que es un clon de Unix - ni los sistemas Unix que derivaron de System V. Ah, ojalá Microsoft hiciese lo mismo con Windows, al menos sus versiones antiguas :)

viernes, septiembre 04, 2015

tmutil: Controlar Time Machine desde la línea de comandos (I)

Introducción

Time Machine es una funcionalidad de copias de seguridad incluida en MacOS X desde la versión 10.5 (Leopard). Permite realizar las copias de seguridad tanto a discos duros locales o a sistemas compartidos en red compatibles con el software. Normalmente se controla desde la interfaz gráfica, pero existe una utilidad de línea de comandos que permite su control.

En el caso de Time Machine, la herramienta de línea de comandos que se encarga del control de las copias de seguridad es tmutil. Normalmente, este comando necesita ejecutarse con permisos de superusuario para realizar su función.

La estructura del comando es la siguiente

tmutil comando [parametros]

Manejo de los discos donde se van a realizar las copias de seguridad

El primer paso que hay que dar para poder utilizar Time Machine es configurar los volúmenes donde se van a realizar las copias de seguridad. Si tenemos un que está montado en /Volumes/My Passport y lo queremos usar para copiar de seguridad, se añade al sistema con el comando setdestination -a path donde en nuestro ejemplo path es /Volumes/My Passport. Con ayuda del comando destinationinfo se pueden ver los volúmenes que están añadidos. El comando destinationinfo permite el uso del argumento -X que vuelca la información en formato XML plist.

root#tmutil  setdestination  -a "/Volumes/My Passport"
root#tmutil  destinationinfo
> ==================================================
Name          : Backups
Kind          : Local
Mount Point   : /Volumes/Backups
ID            : C54F9BEE-AE4F-4E7B-BD9E-6AA18CDD3F83
====================================================
Name          : My Passport
Kind          : Local
Mount Point   : /Volumes/My Passport
ID            : 1044185E-607C-45A6-A5C2-E96BD7C0D836

De la información que vuelca destinationinfo hay dos puntos importantes:

  • Cada volumen usado como copia de seguridad está identificado por un uuid único.
  • Se utiliza > para señalar cual ha sido el volumen donde se ha intentado realizar la última copia de seguridad del sistema en el caso de que haya varios volúmenes disponibles. En el ejemplo anterior puede verse que que el disco con ID C54F9BEE-AE4F-4E7B-BD9E-6AA18CDD3F83 es el último donde se ha realizado dicha copia.

Para quitar un volumen que se está usando para copia de seguridad se utiliza el comando removedestination id, siendo id el identificador que se obtiene. Por ejemplo, para eliminar el volumen /Volumes/My Passport

root#tmutil removedestination  1044185E-607C-45A6-A5C2-E96BD7C0D836
root#tmutil destinationinfo
====================================================
Name          : Backups
Kind          : Local
Mount Point   : /Volumes/Backups
ID            : C54F9BEE-AE4F-4E7B-BD9E-6AA18CDD3F83

Realizar una copia de seguridad

Realizar la copia de seguridad es muy sencillo. Basta con utilizar el comando startbackup.

root#tmutil startbackup

Una vez lanzada la orden anterior, tmutil contactará con el servidor de copias de seguridad y comenzará la operación de copia. La orden anterior lanza la copia en segundo plano, retornando si no ha habido ningún error. Una cosa curiosa que ocurre al lanzar una copia así es que en caso de error, este aparece en la interfaz gráfica.

Esta orden admite una serie de parámetros

startbackup [-a | --auto] [-b | --block] [-r | --rotation] [-d | --destination dest_id]

  • -a La copia de seguridad se realiza de manera similar a aquellas que el sistema programa.
  • -b tmutil espera a la finalización de la copia de seguridad para acabar la ejecución.
  • -r tmutil rotará las copias de seguridad de manera automática en el volumen donde se realice la misma.
  • -d Permite selecionar a través de su identificador el disco donde se quiere que se realice la copia de seguridad.

Por ejemplo, supongamos que se quiere realizar una copia de seguridad del sistema en el disco con id C54F9BEE-AE4F-4E7B-BD9E-6AA18CDD3F83 y esperar a que esta termine:

root#tmutil startbackup -b -d C54F9BEE-AE4F-4E7B-BD9E-6AA18CDD3F83

Restaurar copias de seguridad

El comando que permite la restauración de un fichero determinado es restore src dst. Su sintaxis es la misma que la utilidad cp. Los ficheros o directorios dentro de la copia de seguridad que se quiere restaurar especificado por src y el destino especificado por dst. Por ejemplo si quisiera restaurar dentro de una copia determinada el directorio /Users/terron al directorio /tmp

root#tmutil restore
/Volumes/Backups/Backups.backupdb/menzoberrazan/Latest/Users/terron /tmp

Terminología de Time Machine

Cuando se están realizando copias usando discos locales Time Machine crea en en el mismo la siguiente estructura de directorios

Backups.backupdb
    machine_name
        copia 1
        copia 2
           ⋮
        copia n
        Latest

La terminología que usa Apple para esta estructura es la siguiente

  • Al directorio Backups.backupdb se le llama backup store, que podría traducirse como almacén de copias de seguridad.
  • machine_name es un directorio que contiene todas las copias de seguridad de una máquina determinada. En el caso de estar usando un disco local para almacenar las copias de seguridad, cada directorio contiene las copias de seguridad de una máquina.
  • Dentro de cada máquina, se tiene cada una de las copias de seguridad que se han realizado y un enlace simbólico,Latest, que apunta a la última copia realizada.

A continuación se puede ver un ejemplo de esta estructura:

baldurgate:menzoberrazan terron$ls -al
total 8
drwxr-xr-x@ 4 terron  staff  136 28 ago 12:39 .
drwxr-xr-x+ 7 terron  staff  238  4 feb  2012 ..
drwxr-xr-x@ 7 terron  staff  238 20 may  2010 2010-05-20-225851
lrwxr-xr-x  1 terron  staff   17 28 ago 12:39 Latest -> 2010-05-20-225851
baldurgate:menzoberrazan terron$pwd
/Volumes/Backups/Backups.backupdb/menzoberrazan
baldurgate:menzoberrazan terron$

miércoles, agosto 26, 2015

Autotools, tutorial de uso (VII): Crear librerías dinámicas con libtool

Intruducción

En enlazado o linkado dinámico es un mecanismo implementado en la mayoría de sistemas operativos actuales que permite compartir código entre diferentes procesos ejecutándose en la máquina. se implementa normalmente con ayuda de la gestión de memoria virtual del sistema. Las librerías dinámicas son los ficheros donde se almacenan este código compartido las cuales se construyen de diferente manera en función del sistema operativo.

Para intentar aislar las particularidades en la construcción de librerías dinámicas existe la herramienta libtool que se integrar de manera sencilla con las autotools para generar las librerías dinámicas de manera portable.

libtool incluye un script,libtoolize, el que va a crear una serie de scripts y macros m4 en nuestro proyecto que nos permite generar librerías dinámicas olvidándonos de las particularidades del sistema donde lo hacemos. Estos scripts son usados por autoconf y por el script de configure para generar toda la lógica necesaria. Por defecto, los ficheros y scripts que añade son enlaces simbólicos a los mismos instalados en el sistema, pero pueden copiar a nuestros proyectos si se desea.

Voy a usar de ejemplo el código del tutorial 5 que he subido a SourceForge. El código es muy simple, crear una librería de enlace dinámico libtest con tres funciones que se llaman desde el binario principal. Los ficheros configure.ac, Makefile.am y autogen.sh con las macros necesarias para que compilen la librería y funcione el enlazado dinámico serían los siguientes:

configure.ac

El fichero de configure.ac sólo necesita añadir la macro LT_INIT. Esta macro cuando se expande para formar el fichero configure, añade toda la lógica necesaria para las opciones que controlan la creación de librerías dinámicas. Esta macro puede admitir parámetros para establecer cual debe ser el comportamiento por defecto de las opciones.

 1 dnl Esto es un comentario
 2 dnl Esta macro fuerza a una versión mínima de autoconf
 3 AC_PREREQ([2.59])
 4 AC_INIT([tut5],[1.0],[cterron@users.sourceforge.net],[tut5.tar.gz],[https://sourceforge.net/p/autotutorial/])
 5 LT_INIT
 6 dnl Necesitamos el compilador de C
 7 AC_CONFIG_HEADERS([config.h])
 8 AC_PROG_CC
 9 dnl Init automake 
10 AM_INIT_AUTOMAKE
11 AC_CONFIG_MACRO_DIR([m4])
12 dnl Debe de ir al final de la plantilla. Genera el fichero config.status
13 AC_CONFIG_FILES([Makefile])
14 AC_OUTPUT

Makefile.am

En este fichero se va a definir las plantillas que nos van a generar la libreria (llamada libtest) y el binario (tut5) que usará dicha librería. Para definir la librería usamos la variable lib_LTLIBRARIES. Esta es una lista de las librerías que vamos a crear. En nuestro caso libtest.la. Ahora se definen las fuentes que se van a usar para compilar generar la librería. Puesto que el nombre es libtest.la, la variable que hay que definir es libtest_la_SOURCES, en el caso del ejemplo libtest.c. La librería tiene un fichero de cabecera que queremos instalar para que se pueda usar por parte de otros programas,para lo que usamos la variable include_HEADER con la lista de ficheros de cabecera que se desea instalar. También añadimos una variable ACLOCAL_AMFLAGS para que incluya los ficheros de macros del directorio m4. Para que el binario se compile contra la librería dinámica, lo único que hay que definir la variable tut5_LDADD indicando que utilice libtest.la. El contenido del fichero es el siguiente:

 1 # Configurado par 
 2 # Construir la librería libtest.la con las funcioens f1,f2,f3
 3 # Instala la cabecera libtest.h en el sitio correspondiente
 4 # Compila un programa test_lib que llama a dichas funciones
 5 ACLOCAL_AMFLAGS = -I m4
 6 lib_LTLIBRARIES = libtest.la
 7 libtest_la_SOURCES = libtest.c
 8 include_HEADERS = libtest.h
 9 
10 bin_PROGRAMS = tut5
11 tut5_SOURCES = testlib.c
12 tut5_LDADD = libtest.la
autogen.sh

La única modificación necesaria en este fichero es añadir la llamada a libtoolize. Cuando se ejecute, configurará el sistema con los parámetros que deseemos pasarle

1 #!/bin/sh
2 aclocal -I m4  && \
3 rm -rf autom4te.cache/ && \
4 autoheader && \
5 automake --foreign --add-missing && \
6 libtoolize  && \
7 autoconf && \
8 ./configure $@
9 

Compilar y probar el resultado

Compilar el programa es sencillo. Se puede probar sin necesidad de instalar los binarios y las librerías con ayuda de las variables de entorno.

./autogen --prefix=/usr/local
make
env LD_LIBRARY_PATH=.libs/ .libs/tut5 # En Mac env DYLD_LIBRARY_PATH=.libs .libs/tut5

Enlaces

Actualizado 28/08/2015

miércoles, agosto 19, 2015

Controlar el portapapeles de OS X desde la línea de comandos

Mac OS X tiene dos comandos , pbcopy y pbpaste ,que permiten copiar manejar el portapapeles desde la línea de comandos. pbcopy leerá la entrada estándar almacenando los datos en portapapeles, mientras que pbpaste volcará el contenido del portapapeles por la salida estándar.

Por ejemplo, para copiar al portapapeles la salida del comando ls:

baldurgate:Documents terron$ls | pbcopy

Si se quiere copiar el contenido del portapaples a un fichero:

baldurgate:Documents terron$pbpaste > fichero.txt

Por otra parte, tener en cuenta que pbcopy intenta averiguar si los datos que va a copiar al portapapeles utilizan el formato EPS o RTF. En dicho caso, los copia con esos formatos. pbpaste por otra parte comprueba también los datos del portapapeles antes de volcarlos a la salida estándar: comprobará que es texto plano, sino si es EPS y por último RTF. Si los datos no están en ninguno de estos formatos, no vuelca nada.

Hay que tener en cuenta que estos dos comandos utilizan la variable de entorno LANG para determinar la codificación que deben de usar tanto en la entrada y la saluda.

miércoles, agosto 12, 2015

Crear una autoridad de certificación con OpenSSL

OpenSSL es un conjunto de utilidades y librerías que implementan diferentes rutinas criptográficas que ayudan a implementar todo tipo de protocolos seguros. Una de las funciones incluidas nos permite crear una autoridad de certificación o CA: una entidad en la que confiamos que puede emitir o revocar certificados que se usan para tener una comunicación segura.

En esta entrada pretendo crea una CA que nos permita generar certificados que puedan ser usardos para establecer conexiones https o conexiones cifradas con utilidades como socat. Esta CA estará autofirmada y será necesario que su certificado raíz esté disponible para aquellos programas que deseen comprobar la validez de un certificado firmado por la misma. Existen paquetes como easy rsa para quien no quiera hacer estos pasos manualmente.

Crear la autoridad de certificación

Para crear nuestra CA basta con bajarse el fichero de configuración config.cnf y seguir los siguientes pasos que se dan a continuación. En la última parte del artículo se hace un recorrido por todas las opciones de dicho fichero para comprender su funcionamiento.

  • Crear la estructura de ficheros
    mkdir /Users/terron/prog/ca
    mkdir /Users/terron/prog/ca/{certreqs,crls,private,certsdb}
  • Crear el fichero de configuración y el fichero de base de datos.
    cd /Users/terron/prog/ca
    wget -O config.cnf https://sites.google.com/site/underdarktales/home/propios/config.cnf?attredirects=0&d=1
    touch index.txt
  • Crear la clave privada y el CSR de la autoridad de certificación. El sistema pedirá el valor de ciertos atributos del certificado que están definidos en el fichero de configuración, en la sección de la política - ver al final del artículo -
  • cd /Users/terron/prog/ca
    openssl req -new -nodes -newkey rsa:4096 -keyout private/cakey.pem -out careq.pem -config config.cnf
    Las opciones que se le pasa a openssl req son las siguientes:
    • -config Usa el fichero de configuración config.cnf
    • -new Crea una nueva petición de CSR.
    • -newkey Crea una nueva clave RSA. En este caso de 4096 bits de longitud.
    • -nodes Indica que no se debe cifrar la clave privada. Recordar que para mantener la integridad de la CA, es necesario proteger esta clave al máximo.
    • -keyout Ruta al fichero donde se escribirá la clave privada. Se almacenará en private/cakey.pem
    • -out Ruta al fichero donde se escribirá el CSR. Se almacenará en careq.pem
  • Crear el certificado autofirmado e iniciar el número de serie. Este es el certificado que debe de distribuirse a aquellos programas que quiera verificar la autenticidad de un certificado firmado por nuestra CA.
    cd /Users/terron/prog/ca
    openssl ca -create_serial -out cacert.pem -days 3650 -keyfile private/cakey.pem -selfsign -extensions v3_ca -config ./config.cnf -infiles careq.pem
    Con esta llamada a openssl ca se generará el fichero cacert.pem que será el que se deba de distribuir como certificado raíz de nuestra CA. Los parámetros con los que se llamarán serán los siguientes:
    • -config Ruta al fichero de configuración. En nuestro caso config.cnf.
    • -create_serial Esta opción creará el fichero serial.txt y creará un número aleatorio de 128 bits en hexadecimal que se irá incrementando con cada certificado firmado.
    • -out Ruta donde se depositará el certificado firmado por la CA. Además, creará una copia en el directorio certsdb.
    • -days Número de días en las que será válido el certificado desde el momento en que se firme. En este caso, al ser la raíz de la CA, 10 años.
    • -keyfile Clave privada de la CA que se va a usar para generar el certificado firmado.
    • -selfsign Indica que se quiere un certificado autofirmado. Esto se hace para generar el certificado raíz de la CA.
    • -extensions Utiliza la extensión de certificado X.509 definida en el fichero de configuración. En este caso se utiliza la extensión llamada v3_ca y define los atributos necesarios para que el certificado generado sea el raíz de una CA.

Generar un certificado firmado por nuestra CA

Para generar un certificado firmado por nuestra CA es necesario dar los siguientes pasos:

  • Generar una clave privada y un CSR. Es importante, en el caso de querer usar este certificado para https que el campo CN que nos pregunta el comando coincida con el nombre del host o en su caso con la dirección IP, sino no funcionará.
    openssl req -new -nodes -newkey rsa:4096 -keyout server.key.pem -out server.req.pem -config config.cnf
  • Usar el CSR (fichero server.req.pem) generado en el paso anterior para generar nuestro certificado firmado por nuestra CA. Esta orden nos mostrará los atributos del certificdado que está apunto de firmar para que confirmemos la operación.
    cd /Users/terron/prog/ca
    openssl ca -config config.cnf -days 365 -keyfile private/cakey.pem -extensions v3_req -in server.req.pem -out server.cert.pem
    Las opciones son similares al caso del certificado raíz, pero usando otras extensiones para el certificado X.509

Restricciones y posibles problemas

  • La base de datos de texto que usa openssl ca para guardar los certificados firmados es crítica. Si se pierde peude haber problemas.
  • No hay ningún tipo de soporte para concurrencia en openssl ca a la hora de firmar los certificados.

El fichero de configuración

Esta sección contiene una descripción detallada del fichero de configuración config.cnf usado como ejemplo en los pasos anteriores. Este fichero está compuesto de secciones que se utilizan en función de la utilidad de OpenSSL que se llame. Nosotros vamos a usar openssl req y openssl ca para la generación de la autoridad de certificación.

La sección de ca

La estructura de directorio que se va a usar es la siguiente. ROOT indica cual es el directorio raíz donde va a residir los ficheros de nuestra autoridad de certificación.

ROOT
    certsdb
    private
    certreqs
    crls

En el fichero de configuración se va a definir en primer lugar cuales son las opciones que se van a usar. En primer lugar vamos a definir la sección que se va a usar por defecto para defecto para generar la autoridad de certificación.

[ ca ]
default_ca = CA_default

[ CA_default ]
dir              = /Users/terron/prog/ca
database         = $dir/index.txt
new_certs_dir    = $dir/certsdb
certificate      = $dir/cacert.pem
serial           = $dir/serial
private_key      = $dir/private/cakey.pem
RANDFILE         = $dir/private/.rand
default_days     = 365
default_crl_days = 30
default_md       = sha256
policy           = policy_any
email_in_dn      = no
name_opt         = ca_default
cert_opt         = ca_default
copy_extensions  = none

[ policy_any ]
countryName            = supplied
stateOrProvinceName    = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

Esta primera sección del fichero config.cnf configura el comportamiento del comando openssl ca. Cuando se llame a dicho comando, pasándole la opción -config config.cnf buscar la sección [ ca ]. En dicha sección le hemos dicho, que por defecto, utilice la sección [ CA_default] la cual configura una serie de propiedades de la autoridad de certificación que se está creando.

En primer lugar, se definen una serie de rutas que se van a usar para almacenar los diferentes ficheros y directorios necesarios para el funcionamiento de la autoridad de certificación. Se va a referenciar a partir de la ruta raíz de la autoridad que está definida en la variable dir y en el ejemplo anterior es /Users/terron/prog/ca. Cuando openssl cuando carga el fichero de configuración realizará las sustituciones de variables necesarias por nosotros. Por ejemplo, en nuestro caso $dir/index.txt pasa a ser /Users/terron/prog/ca/index.txt.

Los parámetros que se configuran en esta sección [ Ca_default ]

  • database Configura la ruta hacía la base de datos de certificados. Este parámetro es obligatorio que exista y el fichero debe de existir cuando se empieza a usar la autoridad de certificación. Puede crearse con touch. Se puede especificar la ruta desde la línea de comandos con -database.
  • new_certs_dir Configura la ruta al directorio donde se almacenarán los nuevos certificados firmados por la autoridad de certificación. Este parámetro es obligatorio. Se puede tambiér especificar desde la línea de comandos con -outdir.
  • certificate Ruta hacía el certificado raíz de la autoridad de certificación. Es obligatorio y también puede especificarse desde la línea de comandos con -cert.
  • serial Contiene el siguiente número de serie en hexadecimal para usar en el certificado. Normalmente, en los ejemplos que he visto en Internet se solía configurar con 01, pero es mejor usar una opción cuando se crea el certificado raíz que lo autogenere.Este parámetro es obligatorio.
  • private_key Esta es la clave privada de la autoridad de certificación. De su seguridad depende la integridad de todo el proceso de la autoridad de certificación.
  • RANDFILE Ruta a un fichero usado para leer y escribir semillas que sirvan para la generación de números aleatorios.
  • default_days Número de días en los que será válido un certificado. También puede especificarse con ayuda de la opción de línea de comandos -days.
  • default_crl_days Número de días hasta que se publique la siguiente CRL
  • default_md Algoritmo de huella digital que se utilizará en los certificados y en la lista de revocación de los mismos. Se puede pasar con la línea de comandos con la opción -md. Es obligatoria.
  • policy Configura la sección donde se define la política que va a usar la autoridad de certificación para verificar un certificado. Esta política define qué campos deben de estar presentes y cuales deben de coincidir. Se puede pasar en la línea de comandos con -policy y es obligatoria su definición.
  • email_in_dn Si este campo no está presente o vale yes el campo email, se copiará al . Está configurado para que no se copie.
  • name_opt, cert_opt Estos dos campos controla los campos que se muestran cuando se pide la verificación de un certificado . Existen varios campos, pero lo razonable es dejar el campo ca_default.
  • copy_extensions Controla que hacer con las extensiones que estén presente en las CSR. Si el valor es none , no se copiará ninguna de las extensiones que vengan presenten en el CSR, copy hará que se copia toda extensión que no esté en el certificado destino y copyall copia todas las extensiones del CSR. Hay que tener especial cuidado al usar las opciones copy y copyall porque puede suponer un riesgo de seguridad.

En este fragmento de fichero de configuración se ha definido una política, policy_any. La política corresponde a una serie de campos identificados por su DN. Estos campos tienen tres posibles valores:

  • match El campo debe de existir en el certificado y debe de coincidir con el mismo de la autoridad de certificación.
  • supplied El campo debe de existir.
  • optional El campo puede existir.

Cualquier campo que no esté especificado en la política será descartado sin advertencia. En nuestro ejemplo se ha definido una política que tiene seis campos de los cuales dos son obligatorios y deben de estar presentes. El resto son opcionales.

La sección req

El comando openssl req se controla a través de las sección [ req ] del fichero de configuración. Este comando es el encargado de generar peticiones para que la autoridad de certificación nos la firme. También es el encargado de generar certificados autofirmados para usar en nuestras propias autoridades de certificación. El fragmento del fichero de configuración que se utiliza es el siguiente:

[ req ]
default_bits            = 4096
default_md              = sha256
prompt                  = yes
x509_extensions         = v3_req
distinguished_name      = req_distinguished_name
string_mask             = utf8only
[ v3_req ]
basicConstraints        = CA:FALSE
keyUsage                = keyEncipherment, dataEncipherment
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address
countryName_default             = ES
stateOrProvinceName_default     = Madrid
localityName_default            =
0.organizationName_default      = Testing OpenSSL S.L.

Los paramétros de configuración de la sección anterior define:

  • default_bits Número de bits por defecto - si no se especifica otra cosa - que tendrán la clave privada de los certificados que se generen.
  • default_md Algoritmo de huella digital que se utilizará por defecto.
  • prompt Si vale no, cogerá los valores por defecto de los campos que utilice el certificado del fichero de configuración. En nuestro caso vale yes porque queremos que el sistema nos pregunte por los campos que se quieren que vayan en el certificado.
  • x509_extensions Este campo nos indica una sección dentro del fichero de configuración que se usará cuando se ejecutemos openssl req con la opción -x509. Esta sección especifica una serie de extensiones que se añadirán al certificado. En este caso se está especificando que utilice la sección [ v3_req ].
  • distinguished_name Especifica la sección donde se definen los campos por los cuales se preguntará al usuario cuando se genere un CSR o un certificado. En este caso la sección se llama req_distinguished_name.
  • string_mask indica que tipo de cadenas de caracteres se va a usar en los campos del certificado. En este caso, se indica que sólo se aceptaran cadenas UTF-8 válidas.

En nuestro caso, la extenciones que se quieren añadir al certificado son

  • basicConstraints
  • keyUsage

Las sección req_distinguished_name define qué campos van a ir en el certificados. Se pueden definir aquellos que se deseen, siempre que se definan a través de la sección oid_section o oid_file. Existen ya una serie de nombres definidos (con sus correspondientes identificadores) en OpenSSL. En nuestro ejemplo se han definido siete campos, y posteriormente algunos valores por defecto (nombre del campo_default)

La sección para las extensiones de la Autorida de Certificación

Para terminar, es necesario añadir una sección especial en el fichero de configuración donde se definen una serie de extensiones a los certificados X.509 que nos permitirán crear la autoridad [ v3_ca ]:

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, cRLSign, keyCertSign

Esta sección define una serie de restricciones que se usarán para generar el certificado raíz de la autoridad de certificación:

  • subjectKeyIdentifier Indica como se debe de calcular el atributo Subject Key Identifier del certificado. Debe de dejarse en el valor de hash.
  • authorityKeyIdentifier Este campo configura como debe de calcularse el atributo Authority Key Identifier, que sirve para identificar la autoridad de certificación que ha firmado un certificado. Este campo indica que se usará para indentificar a la misma. En ecaso del ejemplo se usa el keyid - el identificador de la clave de la autoridad de certificación y issuer que hace que se utilicen los campos Subject y el número de serie del certificado de la CA. Aunque esta configuración puede presentar un problema en caso de que tenga que rehacerse la CA con la misma clave privada.
  • basicConstraints Este es una extensión que indica que el certificado puede actuar como una autoridad de certificación y permite restringir la longitud de la cadena de certificación. En este caso se le está indicando que el certificado si es una CA y que es crítica, es decir, que sino puede acceder a ella no puede ser procesado
  • keyUsage Esta extensión determina cuales son los usos apropiados de la clave de la CA: Al menos debe ser capaz de firmar la lista de revocación de certificados (cRLsign) y los certificados (keyCertSign). En el caso de que esta extensión no esté presente, se permiten todos los usos de las claves.

Referencias