ctrld

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 14, 2022 License: MIT Imports: 18 Imported by: 0

README

ctrld

A highly configurable DNS forwarding proxy with support for:

  • Multiple listeners for incoming queries
  • Multiple upstreams with fallbacks
  • Multiple network policy driven DNS query steering
  • Policy driven domain based "split horizon" DNS with wildcard support

All DNS protocols are supported, including:

  • UDP 53
  • DNS-over-HTTPS
  • DNS-over-TLS
  • DNS-over-HTTP/3 (DOH3)
  • DNS-over-QUIC

Use Cases

  1. Use secure DNS protocols on networks and devices that don't natively support them (legacy routers, legacy OSes, TVs, smart toasters).
  2. Create source IP based DNS routing policies with variable secure DNS upstreams. Subnet 1 (admin) uses upstream resolver A, while Subnet 2 (employee) uses upstream resolver B.
  3. Create destination IP based DNS routing policies with variable secure DNS upstreams. Listener 1 uses upstream resolver C, while Listener 2 uses upstream resolver D.
  4. Create domain level "split horizon" DNS routing policies to send internal domains (*.company.int) to a local DNS server, while everything else goes to another upstream.

OS Support

  • Windows (386, amd64, arm)
  • Mac (amd64, arm64)
  • Linux (386, amd64, arm, mips)

Download

Download pre-compiled binaries from the Releases section.

Build

ctrld requires go1.19+:

$ go build ./cmd/ctrld

or

$ go install github.com/Control-D-Inc/ctrld/cmd/ctrld@latest

Arguments

Usage:
  ctrld [command]

Available Commands:
  help        Help about any command
  run         Run the DNS proxy server

Flags:
  -h, --help      help for ctrld
  -v, --verbose   verbose log output
      --version   version for ctrld

Use "ctrld [command] --help" for more information about a command.

Usage

To start the server with default configuration, simply run: ctrld run. This will create a generic config.toml file in the working directory and start the service.

  1. Start the server
$ sudo ./ctrld run
  1. Run a test query using a DNS client, for example, dig:
$ dig verify.controld.com @127.0.0.1 +short
api.controld.com.
147.185.34.1

If verify.controld.com resolves, you're successfully using the default Control D upstream.

Configuration

Example
  • Start listener.0 on 127.0.0.1:53
  • Accept queries from any source address
  • Send all queries to upstream.0 via DoH protocol
Default Config
[listener]

  [listener.0]
    ip = "127.0.0.1"
    port = 53
    restricted = false

[network]

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

[service]
  log_level = "info"
  log_path = ""

[upstream]

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

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

Advanced

The above is the most basic example, which will work out of the box. If you're looking to do advanced configurations using policies, see Configuration Docs for complete documentation of the config file.

Contributing

See Contribution Guideline

Roadmap

The following functionality is on the roadmap and will be available in future releases.

  • Prometheus metrics exporter
  • Local caching
  • Service self-installation

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ProxyLog = zerolog.New(io.Discard)

ProxyLog emits the log record for proxy operations. The caller should set it only once.

Functions

func InitConfig

func InitConfig(v *viper.Viper, name string)

InitConfig initializes default config values for given *viper.Viper instance.

func Log

func Log(ctx context.Context, e *zerolog.Event, format string, v ...any)

Log emits the logs for a particular zerolog event. The request id associated with the context will be included if presents.

func ValidateConfig

func ValidateConfig(validate *validator.Validate, cfg *Config) error

ValidateConfig validates the given config.

Types

type Config

type Config struct {
	Service  ServiceConfig              `mapstructure:"service"`
	Network  map[string]*NetworkConfig  `mapstructure:"network" toml:"network" validate:"min=1,dive"`
	Upstream map[string]*UpstreamConfig `mapstructure:"upstream" toml:"upstream" validate:"min=1,dive"`
	Listener map[string]*ListenerConfig `mapstructure:"listener" toml:"listener" validate:"min=1,dive"`
}

Config represents ctrld supported configuration.

type ListenerConfig

type ListenerConfig struct {
	IP         string                `mapstructure:"ip" toml:"ip" validate:"ip"`
	Port       int                   `mapstructure:"port" toml:"port" validate:"gt=0"`
	Restricted bool                  `mapstructure:"restricted" toml:"restricted"`
	Policy     *ListenerPolicyConfig `mapstructure:"policy" toml:"policy"`
}

ListenerConfig specifies the networks configuration that ctrld will run on.

func (*ListenerConfig) Init

func (lc *ListenerConfig) Init()

Init initialized necessary values for an ListenerConfig.

type ListenerPolicyConfig

type ListenerPolicyConfig struct {
	Name                 string   `mapstructure:"name" toml:"name"`
	Networks             []Rule   `mapstructure:"networks" toml:"networks" validate:"dive,len=1"`
	Rules                []Rule   `mapstructure:"rules" toml:"rules" validate:"dive,len=1"`
	FailoverRcodes       []string `mapstructure:"failover_rcodes" toml:"failover_rcodes" validate:"dive,dnsrcode"`
	FailoverRcodeNumbers []int    `mapstructure:"-" toml:"-"`
}

ListenerPolicyConfig specifies the policy rules for ctrld to filter incoming requests.

type NetworkConfig

type NetworkConfig struct {
	Name   string       `mapstructure:"name" toml:"name"`
	Cidrs  []string     `mapstructure:"cidrs" toml:"cidrs" validate:"dive,cidr"`
	IPNets []*net.IPNet `mapstructure:"-" toml:"-"`
}

NetworkConfig specifies configuration for networks where ctrld will handle requests.

type ReqIdCtxKey

type ReqIdCtxKey struct{}

ReqIdCtxKey is the context.Context key for a request id.

type Resolver

type Resolver interface {
	Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error)
}

Resolver is the interface that wraps the basic DNS operations.

Resolve resolves the DNS query, return the result and the corresponding error.

func NewResolver

func NewResolver(uc *UpstreamConfig) (Resolver, error)

NewResolver creates a Resolver based on the given upstream config.

type Rule

type Rule map[string][]string

Rule is a map from source to list of upstreams. ctrld uses rule to perform requests matching and forward the request to corresponding upstreams if it's matched.

type ServiceConfig

type ServiceConfig struct {
	LogLevel   string `mapstructure:"log_level" toml:"log_level"`
	LogPath    string `mapstructure:"log_path" toml:"log_path"`
	Daemon     bool   `mapstructure:"-" toml:"-"`
	AllocateIP bool   `mapstructure:"-" toml:"-"`
}

ServiceConfig specifies the general ctrld config.

type UpstreamConfig

type UpstreamConfig struct {
	Name        string `mapstructure:"name" toml:"name"`
	Type        string `mapstructure:"type" toml:"type" validate:"oneof=doh doh3 dot doq os legacy"`
	Endpoint    string `mapstructure:"endpoint" toml:"endpoint" validate:"required_unless=Type os"`
	BootstrapIP string `mapstructure:"bootstrap_ip" toml:"bootstrap_ip"`
	Domain      string `mapstructure:"-" toml:"-"`
	Timeout     int    `mapstructure:"timeout" toml:"timeout" validate:"gte=0"`
}

UpstreamConfig specifies configuration for upstreams that ctrld will forward requests to.

func (*UpstreamConfig) Init

func (uc *UpstreamConfig) Init()

Init initialized necessary values for an UpstreamConfig.

Directories

Path Synopsis
cmd
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL