Skip to content

Example Configurations

Yegor S edited this page Sep 11, 2023 · 10 revisions

Example Configurations

The best way to learn something is to see an example. This page provides a few example ctrld configurations for different use cases. You can copy/paste these and use them as a starting point.

Simplest

The simplest possible configuration looks like this. The following config does the following:

  • Spawn a single DNS listener on 0.0.0.0 (all interfaces) and port 53
  • Send all DNS queries to the matching upstream (listener.0 -> upstream.0) which uses DNS-over-HTTPS
[listener]
  [listener.0]
    ip = '0.0.0.0'
    port = 53

[upstream]
  [upstream.0]
    type = 'doh'
    endpoint = 'https://freedns.controld.com/p2'
    timeout = 5000

Multiple Upstreams

Let's get a bit fancier, and specify multiple upstreams and route requests via network policy. The following config does the following:

  • Spawn a single DNS listener on 0.0.0.0 (all interfaces) and port 5354
  • Define 2 networks with 2 different subnets: 192.168.1.0/24 and 192.168.100.0/24
  • Define 2 upstreams with different levels of blocking
  • Using a network policy map 192.168.1.0/24 to upstream.0 and 192.168.100.0/24 to upstream.1. This means that requests originating from each subnet will be sent to a different upstream DNS resolver
  • If a request doesn't match the defined networks, it will use the default upstream.0. To override this behavior and REFUSE queries from undefined networks, use restricted resolver config param.
[listener]
  [listener.0]
    ip = '0.0.0.0'
    port = 5354

    [listener.0.policy]
      name = 'Home Policy'
      networks = [
        { 'network.0' = ['upstream.0']},
        { 'network.1' = ['upstream.1']}
      ]

[network]
  [network.0]
    name = 'Adults'
    cidrs = ['192.168.1.0/24']

  [network.1]
    name = 'Children'
    cidrs = ['192.168.100.0/24']

[upstream]
  [upstream.0]
    name = 'Control D - No Ads'
    type = 'doh'
    endpoint = 'https://freedns.controld.com/p2'
    timeout = 5000

  [upstream.1]
    name = 'Control D - Family Friendly'
    type = 'doh'
    endpoint = 'https://freedns.controld.com/family'
    timeout = 5000

Custom Domains and Upstreams

If you wish to use your own local DNS resolver for your own custom domains, and send everything else to a remote upstream, you can do that too. The following config will do the following:

  • Spawn a single DNS listener on 10.0.0.1 and port 5354
  • Define 2 networks with 3 different subnets: 10.0.0.0/24 + 10.0.1.0/24 (network.0) and 10.0.99.0/24 (network.1)
  • Define 3 upstreams with 3 different endpoints, one of them being a local DNS resolver running on 10.0.0.1:1234
  • Using a network policy map network.0 (10.0.0.0/24, 10.0.1.0/24) to upstream.0, and network.1 (10.0.99.0/24) to upstream.1
  • Using a rules policy map DNS queries for *.domain.local (wildcard) and secret.cheese (specific) to upstream.2 which runs locally on 10.0.0.1:1234. This supersedes network policy rules.
[listener]
  [listener.0]
    ip = '10.0.0.1'
    port = 5354

    [listener.0.policy]
      name = 'My Policy'
      networks = [
          {'network.0' = ['upstream.0']},
          {'network.1' = ['upstream.1']}
      ]
      rules = [
        { '*.domain.local' = ['upstream.2']},
        { 'secret.cheese' = ['upstream.2']}
      ]

[network]
  [network.0]
    name = 'Main Subnets'
    cidrs = ['10.0.0.0/24', '10.0.1.0/24']

  [network.1]
    name = 'Personal Subnet'
    cidrs = ['10.0.99.0/24']

[upstream]
  [upstream.0]
    name = 'Unfiltered Resolver'
    type = 'doh'
    endpoint = 'https://freedns.controld.com/p0'
    timeout = 5000

  [upstream.1]
    name = 'My Control D Resolver'
    type = 'doh3'
    endpoint = 'https://dns.controld.com/abcd1234'
    timeout = 5000
  
  [upstream.2]
    name = 'Custom Resolver'
    type = 'legacy'
    endpoint = '10.0.0.1:1234'
    timeout = 5000

Multiple Listeners

So far all examples used a single listener, which is likely what you want in 99% of cases. But you're the 1% that needs more. Well, we got you covered here as well. The following example config will do the following:

  • Spawn 2 different DNS listeners on 2 different IPs (127.0.0.1:5555 and 127.0.0.2:5555)
  • Define 2 upstreams with different DNS endpoints
  • DNS traffic received on listener.0 uses upstream.0, while DNS traffic on listener.1 uses upstream.1 (this is default behavior unless you have an overriding policy)
[listener]
  [listener.0]
    ip = '127.0.0.1'
    port = 5555

  [listener.1]
    ip = '127.0.0.2'
    port = 5555

[upstream]
  [upstream.0]
    type = 'doh'
    endpoint = 'https://freedns.controld.com/p2'
    timeout = 5000

  [upstream.1]
    type = 'legacy'
    endpoint = '1.1.1.1'
    timeout = 5000

You can now use network and rule policies in conjunction with the above to define highly complex behaviors using multiple listeners. Use the earlier example for a single listener, as it works the same. Just be sure to attach the policy to the correct listener.

Clone this wiki locally