24 jun. 2017

Base de datos InfluxDB en Debian Stretch

InfluxDB es una base de datos opensource de series de tiempo, para manejo de eventos,monitoreo, métricas, Internet de las cosas y Analítica en tiempo real. Desarrollada por InfluxData en Lenguaje Go. Pueden ver más información en wikipedia.

Para instalar en Debian simplemente se usa apt-get:

# apt-cache search influxdb 
golang-github-influxdb-enterprise-client-dev - Golang client for speaking to the InfluxDB Enterprise application
golang-github-influxdb-usage-client-dev - library for speaking to the InfluxDB Anonymous Usage Reporting API
golang-gopkg-alexcesaro-statsd.v1-dev - simple and efficient Golang StatsD client
golang-github-influxdb-influxdb-dev - Scalable datastore for metrics, events, and real-time analytics. Dev package
influxdb - Scalable datastore for metrics, events, and real-time analytics
influxdb-client - command line interface for InfluxDB
influxdb-dev - Transitional package for golang-github-influxdb-influxdb-dev
ruby-influxdb - library for InfluxDB


Para instalar:

# apt-get install influxdb influxdb-client

Para probar que está en funcionamiento:

# influx
Visit https://enterprise.influxdata.com to register for updates, InfluxDB server management, and monitoring.
Connected to http://localhost:8086 version 1.0.2
InfluxDB shell version: 1.0.2




Para crear una base de datos llamada mydb:

> create database mydb

Listar las bases de datos:

> show databases
name: databases
---------------
name
_internal
mydb



Insertar datos y consultarlos en la base de datos mydb:

> use mydb
Using database mydb
> INSERT cpu,host=ServerA,region=us_west value=0.64
> SELECT host, region, value FROM cpu
name: cpu
---------
time                 host         region value
1498340879346347895 ServerA us_west 0.64

Por lo que se ve, la clave primaria de los datos siempre es el tiempo. 

Ahora una pequeña prueba con Python.

Para instalar la librería en Python:
# pip3 install influxdb



Se tiene el siguiente script:


#!/usr/bin/env python3
#Se importa influxdb
from influxdb import InfluxDBClient
#Se define un json con los datos a insertar
json_body = [
    {
        "measurement": "cpu_load_short",
        "tags": {
            "host": "server01",
            "region": "us-west"
        },
        "time": "2009-11-10T23:00:00Z",
        "fields": {
            "value": 0.64
        }
    },
    {
        "measurement": "cpu_load_short",
        "tags": {
            "host": "server02",
            "region": "us-west"
        },
        "time": "2009-12-10T23:00:00Z",
        "fields": {
            "value": 0.65
        }
    }
]
#Se conecta a la base de datos
client = InfluxDBClient('localhost', 8086, 'root', 'root', 'mydb')
#Se crea la base de datos mydb
client.create_database('mydb')
#Se inserta los datos
client.write_points(json_body)
#Se consulta y se muestra en pantalla
result = client.query('select value from cpu_load_short;')
print("Result: {0}".format(result))

Al ejecutar el script, este devuelve lo siguiente:

./prueba-influxdb.py 
Result: ResultSet({'('cpu_load_short', None)': [{'value': 0.64, 'time': '2009-11-10T23:00:00Z'}, {'value': 0.65, 'time': '2009-12-10T23:00:00Z'}]})


O desde el cliente de influxdb:

> use mydb
Using database mydb
> select value from cpu_load_short;
name: cpu_load_short
--------------------
time value
1257894000000000000 0.64
1260486000000000000 0.65

Como se muestra, la clave que maneja las consultas es el tiempo.

Para más información se tiene los siguientes enlaces:



Obtener datos de eventos sismológicos de Funvisis con Python3 (segunda versión)

El primer artículo sobre obtener los datos sismológicos de Funvisis con Python, se usó la librería python-mechanize, en este caso se usará la librería request y Python 3.* .



El código se muestra a continuación:


#!/usr/bin/env python3





#Se importa beautifulSoup

from bs4 import BeautifulSoup

#Se importa la fecha

from datetime import datetime

import requests

import sys

import json



class Sismo(object):

    def __init__(self,url="http://www.funvisis.gob.ve/",home="index.php",referer='http://www.cantv.com.ve'):

        headers = {'User-agent': 'Mozilla/5.0',\

            'SSL_VERIFYHOST': 'False',\

            'FRESH_CONNECT':'True',\

            'RETURNTRANSFER':'True',\

            'SSL_VERIFYPEER': 'False',\

            'Referer': referer

            }

        self.__url = url

        self.__home = home

        self.__urlhome = self.__url + self.__home

        self.__session = requests.Session()

        self.__session.headers.update(headers)



    def GetData(self):

        #Se  obtiene la pagina por medio de session.

        try:

            self.__r = self.__session.get(self.__urlhome)

            self.__page = self.__r.content

        except (requests.exceptions.SSLError):

            print("SSL Error")

            sys.exit(0)

        except (requests.exceptions.ConnectionError):

            print("Connection Error")

            sys.exit(0)

        #Se le pasa la pagina a beautifulsoup usando lxml de parser.

        self.__soup = BeautifulSoup(self.__page,"lxml")

        #Se crea el diccionario que almacena los datos

        self.__sismo = {}



        #SE obtiene el primer  div que tengan class module

        for row in self.__soup('div', {'class': 'module'})[0]:

            #Se obtiene el tag a para luego obtener el href y tener el url

            #del gif del sitio de funvisis que tiene la imagen del sitio donde

            #fue el sismo.

            trs = row.find('a')

            if trs == -1:

                continue

            self.__sismo['urlref'] = self.__url  + trs.get('href',None)



            trs = row.find('tr')

            if trs == -1:

                continue

            #Obtiene los datos del sismo del sitio de funvisis

            datos = trs.find('td').getText().split(' ')

            self.__sismo['fecha'] = datos[0].split('\n\t')[0].split('\xa0')[1]

            self.__sismo['hora'] = datos[0].split('\n\t')[2].split(" ")[-2]

            self.__sismo['magnitud'] = datos[0].split('\n\t')[4].split(" ")[-1]

            mag = datos[0].split('\n\t')[6].split(" ")[-1].split('\xa0')

            self.__sismo['profundidad'] = mag[0] + " "+ mag[1]

            lat = datos[0].split('\n\t')[8].split(" ")

            self.__sismo["latitud"] = lat[-2] + " " + lat[-1]

            lon =  datos[0].split('\n\t')[10].split(" ")

            self.__sismo['longitud'] = lon[-2] + " "+ lon[-1]

            self.__sismo['epicentro'] = datos[0].split('\n\t')[11].split(":")[1].split('\xa0')[-1]

        return self.__sismo







  



  def ToJSON(self):

        self.__sismojson = json.dumps(self.GetData())

        return self.__sismojson





if __name__ == '__main__':
sismo = Sismo(
)
 
  



p
r
int
 
(
sismo.ToJSON())

Al ejecutar el script se tiene de resultado:

{"epicentro": "30 Km al sur de Guiria", "hora": "07:51", "latitud": "10.39 \u00baN", "longitud": "-62.32 \u00baO", "fecha": "24/06/2017", "magnitud": "2.8", "urlref": "http://www.funvisis.gob.ve/images/reportes/2017/06/reporte_7489.gif", "profundidad": "9.1 km"}


El código se puede ver en el repositorio en gitlab.

10 jun. 2017

Fabric como un ssh con esteroides en Debian Stretch

Fabric es una librería y herramienta de línea de comandos que genera un flujo de tareas para la automatización de despliegues y tareas administrativas de manera remota.


Este artículo se basa en un vídeo de youtube de una introducción a Fabric.


Se tiene 3 equipos:

  • 192.168.1.3: Equipo con Debian Stretch y donde se tiene fabric instalado.
  • 192.168.1.2: Equipo con Debian Stretch.
  • 192.168.1.6: Equipo con Debian Jessie.


Sólo se necesita un equipo con Fabric, se usa Debian Stretch por que en esta versión de Debian no es tan complicado de instalar Fabric, en Debian Jessie me ha dado algo de problemas, se logra instalar pero da errores en la ejecución (por lo que he investigado el problema es la librería paramiko).

Instalación de Fabric:
Con pip:
#pip install fabric


Ahora se crea un archivo fabfile.py co el siguiente contenido:


#!/usr/bin/env python

#de la api de fabric de importa run, sudo, task, get y put

from fabric.api import run,sudo,task,get, put



#Se define la tareta cmdrun que ejectua el argumento

@task

def cmdrun(arg):

    run(arg)



#Se define la tarea sudorun que ejecuta el argumento vía sudo

@task

def sudorun(arg):

    sudo(arg)



#Se define la tarea download que se le pasa un argumento que se descarga en /tmp/

@task

def download(arg):

    get(remote_path=arg,local_path="/tmp/",use_sudo=True)



#Se define la tarea upload que se le pasa dos argumentos

#local_path y remote_path.

@task

def upload(arg1,arg2):

    put(local_path=arg1,remote_path=arg2,use_sudo=True)



#Se define la tarea host_type que ejecuta uname.

@task

def host_type():

        run('uname -s')





Para ejecutar las tareaas se usa el comando fab (se define una variable de entorno llamada clave la cual maneja la clave del usuario):

Ejecución de ps en dos equipos en paralelo:
fab -H 192.168.1.2,192.168.1.6 -p $clave -P cmdrum:"ps -ef|wc -l"


Devuelve la ejecución del ps y la cantidad de líneas que resulta en cada equipo.

Se averigua el tipo de host de cada equipo remoto con host_type:
fab -H 192.168.1.2,192.168.1.6 -p $clave   host_type

Acá se muestra de manera secuencial la ejecución de los comandos en los equipos, par aque sea de manera paralela se usa la opción -P.
fab -H 192.168.1.2,192.168.1.6 -p $clave  -P host_type



Ya la ejecución no se hace de manera secuencial en cada equipo.


Se ejecuta fdisk por medio de sudo:
fab -H 192.168.1.2,192.168.1.6 -p $clave -P sudo:"fdisk -l| grep sda"



El comando devuelve las particiones sda que tiene cada equipo.


Se sube un arhivo sources.list al equipo 192.168.1.2, por medio de upload y se pasa como argumento el archivo local y la ruta remota:
fab -h 192.168.1.2 -p $clave upload:"sources.list","/tmp/"


La figura muestra que la subida del archivo se realizó sin problemas, ahora se revisa en el directorio /tmp/:
La figura muestra que el archivo sources.list se encuentra en /tmp/



Se baja el  archivo prueba.txt del equipo 192.168.1.2, por medio de download, pasando la ruta remota del archivo, este archivo se descarga por defecto en /tmp/:

fab -H 192.168.1.2 -p $clave upload:"sources.list","/tmp/"


En este caso se descargo el archivo /home/ernesto/prueba.txt a /tmp/, luego se listo localmente el archivo para verificar que se encuentra el dicho directorio.


Un tutorial más completo sobre Fabric lo pueden encontrar en su sitio.

Otros vídeos de sobre fabric:





6 jun. 2017

Usar tor desde privoxy en Debian Stretch

Privoxy es un proxy web que se usa normalmente con tor.

En el artículo anterior se explica como instalar tor. Ahora se usará privoxy como proxy para tor.

Para instalar simplemente se usa apt:
#apt-get install privoxy

En privoxy se define el sock forward quien será el puerto e IP donde se está ejecutando tor (localhost y puerto 9050), se edita el archivo /etc/privoxy/config y se agrega la siguiente línea:


forward-socks4a / localhost:9050 .




Se reinicia privoxy:

# /etc/init.d/privoxy restart
[ ok ] Restarting privoxy (via systemctl): privoxy.service.


Se revisa que esté funcionando:

# /etc/init.d/privoxy status
privoxy.service - Privacy enhancing HTTP Proxy
   Loaded: loaded (/lib/systemd/system/privoxy.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2017-06-06 22:50:00 -04; 1s ago
     Docs: man:privoxy(8)
           https://www.privoxy.org/user-manual/
  Process: 20044 ExecStopPost=/bin/rm -f $PIDFILE (code=exited, status=0/SUCCESS)
  Process: 20082 ExecStart=/usr/sbin/privoxy --pidfile $PIDFILE --user $OWNER $CONFIGFILE (code=exited, status=0/SUCCESS)
 Main PID: 20083 (privoxy)
    Tasks: 1 (limit: 4915)
   Memory: 1.3M
      CPU: 8ms
   CGroup: /system.slice/privoxy.service
           └─20083 /usr/sbin/privoxy --pidfile /var/run/privoxy.pid --user privoxy /etc/privoxy/config

jun 06 22:49:59 grievous systemd[1]: Starting Privacy enhancing HTTP Proxy...
jun 06 22:50:00 grievous systemd[1]: Started Privacy enhancing HTTP Proxy.



En firefox se instala foxy proxy standar:


Se configura para usar el proxy localhost y puerto 8118:


Al verificar con la siguiente URL el uso de tor https://check.torproject.org/?lang=es_AR, se tiene lo siguiente:


Al lado izquierdo de la caja de busqueda está el icono de foxyproxy, el cual se encuentra activo al momento de verificar si se está usando tor.

Mejorar las respuestas de consultas de DNS con dnsmasq usando DNSCrypt

He usado dnsmasq como dns cache de las consultas de opendns o de los DNS de Google.

Los artículos anteriores que hablan de dnsmasq son:

  1. Usar dnsmasq como servidor DNS cache y local
  2. Mejorando la velocidad de consultas de DNS con dnsmasq y probar pruebas de diagnostico
Y ahora se usará DNSCrypt como lo muestra los siguientes artículos:

  1. Cifrar el tráfico de DNS en Linux con DNSCrypt y OpenDNS
  2. Cifrar el tráfico de DNS en Debian 9 Stretch (actualización 2017)


Para iniciar se instalará dnsmasq:

#apt-get install dnsmasq 


DNSCrypt escucha en la IP 127.0.2.1 en el puerto 53, para el caso de dnsmasq, este escuchará desde la IP 127.0.0.1 y el puerto 53 para evitar conflictos entre ambas aplicaciones.

Se edita el archivo /etc/dnsmasq.conf :

#vim /etc/dnsmasq.conf

#Realizar consultas de dominios completos solamente.
domain-needed
#Evitar busquedas internas de dominios locales
bogus-priv
#Habilita dnssec en dnsmasq
proxy-dnssec
#No tomar en cuenta el contenido del archivo /etc/resolv.conf
no-resolv
#Se escucha el servidor de nombres de dnscrypt
server=127.0.2.1
#Evitar ataques de dns rebinding
stop-dns-rebind
#evitar que servidores resuelvan consultas localhost
rebind-localhost-ok
#Se reciben consultas a dnsmasq en 127.0.0.1
listen-address=127.0.0.1
#No se habilita las interfaces para dhcp
no-dhcp-interface=wlp1s0,enp2s0,lo
#Sólo se realizan busquedas de direcciones que está resolviendo.
bind-interfaces
#No tomar en cuenta los hosts del archivo /etc/hosts
no-hosts
#Se define un cache de 500k
cache-size=500

Se salva el archivo y se reinicia dnsmasq:


#systemctl status dnsmasq.service
dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
   Loaded: loaded (/lib/systemd/system/dnsmasq.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2017-06-04 18:10:08 -04; 2 days ago
  Process: 851 ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf (code=exited, status=0/SUCCESS)
  Process: 814 ExecStart=/etc/init.d/dnsmasq systemd-exec (code=exited, status=0/SUCCESS)
  Process: 793 ExecStartPre=/usr/sbin/dnsmasq --test (code=exited, status=0/SUCCESS)
 Main PID: 842 (dnsmasq)
    Tasks: 1 (limit: 4915)
   Memory: 844.0K
      CPU: 7.042s
   CGroup: /system.slice/dnsmasq.service
           └─842 /usr/sbin/dnsmasq -x /run/dnsmasq/dnsmasq.pid -u dnsmasq -r /run/dnsmasq/resolv.conf -7 /etc/dnsmasq.d,.d

jun 04 18:10:08 grievous systemd[1]: Starting dnsmasq - A lightweight DHCP and caching DNS server...
jun 04 18:10:08 grievous dnsmasq[793]: dnsmasq: revisión de sintaxis OK.
jun 04 18:10:08 grievous dnsmasq[842]: iniciado, versión 2.76 tamaño de caché 500
jun 04 18:10:08 grievous dnsmasq[842]: opciones de compilación: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conn
jun 04 18:10:08 grievous dnsmasq[842]: advertencia: ignorando opción resolv-file porque no-resolv está fijado
jun 04 18:10:08 grievous dnsmasq[842]: usando nombre de servidor 127.0.2.1#53
jun 04 18:10:08 grievous dnsmasq[842]: el caché fue liberado
jun 04 18:10:08 grievous dnsmasq[851]: Too few arguments.
jun 04 18:10:08 grievous systemd[1]: Started dnsmasq - A lightweight DHCP and caching DNS server.


Por lo que se ve dnsmasq trabajando sin problemas. 

Se revisa el archivo /etc/resolv.conf y se tiene lo siguiente:

cat /etc/resolv.conf
# Generated by resolvconf
#nameserver 127.0.2.1
nameserver 127.0.0.1

Se están usando tanto dnscrypt como dnsmasq para resolver las consultas de DNS.

Al consultar un dominio por medio de dig se tiene lo siguiente:

# dig www.google.com

; <<>> DiG 9.10.3-P4-Debian <<>> www.google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41085
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.google.com. IN A

;; ANSWER SECTION:
www.google.com. 190 IN A 172.217.22.164

;; Query time: 300 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Jun 06 20:08:50 -04 2017
;; MSG SIZE  rcvd: 59

# dig www.google.com

; <<>> DiG 9.10.3-P4-Debian <<>> www.google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49000
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.google.com. IN A

;; ANSWER SECTION:
www.google.com. 189 IN A 172.217.22.164

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Jun 06 20:08:51 -04 2017
;; MSG SIZE  rcvd: 59



Al realizar la segunda consulta se nota que el tiempo de respuesta pasa de 300mseg a 0mseg.