Como usar mi propio DNS en un script pt 2


UPDATE 27/05: Se agrega código para Powershell

Este es el segundo artículo de un experimento que he estado haciendo para poder saltarme potenciales bloqueos de DNS de mi casa, para leer el primero puedes pinchar aquí Como usar mi propio DNS en un script.

Luego del artículo anterior me podrían decir “está bien, usas tu propia resolución de DNS en tu script, pero ¿qué pasa con los IDS? Cualquier resolución se puede ver por ahí.”

Tienen toda la razón, pero igualmente se puede generar algo de código para eso.

DoH al rescate

DNS over HTTPS (DoH) es un estándar a través del cual se pueden hacer resoluciones DNS sin usar ese protocolo, solo usando HTTPS (https://blog.chromium.org/2020/05/a-safer-and-more-private-browsing-DoH.html, https://www.ionos.es/digitalguide/servidores/know-how/dns-over-https/).

Con esto podemos forzar la llamada para que en vez que sea con un “dig” en bash, o un “resolver de DNS” con python3, poder tener la respuesta a través de una llamada web. Y para más dolor de cabeza de los equipos defensivos, esta llamada se hace a través de HTTPS, o sea está “protegida” frente a monitoreos de tráfico.

https://blog.chromium.org/2020/05/a-safer-and-more-private-browsing-DoH.html

¿Con quién se puede usar el DoH?

Muchas empresas están dando este servicio y nos conviene mantener variedad en estas definiciones, pero están los “mismos de siempre”:

Ojo que algunos servidores usan el RFC 8484 de manera estricta y otros tienen distintas funcionalidades, por lo que tenemos que “decidirnos” por una implementación para nuestro código. Por supuesto, esa llamada no puede ser al dominio, porque queremos evitar llamar la atención, por lo que es mejor llamar directamente a las IP de los servidores

Por ejemplo, tenemos las siguientes llamadas que sí nos van a dar resultados:

Bash

Para Bash, podemos mantener el código anterior, solamente tenemos que usar dentro de la “pequeña vuelta” otro curl que haga alguna de las llamadas anteriores, por lo que quedaría algo así:

#!/bin/bash
URL="http://0xdeadbeef.tw/"
PORT=80
if [[ "${URL}" =~ 'https://' ]]; then
        PORT=443
fi
DOM=$(echo $URL | sed -e 's|^[^/]*//||' -e 's|/.*$||')
MYIP=$(curl -s -H 'accept: application/dns-json' 'https://8.8.8.8/resolve?name='${DOM}'&type=a' | sed -re 's/^.*"data":"([^"]+)".*$/\1/')
curl --resolve ${DOM}:${PORT}:${MYIP} ${URL}

Python3

Ahora para Python3, tenemos que hacer un request en el código del resolver, y extraer esos datos. Pareciera ser un código igual de complejo, pero la verdad es más sencillo de revisar que el anterior:

#!/usr/bin/env python3
import requests
import sys, re, json
from urllib3.util import connection
def myResolver(host,dnssrv):
    if host in ["127.0.0.1","localhost"]:
        return "127.0.0.1"
    elif re.search("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$",host):
        return host
    r = requests.get("https://8.8.8.8/resolve?name=" + host + "&type=a")
    rdata = json.loads(r.text)["Answer"][0]["data"]
    if "0.0.0.0" == str(rdata):
        raise Exception("0.0.0.0 value for resolution")
    return str(rdata)
def patched_create_connection(address, *args, **kwargs):
    host, port = address
    hostname = myResolver(host,["1.1.1.1"])
    return _orig_create_connection((hostname, port), *args, **kwargs)
connection.create_connection = patched_create_connection
r = requests.get("http://0xdeadbeef.tw/")

Powershell

Para Powershell, lo único que pude realizar es generar una nueva función para hacer la llamada web. Esta función genera la resolución DNS a través de DoH y eso lo usa para hacer la llamada final al destino.

# Basado en: https://gist.github.com/matt40k/03410719493279800d642134ae94cb2e
function ResolveDNS {
    param($DNSHost)
    $r = Invoke-WebRequest -Uri ('https://8.8.8.8/resolve?name=' + $DNSHost + '&type=A') | ConvertFrom-Json
    return $r.Answer[0].data
}

function MyWebRequest {
    param($URL)
    $uri = [System.Uri]::new($URL)
    $res = ResolveDNS -DNSHost $uri.DnsSafeHost
    $newURL = $uri.Scheme + "://" + $res + $uri.PathAndQuery
    return Invoke-WebRequest -Uri $newURL -Headers @{'User-Agent' = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'; 'Host' = $uri.DnsSafeHost }
}

MyWebRequest -URL http://0xdeadbeef.tw/

Conclusión

Revisando las problemáticas anteriores, todavía existen formas de poder evitar los “típicos” monitoreos de DNS que podrían existir en cada una de nuestras casas.

Este tipo de comunicación (DNS over HTTPS) es mucho más complejo de monitorear, por lo que se tiene que pensar en otras alternativas como en detección por comportamiento de usuarios (UBA) u otro tipo de anomalías de tráfico.

Ojalá les sirva en alguna de sus “andanzas”.

Muchas gracias por leer hasta acá.

Deje un comentario

Crea una web o blog en WordPress.com

Subir ↑