Nov 8, 2025

Instalar y configurar ctrld para la mejorar la configuración DNS en SailfishOS

Tutorial para instalar y configurar ctrld en SailfishOS para mejorar la gestión de servidores DNS en el sistema y habilitar características avanzadas como DoH, DOT y DoQ

Llevo mucho tiempo buscando una buena forma de configurar DNS personalizados en SailfishOS. La forma normal de hacerlo es usando la herramienta connmanctl de connman, el gestor de redes de Sailfish, pero es bastante tedioso ya que solo se puede hacer individualmente para cada red, además de no soportar aun protocolos mas modernos como DoH, DoT o DoQ.

Mas tarde probé con DNS Alternative, una herramienta que adapta las configuraciones de DNScrypt-proxy y Dnsmasq a Sailfish, pero no me terminó de funcionar correctamente.

Recientemente me topé con ctrld, una herramienta de código abierto de Control-D, empresa asociada a Windscribe (por si os interesa, referido para su VPN de código abierto en la que dan 1GB adicional en el plan gratuito esp.windscribe.com/yo/yqjmk6e5), la cual además de ser sencilla de configurar y tener muchas opciones de gestión de peticiones, admite todos los protocolos de DNS actuales como DoH, DoH3, DoT y DoQ, por lo que me animé a probar si funcionaba en Sailfish con un resultado exitoso.

Instalar y configurar ctrld

Los comandos deben ser ser ejecutados con permisos de administrador accediento con "devel-su" o usando "sudo".

Descargamos el script de instalación que detectará nuestra arquitectura e instalará la versión óptima para nuestro dispositivo.

sh -c 'sh -c "$(curl -sL https://api.controld.com/dl)"'

Instalación ctrld

Una vez instalado, tendremos que hacer unas modificaciones en connman, el gestor de red que usa SailfishOS, para que deje de gestionar las peticiones DNS del sistema, ya que si intentamos arrancar ctrld con ctrld start nos dirá que el puerto 53 que es el usado para las peticiones DNS ya está en uso.

Nov  8 14:39:24.000 FTL listener.0 could not listen on 0.0.0.0:53: listen udp 127.0.0.1:53: bind: address already in use
listen tcp 127.0.0.1:53: bind: address already in use

Lo primero será pasarle el argumento --nodnsproxy al servicio de connman. Para ello tenemos que crear un fichero en el directorio que tiene asignado el servicio de systemd de connman donde podemos decirle que argumentos pasarle al servicio

nano /var/lib/environment/connman/nodnsproxy.conf

En ese fichero pondremos el contenido CONNMAN_ARGS=--nodnsproxy y guardamos.

Si ya existe un fichero .conf en la ruta /var/lib/environment/connman/ (como es mi caso), en lugar de crear un fichero editaremos el exixtente y añadimos --nodnsproxy como último parámetro.

El siguiente paso será que el fichero /etc/resolv.conf deje de estar controlado por connman, ya que actualmente por defecto es un enlace simbólico a /run/connman/resolv.conf. Para ello, primero vamos a cambiar la ruta donde corre el servicio de connman editando los parámetros del servicio de systemd:

systemctl edit connman

Introducimos el siguiente contenido y guardamos:

[Service]
RuntimeDirectory=connman

Tras realizar ambas cosas, hacemos que systemd recargue el contenido del servicio systemctl daemon-reload.

Ahora vamos a eliminar el enlace simbólico que es el fichero resolv.conf y lo creamos de nuevo como fichero independiente:

rm -f /etc/resolv.conf
touch /etc/resolv.conf
echo nameserver 127.0.0.1 > /etc/resolv.conf

El contenido no es importante (pero ya que estamos le ponemos la IP que usará nuestro servidor local de ctrld), ya que posteriormente el servicio de ctrld sobreescribirá su contenido cuando lo arranquemos.

Reiniciamos el servicio de connman con systemctl restart connman para que recargue los cambios que hemos hecho y ya podremos iniciar el servicio de ctrld:

