Ocultar comunicaciones de miradas indiscretas

Ocultar las comunicaciones con codificación en Base64
Ocultar las comunicaciones con codificación en Base64

Para ocultar nuestras comunicaciones de nuestros dispositivos IOT, no es necesario utilizar complejos métodos de encriptación. En la actualidad se dispone de diversos métodos de codificación para que las comunicaciones entre nuestros dispositivos IOT, ya sean creados con arduino o con el ESP32, y los sistemas centrales, no tengan que hacerse en texto plano.

Una de las premisas que suelen usar los ciberdelincuentes es la de, esfuerzo/recompensa.

Si están intentando vulnerar un sistema bancario, el esfuerzo que les puede llevar sera muy grande, pero la recompensa también lo es.

Pero si lo que están vulnerando es el sistema de riego de mi jardín, la recompensa es muy baja. Con lo que aumentando el grado de esfuerzo necesario para la vulneración, podemos eliminar una gran mayoría de amenazas.

Recordatorio: Esto no es un sistema para asegurar las comunicaciones de la Nasa o del FBI. Solo es un sistema para darle una capa más de seguridad a nuestros pequeños proyectos.

Teniendo en cuenta esta premisa, para ocultar nuestras comunicaciones no hace falta desplegar un gran sistema criptográfico para hacer que los crackers desistan con el ataque a nuestro sistema.

Para ello solo tenemos que utilizar los métodos de codificación que tenemos a nuestro alcance, como puede ser la codificación en Base64.

Un poco de teoría

La codificación base64 se define como:

Base64 es un grupo de esquemas de codificación de binario a texto que representa los datos binarios mediante una cadena ASCII, traduciéndolos en una representación radix-64. El término Base64 se origina de un sistema de codificación de transmisión de contenido MIME específico.

https://developer.mozilla.org/es/docs/Web/API/WindowBase64/Base64_codificando_y_decodificando

Este tipo de codificación la tenemos disponible en cualquier lenguaje de programación. Lo que la hace muy fácil de usar.

Una de las formas más fáciles de identificar que una cadena esta codificada en base64, es, si la cadena termina en uno o dos símbolos de igual. Esto se debe a que base64 usa 6 bits de los 8 de los normales. Para cubrir ese hueco el algoritmo de base64 lo rellena con 1 o con dos símbolos de igual.

Otra forma que se puede usar para identificar la codificación, es que la cadena solo está compuesta por letras de la «a» a la «z», tanto en mayúsculas, como en minúsculas, números del 0 al 9 y los símbolos, normalmente, «+» y «/». Ya que la suma de letras y número es 62, y se usan eso dos símbolos para completar los 64.

¿Pero solo con eso puedo ocultar mis comunicaciones?

Pero, ¿si base64, está implementado en todos los lenguajes?, ¿es fácil de identificar?, el esfuerzo de un malo, más bien es poco ¿no?. Pues si, pero ya tenemos la base de nuestro sistema.

Si ya sabemos los puntos débiles del sistema, podemos detectarlos y reforzarlos.

Por ejemplo, sabemos que base64, nos pone en ocasiones, símbolos de igual si la cadena no tiene la longitud deseada. Pues vamos a controlar que la cadena tenga la longitud necesaria para que no incluya los símbolos de igual.

Esto es fácil, solo tenemos que controlar que el tamaño sea múltiplo de 3. Si no es múltiplo añadiremos tantos caracteres como sean necesarios.

Para el tema de los caracteres usados, es más compleja su solución. Pero podemos aplicar un método fácil para dificultar la codificación. Para ello solo tenemos que invertir la cadena en base64, por ejemplo, antes de su envió. Podría ser una forma de ofuscar. Se podrían aplicar otras.

Código, que es lo que mola

Un código de ejemplo que nos permite ocultar nuestras comunicaciones de lo explicado anteriormente en python sería el siguiente.

#!/usr/bin/env python

"""
    Encode base64
"""
import base64

def encode(encode):
    # Calculamos si la cadena es múmtiplo de 3
    rest_message = len(encode.encode('utf-8')) % 3
    if rest_message == 0:
        temp_message = encode
    else:
        # Si no es múltiplo de 3, le añadimos tantos caracteres
        # como necesitemos    
        temp_message = encode + (" " * (3 - rest_message))
    # Lo codificamos en utf-8
    message_byte = temp_message.encode('utf-8')
    # Lo codificamos en base64
    codec_base64 = base64.b64encode(message_byte)
    # Decodificamos el utf-8e invertimos la cadena
    string_codec_base64 = codec_base64.decode('utf-8')[::-1]

    print(f'encode: {string_codec_base64}')

if __name__ == "__main__":
    string_encode = "Esto es una prueba más"
    encode(encode=string_encode)

Para calcular si la cadena es múltiplo de 3 usamos la siguiente linea

rest_message = len(encode.encode('utf-8')) % 3

Si el resto es cero, la longitud de la cadena es múltiplo de 3, por lo que no tenemos que añadir nada. Si fuera distinto de 0, es decir 1 o 2. El valor nos valdría para calcular cuantos caracteres nos hacen faltan.

if rest_message == 0:
    temp_message = encode
else:
    # Si no es múltiplo de 3, le añadimos tantos caracteres
    # como necesitemos    
    temp_message = encode + (" " * (3 - rest_message))

