{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Blocky","text":"

Blocky is a DNS proxy and ad-blocker for the local network written in Go with following features:

"},{"location":"#features","title":"Features","text":""},{"location":"#contribution","title":"Contribution","text":"

Issues, feature suggestions and pull requests are welcome! Blocky lives on GitHub.

"},{"location":"additional_information/","title":"Additional information","text":""},{"location":"additional_information/#print-current-configuration","title":"Print current configuration","text":"

To print runtime configuration / statistics, you can send SIGUSR1 signal to running process.

Summary

Example output:

INFO server: current configuration:\nINFO server: -> resolver: 'ClientNamesResolver'\nINFO server:      singleNameOrder = \"[2 1]\"\nINFO server:      externalResolver = \"upstream 'tcp+udp:192.168.178.1:53'\"\nINFO server:      cache item count = 7\nINFO server: -> resolver: 'QueryLoggingResolver'\nINFO server:      logDir= \"/logs\"\nINFO server:      perClient = false\nINFO server:      logRetentionDays= 7\nINFO server: -> resolver: 'MetricsResolver'\nINFO server:      metrics:\nINFO server:        Enable = true\nINFO server:        Path   = /metrics\nINFO server: -> resolver: 'ConditionalUpstreamResolver'\nINFO server:      fritz.box = \"parallel upstreams 'upstream 'tcp+udp:192.168.178.1:53''\"\nINFO server: -> resolver: 'CustomDNSResolver'\nINFO server: runtime information:\n...\nINFO server: MEM Alloc =                 9 MB\nINFO server: MEM HeapAlloc =             9 MB\nINFO server: MEM Sys =                  88 MB\nINFO server: MEM NumGC =              1533\nINFO server: RUN NumCPU =                4\nINFO server: RUN NumGoroutine =         18\n

Hint

To send a signal to a process you can use kill -s USR1 <PID> or docker kill -s SIGUSR1 blocky for docker setup

"},{"location":"additional_information/#debug-profiling","title":"Debug / Profiling","text":"

If http listener is enabled, pprof endpoint (/debug/pprof) is enabled automatically.

"},{"location":"additional_information/#list-sources","title":"List sources","text":"

Some links/ideas for lists:

"},{"location":"additional_information/#blacklists","title":"Blacklists","text":"

Warning

Use only blacklists from the sources you trust!

"},{"location":"additional_information/#whitelists","title":"Whitelists","text":""},{"location":"additional_information/#list-of-public-dns-servers","title":"List of public DNS servers","text":"

Warning

DNS server provider has access to all your DNS queries (all visited domain names). Some DNS providers can use (tracking, analyzing, profiling etc.). It is recommended to use different DNS upstream servers in blocky to distribute your DNS queries over multiple providers.

Please read the description before using the DNS server as upstream. Some of them provide already an ad-blocker, some filters other content. If you use external DNS server with included ad-blocker, you can't choose which domains should be blocked, and you can't use whitelisting.

This is only a small excerpt of all free available DNS servers and should only be understood as an idee.

Info

I will NOT rate the DNS providers in the list. This list is sorted alphabetically.

"},{"location":"additional_information/#project-links","title":"Project links","text":""},{"location":"additional_information/#code-repository","title":"Code repository","text":"

Main: GitHub

Mirror: Codeberg

"},{"location":"additional_information/#container-registry","title":"Container Registry","text":"

Main: Docker Hub

Mirror: GitHub Container Registry

"},{"location":"additional_information/#developer-information","title":"Developer Information","text":""},{"location":"additional_information/#docker-images","title":"Docker Images","text":"

To enable Docker image creation on a GitHub fork create a secret with the name DEVELOPMENT_DOCKER and the value true. This will trigger a workflow on every push of a branch starting with fb- and create an image with the branch name.

"},{"location":"additional_information/#automatic-fork-sync","title":"Automatic fork sync","text":"

To enable automatic fork synchronisation create a secret with the name FORK_SYNC_TOKEN with an access token that has write permission to the fork repository. The enabled workflow will sync the main branch every 30 minutes with its upstream.

"},{"location":"configuration/","title":"Configuration","text":"

This chapter describes all configuration options in config.yaml. You can download a reference file with all configuration properties as JSON.

reference configuration file
upstreams:\n  init:\n    # Configure startup behavior.\n    # accepted: blocking, failOnError, fast\n    # default: blocking\n    strategy: fast\n  groups:\n    # these external DNS resolvers will be used. Blocky picks 2 random resolvers from the list for each query\n    # format for resolver: [net:]host:[port][/path]. net could be empty (default, shortcut for tcp+udp), tcp+udp, tcp, udp, tcp-tls or https (DoH). If port is empty, default port will be used (53 for udp and tcp, 853 for tcp-tls, 443 for https (Doh))\n    # this configuration is mandatory, please define at least one external DNS resolver\n    default:\n      # example for tcp+udp IPv4 server (https://digitalcourage.de/)\n      - 5.9.164.112\n      # Cloudflare\n      - 1.1.1.1\n      # example for DNS-over-TLS server (DoT)\n      - tcp-tls:fdns1.dismail.de:853\n      # example for DNS-over-HTTPS (DoH)\n      - https://dns.digitale-gesellschaft.ch/dns-query\n    # optional: use client name (with wildcard support: * - sequence of any characters, [0-9] - range)\n    # or single ip address / client subnet as CIDR notation\n    laptop*:\n      - 123.123.123.123\n  # optional: Determines what strategy blocky uses to choose the upstream servers.\n  # accepted: parallel_best, strict, random\n  # default: parallel_best\n  strategy: parallel_best\n  # optional: timeout to query the upstream resolver. Default: 2s\n  timeout: 2s\n  # optional: HTTP User Agent when connecting to upstreams. Default: none\n  userAgent: \"custom UA\"\n\n# optional: Determines how blocky will create outgoing connections. This impacts both upstreams, and lists.\n# accepted: dual, v4, v6\n# default: dual\nconnectIPVersion: dual\n\n# optional: custom IP address(es) for domain name (with all sub-domains). Multiple addresses must be separated by a comma\n# example: query \"printer.lan\" or \"my.printer.lan\" will return 192.168.178.3\ncustomDNS:\n  customTTL: 1h\n  # optional: if true (default), return empty result for unmapped query types (for example TXT, MX or AAAA if only IPv4 address is defined).\n  # if false, queries with unmapped types will be forwarded to the upstream resolver\n  filterUnmappedTypes: true\n  # optional: replace domain in the query with other domain before resolver lookup in the mapping\n  rewrite:\n    example.com: printer.lan\n  mapping:\n    printer.lan: 192.168.178.3,2001:0db8:85a3:08d3:1319:8a2e:0370:7344\n\n# optional: definition, which DNS resolver(s) should be used for queries to the domain (with all sub-domains). Multiple resolvers must be separated by a comma\n# Example: Query client.fritz.box will ask DNS server 192.168.178.1. This is necessary for local network, to resolve clients by host name\nconditional:\n  # optional: if false (default), return empty result if after rewrite, the mapped resolver returned an empty answer. If true, the original query will be sent to the upstream resolver\n  # Example: The query \"blog.example.com\" will be rewritten to \"blog.fritz.box\" and also redirected to the resolver at 192.168.178.1. If not found and if `fallbackUpstream` was set to `true`, the original query \"blog.example.com\" will be sent upstream.\n  # Usage: One usecase when having split DNS for internal and external (internet facing) users, but not all subdomains are listed in the internal domain.\n  fallbackUpstream: false\n  # optional: replace domain in the query with other domain before resolver lookup in the mapping\n  rewrite:\n    example.com: fritz.box\n  mapping:\n    fritz.box: 192.168.178.1\n    lan.net: 192.168.178.1,192.168.178.2\n\n# optional: use black and white lists to block queries (for example ads, trackers, adult pages etc.)\nblocking:\n  # definition of blacklist groups. Can be external link (http/https) or local file\n  blackLists:\n    ads:\n      - https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt\n      - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts\n      - http://sysctl.org/cameleon/hosts\n      - https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt\n      - |\n        # inline definition with YAML literal block scalar style\n        someadsdomain.com\n        *.example.com\n    special:\n      - https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hosts\n  # definition of whitelist groups. Attention: if the same group has black and whitelists, whitelists will be used to disable particular blacklist entries. If a group has only whitelist entries -> this means only domains from this list are allowed, all other domains will be blocked\n  whiteLists:\n    ads:\n      - whitelist.txt\n      - |\n        # inline definition with YAML literal block scalar style\n        # hosts format\n        whitelistdomain.com\n        # this is a regex\n        /^banners?[_.-]/\n  # definition: which groups should be applied for which client\n  clientGroupsBlock:\n    # default will be used, if no special definition for a client name exists\n    default:\n      - ads\n      - special\n    # use client name (with wildcard support: * - sequence of any characters, [0-9] - range)\n    # or single ip address / client subnet as CIDR notation\n    laptop*:\n      - ads\n    192.168.178.1/24:\n      - special\n  # which response will be sent, if query is blocked:\n  # zeroIp: 0.0.0.0 will be returned (default)\n  # nxDomain: return NXDOMAIN as return code\n  # comma separated list of destination IP addresses (for example: 192.100.100.15, 2001:0db8:85a3:08d3:1319:8a2e:0370:7344). Should contain ipv4 and ipv6 to cover all query types. Useful with running web server on this address to display the \"blocked\" page.\n  blockType: zeroIp\n  # optional: TTL for answers to blocked domains\n  # default: 6h\n  blockTTL: 1m\n  # optional: Configure how lists, AKA sources, are loaded\n  loading:\n    # optional: list refresh period in duration format.\n    # Set to a value <= 0 to disable.\n    # default: 4h\n    refreshPeriod: 24h\n    # optional: Applies only to lists that are downloaded (HTTP URLs).\n    downloads:\n      # optional: timeout for list download (each url). Use large values for big lists or slow internet connections\n      # default: 5s\n      timeout: 60s\n      # optional: Maximum download attempts\n      # default: 3\n      attempts: 5\n      # optional: Time between the download attempts\n      # default: 500ms\n      cooldown: 10s\n    # optional: Maximum number of lists to process in parallel.\n    # default: 4\n    concurrency: 16\n    # Configure startup behavior.\n    # accepted: blocking, failOnError, fast\n    # default: blocking\n    strategy: failOnError\n    # Number of errors allowed in a list before it is considered invalid.\n    # A value of -1 disables the limit.\n    # default: 5\n    maxErrorsPerSource: 5\n\n# optional: configuration for caching of DNS responses\ncaching:\n  # duration how long a response must be cached (min value).\n  # If <=0, use response's TTL, if >0 use this value, if TTL is smaller\n  # Default: 0\n  minTime: 5m\n  # duration how long a response must be cached (max value).\n  # If <0, do not cache responses\n  # If 0, use TTL\n  # If > 0, use this value, if TTL is greater\n  # Default: 0\n  maxTime: 30m\n  # Max number of cache entries (responses) to be kept in cache (soft limit). Useful on systems with limited amount of RAM.\n  # Default (0): unlimited\n  maxItemsCount: 0\n  # if true, will preload DNS results for often used queries (default: names queried more than 5 times in a 2-hour time window)\n  # this improves the response time for often used queries, but significantly increases external traffic\n  # default: false\n  prefetching: true\n  # prefetch track time window (in duration format)\n  # default: 120\n  prefetchExpires: 2h\n  # name queries threshold for prefetch\n  # default: 5\n  prefetchThreshold: 5\n  # Max number of domains to be kept in cache for prefetching (soft limit). Useful on systems with limited amount of RAM.\n  # Default (0): unlimited\n  prefetchMaxItemsCount: 0\n  # Time how long negative results (NXDOMAIN response or empty result) are cached. A value of -1 will disable caching for negative results.\n  # Default: 30m\n  cacheTimeNegative: 30m\n\n# optional: configuration of client name resolution\nclientLookup:\n  # optional: this DNS resolver will be used to perform reverse DNS lookup (typically local router)\n  upstream: 192.168.178.1\n  # optional: some routers return multiple names for client (host name and user defined name). Define which single name should be used.\n  # Example: take second name if present, if not take first name\n  singleNameOrder:\n    - 2\n    - 1\n  # optional: custom mapping of client name to IP addresses. Useful if reverse DNS does not work properly or just to have custom client names.\n  clients:\n    laptop:\n      - 192.168.178.29\n\n# optional: configuration for prometheus metrics endpoint\nprometheus:\n  # enabled if true\n  enable: true\n  # url path, optional (default '/metrics')\n  path: /metrics\n\n# optional: write query information (question, answer, client, duration etc.) to daily csv file\nqueryLog:\n  # optional one of: mysql, postgresql, csv, csv-client. If empty, log to console\n  type: mysql\n  # directory (should be mounted as volume in docker) for csv, db connection string for mysql/postgresql\n  target: db_user:db_password@tcp(db_host_or_ip:3306)/db_name?charset=utf8mb4&parseTime=True&loc=Local\n  #postgresql target: postgres://user:password@db_host_or_ip:5432/db_name\n  # if > 0, deletes log files which are older than ... days\n  logRetentionDays: 7\n  # optional: Max attempts to create specific query log writer, default: 3\n  creationAttempts: 1\n  # optional: Time between the creation attempts, default: 2s\n  creationCooldown: 2s\n  # optional: Which fields should be logged. You can choose one or more from: clientIP, clientName, responseReason, responseAnswer, question, duration. If not defined, it logs all fields\n  fields:\n    - clientIP\n    - duration\n  # optional: Interval to write data in bulk to the external database, default: 30s\n  flushInterval: 30s\n\n# optional: Blocky can synchronize its cache and blocking state between multiple instances through redis.\nredis:\n  # Server address and port or master name if sentinel is used\n  address: redismaster\n  # Username if necessary\n  username: usrname\n  # Password if necessary\n  password: passwd\n  # Database, default: 0\n  database: 2\n  # Connection is required for blocky to start. Default: false\n  required: true\n  # Max connection attempts, default: 3\n  connectionAttempts: 10\n  # Time between the connection attempts, default: 1s\n  connectionCooldown: 3s\n  # Sentinal username if necessary\n  sentinelUsername: usrname\n  # Sentinal password if necessary\n  sentinelPassword: passwd\n  # List with address and port of sentinel hosts(sentinel is activated if at least one sentinel address is configured)\n  sentinelAddresses:\n    - redis-sentinel1:26379\n    - redis-sentinel2:26379\n    - redis-sentinel3:26379\n\n# optional: Mininal TLS version that the DoH and DoT server will use\nminTlsServeVersion: 1.3\n\n# if https port > 0: path to cert and key file for SSL encryption. if not set, self-signed certificate will be generated\n#certFile: server.crt\n#keyFile: server.key\n\n# optional: use these DNS servers to resolve blacklist urls and upstream DNS servers. It is useful if no system DNS resolver is configured, and/or to encrypt the bootstrap queries.\nbootstrapDns:\n  - tcp+udp:1.1.1.1\n  - https://1.1.1.1/dns-query\n  - upstream: https://dns.digitale-gesellschaft.ch/dns-query\n    ips:\n      - 185.95.218.42\n\n# optional: drop all queries with following query types. Default: empty\nfiltering:\n  queryTypes:\n    - AAAA\n\n# optional: return NXDOMAIN for queries that are not FQDNs.\nfqdnOnly:\n  # default: false\n  enable: true\n\n# optional: if path defined, use this file for query resolution (A, AAAA and rDNS). Default: empty\nhostsFile:\n  # optional: Hosts files to parse\n  sources:\n    - /etc/hosts\n    - https://example.com/hosts\n    - |\n      # inline hosts\n      127.0.0.1 example.com\n  # optional: TTL, default: 1h\n  hostsTTL: 30m\n  # optional: Whether loopback hosts addresses (127.0.0.0/8 and ::1) should be filtered or not\n  # default: false\n  filterLoopback: true\n  # optional: Configure how sources are loaded\n  loading:\n    # optional: file refresh period in duration format.\n    # Set to a value <= 0 to disable.\n    # default: 4h\n    refreshPeriod: 24h\n    # optional: Applies only to files that are downloaded (HTTP URLs).\n    downloads:\n      # optional: timeout for file download (each url). Use large values for big files or slow internet connections\n      # default: 5s\n      timeout: 60s\n      # optional: Maximum download attempts\n      # default: 3\n      attempts: 5\n      # optional: Time between the download attempts\n      # default: 500ms\n      cooldown: 10s\n    # optional: Maximum number of files to process in parallel.\n    # default: 4\n    concurrency: 16\n    # Configure startup behavior.\n    # accepted: blocking, failOnError, fast\n    # default: blocking\n    strategy: failOnError\n    # Number of errors allowed in a file before it is considered invalid.\n    # A value of -1 disables the limit.\n    # default: 5\n    maxErrorsPerSource: 5\n\n# optional: ports configuration\nports:\n  # optional: DNS listener port(s) and bind ip address(es), default 53 (UDP and TCP). Example: 53, :53, \"127.0.0.1:5353,[::1]:5353\"\n  dns: 53\n  # optional: Port(s) and bind ip address(es) for DoT (DNS-over-TLS) listener. Example: 853, 127.0.0.1:853\n  tls: 853\n  # optional: Port(s) and optional bind ip address(es) to serve HTTPS used for prometheus metrics, pprof, REST API, DoH... If you wish to specify a specific IP, you can do so such as 192.168.0.1:443. Example: 443, :443, 127.0.0.1:443,[::1]:443\n  https: 443\n  # optional: Port(s) and optional bind ip address(es) to serve HTTP used for prometheus metrics, pprof, REST API, DoH... If you wish to specify a specific IP, you can do so such as 192.168.0.1:4000. Example: 4000, :4000, 127.0.0.1:4000,[::1]:4000\n  http: 4000\n\n# optional: logging configuration\nlog:\n  # optional: Log level (one from debug, info, warn, error). Default: info\n  level: info\n  # optional: Log format (text or json). Default: text\n  format: text\n  # optional: log timestamps. Default: true\n  timestamp: true\n  # optional: obfuscate log output (replace all alphanumeric characters with *) for user sensitive data like request domains or responses to increase privacy. Default: false\n  privacy: false\n\n# optional: add EDE error codes to dns response\nede:\n  # enabled if true, Default: false\n  enable: true\n\n# optional: configure optional Special Use Domain Names (SUDN)\nspecialUseDomains:\n  # optional: block recomended private TLDs\n  # default: true\n  rfc6762-appendixG: true\n\n# optional: configure extended client subnet (ECS) support\necs:\n  # optional: if the request ecs option with a max sice mask the address will be used as client ip\n  useAsClient: true\n  # optional: if the request contains a ecs option it will be forwarded to the upstream resolver\n  forward: true\n
"},{"location":"configuration/#basic-configuration","title":"Basic configuration","text":"Parameter Type Mandatory Default value Description certFile path no Path to cert and key file for SSL encryption (DoH and DoT); if empty, self-signed certificate is generated keyFile path no Path to cert and key file for SSL encryption (DoH and DoT); if empty, self-signed certificate is generated minTlsServeVersion string no 1.2 Minimum TLS version that the DoT and DoH server use to serve those encrypted DNS requests connectIPVersion enum (dual, v4, v6) no dual IP version to use for outgoing connections (dual, v4, v6)

Example

minTlsServeVersion: 1.1\nconnectIPVersion: v4\n
"},{"location":"configuration/#ports-configuration","title":"Ports configuration","text":"

All logging port are optional.

Parameter Type Default value Description ports.dns [IP]:port[,[IP]:port]* 53 Port(s) and optional bind ip address(es) to serve DNS endpoint (TCP and UDP). If you wish to specify a specific IP, you can do so such as 192.168.0.1:53. Example: 53, :53, 127.0.0.1:53,[::1]:53 ports.tls [IP]:port[,[IP]:port]* Port(s) and optional bind ip address(es) to serve DoT DNS endpoint (DNS-over-TLS). If you wish to specify a specific IP, you can do so such as 192.168.0.1:853. Example: 83, :853, 127.0.0.1:853,[::1]:853 ports.http [IP]:port[,[IP]:port]* Port(s) and optional bind ip address(es) to serve HTTP used for prometheus metrics, pprof, REST API, DoH... If you wish to specify a specific IP, you can do so such as 192.168.0.1:4000. Example: 4000, :4000, 127.0.0.1:4000,[::1]:4000 ports.https [IP]:port[,[IP]:port]* Port(s) and optional bind ip address(es) to serve HTTPS used for prometheus metrics, pprof, REST API, DoH... If you wish to specify a specific IP, you can do so such as 192.168.0.1:443. Example: 443, :443, 127.0.0.1:443,[::1]:443

Example

ports:\n  dns: 53\n  http: 4000\n  https: 443\n
"},{"location":"configuration/#logging-configuration","title":"Logging configuration","text":"

All logging options are optional.

Parameter Type Default value Description log.level enum (debug, info, warn, error) info Log level log.format enum (text, json) text Log format (text or json). log.timestamp bool true Log time stamps (true or false). log.privacy bool false Obfuscate log output (replace all alphanumeric characters with *) for user sensitive data like request domains or responses to increase privacy.

Example

log:\n  level: debug\n  format: json\n  timestamp: false\n  privacy: true\n
"},{"location":"configuration/#init-strategy","title":"Init Strategy","text":"

A couple of features use an \"init/loading strategy\" which configures behavior at Blocky startup. This applies to all of them. The default strategy is blocking.

strategy Description blocking Initialization happens before DNS resolution starts. Any errors are logged, but Blocky continues running if possible. failOnError Like blocking but Blocky will exit with an error if initialization fails. fast Blocky starts serving DNS immediately and initialization happens in the background. The feature requiring initialization will enable later on (if it succeeds)."},{"location":"configuration/#upstreams-configuration","title":"Upstreams configuration","text":"Parameter Type Mandatory Default value Description usptreams.groups map of name to upstream yes Upstream DNS servers to use, in groups. usptreams.init.strategy enum (blocking, failOnError, fast) no blocking See Init Strategy and below. usptreams.strategy enum (parallel_best, random, strict) no parallel_best Upstream server usage strategy. usptreams.timeout duration no 2s Upstream connection timeout. usptreams.userAgent string no HTTP User Agent when connecting to upstreams.

For init.strategy, the \"init\" is testing the given resolvers for each group. The potentially fatal error, depending on the strategy, is if a group has no functional resolvers.

"},{"location":"configuration/#upstream-groups","title":"Upstream Groups","text":"

To resolve a DNS query, blocky needs external public or private DNS resolvers. Blocky supports DNS resolvers with following network protocols (net part of the resolver URL):

Hint

You can (and should!) configure multiple DNS resolvers. Per default blocky uses the parallel_best upstream strategy where blocky picks 2 random resolvers from the list for each query and returns the answer from the fastest one.

Each resolver must be defined as a string in following format: [net:]host:[port][/path][#commonName].

Parameter Type Mandatory Default value net enum (tcp+udp, tcp-tls or https) no tcp+udp host IP or hostname yes port int (1 - 65535) no 53 for udp/tcp, 853 for tcp-tls and 443 for https commonName string no the host value

The commonName parameter overrides the expected certificate common name value used for verification.

Note

Blocky needs at least the configuration of the default group with at least one upstream DNS server. This group will be used as a fallback, if no client specific resolver configuration is available.

See List of public DNS servers if you need some ideas, which public free DNS server you could use.

You can specify multiple upstream groups (additional to the default group) to use different upstream servers for different clients, based on client name (see Client name lookup), client IP address or client subnet (as CIDR).

Tip

You can use * as wildcard for the sequence of any character or [0-9] as number range

Example

upstreams:\n  groups:\n    default:\n      - 5.9.164.112\n      - 1.1.1.1\n      - tcp-tls:fdns1.dismail.de:853\n      - https://dns.digitale-gesellschaft.ch/dns-query\n    laptop*:\n      - 123.123.123.123\n    10.43.8.67/28:\n      - 1.1.1.1\n      - 9.9.9.9\n

The above example results in:

The logic determining what group a client belongs to follows a strict order: IP, client name, CIDR

If a client matches multiple client name or CIDR groups, a warning is logged and the first found group is used.

"},{"location":"configuration/#upstream-connection-timeout","title":"Upstream connection timeout","text":"

Blocky will wait 2 seconds (default value) for the response from the external upstream DNS server. You can change this value by setting the timeout configuration parameter (in duration format).

Example

upstreams:\n  timeout: 5s\n  groups:\n    default:\n      - 46.182.19.48\n      - 80.241.218.68\n
"},{"location":"configuration/#upstream-strategy","title":"Upstream strategy","text":"

Blocky supports different upstream strategies (default parallel_best) that determine how and to which upstream DNS servers requests are forwarded.

Currently available strategies:

Example

upstreams:\n  strategy: strict\n  groups:\n    default:\n      - 1.2.3.4\n      - 9.8.7.6\n
"},{"location":"configuration/#bootstrap-dns-configuration","title":"Bootstrap DNS configuration","text":"

These DNS servers are used to resolve upstream DoH and DoT servers that are specified as host names, and list domains. It is useful if no system DNS resolver is configured, and/or to encrypt the bootstrap queries.

Parameter Type Mandatory Default value Description upstream Upstream (see above) no ips List of IPs yes, if upstream is DoT/DoH Only valid if upstream is DoH or DoT

When using an upstream specified by IP, and not by hostname, you can write only the upstream and skip ips.

Note

Works only on Linux/*nix OS due to golang limitations under Windows.

Example

    bootstrapDns:\n      - upstream: tcp-tls:dns.example.com\n        ips:\n        - 123.123.123.123\n      - upstream: https://234.234.234.234/dns-query\n
"},{"location":"configuration/#filtering","title":"Filtering","text":"

Under certain circumstances, it may be useful to filter some types of DNS queries. You can define one or more DNS query types, all queries with these types will be dropped (empty answer will be returned).

Example

filtering:\n  queryTypes:\n    - AAAA\n

This configuration will drop all 'AAAA' (IPv6) queries.

"},{"location":"configuration/#fqdn-only","title":"FQDN only","text":"

In domain environments, it may be useful to only response to FQDN requests. If this option is enabled blocky respond immediately with NXDOMAIN if the request is not a valid FQDN. The request is therefore not further processed by other options like custom or conditional. Please be aware that by enabling it your hostname resolution will break unless every hostname is part of a domain.

Example

fqdnOnly:\n  enable: true\n
"},{"location":"configuration/#custom-dns","title":"Custom DNS","text":"

You can define your own domain name to IP mappings. For example, you can use a user-friendly name for a network printer or define a domain name for your local device on order to use the HTTPS certificate. Multiple IP addresses for one domain must be separated by a comma.

Parameter Type Mandatory Default value customTTL duration (no unit is minutes) no 1h rewrite string: string (domain: domain) no mapping string: string (hostname: address list) no filterUnmappedTypes boolean no true

Example

customDNS:\n  customTTL: 1h\n  filterUnmappedTypes: true\n  rewrite:\n    home: lan\n    replace-me.com: with-this.com\n  mapping:\n    printer.lan: 192.168.178.3\n    otherdevice.lan: 192.168.178.15,2001:0db8:85a3:08d3:1319:8a2e:0370:7344\n

This configuration will also resolve any subdomain of the defined domain, recursively. For example querying any of printer.lan, my.printer.lan or i.love.my.printer.lan will return 192.168.178.3.

With the optional parameter rewrite you can replace domain part of the query with the defined part before the resolver lookup is performed. The query \"printer.home\" will be rewritten to \"printer.lan\" and return 192.168.178.3.

With parameter filterUnmappedTypes = true (default), blocky will filter all queries with unmapped types, for example: AAAA for \"printer.lan\" or TXT for \"otherdevice.lan\". With filterUnmappedTypes = false a query AAAA \"printer.lan\" will be forwarded to the upstream DNS server.

"},{"location":"configuration/#conditional-dns-resolution","title":"Conditional DNS resolution","text":"

You can define, which DNS resolver(s) should be used for queries for the particular domain (with all subdomains). This is for example useful, if you want to reach devices in your local network by the name. Since only your router know which hostname belongs to which IP address, all DNS queries for the local network should be redirected to the router.

The optional parameter rewrite behaves the same as with custom DNS.

The optional parameter fallbackUpstream, if false (default), return empty result if after rewrite, the mapped resolver returned an empty answer. If true, the original query will be sent to the upstream resolver.

Usage: One usecase when having split DNS for internal and external (internet facing) users, but not all subdomains are listed in the internal domain

Example

conditional:\n  fallbackUpstream: false\n  rewrite:\n    example.com: fritz.box\n    replace-me.com: with-this.com\n  mapping:\n    fritz.box: 192.168.178.1\n    lan.net: 192.170.1.2,192.170.1.3\n    # for reverse DNS lookups of local devices\n    178.168.192.in-addr.arpa: 192.168.178.1\n    # for all unqualified hostnames\n    .: 168.168.0.1\n

Tip

You can use . as wildcard for all non full qualified domains (domains without dot)

In this example, a DNS query \"client.fritz.box\" will be redirected to the router's DNS server at 192.168.178.1 and client.lan.net to 192.170.1.2 and 192.170.1.3. The query \"client.example.com\" will be rewritten to \"client.fritz.box\" and also redirected to the resolver at 192.168.178.1.

If not found and if fallbackUpstream was set to true, the original query \"blog.example.com\" will be sent upstream.

All unqualified host names (e.g. \"test\") will be redirected to the DNS server at 168.168.0.1.

One usecase for fallbackUpstream is when having split DNS for internal and external (internet facing) users, but not all subdomains are listed in the internal domain.

"},{"location":"configuration/#client-name-lookup","title":"Client name lookup","text":"

Blocky can try to resolve a user-friendly client name from the IP address or server URL (DoT and DoH). This is useful for defining of blocking groups, since IP address can change dynamically.

"},{"location":"configuration/#resolving-client-name-from-urlhost","title":"Resolving client name from URL/Host","text":"

If DoT or DoH is enabled, you can use a subdomain prefixed with id- to provide a client name (wildcard ssl certificate recommended).

Example: domain example.com

DoT Host: id-bob.example.com -> request's client name is bob DoH URL: https://id-bob.example.com/dns-query -> request's client name is bob

For DoH you can also pass the client name as url parameter:

DoH URL: https://blocky.example.com/dns-query/alice -> request's client name is alice

"},{"location":"configuration/#resolving-client-name-from-ip-address","title":"Resolving client name from IP address","text":"

Blocky uses rDNS to retrieve client's name. To use this feature, you can configure a DNS server for client lookup ( typically your router). You can also define client names manually per IP address.

"},{"location":"configuration/#single-name-order","title":"Single name order","text":"

Some routers return multiple names for the client (host name and user defined name). With parameter clientLookup.singleNameOrder you can specify, which of retrieved names should be used.

"},{"location":"configuration/#custom-client-name-mapping","title":"Custom client name mapping","text":"

You can also map a particular client name to one (or more) IP (ipv4/ipv6) addresses. Parameter clientLookup.clients contains a map of client name and multiple IP addresses.

Example

clientLookup:\n  upstream: 192.168.178.1\n  singleNameOrder:\n    - 2\n    - 1\n  clients:\n    laptop:\n      - 192.168.178.29\n

Use 192.168.178.1 for rDNS lookup. Take second name if present, if not take first name. IP address 192.168.178.29 is mapped to laptop as client name.

"},{"location":"configuration/#blocking-and-whitelisting","title":"Blocking and whitelisting","text":"

Blocky can use lists of domains and IPs to block (e.g. advertisement, malware, trackers, adult sites). You can group several list sources together and define the blocking behavior per client. Blocking uses the DNS sinkhole approach. For each DNS query, the domain name from the request, IP address from the response, and any CNAME records will be checked to determine whether to block the query or not.

To avoid over-blocking, you can use whitelists.

"},{"location":"configuration/#definition-black-and-whitelists","title":"Definition black and whitelists","text":"

Lists are defined in groups. This allows using different sets of lists for different clients.

Each list in a group is a \"source\" and can be downloaded, read from a file, or inlined in the config. See Sources for details and configuring how those are loaded and reloaded/refreshed.

The supported list formats are:

  1. the well-known Hosts format
  2. one domain per line (plain domain list)
  3. one wildcard per line
  4. one regex per line

Example

blocking:\n  blackLists:\n    ads:\n      - https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt\n      - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts\n      - |\n        # inline definition using YAML literal block scalar style\n        # content is in plain domain list format\n        someadsdomain.com\n        anotheradsdomain.com\n        *.wildcard.example.com # blocks wildcard.example.com and all subdomains\n      - |\n        # inline definition with a regex\n        /^banners?[_.-]/\n    special:\n      - https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hosts\n  whiteLists:\n    ads:\n      - whitelist.txt\n      - /path/to/file.txt\n      - |\n        # inline definition with YAML literal block scalar style\n        whitelistdomain.com\n

In this example you can see 2 groups: ads and special with one list. The ads group includes 2 inline lists.

Warning

If the same group has black and whitelists, whitelists will be used to disable particular blacklist entries. If a group has only whitelist entries -> this means only domains from this list are allowed, all other domains will be blocked.

Warning

You must also define client group mapping, otherwise you black and whitelist definition will have no effect.

"},{"location":"configuration/#wildcard-support","title":"Wildcard support","text":"

You can use wildcards to block a domain and all its subdomains. Example: *.example.com will block example.com and any.subdomains.example.com.

"},{"location":"configuration/#regex-support","title":"Regex support","text":"

You can use regex to define patterns to block. A regex entry must start and end with the slash character (/). Some Examples:

Warning

Regexes use more a lot more memory and are much slower than wildcards, you should use them as a last resort.

"},{"location":"configuration/#client-groups","title":"Client groups","text":"

In this configuration section, you can define, which blocking group(s) should be used for which client in your network. Example: All clients should use the ads group, which blocks advertisement and kids devices should use the adult group, which blocky adult sites.

Clients without an explicit group assignment will use the default group.

You can use the client name (see Client name lookup), client's IP address, client's full-qualified domain name or a client subnet as CIDR notation.

If full-qualified domain name is used (for example \"myclient.ddns.org\"), blocky will try to resolve the IP address (A and AAAA records) of this domain. If client's IP address matches with the result, the defined group will be used.

Example

blocking:\n  clientGroupsBlock:\n  # default will be used, if no special definition for a client name exists\n    default:\n      - ads\n      - special\n    laptop*:\n      - ads\n    192.168.178.1/24:\n      - special\n    kid-laptop:\n      - ads\n      - adult\n

All queries from network clients, whose device name starts with laptop, will be filtered against the ads group's lists. All devices from the subnet 192.168.178.1/24 against the special group and kid-laptop against ads and adult. All other clients: ads and special.

Tip

You can use * as wildcard for the sequence of any character or [0-9] as number range

"},{"location":"configuration/#block-type","title":"Block type","text":"

You can configure, which response should be sent to the client, if a requested query is blocked (only for A and AAAA queries, NXDOMAIN for other types):

blockType Example Description zeroIP zeroIP This is the default block type. Server returns 0.0.0.0 (or :: for IPv6) as result for A and AAAA queries nxDomain nxDomain return NXDOMAIN as return code custom IPs 192.100.100.15, 2001:0db8:85a3:08d3:1319:8a2e:0370:7344 comma separated list of destination IP addresses. Should contain ipv4 and ipv6 to cover all query types. Useful with running web server on this address to display the \"blocked\" page.

Example

blocking:\n  blockType: nxDomain\n
"},{"location":"configuration/#block-ttl","title":"Block TTL","text":"

TTL for answers to blocked domains can be set to customize the time (in duration format) clients ask for those domains again. Default Block TTL is 6hours. This setting only makes sense when blockType is set to nxDomain or zeroIP, and will affect how much time it could take for a client to be able to see the real IP address for a domain after receiving the custom value.

Example

blocking:\n  blockType: 192.100.100.15, 2001:0db8:85a3:08d3:1319:8a2e:0370:7344\n  blockTTL: 10s\n
"},{"location":"configuration/#lists-loading","title":"Lists Loading","text":"

See Sources Loading.

"},{"location":"configuration/#caching","title":"Caching","text":"

Each DNS response has a TTL (Time-to-live) value. This value defines, how long is the record valid in seconds. The values are maintained by domain owners, server administrators etc. Blocky caches the answers from all resolved queries in own cache in order to avoid repeated requests. This reduces the DNS traffic and increases the network speed, since blocky can serve the result immediately from the cache.

With following parameters you can tune the caching behavior:

Warning

Wrong values can significantly increase external DNS traffic or memory consumption.

Parameter Type Mandatory Default value Description caching.minTime duration format no 0 (use TTL) How long a response must be cached (min value). If <=0, use response's TTL, if >0 use this value, if TTL is smaller caching.maxTime duration format no 0 (use TTL) How long a response must be cached (max value). If <0, do not cache responses. If 0, use TTL. If > 0, use this value, if TTL is greater caching.maxItemsCount int no 0 (unlimited) Max number of cache entries (responses) to be kept in cache (soft limit). Default (0): unlimited. Useful on systems with limited amount of RAM. caching.prefetching bool no false if true, blocky will preload DNS results for often used queries (default: names queried more than 5 times in a 2 hour time window). Results in cache will be loaded again on their expire (TTL). This improves the response time for often used queries, but significantly increases external traffic. It is recommended to increase \"minTime\" to reduce the number of prefetch queries to external resolvers. caching.prefetchExpires duration format no 2h Prefetch track time window caching.prefetchThreshold int no 5 Name queries threshold for prefetch caching.prefetchMaxItemsCount int no 0 (unlimited) Max number of domains to be kept in cache for prefetching (soft limit). Default (0): unlimited. Useful on systems with limited amount of RAM. caching.cacheTimeNegative duration format no 30m Time how long negative results (NXDOMAIN response or empty result) are cached. A value of -1 will disable caching for negative results.

Example

caching:\n  minTime: 5m\n  maxTime: 30m\n  prefetching: true\n
"},{"location":"configuration/#redis","title":"Redis","text":"

Blocky can synchronize its cache and blocking state between multiple instances through redis. Synchronization is disabled if no address is configured.

Parameter Type Mandatory Default value Description redis.address string no Server address and port or master name if sentinel is used redis.username string no Username if necessary redis.password string no Password if necessary redis.database int no 0 Database redis.required bool no false Connection is required for blocky to start redis.connectionAttempts int no 3 Max connection attempts redis.connectionCooldown duration format no 1s Time between the connection attempts redis.sentinelUsername string no Sentinel username if necessary redis.sentinelPassword string no Sentinel password if necessary redis.sentinelAddresses string[] no Sentinel host list (Sentinel is activated if addresses are defined)

Example

redis:\n  address: redismaster\n  username: usrname\n  password: passwd\n  database: 2\n  required: true\n  connectionAttempts: 10\n  connectionCooldown: 3s\n  sentinelUsername: sentUsrname\n  sentinelPassword: sentPasswd\n  sentinelAddresses:\n    - redis-sentinel1:26379\n    - redis-sentinel2:26379\n    - redis-sentinel3:26379\n
"},{"location":"configuration/#prometheus","title":"Prometheus","text":"

Blocky can expose various metrics for prometheus. To use the prometheus feature, the HTTP listener must be enabled ( see Basic Configuration).

Parameter Mandatory Default value Description prometheus.enable no false If true, enables prometheus metrics prometheus.path no /metrics URL path to the metrics endpoint

Example

prometheus:\n  enable: true\n  path: /metrics\n
"},{"location":"configuration/#query-logging","title":"Query logging","text":"

You can enable the logging of DNS queries (question, answer, client, duration etc.) to a daily CSV file (can be opened in Excel or OpenOffice Calc) or MySQL/MariaDB database.

Warning

Query file/database contains sensitive information. Please ensure to inform users, if you log their queries.

"},{"location":"configuration/#query-log-types","title":"Query log types","text":"

You can select one of following query log types:

"},{"location":"configuration/#query-log-fields","title":"Query log fields","text":"

You can choose which information from processed DNS request and response should be logged in the target system. You can define one or more of following fields:

Hint

If not defined, blocky will log all available information

Configuration parameters:

Parameter Type Mandatory Default value Description queryLog.type enum (mysql, postgresql, csv, csv-client, console, none (see above)) no Type of logging target. Console if empty queryLog.target string no directory for writing the logs (for csv) or database url (for mysql or postgresql) queryLog.logRetentionDays int no 0 if > 0, deletes log files/database entries which are older than ... days queryLog.creationAttempts int no 3 Max attempts to create specific query log writer queryLog.creationCooldown duration format no 2s Time between the creation attempts queryLog.fields list enum (clientIP, clientName, responseReason, responseAnswer, question, duration) no all which information should be logged queryLog.flushInterval duration format no 30s Interval to write data in bulk to the external database

Hint

Please ensure, that the log directory is writable or database exists. If you use docker, please ensure, that the directory is properly mounted (e.g. volume)

example for CSV format with limited logging information

Example

queryLog:\n  type: csv\n  target: /logs\n  logRetentionDays: 7\n  fields:\n  - clientIP\n  - duration\n  flushInterval: 30s\n

example for Database

Example

queryLog:\n  type: mysql\n  target: db_user:db_password@tcp(db_host_or_ip:3306)/db_user?charset=utf8mb4&parseTime=True&loc=Local\n  logRetentionDays: 7\n
"},{"location":"configuration/#hosts-file","title":"Hosts file","text":"

You can enable resolving of entries, located in local hosts file.

Configuration parameters:

Parameter Type Mandatory Default value Description hostsFile.sources list of string no Host files (e.g. /etc/hosts on Linux) hostsFile.hostsTTL duration (no units is minutes) no 1h TTL hostsFile.refreshPeriod duration format no 1h Time between hosts file refresh hostsFile.filterLoopback bool no false Filter loopback addresses (127.0.0.0/8 and ::1) hostsFile.loading no See Sources Loading

Example

hostsFile:\n  filePath: /etc/hosts\n  hostsTTL: 1h\n  refreshPeriod: 30m\n  loading:\n    strategy: fast\n
"},{"location":"configuration/#deliver-ede-codes-as-edns0-option","title":"Deliver EDE codes as EDNS0 option","text":"

DNS responses can be extended with EDE codes according to RFC8914.

Configuration parameters:

Parameter Type Mandatory Default value Description ede.enable bool no false If true, DNS responses are deliverd with EDE codes

Example

ede:\n  enable: true\n
"},{"location":"configuration/#edns-client-subnet-options","title":"EDNS Client Subnet options","text":"

EDNS Client Subnet (ECS) configuration parameters:

Parameter Type Mandatory Default value Description ecs.useAsClient bool no false Use ECS information if it is present with a netmask is 32 for IPv4 or 128 for IPv6 as CientIP ecs.forward bool no false Forward ECS option to upstream ecs.ipv4Mask int no 0 Add ECS option for IPv4 requests if mask is greater than zero (max value 32) ecs.ipv6Mask int no 0 Add ECS option for IPv6 requests if mask is greater than zero (max value 128)

Example

ecs:\n  ipv4Mask: 32\n  ipv6Mask: 128\n
"},{"location":"configuration/#special-use-domain-names","title":"Special Use Domain Names","text":"

SUDN (Special Use Domain Names) are always enabled as they are required by various RFCs. Some RFCs have optional recommendations, which are configurable as described below.

Configuration parameters:

Parameter Type Mandatory Default value Description specialUseDomains.rfc6762-appendixG bool no true Block TLDs listed in RFC 6762 Appendix G

Example

specialUseDomains:\n  rfc6762-appendixG: true\n
"},{"location":"configuration/#ssl-certificate-configuration-doh-tls-listener","title":"SSL certificate configuration (DoH / TLS listener)","text":"

See Wiki - Configuration of HTTPS for detailed information, how to create and configure SSL certificates.

DoH url: https://host:port/dns-query

"},{"location":"configuration/#sources","title":"Sources","text":"

Sources are a concept shared by the blocking and hosts file resolvers. They represent where to load the files for each resolver.

The supported source types are:

Note

The format/content of the sources depends on the context: lists and hosts files have different, but overlapping, supported formats.

Example

- https://example.com/a/source # blocky will download and parse the file\n- /a/file/path # blocky will read the local file\n- | # blocky will parse the content of this multi-line string\n  # inline configuration\n
"},{"location":"configuration/#sources-loading","title":"Sources Loading","text":"

This sections covers loading configuration that applies to both the blocking and hosts file resolvers. These settings apply only to the resolver under which they are nested.

Example

blocking:\n  loading:\n    # only applies to white/blacklists\n\nhostsFile:\n  loading:\n    # only applies to hostsFile sources\n
"},{"location":"configuration/#refresh-reload","title":"Refresh / Reload","text":"

To keep source contents up-to-date, blocky can periodically refresh and reparse them. Default period is ** 4 hours. You can configure this by setting the refreshPeriod parameter to a value in duration format**. A value of zero or less will disable this feature.

Example

loading:\n  refreshPeriod: 1h\n

Refresh every hour.

"},{"location":"configuration/#downloads","title":"Downloads","text":"

Configures how HTTP(S) sources are downloaded:

Parameter Type Mandatory Default value Description timeout duration no 5s Download attempt timeout attempts int no 3 How many download attempts should be performed cooldown duration no 500ms Time between the download attempts

Example

loading:\n  downloads:\n    timeout: 4m\n    attempts: 5\n    cooldown: 10s\n
"},{"location":"configuration/#strategy","title":"Strategy","text":"

See Init Strategy. In this context, \"init\" is loading and parsing each source, and an error is a single source failing to load/parse.

Example

loading:\n  strategy: failOnError\n
"},{"location":"configuration/#max-errors-per-source","title":"Max Errors per Source","text":"

Number of errors allowed when parsing a source before it is considered invalid and parsing stops. A value of -1 disables the limit.

Example

loading:\n  maxErrorsPerSource: 10\n
"},{"location":"configuration/#concurrency","title":"Concurrency","text":"

Blocky downloads and processes sources concurrently. This allows limiting how many can be processed in the same time. Larger values can reduce the overall list refresh time at the cost of using more RAM. Please consider reducing this value on systems with limited memory. Default value is 4.

Example

loading:\n  concurrency: 10\n

Note

As with other settings under loading, the limit applies to the blocking and hosts file resolvers separately. The total number of concurrent sources concurrently processed can reach the sum of both values. For example if blocking has a limit set to 8 and hosts file's is 4, there could be up to 12 concurrent jobs.

"},{"location":"installation/","title":"Installation","text":"

You can choose one of the following installation options:

"},{"location":"installation/#prepare-your-configuration","title":"Prepare your configuration","text":"

Blocky supports single or multiple YAML files as configuration. Create new config.yaml with your configuration ( see Configuration for more details and all configuration options).

Simple configuration file, which enables only basic features:

upstream:\n  default:\n    - 46.182.19.48\n    - 80.241.218.68\n    - tcp-tls:fdns1.dismail.de:853\n    - https://dns.digitale-gesellschaft.ch/dns-query\nblocking:\n  blackLists:\n    ads:\n      - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts\n  clientGroupsBlock:\n    default:\n      - ads\nports:\n  dns: 53\n  http: 4000\n
"},{"location":"installation/#run-as-standalone-binary","title":"Run as standalone binary","text":"

Download the binary file from GitHub for your architecture and run ./blocky --config config.yml.

Warning

Please be aware, if you want to use port 53 or 953 on Linux you should add CAP_NET_BIND_SERVICE capability to the binary or run with root privileges (running as root is not recommended).

"},{"location":"installation/#run-with-docker","title":"Run with docker","text":""},{"location":"installation/#alternative-registry","title":"Alternative registry","text":"

Blocky docker images are deployed to DockerHub (spx01/blocky) and GitHub Container Registry (ghcr.io/0xerr0r/blocky) .

"},{"location":"installation/#parameters","title":"Parameters","text":"

You can define the location of the config file in the container with environment variable \"BLOCKY_CONFIG_FILE\". Default value is \"/app/config.yml\".

"},{"location":"installation/#docker-from-command-line","title":"Docker from command line","text":"

Execute following command from the command line:

docker run --name blocky -v /path/to/config.yml:/app/config.yml -p 4000:4000 -p 53:53/udp spx01/blocky\n
"},{"location":"installation/#run-with-docker-compose","title":"Run with docker-compose","text":"

Create following docker-compose.yml file

version: \"2.1\"\nservices:\n  blocky:\n    image: spx01/blocky\n    container_name: blocky\n    restart: unless-stopped\n    # Optional the instance hostname for logging purpose\n    hostname: blocky-hostname\n    ports:\n      - \"53:53/tcp\"\n      - \"53:53/udp\"\n      - \"4000:4000/tcp\"\n    environment:\n      - TZ=Europe/Berlin # Optional to synchronize the log timestamp with host\n    volumes:\n      # Optional to synchronize the log timestamp with host\n      - /etc/localtime:/etc/localtime:ro\n      # config file\n      - ./config.yml:/app/config.yml\n

and start docker container with

docker-compose up -d\n
"},{"location":"installation/#advanced-setup","title":"Advanced setup","text":"

Following example shows, how to run blocky in a docker container and store query logs on a SAMBA share. Local black and whitelists directories are mounted as volume. You can create own black or whitelists in these directories and define the path like '/app/whitelists/whitelist.txt' in the config file.

Example

version: \"2.1\"\nservices:\n  blocky:\n    image: spx01/blocky\n    container_name: blocky\n    restart: unless-stopped\n    ports:\n      - \"53:53/tcp\"\n      - \"53:53/udp\"\n      - \"4000:4000/tcp\" # Prometheus stats (if enabled).\n    environment:\n      - TZ=Europe/Berlin\n    volumes:\n      # config file\n      - ./config.yml:/app/config.yml\n      # write query logs in this volume\n      - queryLogs:/logs\n      # put your custom white and blacklists in these directories\n      - ./blacklists:/app/blacklists/\n      - ./whitelists:/app/whitelists/\n\nvolumes:\n  queryLogs:\n    driver: local\n    driver_opts:\n      type: cifs\n      o: username=USER,password=PASSWORD,rw\n      device: //NAS_HOSTNAME/blocky  \n
"},{"location":"installation/#multiple-configuration-files","title":"Multiple configuration files","text":"

For complex setups, splitting the configuration between multiple YAML files might be desired. In this case, folder containing YAML files is passed on startup, Blocky will join all the files.

./blocky --config ./config/

Warning

Blocky simply joins the multiple YAML files. If a directive (e.g. upstream) is repeated in multiple files, the configuration will not load and start will fail.

"},{"location":"installation/#other-installation-types","title":"Other installation types","text":"

Warning

These projects are maintained by other people.

"},{"location":"installation/#web-ui","title":"Web UI","text":"

Blocky Frontend provides a Web UI to control blocky. See linked project for installation instructions.

"},{"location":"installation/#run-with-helm-chart-on-kubernetes","title":"Run with helm chart on Kubernetes","text":"

See this repo, the documentation and the configuration instructions for details about running blocky via helm in kubernetes.

"},{"location":"installation/#run-as-an-app-for-truenas-scale","title":"Run as an App for TrueNAS SCALE","text":"

You can find the App in the TrueCharts App Catalog or read the documentation and configuration instructions for details about running blocky as a native TrueNAS SCALE App.

"},{"location":"installation/#aur-package-for-arch-linux","title":"AUR package for Arch Linux","text":"

See https://aur.archlinux.org/packages/blocky/

"},{"location":"installation/#package-for-alpine-linux","title":"Package for Alpine Linux","text":"

See https://pkgs.alpinelinux.org/package/edge/testing/x86/blocky

"},{"location":"installation/#installation-script-for-centosfedora","title":"Installation script for CentOS/Fedora","text":"

See https://github.com/m0zgen/blocky-installer

"},{"location":"installation/#package-for-freebsd","title":"Package for FreeBSD","text":"

See https://www.freebsd.org/cgi/ports.cgi?query=blocky&stype=all

"},{"location":"installation/#homebrew-package-for-macos","title":"Homebrew package for MacOS","text":"

See https://formulae.brew.sh/formula/blocky

"},{"location":"interfaces/","title":"Interfaces","text":""},{"location":"interfaces/#rest-api","title":"REST API","text":"OpenAPI specification
openapi: 3.1.1\ninfo:\n  title: blocky API\n  description: >-\n    # Blocky\n\n    Blocky is a DNS proxy and ad-blocker for the local network written in Go with following features:\n\n    ## Features\n\n    - **Blocking** - Blocking of DNS queries with external lists (Ad-block, malware) and whitelisting\n\n      - Definition of black and white lists per client group (Kids, Smart home devices, etc.)\n      - Periodical reload of external black and white lists\n      - Regex support\n      - Blocking of request domain, response CNAME (deep CNAME inspection) and response IP addresses (against IP lists)\n\n    - **Advanced DNS configuration** - not just an ad-blocker\n\n      - Custom DNS resolution for certain domain names\n      - Conditional forwarding to external DNS server\n      - Upstream resolvers can be defined per client group\n\n    - **Performance** - Improves speed and performance in your network\n\n      - Customizable caching of DNS answers for queries -> improves DNS resolution speed and reduces amount of external DNS\n        queries\n      - Prefetching and caching of often used queries\n      - Using multiple external resolver simultaneously\n      - Low memory footprint\n\n    - **Various Protocols** - Supports modern DNS protocols\n\n      - DNS over UDP and TCP\n      - DNS over HTTPS (aka DoH)\n      - DNS over TLS (aka DoT)\n\n    - **Security and Privacy** - Secure communication\n\n      - Supports modern DNS extensions: DNSSEC, eDNS, ...\n      - Free configurable blocking lists - no hidden filtering etc.\n      - Provides DoH Endpoint\n      - Uses random upstream resolvers from the configuration - increases your privacy through the distribution of your DNS\n        traffic over multiple provider\n      - Blocky does **NOT** collect any user data, telemetry, statistics etc.\n\n    - **Integration** - various integration\n\n      - [Prometheus](https://prometheus.io/) metrics\n      - Prepared [Grafana](https://grafana.com/) dashboards (Prometheus and database)\n      - Logging of DNS queries per day / per client in CSV format or MySQL/MariaDB/PostgreSQL database - easy to analyze\n      - Various REST API endpoints\n      - CLI tool\n\n    - **Simple configuration** - single or multiple configuration files in YAML format\n\n      - Simple to maintain\n      - Simple to backup\n\n    - **Simple installation/configuration** - blocky was designed for simple installation\n\n      - Stateless (no database, no temporary files)\n      - Docker image with Multi-arch support\n      - Single binary\n      - Supports x86-64 and ARM architectures -> runs fine on Raspberry PI\n      - Community supported Helm chart for k8s deployment\n\n    ## Quick start\n\n    You can jump to [Installation](https://0xerr0r.github.io/blocky/installation/) chapter in the documentation.\n\n    ## Full documentation\n\n    You can find full documentation and configuration examples\n    at: [https://0xERR0R.github.io/blocky/](https://0xERR0R.github.io/blocky/)\n  contact:\n    name: blocky@github\n    url: https://github.com/0xERR0R/blocky\n  license:\n    name: Apache 2.0\n    url: http://www.apache.org/licenses/LICENSE-2.0.html\n  version: '1.0'\nservers:\n  - url: /api\npaths:\n  /blocking/disable:\n    get:\n      operationId: disableBlocking\n      tags:\n        - blocking\n      summary: Disable blocking\n      description: disable the blocking status\n      parameters:\n        - name: duration\n          in: query\n          description: 'duration of blocking (Example: 300s, 5m, 1h, 5m30s)'\n          schema:\n            type: string\n        - name: groups\n          in: query\n          description: groups to disable (comma separated). If empty, disable all groups\n          schema:\n            type: string\n      responses:\n        '200':\n          description: Blocking is disabled\n        '400':\n          description: Bad request (e.g. unknown group)\n          content:\n            text/plain:\n              schema:\n                type: string\n                example: Bad request\n  /blocking/enable:\n    get:\n      operationId: enableBlocking\n      tags:\n        - blocking\n      summary: Enable blocking\n      description: enable the blocking status\n      responses:\n        '200':\n          description: Blocking is enabled\n  /blocking/status:\n    get:\n      operationId: blockingStatus\n      tags:\n        - blocking\n      summary: Blocking status\n      description: get current blocking status\n      responses:\n        '200':\n          description: Returns current blocking status\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/api.BlockingStatus'\n  /lists/refresh:\n    post:\n      operationId: listRefresh\n      tags:\n        - lists\n      summary: List refresh\n      description: Refresh all lists\n      responses:\n        '200':\n          description: Lists were reloaded\n        '500':\n          description: List refresh error\n          content:\n            text/plain:\n              schema:\n                type: string\n                example: Error text\n  /query:\n    post:\n      operationId: query\n      tags:\n        - query\n      summary: Performs DNS query\n      description: Performs DNS query\n      requestBody:\n        description: query data\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/api.QueryRequest'\n        required: true\n      responses:\n        '200':\n          description: query was executed\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/api.QueryResult'\n        '400':\n          description: Wrong request format\n          content:\n            text/plain:\n              schema:\n                type: string\n                example: Bad request\n  /cache/flush:\n    post:\n      operationId: cacheFlush\n      tags:\n        - cache\n      summary: Clears the DNS response cache\n      description: Removes all DNS responses from cache\n      responses:\n        '200':\n          description: All caches cleared\ncomponents:\n  schemas:\n    api.BlockingStatus:\n      type: object\n      properties:\n        autoEnableInSec:\n          type: integer\n          minimum: 0\n          description: >-\n            If blocking is temporary disabled: amount of seconds until blocking\n            will be enabled\n        disabledGroups:\n          type: array\n          description: Disabled group names\n          items:\n            type: string\n        enabled:\n          type: boolean\n          description: True if blocking is enabled\n      required:\n        - enabled\n    api.QueryRequest:\n      type: object\n      properties:\n        query:\n          type: string\n          description: query for DNS request\n        type:\n          type: string\n          description: request type (A, AAAA, ...)\n      required:\n        - query\n        - type\n    api.QueryResult:\n      type: object\n      properties:\n        reason:\n          type: string\n          description: blocky reason for resolution\n        response:\n          type: string\n          description: actual DNS response\n        responseType:\n          type: string\n          description: response type (CACHED, BLOCKED, ...)\n        returnCode:\n          type: string\n          description: DNS return code (NOERROR, NXDOMAIN, ...)\n      required:\n        - reason\n        - response\n        - responseType\n        - returnCode\n

If http listener is enabled, blocky provides REST API. You can download the OpenAPI YAML interface specification.

You can also browse the interactive API documentation (RapiDoc) documentation online.

"},{"location":"interfaces/#cli","title":"CLI","text":"

Blocky provides a CLI interface to control. This interface uses internally the REST API.

To run the CLI, please ensure, that blocky DNS server is running, then execute blocky help for help or

Tip

To run this inside docker run docker exec blocky ./blocky blocking status

"},{"location":"network_configuration/","title":"Network configuration","text":"

In order, to benefit from all the advantages of blocky like ad-blocking, privacy and speed, it is necessary to use blocky as DNS server for your devices. You can configure DNS server on each device manually or use DHCP in your network router and push the right settings to your device. With this approach, you will configure blocky only once in your router and each device in your network will automatically use blocky as DNS server.

"},{"location":"network_configuration/#transparent-configuration-with-dhcp","title":"Transparent configuration with DHCP","text":"

Let us assume, blocky is installed on a Raspberry PI with fix IP address 192.168.178.2. Each device which connects to the router will obtain an IP address and receive the network configuration. The IP address of the Raspberry PI should be pushed to the device as DNS server.

\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502              \u2502         \u2502 Raspberry PI    \u2502\n\u2502  Router      \u2502         \u2502   blocky        \u2502        \n\u2502              \u2502         \u2502 192.168.178.2   \u2502            \n\u2514\u2500\u25b2\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2518         \u2514\u2500\u2500\u2500\u2500\u25b2\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518        \n  \u25021    \u2502                     \u2502  3                  \n  \u2502     \u2502                     \u2502                         \n  \u2502     \u2502                     \u2502 \n  \u2502     \u2502                     \u2502                     \n  \u2502     \u2502                     \u2502\n  \u2502     \u2502                     \u2502\n  \u2502     \u2502                     \u2502\n  \u2502     \u2502       \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n  \u2502     \u2502   2   \u2502                    \u2502\n  \u2502     \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba  Network device    \u2502\n  \u2502             \u2502    Android         \u2502\n  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524                    \u2502\n                \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n

1 - Network device asks the DHCP server (on Router) for the network configuration

2 - Router assigns a free IP address to the device and says \"Use 192.168.178.2\" as DNS server

3 - Clients makes DNS queries and is happy to use blocky

Warning

It is necessary to assign the server which runs blocky (e.g. Raspberry PI) a fix IP address.

"},{"location":"network_configuration/#example-configuration-with-fritzbox","title":"Example configuration with FritzBox","text":"

To configure the DNS server in the FritzBox, please open in the FritzBox web interface:

"},{"location":"prometheus_grafana/","title":"Integration in Grafana","text":""},{"location":"prometheus_grafana/#prometheus","title":"Prometheus","text":""},{"location":"prometheus_grafana/#prometheus-export","title":"Prometheus export","text":"

Blocky can optionally export metrics for Prometheus.

Following metrics will be exported:

name Description blocky_blacklist_cache / blocky_whitelist_cache Number of entries in blacklist/whitelist cache, partitioned by group blocky_error_total Number of total queries that ended in error for any reason blocky_query_total Number of total queries, partitioned by client and DNS request type (A, AAAA, PTR, etc) blocky_request_duration_ms_bucket Request duration histogram, partitioned by response type (Blocked, cached, etc) blocky_response_total Number of responses, partitioned by response type (Blocked, cached, etc), DNS response code, and reason blocky_blocking_enabled 1 if blocking is enabled, 0 otherwise blocky_cache_entry_count Number of entries in cache blocky_cache_hit_count / blocky_cache_miss_count Cache hit/miss counters blocky_prefetch_count Amount of prefetched DNS responses blocky_prefetch_domain_name_cache_count Amount of domain names being prefetched blocky_failed_download_count Number of failed list downloads"},{"location":"prometheus_grafana/#grafana-dashboard","title":"Grafana dashboard","text":"

Example Grafana dashboard definition as JSON or at grafana.com .

This dashboard shows all relevant statistics and allows enabling and disabling the blocking status.

"},{"location":"prometheus_grafana/#grafana-configuration","title":"Grafana configuration","text":"

Please install grafana-piechart-panel and set disable_sanitize_html in config or as env to use control buttons to enable/disable the blocking status.

"},{"location":"prometheus_grafana/#grafana-and-prometheus-example-project","title":"Grafana and Prometheus example project","text":"

This repo contains example docker-compose.yml with blocky, prometheus (with configured scraper for blocky) and grafana with prometheus datasource.

"},{"location":"prometheus_grafana/#mysql-mariadb","title":"MySQL / MariaDB","text":"

If database query logging is activated (see Query logging), you can use following Grafana Dashboard as JSON or at grafana.com

.

Please define the MySQL source in Grafana, which points to the database with blocky's log entries.

"},{"location":"prometheus_grafana/#postgres","title":"Postgres","text":"

The JSON for a Grafana dashboard equivalent to the MySQL/MariaDB version is located here

"}]}