Ir al contenido principal

Resolviendo nombres con Tor

El protocolo DNS tiene su tiempo, los RFC que lo definen, 1034 (conceptos e instalaciones) y 1035 (implementación y especificación) datan del 1987 y como en todos los protocolos de la época la seguridad brilla por su ausencia, cualquiera que sniffe la red puede ver que dominios visita alguien, ya no digamos quien provea el servidor DNS, pero poca solución tiene a corto plazo, Internet depende de este sistema de nombres y no hay otro sistema mejor que disponga de la infraestructura necesaria, no?

Resulta que la interfaz SOCKS de los proxy Tor ofrece una opción no estándar (punto 2) que permite usar esta red para resolver nombres, se puede acceder a esta funcionalidad a través de la línea de comandos con tor-resolve, esta capacidad de la red se puede explotar para montar un servidor DNS privado que no filtre que dominios se buscan (eso sí, necesitará un punto de acceso a la red Tor, claro).

Utilizando Twisted es sencillo montar este servidor DNS que utilice Tor como backend para realizar las búsquedas (aunque estas estarán limitadas a los campos A y AAAA), esto es lo que implementa Onion-dir (En Gitorious | En Github).

Esto se puede usar añadiendo DNSPort 53 al archivo /etc/tor/torrc, por último decir que el rendimiento es bastante mejor que el esperado, un bind9 en local tarda ~52s en resolver las IP de las "100 webs más populares" mientras que Tor lo hace en ~58s (ambos casos con la caché vacía), con la caché llena los tiempos para ambos casos son de ~2.8s, pero aún da problemas resolviendo dominios como _xmppconnect.gmail.com, el servidor XMPP de Google, dominio que por otro lado realmente no existe.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
$ dig @8.8.8.8 _xmppconnect.gmail.com

; <<>> DiG 9.8.1-P1 <<>> @8.8.8.8 _xmppconnect.gmail.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 54080
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

;; QUESTION SECTION:
;_xmppconnect.gmail.com.        IN  A

;; AUTHORITY SECTION:
gmail.com.      60  IN  SOA ns1.google.com. dns-admin.google.com. 1523590 21600 3600 1209600 300

;; Query time: 87 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Jun 14 19:44:34 2013
;; MSG SIZE  rcvd: 97

Y ese parece el único problema grave que queda...

nikto visto desde el servidor

Os habéis preguntado como se vé un escaneo de vulnerabilidades desde el servidor? Pues no es muy silencioso precisamente :P

En tiempo real, si cada pelota representa una petición, las que rebotan son las que son atendidas satisfactoriamente y las que no... pues no:

Visualizado con logstalgia

CM sin agentes de servidor? Prueba ansible

Hace unas semanas había hechado un vistazo a algunas herramientas de gestión de la onfiguración como chef, puppet y salt, pero lo dejé cuando vi que requerían un servicio en el servidor donde se instalaran.

Pues bien, resulta que este sábado, en el hackmeeting se habló de ansible, una herramienta para este propósito escrita en python. Me perdí la charla pero hoy le heché un vistazo a la página web

Ansible is a radically simple IT orchestration engine that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.

Eso suena muy, muy bien, ando probándolo y por ahora anda genial, quizá es lo que estabas buscando :P.

Script para limpiar zombies

Toma como parámetro el id del proceso que generó los zombies y usa GDB para hacer waitpid, lo más seguro es que haga falta root :/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env bash
# Kills zombie process spawning from a parent PID

# check parameter number
if [ -z "$1" ];then
    echo "$0 <zombie parent pid>"
    exit 0
fi

# assign reasonable names to variables
ppid=$1
fname=`tempfile`

# GDB instructions
(for zpid in `ps h --ppid=$ppid|grep -P '^\s*\d+\s+[^ ]+\s+Z'|awk '{print $1;}'`;do
    echo "print waitpid($zpid, 0, 0)" # wait for each zombie
 done
 # and detach
 echo "detach") > $fname

# launch GDB
gdb -batch -p $ppid /proc/$ppid/exe -x $fname

# and cleanup
rm $fname

Leer más…

Estamos de vuelta!

Después de 3 meses vuelve Código para llevar, habrá cambios, para empezar los cambios el sistema de blogging ha pasado de Wordpress a acrylamid, mucho más ligero. La migración no está del todo completa y los comentarios tardarán un rato :P.

Detectando el lenguaje de un texto

A veces puede resultar útil detectar el lenguaje de un texto, en los sistemas *NIX es habitual tener un directorio con listas de palabras habituales de varios idiomas, simplemente comparando la proporción de palabras de un texto que cae en esa lista a través de los distintos lenguajes da un número que parece bastante significativo acerca de que idioma se trata.

Por ejemplo, probando esta aproximación sobre el texto traducido (en Markdown, sin convertir a HTML) de la entrevista de Snowden para Der Spiegel muestra los siguientes resultados:

1
2
3
4
5
6
7
$ python lang.py entrevista-de-edward-snowden-para-der-spiegel.txt
entrevista-de-edward-snowden-para-der-spiegel.txt [2341]

58.61%  spanish
51.60%  galician
29.18%  american-english
29.09%  british-english

Hacerlo sobre el texto de la GPLv3 (en inglés) resulta en:

1
2
3
4
5
6
7
$ python lang.py LICENSE
LICENSE [5251]

98.36%  american-english
98.15%  british-english
12.82%  spanish
10.68%  galician

Si bien la aproximación es muy basta, parece que el resultado es aceptable.

El script usado para las pruebas fué este, está pensado para usar los diccionarios de "american-english", "british-english", "galician" y "spanish" pero se podría usar cualquiera, claro:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env python

import re
import os
import sys

# Define un color para mostrar los resultados
color = True
if color:
    colorfile = "\x1b[0;92m" # Verde
    colorend = "\x1b[0m"     # Fin del color
else:
    colorfile = colorend = ""

# Diccionarios a comprobar
dictionaries = ["american-english", "british-english", "galician", "spanish"]
path = "/usr/share/dict"

class LangReader:
    words = re.compile(r'\w+')

    def __init__(self, dicts):
        '''Carga los diccionarios con las palabras, una por línea, en minúsculas.'''
        self.dicts = {}
        for d in dicts:
            self.dicts[d] = set(map(lambda x: x.strip().lower(),
                                       open(d, "rt").read().strip().split("\n")))

    def get_file_props(self, f):
        return self.get_props(f.read())

    def get_percents(self, data):
        '''Devuelve el porcentaje de palabras de cada idioma.'''
        props, total = self.get_props(data)
        percents = {}
        for lang in props:
            percents[lang] = round((float(props[lang]) / total) * 100, 2)
        return percents


    def get_props(self, data):
        '''Devuelve el número de palabras que se corresponde
           con el diccionario de cada idioma.'''
        counters = {}
        total = 0
        words = map(lambda w: w.lower(), self.words.findall(data))

        for lang in self.dicts:
            ldict = self.dicts[lang]
            counter = 0
            for word in words:
                if word in ldict:
                    counter += 1

            counters[lang] = counter

        return counters, len(words)


if __name__ == "__main__":
    if len(sys.argv) == 1:
        print >>sys.stderr, "%s <file>" % sys.argv[0]
        exit(0)

    files = map(lambda x: open(x, "rt"), sys.argv[1:])
    os.chdir(path)

    ld = LangReader(dictionaries)
    first = True
    for f in files:

        if not first:
            print "\n"

        props, total = ld.get_file_props(f)
        if total > 0:
            print "%s%s%s [%i]\n" % (colorfile, f.name, colorend, total)
            for i in sorted(props,
                            lambda x, y: props[x].__cmp__(props[y]),
                            reverse = True):

                print "%5.2f%%  %s" % ((props[i] / float(total)) * 100, i)

        else:
            print "%s%s%s nothing found" % (colorfile, f.name, colorend)
        first = False

Just for fun

Últimamente encuentro bastantes sítios de humor por aquí dejo los que he encontrado (dádle al título del post para ver las imágenes):

Sólo lo toque y la aplicación cayo sola

Desarrollando sin especificaciones

Cuando llega un informe de error el viernes a las 4

“Cuando los compañeros intentan explicar por que deberíamos programar en Java”

Cuando los compañeros intentan explicar por que deberíamos programar en Java

 

1
saveurl() { cat > /dev/null; } # Save a url for reading later when you "have time".