Una vez que ya tenemos ajustado el tamaño solo nos queda codificarla en base64

# Lo codificamos en utf-8
message_byte = temp_message.encode('utf-8')
# Lo codificamos en base64
codec_base64 = base64.b64encode(message_byte)

Para darle la vuelta solo tenemos que añadir [::-1] a la cadena con la codificación en base64

string_codec_base64 = codec_base64.decode('utf-8')[::-1]

Y con esto ya tenemos un sistema fácil de implementar, todos los lenguajes tiene librerías para trabajar con ello. Y que a los malos no le resulte tan fácil.

Vuelta el recordatorio: Esto no es un sistema para proteger información delicada, si no, un método para darle una capa mayor de seguridad a nuestros pequemos proyectos.

Como dormir el ESP32 (deep-sleep)

Dormir nuestro controlador esp32 es la forma más fácil de ahorro de energía que podemos implementar en nuestros sensores de IOT.

En mucho desarrollos con arduino o con similares, como el esp32, por ejemplo. La mayoría de las veces no hace falta que esté constantemente enviando datos o procesándolos. Y si además nuestro dispositivo es autónomo la variable de ahorro de energía cobra mayor importancia.

En los sistemas basados en ESP32 tenemos una forma fácil y sencilla de que nuestro dispositivo IOT pueda ahorrar energía. Para ello solo tenemos que añadir el código para indicarle que pase a modo «durmiente» y conectar la salida D0 al pin de reset. 

El comando que necesitamos para dormir el ESP32 es el siguiente.

ESP.deepSleep(tiempo_milisegundos, modo reinicio)

Modos de uso para dormir el ESP32

Los modos que podemos usar son:

  • modem-sleep: este modo de ahorro permite desactivar la conexión WiFi de tipo Station , establecida con un punto de acceso (router), cuando no sea necesario su uso y volver a activarla cuando se necesite.. El consumo típico en este modo es de 15mA.
  • light-sleep: este modo de ahorro permite mantener la conexión WiFi de tipo Station, pero reduce el consumo de energía en los momentos en los que no hay envío de información.. El consumo típico pasa a ser de unos 0,5 mA.
  • deep-sleep: es el modo que genera mayor ahorro, pero a costa de dejar la placa en suspenso. La única parte de la placa que funciona durante este modo es reloj en tiempo real (Real Time Clock o RTC) para poder reiniciarla cuando haya finalizado el tiempo de reposo. El consumo típico pasa a ser de unos 10 uA.

Además de dispones de los siguientes modos de reinicio.

  • WAKE_RF_DEFAULT: Calibración de señal de radio si es necesario
  • WAKE_RFCAL: Calibración de señal de radio siempre
  • WAKE_NO_RFCAL: Sin calibración de la señal de radio
  • WAKE_RF_DISABLED: Deshabilita la señal de radio después del reencendido

El modo en el que más ahorro de energía conseguiremos es en el modo WAKE_RF_DEFAULT, ya que este modo es el que desactiva todos los sistemas no esenciales del ESP32.

En el siguiente enlace, podemos obtener más información de estos modos de uso y reinicio:

http://arduinoamuete.blogspot.com/2017/01/modo-deep-sleep-en-esp8266.html

La otra condición que tenemos que establecer, es el de conectar el pin D0 con el pin de reset. Ya que una vez que transcurra el tiempo que hemos indicado, este enviara una señal por el pin D0 para activar el reinicio del dispositivo.

ESP32 Deep Sleep
Puente entre D0 y reset para el reinicio

Código de ejemplo

Para la gestión podemos usar el siguiente ejemplo:

// Deep sleep mode

if (millis() >= (time_sleep + start_time)) {

    // Deep sleep mode, the ESP8266 wakes up by itself when GPIO 16 (D0 in NodeMCU board) is connected to the RESET pin

    Serial.print("I'm awake, but I'm going into deep sleep mode for ");

    Serial.print(SLEEP_TIME);

    Serial.println(" seconds");

    ESP.deepSleep(SLEEP_TIME * SECONDS, WAKE_RF_DEFAULT);

}

else

{

    Serial.println("I'm alive");

    delay(500);

}

 

Con esto conseguiremos que nuestro sensores autónomos tenga una mayor autonomía.

 

conocer modelo tarjeta grafica mediante consola de Linux

Los sistemas linux ofrecen una serie de comandos para obtener diversa información del hardware instalado en el sistema.

Para obtener la información de la tarjeta grafica del sistema, podemos usar los siguientes comandos.

Para obtener la información basica del dispositivo, podemos ejecutar el siguiente comando:

lspci | grep VGA

la respuesta de este comando puede ser algo parecido a lo siguiente:

00:02.0 VGA compatible controller: Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 0b)

La información que devuelve este comando se divide en la siguiente información

  • 00:02.0: Id del dispositivo. Este valor va ha ser muy importante para la obtención de más información.
  • VGA compatible controller: Clase de dispositivo.
  • Intel Corporation: Fabricante del dispositivo.
  • Haswell-ULT Integrated Graphics Controller (rev 0b): Descripción del dispositivo.

Si lo que necesitamos es solo el Id del dispositivo podemos usar la siguiente combinación de comandos.

lspci |grep VGA | awk '{print $1}'

Una vez que conocemos el id del dispositivo podemos utilizar otra conjunción de comandos para obtener más información del dispositivo.

lspci -v -s 00:02.0

Esta conjunción de comandos nos mostrara una información más detallada sobre el dispositivo. Mostrara algo parecido a lo siguiente

00:02.0 VGA compatible controller: Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 0b) (prog-if 00 [VGA controller]) Subsystem: Lenovo Haswell-ULT Integrated Graphics Controller Flags: bus master, fast devsel, latency 0, IRQ 49 Memory at b2000000 (64-bit, non-prefetchable) [size=4M] Memory at a0000000 (64-bit, prefetchable) [size=256M] I/O ports at 5000 [size=64] Expansion ROM at 000c0000 [virtual] [disabled] [size=128K] Capabilities: Kernel driver in use: i915 Kernel modules: i915

Podemos simplificar estos comandos usando la siguiente conjunción de comandos.

lspci -v -s `lspci | grep VGA | awk '{print $1}'`

Si ejecutamos el comando sin privilegios de superusuario, la información del campo «Capabilities» no se mostrara. Si deseamos ver esa información tendremos que lanzar el comando con un nivel de superadministrador. De la siguiente forma.

sudo lspci -v -s `lspci | grep VGA | awk '{print $1}'`

Con lo que ya tendremos acceso a toda la información.

00:02.0 VGA compatible controller: Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 0b) (prog-if 00 [VGA controller]) Subsystem: Lenovo Haswell-ULT Integrated Graphics Controller Flags: bus master, fast devsel, latency 0, IRQ 49 Memory at b2000000 (64-bit, non-prefetchable) [size=4M] Memory at a0000000 (64-bit, prefetchable) [size=256M] I/O ports at 5000 [size=64] Expansion ROM at 000c0000 [virtual] [disabled] [size=128K] Capabilities: [90] MSI: Enable+ Count=1/1 Maskable- 64bit- Capabilities: [d0] Power Management version 2 Capabilities: [a4] PCI Advanced Features Kernel driver in use: i915 Kernel modules: i915

En este ejemplo nos hemos centrado en la tarjeta grafica, pero se puede utilizar para obtener información de cualquier tipo dispositivo conectado al ordenador.

Como siempre, si tienes cualquier duda o problema, nu dudes en escrbirnos un comentario.

Activar ejecución de script en PowerShell

La ejecución de script en PowerShell esta bloqueado por defecto, ademas de la recomendación de bloquearlo en las directivas de grupo si estamos dentro de un directorio activo.Script en PowerShell

Pero en ocasiones nos vemos en la necesidad de ejecutar algun script en powershell. Como fue en mi caso activar el entrono virtual para desarrollar en Python. No suelo utilizar windows, pero las obligaciones son las que son.

Powershell nos ofrece varios comandos para configurar este tipo de configuraciones.

Estado de las politicas de ejecución

Para ver nuestra configuración respecto a la politica de ejecución de script en nuestro powershell podemos utlizar el comando

Get-ExecutionPolicy

La salida de este comando nos mostrara el nivel de restriccion en el que nos escontramos actualmente. El valor por defecto suele ser «Restricted». No podemos ejecutar ningun tipo de de script .ps1.

Tipos de politicas de ejecución de PowerShell

Los tipos de restricciones que nos podemos encontrar son las siguientes.

RESTRICTED: Es la opción predetermida a partir de sistemas Windows 8 y Windows Server 2012. No permite la ejecución de ningun tipo de script.

ALLSIGNED: Podemos ejecutar, siempre y cuando, el script este firmado por una organización de confianza. Antes de la ejecuión nos pedira autorización.

REMOTESIGNED: Es la opción predeterminada en Windows Server 2012 R2. Podemos ejecutar script, tanto locales como remotos. Los descargados desde internet tendran que estar desbloqueados.

UNRESTRICTED: Podemos ejecutar cualquier tipo de script, tanto lo firmado como los que no lo estan. Alto riesgo de ejecutar script peligrosos.

BYPASS: No bloquea la ejecuación de ningun script, tampoco nos pìde confirmación. Este modulo esta pensado para los script que se ejecutan embebidos dentro de otras aplicaciones más grandes.

UNDEFINED: Sin ningun tipo de restricciones.

Como cambiar las policas de ejecución en PowerShell

Aunque tengamos establecida la politica predeterminada, podemos establecer otro tipo de politica global que mejor se ajuste a nuestras necesidades. Para hacer esto utilizaremos el comando

Set-ExecutionPolicy

Si ejecutamos el comando sin ningun tipo de parametro, este no pedira el tipo de politca que deseamos utilizar.

Para saltarnos este paso podemos establecer el tipo de politica que deseamos utlizar seguido del comando, o seguido del paramentro «-ExecutionPolicy», por ejemplo

Set-ExecutionPolicy Unrestricted

o

Set-ExecutionPolicy -ExecutionPolicy Unrestricted

Pero en ocasiones las directivas establecidas en las politicas del dominio en el directorio activo, nos lo impide.

Ambitos en las directivas de ejecución

PowerShell nos estable varios ambitos de ejecución. Si por politicas en el directorio activo, estas bloque algun tipo, como es mi caso, el cambio global puede no estar permitido. Para saltar esta restrición podemos establecer el tipo de politica de ejecución ha algun ambito de ejecución en concreto.