ctrld start

Arranque ctrld

Tras el arranque, vemos que nos habrá creado su fichero de configuración que modificaremos mas adelante en la ruta /etc/controld/ctrld.toml, y si consultamos el contenido del fichero /etc/resolv.conf veremos que se ha actualizado:

# resolv.conf(5) file generated by ctrld
# DO NOT EDIT THIS FILE BY HAND -- CHANGES WILL BE OVERWRITTEN

nameserver 127.0.0.1

Para testear que está funcionando ctrld con sus DNS por defecto escribiremos dig verify.controld.com @127.0.0.1 +short y si nos responde lo siguiente es que ya está en funcionamiento:

api.controld.com.
147.185.34.1

Por defecto, usa los servidores DNS de Control-D, los cuales tienen varias configuraciones, pero en mi caso, voy a cambiarlos por los de Rocks DNS y así vemos como funciona el fichero de configuración. Para ello, abrimos el fichero de configuración para editarlo:

nano /etc/controld/ctrld.toml

El contenido por defecto es el siguiente (podemos ver en la documentación sus diferentes posibilidades de configuración que son muchas github.com/Control-D-Inc/ctrld/blob/main/docs/config.md):

[listener]
  [listener.0]
    ip = '0.0.0.0'
    port = 53

    [listener.0.policy]
      name = 'Main Policy'
      networks = [
        {        'network.0' = ['upstream.0']}
      ]
      rules = [
        {        'example.com' = ['upstream.0']},
        {        '*.ads.com' = ['upstream.1']}
      ]

[network]
  [network.0]
    name = 'Network 0'
    cidrs = ['0.0.0.0/0']

[upstream]
  [upstream.0]
    name = 'Control D - Anti-Malware'
    type = 'doh'
    endpoint = 'https://freedns.controld.com/p1'
    bootstrap_ip = '76.76.2.11'
    timeout = 5000

  [upstream.1]
    name = 'Control D - No Ads'
    type = 'doq'
    endpoint = 'p2.freedns.controld.com'
    bootstrap_ip = '76.76.2.11'
    timeout = 3000

Tiene 4 partes principales:

  • [Service] - Configuraciones generales (no incluida en el fichero por defecto).
    • Aquí podremos configurar cosas como el directorio y nivel de logs almacenados por el servicio local, si queremos cachear las peticiones DNS, configurar métricas con un servidor Prometheus, etc.
  • [Networks] - De dónde proceden las consultas DNS.
    • Aquí podemos definir varias redes. Útil cuando se manejan VLANs o subredes que no es nuestro caso.
  • [Listeners] - Lo que recibe las consultas DNS y define las políticas.
    • Aquí podremos configurar la IP y el puerto que usará el servicio ctrld para realizar las escuchas de las peticiones DNS. Podemos configurar varios listeners
    • [Policies] - Define los Upstream a usar en base a diferentes políticas.
      • Esto es útil si queremos configurar políticas para usar diferentes servidores DNS en base a dominios, direcciones MAC o subredes.
  • [Upstreams] - Dónde enviar las consultas DNS.
    • Aquí es donde definiremos los servidores DNS a usar, y donde podremos configurar cosas interesantes como el tipo de DNS (DoH, DoT, DoQ, legacy) o si admite direcciones IPv4,v6.

Tras añadir los DNS de Rock DNS en todas sus formas y cosas relativas a logs del servicio, mi fichero de configuración queda así:

[service]
    log_level = "notice"
    log_path = "/var/logs/ctrld/crld.log"
    cache_enable = true
    cache_size = 4096  
    cache_ttl_override = 60
    cache_serve_stale = true

[listener]
  [listener.0]
    ip = '0.0.0.0'
    port = 53

    [listener.0.policy]
      name = 'Main Policy'
      networks = [
        {        'network.0' = ['upstream.0','upstream.6']}
      ]
      rules = [
        {        '*.ads.com' = ['upstream.8']}
      ]