Tipos de ambitos de policas de ejecuión

En PowerShell tenemos tres ambitos para ejecutar nuestro script.

PROCESS: La politica de ejecución se estable para la sesión actual. Al reiniciar se establecera de nuevo la politica establecida por defecto.

CURRENTUSER: Este ambito avarca al usuario actual. Se cambia en estado en la subclave que se encuentra en HKEY_CURRENT_USER que se encarga de almacenar la configuración del usuario actual.

LOCALMACHINE: Este ambito se aplica a la maquina local, cualquier usuario que se registra en la maquina afectada tendra la politica de ejecución que establezcamos.

Em mi caso el problema que me impedia cambiar la politica global es la restricción en las politicas del directorio activo para establecer el tipo en el ambito de LOCALMACHINE.

Podemos ver las configuraciones de los diferentes ambitos los podemos realizarar indicando el parametro -List al comando Get-ExecutionPolicy

Get-ExecutionPolicy -List

El comando de Set-ExecutionPolicy nos permite especificar en que ambito queremos interactuar.

Para ello ejecutaremos el comando de la siguiente forma Set-ExecutionPolicy -Scope Ambito_queremos_actuar tipo_politica, por ejemplo

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

 

Instalar servidor NGINX, y configurar virtual host en Ubuntu 18.04

Entre la variedad de seServidor web nginx en ubuntu 18.04rvidores web para linux, el más habitual suele ser Apache. Pero hay uno que esta comiendole terreno. Este es NGINX.

Instalación del servidor web NGINX

Para instalar este servidor en un Ubuntu 18.04 es facil, solo tenemos que tirar de repositorio y lo tendremos instalado sin ningun problema.

sudo apt-get update
sudo apt-get install nginx

En cuanto termine, ya tendremos instalado nuestro servidor web en nuestro sistema bajo Ubuntu 18.04

Abrir los puertos en el firewall del Ubuntu 18.04

Una de las opciones que nos agrega la instalación de nginx, es añadir los diferentes modos de funcional el servidor web, al firewall que trae por defecto la distribución de Ubuntu.

sudo ufw app list

Para activar los puertos de nginx en el firewall solo tendremos que utilizar el nombre del metodo que deseamos activar.

Para el modo de «http», le indicamos a firewall que queremos usar el metodo «Nginx HTTP». Con esta opción abriremos el puerto 80 en el firewall.

sudo ufw allow 'Nginx HTTP'

Para activar el modo HTTPS, y abrir el puerto 443 para la conexión seguras, utilizaremos la opción ‘Nginx HTTPS’

sudo ufw allow 'Nginx HTTPS'

Configurar un virtual host en el nginx

La configuración de los virtual host en el servidor nginx, es muy parecida a la que utilizamos en el servidor apache. en el directorio de nginx (/etc/nginx), tenemos las mismas carpetas que encontramos en el apache (sites-avaliable, sites-enabled, modules-available, modules-enabled, etc). La unica diferencia que encontramos con respecto Apache, es que los enlace simbolicos, que en apache los creamos con a2ensite o a2dissite, etc. En el caso de nginx los tendremos que crear manualmente.

sudo ln -s /etc/nginx/sites-available/virtualhost.conf /etc/nginx/sites/enabled/

Crear el fichero de configuración del virtualhost

En la carpeta de /etc/nignx/sites-available/ tenemos un fichero con la configuración por defecto del servidor. Podemos usar este fichero como plantilla para nuestros virtual host.

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/virtualhost1.conf

Editamos el fichero que hemos creado, para personalizar la configuración de nuestro virtual host.

sudo nano /etc/nginx/sites-available/virtualhost1.conf

Una de las primeras lineas que nos encotramos son las siguientes

listen 80 default_server;
listen [::]:80 default_server;

Lo primero que deberemos de hacer es eliminar «default_server»,  de las dos lineas. A no ser que queramos que este virtual host que estamos configurando sea el servidor por defecto. En ese caso tendremos que, o eliminar el enlace simbolico de «default» dentro de la carpeta de los sites activados (/etc/nginx/sites/enabled/). O eliminar esa opción del fichero «default». Tener dos host configurados como servidor por defecto da un conflicto en el servidor web.

El siguiente parametro que tendremos que modificar es la linea

root /var/www/html;

Estableciendo la ruta donde queremos que apunte nuestro virtual host.

root /var/www/mi_virtual_host;

La siguiente linea que tendremos que modificar sera la de

server_name _;

En esta linea especificaremos el nombre del dominio que deseamos utilizar en el virtual host

server_name dominio.local www.dominio.local;

Pondremos todos los dominio que desemos que responda nuestro servidor web.

Para una configuración basica ya tendriamos nuestro vistual host configurado. Solo nos queda pulsar Ctrl+X, confirmar el guardado de los cambios en nuestro fichero, y salir del editor.

Verificación de la configuración del virtual host

Una vez que tengamos nuestro fichero de configuración creado, comprobamos que los hemos hecho todo correctamente usando el siguiente comando

sudo nginx -t

Si recibimos una respuesta parecida a esta

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Nuestra configuración es correcta, y esta listos para reiniciar el servidor web.

Si recibimos cualquier otro mensaje, con algo parecido a esto.

nginx: configuration file /etc/nginx/nginx.conf test failed

Tenemos algun fallo en la configuración de nuestro servidor. tendremos que revisar la configuración, centrandonos en el error que acompaña al mensaje.

Una vez que tengamos el ok por parte del servidor nginx, solo nos queda resetar el servidor para que carge la nueva condiguración.

sudo systemctl restart nginx.service

Una vez reseteado el servidor web, ya tenemos nuestro virtual host funcionando sin problemas.

Si queremos verificar si el servidor funciona correctamente, aparte de probar a cargar la pagina,. Podemos utilizar el siguiente comando

sudo systemctl status nginx.conf

Donde en la linea de «active» no tendra que mostrar el siguiente mensaje si todo esta funcionando correctamente.

Active: active (running) since Thu 2018-05-17 13:33:58 UTC; 1h 18min ago

Como siempre, si tienes cualquier duda o problema, nu dudes en escrbirnos un comentario.

 

Configurar replicas en nuestro servidor MongoDB

Establecer las replicas en nuestro servidor de bases de datos MongoDB

MongoDB nos permite establecer unas replicas, que en caso de percance en el servidor principal, tomara el control una de estas replicas.

El numero de servidores que una instalación de mongoDB, es decir, contado el servidor principal y sus replicas tiene que ser impar. Esto Configuración de replicas en MomgoDBes debido a que la replica que de valla a utilizar se realizar por «votación», y el que tenga más del 50% por ciento de los votos, es el que ocupara el puesto de primero. Esto no lo tengo yo muy bien entendido.

Por ello la configuración más habitual en un sistema MongoDB suele ser de 3 servidores, el principal y las dos replicas.

Configuración de las replicas en nuestro servicio.

El configurar las replicas en nuestro servidor MongoDB es muy sencillo.

Lo primero que tenemos que hacer es crear las carpetas donde se alojaran los ficheros de las bases de datos.

Para esta prueba, vamos a crear las carpetas en el propio servidor donde tenemos nuestra instalación de MongoDB.

mkdir /datos
mkdir /datos/principal
mkdir /datos/replica1
mkdir /datos/replica2
mkdir /datos/logs
sudo chown -R mongodb:mongodb /datos

Ademas de crear las carpetas donde se alojaran los ficheros de las bases de datos de cada uno de los servidores, hemos establecido a mongodb el propietario de las misma.

El siguiente paso que nos queda, es la crear las instancias de los servidores.

Configuración del servicio principal

Para el servidor principal quedaría de la siguiente manera.

sudo -u mongodb mongod --dbpath /datos/principal --logpath /datos/logs/principal.log --replSet servidoresMongo --smallfiles --oplogSize 128 --port 27017 --fork

La primera observación hemos ejecuta el comando bajo el usuario «mongodb», sudo -u mongodb. Si lo hiciésemos con sudo normal, estaríamos dándole los permisos de root al proceso, se puede hacer, pero no es recomendable.

Explicación de los parámetros:

  • –dbpath: ruta donde se va ha almacenar los ficheros de las bases de datos.
  • –logpath: ruta donde queremos que se cree el fichero de log del servidor.
  • –replSet: Nombre del sistema. Todos los sistemas que pertenezcan al mismo sistema tendrá que tener el mismo replSet.
  • –smallfiles: control de los tamaños de los ficheros que componen el sistema.
  • –oplogSize: tamaño de los ficheros de log.
  • –port: Puerto donde esta a la escucha el servidor.
  • –fork: No se bloquea la sesión que inicio el mongod.
Configuración de las replicas

Para establecer los procesos de las replicas ejecutaremos el mismo comando, cambiando los parámetros de –dbpath, –logpath y –port, a los valores propios de cada proceso:

Replica 1:

sudo -u mongodb mongod --dbpath /datos/replica1 --logpath /datos/logs/replica1.log --replSet servidoresMongo --smallfiles --oplogSize 128 --port 27018 --fork

Replica 2:

sudo -u mongodb mongod --dbpath /datos/replica2 --logpath /datos/logs/replica2.log --replSet servidoresMongo --smallfiles --oplogSize 128 --port 27019 --fork

Una vez establecido los procesos que van a controlar cada uno de los servicios, entramos en la consola de mongo para configurar el uso de las replicas.

mongo --port 27017

Y creamos una variable con este formato para establecer los miembros del sistema.
cfg = {"_id":"nombreSistema", "members":[
{"_id":0, "host":"direccion_servidor:puerto"},
{"_id":1, "host":"direccion_servidor:puerto"},
{"_id":2, "host":"direccion_servidor:puerto"}
]
}

Para nuestro ejemplo, y suponiendo que los estamos haciendo en el propio servidor quedaría de la siguiente forma:
cfg = {"_id":"servidoresMongo", "members":[
{"_id":0, "host":"localhost:27017"},
{"_id":1, "host":"localhost:27018"},
{"_id":2, "host":"localhost:27019"}
]
}

Con la variable que acabamos de crear vamos ha cargar la configuración de las replicas en la configuración de nuestro MongoDB

rs.initiate(cfg)

Si todo ha sido correcto, una de las lineas que nos aparecerá sera un:

{ «ok» : 1 }

Verificación de nuestra configuración

Para verificar que así a sido, podemos ejecutar el siguiente comando.