[network]
  [network.0]
    name = 'Network 0'
    cidrs = ['0.0.0.0/0']

[upstream]
  [upstream.0]
    name = 'RocksDNS - DoT'
    type = 'dot'
    endpoint = 'dns.rocksdns.ovh'
    bootstrap_ip = '82.223.31.111'
    timeout = 5000

  [upstream.1]
    name = 'RocksDNS - DoQ'
    type = 'doq'
    endpoint = 'dns.rocksdns.ovh'
    bootstrap_ip = '82.223.31.111'
    timeout = 5000

  [upstream.2]
    name = 'RocksDNS - DoH'
    type = 'doh'
    endpoint = 'https://dns.rocksdns.ovh/dns-query'
    bootstrap_ip = '82.223.31.111'
    timeout = 5000
    send_client_info = true

  [upstream.3]
    name = 'RocksDNS - DoH3'
    type = 'doh3'
    endpoint = 'https://dns.rocksdns.ovh/dns-query'
    bootstrap_ip = '82.223.31.111'
    timeout = 5000
    send_client_info = true

  [upstream.4]
    name = 'RocksDNS2 - DoT'
    type = 'dot'
    endpoint = 'dns2.rocksdns.ovh'
    bootstrap_ip = '116.203.57.216'
    timeout = 5000

  [upstream.5]
    name = 'RocksDNS2 - DoQ'
    type = 'doq'
    endpoint = 'dns2.rocksdns.ovh'
    bootstrap_ip = '116.203.57.216'
    timeout = 5000

  [upstream.6]
    name = 'RocksDNS2 - DoH'
    type = 'doh'
    endpoint = 'https://dns2.rocksdns.ovh/dns-query'
    bootstrap_ip = '116.203.57.216'
    timeout = 5000
    send_client_info = true

  [upstream.7]
    name = 'RocksDNS2 - DoH3'
    type = 'doh3'
    endpoint = 'https://dns2.rocksdns.ovh/dns-query'
    bootstrap_ip = '116.203.57.216'
    timeout = 5000
    send_client_info = true

  [upstream.8]
    bootstrap_ip = "76.76.2.11"
    endpoint = "p2.freedns.controld.com"
    name = "Control D - Anti-Malware, Ads & Tracking DoQ"
    timeout = 5000
    type = "doq"
    ip_stack = "both"

  [upstream.9]
    bootstrap_ip = "76.76.2.11"
    endpoint = "https://freedns.controld.com/p2"
    name = "Control D - Anti-Malware, Ads & Tracking DOH3"
    timeout = 5000
    type = "doh3"
    ip_stack = "both"

  [upstream.10]
    bootstrap_ip = "76.76.2.11"
    endpoint = "p2.freedns.controld.com"
    name = "Control D - Anti-Malware, Ads & Tracking DoT"
    timeout = 5000
    type = "dot"
    ip_stack = "split"

En él se puede ver que he configurado que use RocksDNS - DoT como principal y RocksDNS2 - DoH como secundario si falla el primero, y además, para las peticiones DNS de dominios que contienen *.ads.com he puesto que use los DNS de Control D - Anti-Malware, Ads & Tracking DoQ y como secundario Control D - Anti-Malware, Ads & Tracking DOH3, haciendo de esa forma uso de diferentes reglas y diferentes tecnologías de DNS.

Tras ello, para que se apliquen los cambios reiniciamos el servicio con ctrld restart y ya podremos distrutar de nuestros nuevos DNS y cambiarlos facilmente cuando queramos.

Podemos testear que nos está asignando el DNS que queremos en páginas como controld.com/tools/dns-leak-test, www.dnsleaktest.com o dnscheck.tools.

Para actualizar el servicio de ctrld en caso de haber nuevas versiones, solo tenemos que ejecutar ctrld upgrade para que se nos actualice a la última versión.