rs.status()

Este nos mostrara el estado de las replicas, si están funcionando correctamente.

{
"set" : "nombreSistema",
"date" : ISODate("2018-04-12T16:27:39.682Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1523550459, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1523550459, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1523550459, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1523550459, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "localhost:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 6786,
"optime" : {
"ts" : Timestamp(1523550459, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-04-12T16:27:39Z"),
"electionTime" : Timestamp(1523544257, 1),
"electionDate" : ISODate("2018-04-12T14:44:17Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "localhost:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 6213,
"optime" : {
"ts" : Timestamp(1523550449, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1523550449, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-04-12T16:27:29Z"),
"optimeDurableDate" : ISODate("2018-04-12T16:27:29Z"),
"lastHeartbeat" : ISODate("2018-04-12T16:27:38.545Z"),
"lastHeartbeatRecv" : ISODate("2018-04-12T16:27:39.322Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "localhost:27017",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "localhost:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 6213,
"optime" : {
"ts" : Timestamp(1523550449, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1523550449, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-04-12T16:27:29Z"),
"optimeDurableDate" : ISODate("2018-04-12T16:27:29Z"),
"lastHeartbeat" : ISODate("2018-04-12T16:27:38.545Z"),
"lastHeartbeatRecv" : ISODate("2018-04-12T16:27:39.321Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "localhost:27017",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1523550459, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1523550459, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}

Si obtenemos una respuesta parecida a la de arriba, es que nuestro sistema esta funcionando correctamente.

Como de costumbre al final de los post, ya sabéis, ante cualquier duda, pues un comentario 8-))))

Importar ficheros CSV a nuestra base de datos en MongoDB

Como importar datos en formato csv a nuestro servidor en MongoDB

CSV es un formato de archivo muy extendido para el intercambio de información. El formato de este es muy simple. La primera fila suele importar fichero csv a mongodbser el nombre de los campos, separados por comas. Las demás filas son los datos en si.

Para importar este tipo de archivos csv ha nuestro servidor de bases de base de datos usaremos el mismo comando que nos proporciona la empresa detrás de MongoDB para importar datos desde un fichero en formato json.

Comando mongoimport

Como ya explique en el otro post donde importamos los datos en formato josn a nuestro servidor MongoDB el comando que utilizaremos es el que MongoDB nos pone a disposición de estas tareas. Este comando es mongoimport. Este comando tiene el siguiente formato básico.

mongoimport --db baseDatos --collection coleccion --file fichero_a_importar --type csv

Si nuestro servidor esta instalado en local, escuchando en el puerto por defecto, es decir, el 27017. Y ademas no tiene credenciales de acceso, sera suficiente.

Explicacion del comando mongoimport

Con el parámetro «–db»,  o «-d», establecemos el nombre donde vamos a importar los datos. No tiene por que existir. Por norma en mongodb, si la base de datos no existe automáticamente el servidor de base de datos no lo crea por nosotros.

El parámetro «–collection», o «-c»,  estableceremos el nombre de la colección que va ha albergar los documentos que vamos ha importar. Como en el caso de la base de datos, si esta no existiera, el servidor de mongodb la crearlo por nosotros.

El parámetro siguiente, «–file», establecemos el nombre del fichero en formato csv que vamos a importar.

El parámetro «–type csv» establecemos que el tipo de archivo que vamos ha importar esta en formato csv. En el anterior post, no utilizamos este parámetro, ya que el comando de mongoimport, si no lo indicamos, asume que vamos a utilizar el formato json.

Y en escenario básico, dando se las condiciones anteriores, esto sería suficiente.

Otro parámetros de mongoimport

Pero lo habitual no es tener este escenario idílico, tendremos que utilizar otro parámetros para establecer, tanto el host donde se encuentra el servidor, el puerto en el cual está a la escucha. Y el nombre de usuario y contraseña que necesitaremos para autentificarnos.

Lo parámetros necesarios para estas operaciones son los siguiente.

Para establecer el host del servidor utilizaremos el parámetro «–host» o en su versión abreviada «-h» seguido de la dirección del servidor.

Para el puerto el parámetro que necesitamos es «–port» seguido del puerto que utiliza el servidor de mongodb.

También podemos establecer el host y el puerto con el mismo parámetro host. Para ello lo podemos hacer de la siguiente formato.

mongoimport --host direccion_o_IP:puerto

o en formato abreviado

mongoimport -h direccion_o_IP:puerto

Para lo que se refiere al registro en el servidor, usaremos el parámetro «–username» o «-u» seguido del nombre de usuario que vamos a utilizar. Para establecer la contraseña usaremos el siguiente parámetro «–password» o en versión abreviada «-p».

Ejemplo de uso de mongoimport

Un ejemplo de uso quedaría de esta forma.

mongoimport --db baseDatos --collection coleccion --type csv --host direccion_o_ip --port 23456 --username usuario --password contraseña --file ficheroImportar.csv

Y si todo lo hemos escrito correctamente, y no se ha producido ningún error, ya tendríamos nuestros datos importados a nuestro servidor de base de datos con MongoDB.

Si te has quedado con alguna duda, me puedes dejar un comentario.

Configurar interface de red en versiones de Ubuntu 17.10 o superiores

Configuración de la interface de red en Ubuntu 17.10

Desde la versión 17.10, Ubuntu ha activado por defecto en sistema «Netplan» para la configuración de los interfaces de red. Aunque en la versión 17.10 se ha activado como la opción de configuración de red por defecto. El sistema ya viene implementatado desde la versión 16.04.

Este sistema es totalmente distinto a lo que hasta ahora veniamos Configuración de redutilizando para la configuración de las tarjetas de red.

El primer cambio que nos encontramos, es la ubicación de los ficheros de configuración. Pasando de estar en /etc/network/interfaces a estar en /etc/netplan/01-netcfg.yaml.

Configuración de la interface

El formato de esta nueva versión es completamente diferente a la que normalmente veniamos usando en las versiones anteriores.

Una estructura basica del fichero 01-netcfg.yaml, seria la siguiente:

# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: yes

Una de las cosas que hay que tener muy en cuenta es respetar las tabulaciones, si la establecemos mal, sera una de las causas que nos pueden probocar un error en la configuración.

El ejemplo muestra como seria una configuración por defecto para una interface que obtega la dirección ip desde una servidor de DHCP.

La configuración se divide en dos zonas, la primera con indicaciones para la herramienta Netplan. Y la segunda, con la configuración de las interfaces de red.

Debajo del paramentro «ethernets» pondremos la configuración de todas nuestas interfaces de red que tengamos instaladas en nuestro sistema.

Para realizar esta configuración los primeros que debemos de indicar sera, el nombre logico asignado a la tarjeta. En el caso del ejemplo «enp0s3».

Debajo de el y con un nuevo nivel de tabulación pondremos la configuracion. En el caso del ejemplo, como esta configurada, para que obtega la dirección IP desde el servidor de DHCP. Solo tendremos que poner:

dhcp4: yes

Y ya tendriamos la configuración establecida.

Otras configuraciones

En el caso que queramos personalizar la dirección ip de la interface, utilizariamos los siguientes comandos:

  • addresses: Dirección que queremos establecer para la interface. Para establecer la mascara de red, se lo indicaremos mediante su longitud en la dirección ip. Ejemplo: 192.168.0.10/24. Pueder ver en esta entrada de la Wikipedia los valores utlizados.
  • gateway4: Dirección ip del gateway para la versión 4 del protocolo IP. Para establecer el gateway para la versión 6, solo tendriamos que cambiar en 4 por el 6, y establecer una dirección de tipo v6.
  • nameservers: bloque para establecer los servidores de dns que va ha usar la tarjeta de red. Para indicar la dirección utilizaremos el parametros addresses, al igual que la dirección IP, la acotaresmos entre corchetes, las direcciones IP de los servidores de DNS, las separaremos por comas.

Estos serian los paramentros basicos para establecer la dirección estatica para la tarjeta de red.

Ejemplo:

network:
version: 2
renderer: networkd
ethernets:
enp0s8:
dhcp4: yes
enp0s3:
dhcp4: no
addresses: [192.168.100.10/24]
gateway4: 192.168.100.1
nameservers:
addresses: [9.9.9.9, 8.8.8.8]

Si queremos establecer la configuración para más de una interface la podríamos a continuación con el mismo formato.

Con esto ya tenemos nuestra tarjeta configurada.

Como de costumbre, cualquier duda comentario.

Importar datos en nuestra base de dsatos en MongoDB

Importar datos desde un fichero json a nuestro servidor de MongoDB

Cuando trabajamos con bases de datos, ya sea para pruebas o para iniciar una puesta en marcha en producción. Lo habitual es que tengamos que importar datos desde otro sistema.

El formato JSon es uno de los formatos de intercambio de datos que Importación datos a MongoDBmás popularidad tiene en la actualidad. Este formato nos permite una gran flexibilidad en el manejo de estos. Casi todos los lenguajes de programación, por no decir todos, en la actualidad cuenta con librerías para el manejo de este tipo de datos. Por lo que el manejo de estos se vuelve muy sencillo.

En el caso de MongoDB, no necesitamos utilizar ningún lenguaje de programación para importar un fichero en formato JSon a nuestra base de datos.

Dentro de la instalación de MongoDB podemos encontrar un comando que nos facilita y mucho esta tarea. Este comando es «mongoimport»

Ha este comando le tendremos que pasar una serie de parámetros para indicarle en que base de datos queremos guardas las colecciones, las tablas en el formato de bases de datos relacionales. El nombre de la colección donde queremos que se guarden nuestros documentos, los registros siguiendo la analogía con las bases de datos relaciones. Y por ultimo, el fichero en formato json donde se encuentran nuestros datos.

MongoDB nos facilita un fichero json con las ciudades de Estados Unidos para hacer pruebas. Vamos a usar este fichero para mostrar un ejemplo. El fichero lo podéis encontrar en la siguiente dirección: http://media.mongodb.org/zips.json. Lo descargamos y lo guardamos en nuestro sistema.

Una aclaración, este método es independiente del sistema donde tengamos instalado nuestro servidor MongoDB. Funciona tanto en Linux, Windows, o Mac. En este caso y que no sirva de precedente, las pruebas la he realizado con un windows 10, y con servidor Debian. Lo habitual es tener el servidor de MongoDB corriendo en un servidor Linux.

Importar los datos a nuestro servidor de MongoDB.

Una vez que ya tenemos nuestro fichero descargado vamos a ver como lo importamos.
mongoimport --db ciudadesdb --collection ciudades --drop --file zips.json --port 8080
Con el parámetro «–db» le indicamos que queremos guardar los datos en la siguiente base de datos. En este caso «ciudadesdb».

Con el parámetro «–collection» le indicamos la colección, es decir, la tabla donde queremos guardar los datos. En este caso «ciudades».

El parámetro «–drop» le indicar a mongoimport que descarte todos los datos que hubiese ya en la colección. Es decir, borraría todos los datos que tuviese la tabla antes de realizar la importación de los datos. Cuidado con este parámetro, si queremos añadir los nuevos datos a los ya existentes, no debemos incluir este parámetro.

El parámetro «–file» es donde le indicamos a mongoimport donde está el fichero en formato json con los datos que deseamos importar.

Y esto sería suficiente que nuestro servidor,

  1. Esta en el equipo local, es decir, está en «localhost».
  2. El puerto que está a la escucha es el de por defecto de la instalación de MongoDB.
  3. Y además no tiene nombre de usuario ni contraseña para acceder a él.

Parámetros avanzados para mongoimport

Como en muchos de los casos no se va a dar alguna de estas opciones tendremos que utilizar alguno de los siguientes parámetros.

Para indicarle a mongoimport en qué dirección esta nuestro servidor usaremos el paramento «–host» y le indicaremos la dirección donde se encuentra nuestro servidor.

Para indicarle el puerto por que cual está a la escucha nuestro MongoDB utilizaremos el paramento «–port» y el puerto que hemos configurado.

Para autentificarnos en el servidor tendremos que utilizar los siguientes paramentos. Para indicarle el nombre de usuario que tenemos que usar usaremos el parámetro «–username» o en versión corta «-u» seguido del nombre de usuario que deseamos usar. Para indicarle la contraseña utilizaremos le parámetro «–password» o «-p» seguido de la contraseña deseada.

Con estos parámetros ya podremos indicar el servidor que deseamos usar, y el usuario de queremos utilizar.

Si queréis saber más parámetros que podéis utilizar para importar datos a nuestro servidor MongoDB utilizando el comando mongoimport tenéis más información en la página oficial en https://docs.mongodb.com/manual/reference/program/mongoimport/

Y esto sería todo, alguna duda, ya sabéis comentario al canto.

 

 

Instalar antivirus en servidor Linux

En muchas ocasiones necesitamos instalar un antivirus en nuestro servidor de ficheros bajo un sistemas Linux. Al tratarse de un sistema Linux, las opciones son un poco escasas.

ClamAV AntivirusLa mejor opción que podemos utilizar es instalar el antivirus ClamAV. Este antivirus es preparado para correr sin ningún problema en nuestro servidor de aplicaciones.

Instalar el antivirus ClamAV en nuestro servidor

Lo primero que debemos hacer antes de instalar ClamAv, o cualquier otro programa, es tener nuestro sistema actualizado. Esto lo podemos hacer con los siguientes comandos.

sudo apt-get update; sudo apt-get uprade -y

Una vez que ya tenemos actualizado nuestro sistema, pasamos ha instalar el antivirus.

sudo apt-get install clamav clamav-daemon -y

Con clamav instalamos el antivirus propiamente dicho. Con clamav-daemon instalamos el servicio que se ejecutara al inicio de nuestro servidor.

Actualizar la base de datos del ClamAV

Con los pasos anteriores hemos instalado el software del antivirus. El siguiente paso que tenemos que hacer, es actualizarla base de datos de firmas de los virus. Para ellos solo tenemos que ejecutar el siguiente comando.

sudo freshclam

En algunas ocasiones, al ejecutarse este comando, nos muestra un mensaje de error. Este error es que no puede tener acceso en exclusiva. Esto esta ocasionado, por que le programa de ClamAV tiene abierta ya la base de datos. Para resolver este problema solo tenemos que para ClamAV.

Paramos el servicio

sudo service clamav-freshclam stop

Volvemos a ejecutar el programa para actualizar la base de datos

sudo freshclam

Una vez que termina de actualizar la base de datos, volvemos a activar el servicio de ClamAV

sudo service clamav-fressclam start

Realizar un escaneo con ClamAV

Para realizar un escaneo están fácil como ejecutar el programa e indicarle el direcctoria que deseamos escanear.

sudo clamscan -r /directorio/scanear/

En este ejemplo usamos el parámetro «-r». Este parámetro lo que hace un escaneo recursivo, es decir, escaneamos la carpeta indicada y todas las incluidas dentro.

Escanear y eliminar los virus encontrados

Para escáner y eliminar los virus que encontremos los haremos de la siguiente manera:

sudo clamscan --remove /direcorio_escanear/

Activar el antivirus ClamAV en el inicio

Para que nuestro sistema este protegido cada vez que iniciemos nuestro equipo tendremos que añadir al arranque, tanto el servicio de CalmAv, como el servicio que se encarga de tener la base de datos actualizada.

Activar servicio de ClamAv

sudo /etc/init.d/clamav-daemon start

Activar servicio para el gestor de la base de datos

sudo /etc/init.d/clamav-freshclam start

Con esto ya tendremos nuestros servidor de ficheros protegido ante los virus.