diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..e1c5b0c7 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,16 @@ +name: docs +on: + push: + branches: + - docs + - master +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.x + - run: pip install mkdocs-material + - run: mkdocs gh-deploy --force diff --git a/.gitignore b/.gitignore index 7d87d317..8d9d00ac 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ bin/ docs/swagger.json docs/swagger.yaml docs/docs.go +site/ config.yml coverage.txt todo.txt diff --git a/Makefile b/Makefile index 13826d6d..8d9f1d42 100644 --- a/Makefile +++ b/Makefile @@ -12,13 +12,16 @@ all: test lint build ## Build binary (with tests) clean: ## cleans output directory $(shell rm -rf $(BIN_OUT_DIR)/*) -swagger: +swagger: ## creates swagger documentation as html file go get github.com/swaggo/swag/cmd/swag@v1.6.9 npm install bootprint bootprint-openapi html-inline $(shell go env GOPATH)/bin/swag init -g api/api.go $(shell) node_modules/bootprint/bin/bootprint.js openapi docs/swagger.json /tmp/swagger/ $(shell) node_modules/html-inline/bin/cmd.js /tmp/swagger/index.html > docs/swagger.html +serve_docs: ## serves online docs + mkdocs serve + build: ## Build binary go build -v -ldflags="-w -s -X blocky/cmd.version=${VERSION} -X blocky/cmd.buildTime=${BUILD_TIME}" -o $(BIN_OUT_DIR)/$(BINARY_NAME)$(BINARY_SUFFIX) diff --git a/README.md b/README.md new file mode 100644 index 00000000..8650be10 --- /dev/null +++ b/README.md @@ -0,0 +1,89 @@ +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/0xERR0R/blocky/CI%20Build?label=CI%20Build "CI Build")](#) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/0xERR0R/blocky/Release?label=Release "Release")](#) +[![GitHub latest version](https://img.shields.io/github/v/release/0xERR0R/blocky "Latest version")](https://github.com/0xERR0R/blocky/releases) +[![GitHub Release Date](https://img.shields.io/github/release-date/0xERR0R/blocky "Latest release date")](https://github.com/0xERR0R/blocky/releases) +[![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/0xERR0R/blocky "Go version")](#) +[![Docker pulls](https://img.shields.io/docker/pulls/spx01/blocky "Latest version")](https://hub.docker.com/r/spx01/blocky) +[![Docker Image Size (latest)](https://img.shields.io/docker/image-size/spx01/blocky/latest)](https://hub.docker.com/r/spx01/blocky) +[![Codecov](https://img.shields.io/codecov/c/gh/0xERR0R/blocky "Code coverage")](https://codecov.io/gh/0xERR0R/blocky) +[![Codacy grade](https://img.shields.io/codacy/grade/8fcd8f8420b8419c808c47af58ed9282 "Codacy grade")](#) +[![Go Report Card](https://goreportcard.com/badge/github.com/0xERR0R/blocky)](https://goreportcard.com/report/github.com/0xERR0R/blocky) +[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=0xERR0R/blocky)](https://dependabot.com) + +

+ +

+ +# Blocky + +Blocky is a DNS proxy and ad-blocker for the local network written in Go with following features: + +## Features + +- **Blocking** - Blocking of DNS queries with external lists (Ad-block, malware) and whitelisting + + * Definition of black and white lists per client group (Kids, Smart home devices, etc.) + * Periodical reload of external black and white lists + * Blocking of request domain, response CNAME (deep CNAME inspection) and response IP addresses (against IP lists) + +- **Advanced DNS configuration** - not just an ad-blocker + + * Custom DNS resolution for certain domain names + * Conditional forwarding to external DNS server + +- **Performance** - Improves speed and performance in your network + + * Customizable caching of DNS answers for queries -> improves DNS resolution speed and reduces amount of external DNS + queries + * Prefetching and caching of often used queries + * Using multiple external resolver simultaneously + * Low memory footprint + +- **Various Protocols** - Supports modern DNS protocols + + * DNS over UDP and TCP + * DNS over HTTPS (aka DoH) + * DNS over TLS (aka DoT) + +- **Security and Privacy** - Secure communication + + * Supports modern DNS extensions: DNSSEC, eDNS, ... + * Free configurable blocking lists - no hidden filtering etc. + * Provides DoH Endpoint + * Uses random upstream resolvers from the configuration - increases you privacy though the distribution of your DNS + traffic over multiple provider + * Blocky does **NOT** collect any user data, telemetry, statistics etc. + +- **Integration** - various integration + + * [Prometheus](https://prometheus.io/) metrics + * Prepared [Grafana](https://grafana.com/) dashboard + * Logging of DNS queries per day / per client in CSV format - easy to analyze + * Statistics report via CLI + * Various REST API endpoints + * CLI tool + +- **Simple configuration** - single configuration file in YAML format + + * Simple to maintain + * Simple to backup + +- **Simple installation/configuration** - blocky was designed + + * Docker image with Multi-arch support + * Single binary + * Supports x86-64 and ARM architectures -> runs fine on Raspberry PI + * Community supported Helm chart for k8s deployment + +## Quick start + +You can jump to [Installation](https://0xerr0r.github.io/blocky/installation/) chapter in the documentation. + +## Full documentation + +You can find full documentation and configuration examples +at: [https://0xERR0R.github.io/blocky/](https://0xERR0R.github.io/blocky/) + +## Contribution + +Issues, feature suggestions and pull requests are welcome! diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index a294782d..00000000 --- a/docs/README.md +++ /dev/null @@ -1,241 +0,0 @@ -[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/0xERR0R/blocky/CI%20Build?label=CI%20Build "CI Build")](#) -[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/0xERR0R/blocky/Release?label=Release "Release")](#) -[![GitHub latest version](https://img.shields.io/github/v/release/0xERR0R/blocky "Latest version")](https://github.com/0xERR0R/blocky/releases) -[![GitHub Release Date](https://img.shields.io/github/release-date/0xERR0R/blocky "Latest release date")](https://github.com/0xERR0R/blocky/releases) -[![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/0xERR0R/blocky "Go version")](#) -[![Docker pulls](https://img.shields.io/docker/pulls/spx01/blocky "Latest version")](https://hub.docker.com/r/spx01/blocky) -[![Docker Image Size (latest)](https://img.shields.io/docker/image-size/spx01/blocky/latest)](https://hub.docker.com/r/spx01/blocky) -[![Codecov](https://img.shields.io/codecov/c/gh/0xERR0R/blocky "Code coverage")](https://codecov.io/gh/0xERR0R/blocky) -[![Codacy grade](https://img.shields.io/codacy/grade/8fcd8f8420b8419c808c47af58ed9282 "Codacy grade")](#) -[![Go Report Card](https://goreportcard.com/badge/github.com/0xERR0R/blocky)](https://goreportcard.com/report/github.com/0xERR0R/blocky) -[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=0xERR0R/blocky)](https://dependabot.com) - -

- -

- -# Blocky -Blocky is a DNS proxy for the local network written in Go with following features: -- Blocking of DNS queries with external lists (Ad-block) with whitelisting - - Definition of black and white lists per client group (Kids, Smart home devices etc) -> for example: you can block some domains for you Kids and allow your network camera only domains from a whitelist - - periodical reload of external black and white lists - - blocking of request domain, response CNAME (deep CNAME inspection) and response IP addresses (against IP lists) -- Caching of DNS answers for queries -> improves DNS resolution speed and reduces amount of external DNS queries -- Custom DNS resolution for certain domain names -- Serves DNS over UDP, TCP and HTTPS (DNS over HTTPS, aka DoH) -- Supports UDP, TCP and TCP over TLS DNS resolvers with DNSSEC support -- Supports DNS over HTTPS (DoH) resolvers -- Delegates DNS query to 2 external resolvers from a list of configured resolvers, uses the answer from the fastest one - -> improves you privacy and resolution time - - Blocky peeks 2 random resolvers with weighted random algorithm: resolvers with error will be used less frequently -- Prefetching of often used queries -- Logging of all DNS queries per day / per client in a text file -- Simple configuration in a single file -- Prometheus metrics -- Only one binary in docker container, low memory footprint -- Runs fine on raspberry pi - -## Installation and configuration -Create `config.yml` file with your configuration [as yml](config.yml): -```yml -upstream: - # these external DNS resolvers will be used. Blocky picks 2 random resolvers from the list for each query - # 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)) - externalResolvers: - - 46.182.19.48 - - 80.241.218.68 - - tcp-tls:fdns1.dismail.de:853 - - https://dns.digitale-gesellschaft.ch/dns-query - -# optional: custom IP address for domain name (with all sub-domains) -# example: query "printer.lan" or "my.printer.lan" will return 192.168.178.3 -customDNS: - mapping: - printer.lan: 192.168.178.3 - -# optional: definition, which DNS resolver(s) should be used for queries to the domain (with all sub-domains). Multiple resolvers must be separated by comma -# 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 -conditional: - mapping: - fritz.box: udp:192.168.178.1 - lan.net: udp:192.168.178.1,udp:192.168.178.2 - # for reverse DNS lookups of local devices - 178.168.192.in-addr.arpa: udp:192.168.178.1 - -# optional: use black and white lists to block queries (for example ads, trackers, adult pages etc.) -blocking: - # definition of blacklist groups. Can be external link (http/https) or local file - blackLists: - ads: - - https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt - - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts - - https://mirror1.malwaredomains.com/files/justdomains - - http://sysctl.org/cameleon/hosts - - https://zeustracker.abuse.ch/blocklist.php?download=domainblocklist - - https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt - special: - - https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hosts - # 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 - whiteLists: - ads: - - whitelist.txt - # definition: which groups should be applied for which client - clientGroupsBlock: - # default will be used, if no special definition for a client name exists - default: - - ads - - special - # use client name (with wildcard support: * - sequence of any characters, [0-9] - range) - # or single ip address / client subnet as CIDR notation - laptop*: - - ads - 192.168.178.1/24: - - special - # which response will be sent, if query is blocked: - # zeroIp: 0.0.0.0 will be returned (default) - # nxDomain: return NXDOMAIN as return code - # comma separated list of destination IP adresses (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. - blockType: zeroIp - # optional: automatically list refresh period in minutes. Default: 4h. - # Negative value -> deactivate automatically refresh. - # 0 value -> use default - refreshPeriod: 0 - -# optional: configuration for caching of DNS responses -caching: - # amount in minutes, how long a response must be cached (min value). - # If <=0, use response's TTL, if >0 use this value, if TTL is smaller - # Default: 0 - minTime: 5 - # amount in minutes, 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 - # Default: 0 - maxTime: -1 - # if true, will preload DNS results for often used queries (names queried more than 5 times in a 2 hour time window). - # Results in cache will be loaded again on their expire (Time-to-live). - # 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. - # default: false - prefetching: true - -# optional: configuration of client name resolution -clientLookup: - # optional: this DNS resolver will be used to perform reverse DNS lookup (typically local router) - upstream: udp:192.168.178.1 - # optional: some routers return multiple names for client (host name and user defined name). Define which single name should be used. - # Example: take second name if present, if not take first name - singleNameOrder: - - 2 - - 1 - # optional: custom mapping of client name to IP addresses. Useful if reverse DNS does not work properly or just to have custom client names. - clients: - laptop: - - 192.168.178.29 -# optional: configuration for prometheus metrics endpoint -prometheus: - # enabled if true - enable: true - # url path, optional (default '/metrics') - path: /metrics - -# optional: write query information (question, answer, client, duration etc) to daily csv file -queryLog: - # directory (should be mounted as volume in docker) - dir: /logs - # if true, write one file per client. Writes all queries to single file otherwise - perClient: true - # if > 0, deletes log files which are older than ... days - logRetentionDays: 7 - -# optional: DNS listener port and bind ip address, default 53 (UDP and TCP). Example: 53, :53, 127.0.0.1:53 -port: 53 -# optional: HTTP listener port, default 0 = no http listener. If > 0, will be used for prometheus metrics, pprof, REST API, DoH ... -httpPort: 4000 -# optional: HTTPS listener port, default 0 = no http listener. If > 0, will be used for prometheus metrics, pprof, REST API, DoH... -httpsPort: 443 -# mandatory, if https port > 0: path to cert and key file for SSL encryption -httpsCertFile: server.crt -httpsKeyFile: server.key -# optional: use this DNS server to resolve blacklist urls and upstream DNS servers (DOH). Useful if no DNS resolver is configured and blocky needs to resolve a host name. Format net:IP:port, net must be udp or tcp -bootstrapDns: tcp:1.1.1.1 -# optional: Log level (one from debug, info, warn, error). Default: info -logLevel: info -# optional: Log format (text or json). Default: text -logFormat: text -``` - -### Run with docker -Start docker container with following `docker-compose.yml` file: -```yml -version: "2.1" -services: - blocky: - image: spx01/blocky - container_name: blocky - restart: unless-stopped - ports: - - "53:53/tcp" - - "53:53/udp" - - "4000:4000/tcp" # Prometheus stats (if enabled). - environment: - - TZ=Europe/Berlin - volumes: - # config file - - ./config.yml:/app/config.yml - # write query logs in this directory. You can also use a volume - - ./logs:/logs -``` - -See [Wiki - Run with docker](https://github.com/0xERR0R/blocky/wiki/Run-with-docker) for more examples and additional information. - -### Run standalone -Download the binary file for your architecture and run `./blocky --config config.yml`. 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). - -### Run with kubernetes (helm) -See [this repo](https://github.com/k8s-at-home/charts/tree/master/charts/blocky) or [artifacthub](https://hub.helm.sh/charts/k8s-at-home/blocky) for details about running blocky via helm in kubernetes. - -## CLI / REST API -If http listener is enabled, blocky provides REST API to control blocking status. Swagger documentation under `http://host:port/swagger` - -To run CLI, please ensure, that blocky DNS server is running, than execute `blocky help` for help or -- `./blocky blocking enable` to enable blocking -- `./blocky blocking disable` to disable blocking -- `./blocky blocking disable --duration [duration]` to disable blocking for a certain amount of time (30s, 5m, 10m30s, ...) -- `./blocky blocking status` to print current status of blocking -- `./blocky query ` execute DNS query (A) (simple replacement for dig, useful for debug purposes) -- `./blocky query --type ` execute DNS query with passed query type (A, AAAA, MX, ...) - -To run this inside docker run `docker exec blocky ./blocky blocking status` - -## Additional information - -### HTTPS configuration (for DoH) -See [Wiki - Configuration of HTTPS](https://github.com/0xERR0R/blocky/wiki/Configuration-of-HTTPS-for-DoH-and-Rest-API) for detailed information, how to configure HTTPS. - -DoH url: https://host:port/dns-query - -### Prometheus / Grafana -Blocky can export metrics for prometheus. Example grafana dashboard definition [as JSON](blocky-grafana.json) -or [at grafana.com](https://grafana.com/grafana/dashboards/13768) -![grafana-dashboard](grafana-dashboard.png). - -See [Wiki - Prometheus / Grafana](https://github.com/0xERR0R/blocky/wiki/Prometheus---Grafana-integration) for more -information. - - -### Print current configuration -To print runtime configuration / statistics, you can send `SIGUSR1` signal to running process - -### Statistics -blocky collects statistics and aggregates them hourly. If signal `SIGUSR2` is received, this will print statistics for last 24 hours: -* Top 20 queried domains -* Top 20 blocked domains -* Query count per client -... - -Hint: To send a signal to a process you can use `kill -s USR1 ` or `docker kill -s SIGUSR1 blocky` for docker setup - -### Debug / Profiling -If http listener is enabled, pprof endpoint (`/debug/pprof`) is enabled automatically. diff --git a/docs/additional_information.md b/docs/additional_information.md new file mode 100644 index 00000000..a22c40fe --- /dev/null +++ b/docs/additional_information.md @@ -0,0 +1,228 @@ +# Additional information + +## Print current configuration + +To print runtime configuration / statistics, you can send `SIGUSR1` signal to running process. + +!!! summary + + Example output: + + ``` + INFO server: current configuration: + INFO server: -> resolver: 'ClientNamesResolver' + INFO server: singleNameOrder = "[2 1]" + INFO server: externalResolver = "upstream 'tcp+udp:192.168.178.1:53'" + INFO server: cache item count = 7 + INFO server: -> resolver: 'QueryLoggingResolver' + INFO server: logDir= "/logs" + INFO server: perClient = false + INFO server: logRetentionDays= 7 + INFO server: -> resolver: 'StatsResolver' + INFO server: stats: + INFO server: - Top 20 queries + INFO server: - Top 20 blocked queries + INFO server: - Query count per client + INFO server: - Reason + INFO server: - Query type + INFO server: - Response type + INFO server: -> resolver: 'MetricsResolver' + INFO server: metrics: + INFO server: Enable = true + INFO server: Path = /metrics + INFO server: -> resolver: 'ConditionalUpstreamResolver' + INFO server: fritz.box = "parallel upstreams 'upstream 'tcp+udp:192.168.178.1:53''" + INFO server: -> resolver: 'CustomDNSResolver' + INFO server: runtime information: + ... + INFO server: MEM Alloc = 9 MB + INFO server: MEM HeapAlloc = 9 MB + INFO server: MEM Sys = 88 MB + INFO server: MEM NumGC = 1533 + INFO server: RUN NumCPU = 4 + INFO server: RUN NumGoroutine = 18 + + ``` + +!!! hint + + To send a signal to a process you can use `kill -s USR1 ` or `docker kill -s SIGUSR1 blocky` for docker setup + +## Statistics + +blocky collects statistics and aggregates them hourly. If signal `SIGUSR2` is received, this will print statistics for +last 24 hours: + +* Top 20 queried domains +* Top 20 blocked domains +* Query count per client ... + +!!! summary + + Example output: + + ``` + INFO stats_resolver: ******* STATS 24h ******* + INFO stats_resolver: ┌───────────────────────────────────────────────────────────┐ + INFO stats_resolver: │ Top 20 queries │ + INFO stats_resolver: ├────────────────────────────────────────────────────┬──────┤ + INFO stats_resolver: │ 123.fritz.box │ 5760 │ + INFO stats_resolver: │ checkip.12344567.com │ 1431 │ + INFO stats_resolver: │ wpad.fritz.box │ 379 │ + INFO stats_resolver: │ raw.githubusercontent.com │ 299 │ + INFO stats_resolver: │ grafana.com │ 288 │ + INFO stats_resolver: │ www.google.com │ 224 │ + INFO stats_resolver: │ www.youtube.com │ 193 │ + INFO stats_resolver: │ www.googleapis.com │ 169 │ + INFO stats_resolver: │ fritz.box │ 156 │ + INFO stats_resolver: │ incoming.telemetry.mozilla.org │ 148 │ + INFO stats_resolver: │ android.googleapis.com │ 114 │ + INFO stats_resolver: │ userlocation.googleapis.com │ 101 │ + INFO stats_resolver: │ play.googleapis.com │ 100 │ + INFO stats_resolver: │ safebrowsing.googleapis.com │ 97 │ + INFO stats_resolver: │ api-mifitsdfsdfsdfi.com │ 84 │ + INFO stats_resolver: │ connectivitycheck.gstatic.com │ 75 │ + INFO stats_resolver: │ fonts.gstatic.com │ 66 │ + INFO stats_resolver: │ i.ytimg.com │ 62 │ + INFO stats_resolver: │ android.clients.google.com │ 55 │ + INFO stats_resolver: │ play.google.com │ 50 │ + INFO stats_resolver: └────────────────────────────────────────────────────┴──────┘ + INFO stats_resolver: ┌──────────────────────────────────────────────────────────┐ + INFO stats_resolver: │ Top 20 blocked queries │ + INFO stats_resolver: ├────────────────────────────────────────────────────┬─────┤ + INFO stats_resolver: │ incoming.telemetry.mozilla.org │ 148 │ + INFO stats_resolver: │ googleads.g.doubleclick.net │ 47 │ + INFO stats_resolver: │ data.mistat.intl.xiaomi.com │ 29 │ + INFO stats_resolver: │ ssl.google-analytics.com │ 25 │ + INFO stats_resolver: │ app-measurement.com │ 25 │ + INFO stats_resolver: │ www.googletagmanager.com │ 24 │ + INFO stats_resolver: │ www.googleadservices.com │ 23 │ + INFO stats_resolver: │ privatestats.whatsapp.net │ 22 │ + INFO stats_resolver: │ find.api.micloud.xiaomi.net │ 21 │ + INFO stats_resolver: │ sdkconfig.ad.intl.xiaomi.com │ 18 │ + INFO stats_resolver: │ sessionssdfsdfasdfam │ 16 │ + INFO stats_resolver: │ pagead2.googlesyndication.com │ 16 │ + INFO stats_resolver: │ firebase-settings.crashlytics.com │ 16 │ + INFO stats_resolver: │ abroad.apilocate.amap.com │ 16 │ + INFO stats_resolver: │ www.google-analytics.com │ 15 │ + INFO stats_resolver: │ tracking.intl.miui.com │ 15 │ + INFO stats_resolver: │ resolver.asdfsadfsdfsdfsdfsdfd │ 14 │ + INFO stats_resolver: │ adfgdfgsfgdg │ 14 │ + INFO stats_resolver: │ adservice.google.com │ 14 │ + INFO stats_resolver: │ www.tns-cdfgffgdfg │ 12 │ + INFO stats_resolver: └────────────────────────────────────────────────────┴─────┘ + INFO stats_resolver: ┌───────────────────────────────────────────────────────────┐ + INFO stats_resolver: │ Query count per client │ + INFO stats_resolver: ├────────────────────────────────────────────────────┬──────┤ + INFO stats_resolver: │ sdf.fritz.box │ 6338 │ + INFO stats_resolver: │ dfdgsfgsfg.fritz.box │ 2075 │ + INFO stats_resolver: │ df.fritz.box │ 1484 │ + INFO stats_resolver: │ sdfgsdfg.fritz.box │ 1129 │ + INFO stats_resolver: │ Android-3.fritz.box │ 1007 │ + INFO stats_resolver: │ dfgsdfgsdfgsdf.fritz.box │ 956 │ + INFO stats_resolver: │ 172.20.0.2 │ 833 │ + INFO stats_resolver: │ 345345354353453iNote.fritz.box │ 393 │ + INFO stats_resolver: │ R334534545-D.fritz.box │ 359 │ + INFO stats_resolver: │ Android-2.fritz.box │ 347 │ + INFO stats_resolver: │ Android.fritz.box │ 317 │ + INFO stats_resolver: │ wererrw-TV.fritz.box │ 244 │ + INFO stats_resolver: │ dfsdf-dfsddsdfsdf.fritz.box │ 77 │ + INFO stats_resolver: │ sdfdf.fritz.box │ 18 │ + INFO stats_resolver: │ sdfsdffsd.fritz.box │ 10 │ + INFO stats_resolver: │ android-936072d2983c456a.fritz.box │ 8 │ + INFO stats_resolver: └────────────────────────────────────────────────────┴──────┘ + INFO stats_resolver: ┌───────────────────────────────────────────────────────────┐ + INFO stats_resolver: │ Reason │ + INFO stats_resolver: ├────────────────────────────────────────────────────┬──────┤ + INFO stats_resolver: │ CONDITIONAL │ 6518 │ + INFO stats_resolver: │ CACHED │ 5431 │ + INFO stats_resolver: │ BLOCKED (ads) │ 1104 │ + INFO stats_resolver: │ RESOLVED (1.1.1.1:53) │ 928 │ + INFO stats_resolver: │ RESOLVED (9.9.9.9:53) │ 630 │ + INFO stats_resolver: │ RESOLVED (80.241.218.68:53) │ 374 │ + INFO stats_resolver: │ RESOLVED (89.233.43.71:53) │ 277 │ + INFO stats_resolver: │ RESOLVED (46.182.19.48:53) │ 177 │ + INFO stats_resolver: │ RESOLVED (91.239.100.100:53) │ 77 │ + INFO stats_resolver: │ CUSTOM DNS │ 39 │ + INFO stats_resolver: │ BLOCKED (kids) │ 14 │ + INFO stats_resolver: │ BLOCKED IP (ads) │ 9 │ + INFO stats_resolver: │ CACHED NEGATIVE │ 8 │ + INFO stats_resolver: │ BLOCKED CNAME (ads) │ 7 │ + INFO stats_resolver: └────────────────────────────────────────────────────┴──────┘ + INFO stats_resolver: ┌───────────────────────────────────────────────────────────┐ + INFO stats_resolver: │ Query type │ + INFO stats_resolver: ├────────────────────────────────────────────────────┬──────┤ + INFO stats_resolver: │ A │ 8206 │ + INFO stats_resolver: │ AAAA │ 7330 │ + INFO stats_resolver: │ SRV │ 44 │ + INFO stats_resolver: │ NAPTR │ 15 │ + INFO stats_resolver: └────────────────────────────────────────────────────┴──────┘ + INFO stats_resolver: ┌────────────────────────────────────────────────────────────┐ + INFO stats_resolver: │ Response type │ + INFO stats_resolver: ├────────────────────────────────────────────────────┬───────┤ + INFO stats_resolver: │ NOERROR │ 15368 │ + INFO stats_resolver: │ NXDOMAIN │ 222 │ + INFO stats_resolver: │ SERVFAIL │ 5 │ + INFO stats_resolver: └────────────────────────────────────────────────────┴───────┘ + + ``` + +!!! hint + + To send a signal to a process you can use `kill -s USR2 ` or `docker kill -s SIGUSR2 blocky` for docker setup + +## Debug / Profiling + +If http listener is enabled, [pprof](https://golang.org/pkg/net/http/pprof/) endpoint (`/debug/pprof`) is enabled +automatically. + +## List sources + +Some links/ideas for lists: + +### Blacklists + +* [https://github.com/StevenBlack/hosts](https://github.com/StevenBlack/hosts) +* [https://github.com/nickspaargaren/no-google](https://github.com/nickspaargaren/no-google) +* [https://energized.pro/](https://energized.pro/) +* [https://github.com/Perflyst/PiHoleBlocklist](https://github.com/Perflyst/PiHoleBlocklist) +* [https://github.com/kboghdady/youTube_ads_4_pi-hole](https://github.com/kboghdady/youTube_ads_4_pi-hole) +* [https://github.com/chadmayfield/my-pihole-blocklists](https://github.com/chadmayfield/my-pihole-blocklists) + +!!! warning + + Use only blacklists from the sources you trust! + +### Whitelists + +* [https://github.com/anudeepND/whitelist](https://github.com/anudeepND/whitelist) + +## List of public DNS servers + +!!! 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. + +* [AdGuard](https://adguard.com/en/adguard-dns/setup.html) +* [CloudFlare](https://1.1.1.1/) +* [Comodo](https://www.comodo.com/secure-dns/) +* [DigitalCourage](https://digitalcourage.de/support/zensurfreier-dns-server) +* [DigitaleGesellschaft](https://www.digitale-gesellschaft.ch/dns/) +* [Dismail](https://dismail.de/info.html#dns) +* [dnsforge](https://dnsforge.de/) +* [Google](https://developers.google.com/speed/public-dns) +* [OpenDNS](https://www.opendns.com/setupguide/#familyshield) +* [Quad9](https://www.quad9.net/) +* [UncensoredDNS](https://blog.uncensoreddns.org/dns-servers/) + +--8<-- "docs/includes/abbreviations.md" diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 00000000..69779f3a --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,331 @@ +# Configuration + +This chapter describes all configuration options in `config.yaml` + +## Basic configuration + +| Parameter | Mandatory | Default value | Description | +| --------------- | --------- | -------------------| ------------------------------------------------- | +| port | no | 53 | Port to serve DNS endpoint (TCP and UDP) | +| httpPort | no | 0 | HTTP listener port. If > 0, will be used for prometheus metrics, pprof, REST API, DoH ... | +| httpsPort | no | 0 | HTTPS listener port. If > 0, will be used for prometheus metrics, pprof, REST API, DoH... | +| httpsCertFile | yes, if httpsPort > 0 | | path to cert and key file for SSL encryption | +| httpsKeyFile | yes, if httpsPort > 0 | | path to cert and key file for SSL encryption | +| bootstrapDns | no | | use this DNS server to resolve blacklist urls and upstream DNS servers (DoH). Useful if no DNS resolver is configured and blocky needs to resolve a host name. Format net:IP:port, net must be udp or tcp| +| logLevel | no | info | Log level (one from debug, info, warn, error) | +| logFormat | no | text | Log format (text or json). | + +!!! example + + ```yaml + port: 53 + httpPort: 4000 + httpsPort: 443 + logLevel: info + ``` + +## Upstream configuration + +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): + +- udp (only UDP) +- tcp (only TCP) +- tcp+udp (UDP and TCP, dependent on query type) +- https (aka DoH) +- tcp-tls (aka DoT) + +!!! hint + + You can (and should!) configure multiple DNS resolvers. Blocky picks 2 random resolvers from the list for each query and + returns the answer from the fastest one. This improves your network speed and increases your privacy - your DNS traffic + will be distributed over multiple providers. + +Each resolver must be defined as a string in following format: `[net:]host:[port][/path]`. + +| Parameter | Mandatory | Value | Default value | +| --------- | --------- | -------------------------------------------- | ------------------------------------------------- | +| net | no | one of (tcp+udp, tcp, udp, tcp-tls or https) | tcp+udp | +| host | yes | full qualified domain name or ip address | | +| port | no | number < 65535 | 53 for udp/tcp, 853 for tcp-tls and 443 for https | + +!!! example + + ```yaml + upstream: + externalResolvers: + - 46.182.19.48 + - 80.241.218.68 + - tcp-tls:fdns1.dismail.de:853 + - https://dns.digitale-gesellschaft.ch/dns-query + ``` + +!!! note + + ** Blocky needs at least one upstream DNS server ** + +See [List of public DNS servers](additional_information.md#list-of-public-dns-servers) if you need some ideas, which +public free DNS server you could use. + +## Custom DNS + +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. + +!!! example + + ```yaml + customDNS: + mapping: + printer.lan: 192.168.178.3 + otherdevice.lan: 192.168.178.15 + ``` + +This configuration will also resolve any subdomain of the defined domain. For example a query "printer.lan" or " +my.printer.lan" will return 192.168.178.3 as IP address. + +## Conditional DNS resolution + +You can define, which DNS resolver(s) should be used for queries for the particular domain (with all sub-domains). 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. + +!!! example + + ```yaml + conditional: + mapping: + fritz.box: udp:192.168.178.1 + lan.net: udp:192.170.1.2,udp:192.170.1.3 + # for reverse DNS lookups of local devices + 178.168.192.in-addr.arpa: udp:192.168.178.1 + ``` + + 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. + +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. + +## Client name lookup + +Blocky can try to resolve a user-friendly client name from the IP address. This is useful for defining of blocking +groups, since IP address can change dynamically. 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. + +### Single name order + +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. + +### Custom client name mapping + +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 + + ```yaml + clientLookup: + upstream: udp:192.168.178.1 + singleNameOrder: + - 2 + - 1 + clients: + laptop: + - 192.168.178.29 + ``` + + 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. + +## Blocking and whitelisting + +Blocky can download and use external lists with domains or IP addresses to block DNS query (e.g. advertisement, malware, +trackers, adult sites). You can group several list sources together and define the blocking behavior per client. +External blacklists must be in the well-known [Hosts format](https://en.wikipedia.org/wiki/Hosts_(file)). + +Blocky uses [DNS sinkhole](https://en.wikipedia.org/wiki/DNS_sinkhole) approach to block a DNS query. Domain name from +the request, IP address from the response, and the CNAME record will be checked against configured blacklists. + +To avoid overblocking, you can define or use already existing whitelists. + +### Definition black and whitelists + +Each black or whitelist can be either a path to the local file, or a URL to download. All Urls must be grouped to a +group name. + +!!! example + + ```yaml + blocking: + blackLists: + ads: + - https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt + - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts + special: + - https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hosts + whiteLists: + ads: + - whitelist.txt + ``` + + In this example you can see 2 groups: **ads** with 2 lists and **special** with one list. One local whitelist was defined for the **ads** group. + +!!! 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 + +### Client groups + +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 a group assignment will use automatically the **default** group. + +You can use the client name (see [Client name lookup](#client-name-lookup)), client's IP address or a client subnet as +CIDR notation. + +!!! example + + ```yaml + blocking: + clientGroupsBlock: + # default will be used, if no special definition for a client name exists + default: + - ads + - special + laptop*: + - ads + 192.168.178.1/24: + - special + kid-laptop: + - ads + - adult + ``` + + 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 + +### Block type + +You can configure, which response should be sent to the client, if a requested query is blocked: + +| blockType | Example | Description | +| ---------- | ------- | ---------------------------------------------------------------- | +| **zeroIP** | zeroIP | This is the **default** block type. Server returns 0.0.0.0 as result | +| **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 + + ```yaml + blocking: + blockType: nxDomain + ``` + +### List refresh period + +To keep the list cache up-to-date, blocky will periodically download and reload all external lists. Default period is ** +4 hours**. You can configure this by setting the `blocking.refreshPeriod` parameter to a value in **minutes**. Negative +value will deactivate automatically refresh. + +!!! example + + ```yaml + blocking: + refreshPeriod: 60 + ``` + + Refresh every hour. + +## Caching + +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 | Mandatory | Default value | Description | +| --------------- | --------- | -------------------| ------------------------------------------------- | +| caching.minTime | no | 0 (use TTL) | Amount in minutes, 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 | no | 0 (use TTL) | Amount in minutes, 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.prefetching | no | false | if true, blocky will preload DNS results for often used queries (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. | + +!!! example + + ```yaml + blocking: + minTime: 5 + maxTime: 30 + prefetching: true + ``` + +## Prometheus + +Blocky can expose various metrics for prometheus. To use the prometheus feature, the HTTP listener must be enabled ( +see [Basic Configuration](#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 + + ```yaml + prometheus: + enable: true + path: /metrics + ``` + +## Query logging + +You can enable the logging of DNS queries (question, answer, client, duration etc) to a daily CSV file. This file can be +opened in Excel or OpenOffice writer for analyse purposes. + +!!! warning + + Query file contain sensitive information. Please ensure to inform users, if you log their queries. + +Configuration parameters: + +| Parameter | Mandatory | Default value | Description | +| --------------- | --------- | -------------------| ------------------------------------------------- | +| queryLog.dir | no | | If defined, directory for writing the logs | +| queryLog.perClient | no | false | if true, write one file per client. Writes all queries to single file otherwise | +| queryLog.logRetentionDays| no | 0 | if > 0, deletes log files which are older than ... days | + +!!! hint + + Please ensure, that the log directory is writable. If you use docker, please ensure, that the directory is properly + mounted (e.g. volume) + +!!! example + + ```yaml + queryLog: + dir: /logs + perClient: true + logRetentionDays: 7 + ``` + +## HTTPS configuration (for DoH) + +See [Wiki - Configuration of HTTPS](https://github.com/0xERR0R/blocky/wiki/Configuration-of-HTTPS-for-DoH-and-Rest-API) +for detailed information, how to configure HTTPS. + +DoH url: `https://host:port/dns-query` + +--8<-- "docs/includes/abbreviations.md" diff --git a/docs/fb_dns_config.png b/docs/fb_dns_config.png new file mode 100644 index 00000000..7e203714 Binary files /dev/null and b/docs/fb_dns_config.png differ diff --git a/docs/includes/abbreviations.md b/docs/includes/abbreviations.md new file mode 100644 index 00000000..7b73438a --- /dev/null +++ b/docs/includes/abbreviations.md @@ -0,0 +1,24 @@ +*[DNS]: Domain Name System +*[k8s]: Kubernetes +*[UDP]: User Datagram Protocol +*[TCP]: Transmission Control Protocol +*[HTTP]: Hypertext Transfer Protocol +*[HTTPS]: Hypertext Transfer Protocol Secure +*[DoH]: DNS-over-HTTPS +*[DoT]: DNS-over-TLS +*[DNSSEC]: Domain Name System Security Extensions +*[eDNS]: Extended DNS +*[REST]: Representational State Transfer +*[API]: Application Programming Interface +*[CLI]: Command Line Interface +*[YAML]: YAML Ain't Markup Language +*[Helm]: package manager for Kubernetes +*[CNAME]: Canonical Name +*[CIDR]: Classless Inter-Domain Routing +*[NXDOMAIN]: Non-Existence Domain +*[TTL]: Time-To-Live +*[rDNS]: Reverse DNS +*[SSL]: Secure Sockets Layer +*[CSV]: Comma-separated values +*[SAMBA]: Server Message Block Protocol (Windows Network File System) +*[DHCP]: Dynamic Host Configuration Protocol \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..1262b6f1 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,72 @@ +# Blocky + +
+ +
+ +Blocky is a DNS proxy and ad-blocker for the local network written in Go with following features: + +## Features + +- **Blocking** - :no_entry: Blocking of DNS queries with external lists (Ad-block, malware) and whitelisting + + * Definition of black and white lists per client group (Kids, Smart home devices, etc.) + * Periodical reload of external black and white lists + * Blocking of request domain, response CNAME (deep CNAME inspection) and response IP addresses (against IP lists) + +- **Advanced DNS configuration** - :nerd: not just an ad-blocker + + * Custom DNS resolution for certain domain names + * Conditional forwarding to external DNS server + +- **Performance** - :rocket: Improves speed and performance in your network + + * Customizable caching of DNS answers for queries -> improves DNS resolution speed and reduces amount of external DNS + queries + * Prefetching and caching of often used queries + * Using multiple external resolver simultaneously + * Low memory footprint + +- **Various Protocols** - :computer: Supports modern DNS protocols + + * DNS over UDP and TCP + * DNS over HTTPS (aka DoH) + * DNS over TLS (aka DoT) + +- **Security and Privacy** - :dark_sunglasses: Secure communication + + * Supports modern DNS extensions: DNSSEC, eDNS, ... + * Free configurable blocking lists - no hidden filtering etc. + * Provides DoH Endpoint + * Uses random upstream resolvers from the configuration - increases your privacy through the distribution of your DNS + traffic over multiple provider + * Open source development + * Blocky does **NOT** collect any user data, telemetry, statistics etc. + +- **Integration** - :notebook_with_decorative_cover: various integration + + * [Prometheus](https://prometheus.io/) metrics + * Prepared [Grafana](https://grafana.com/) dashboard + * Logging of DNS queries per day / per client in CSV format - easy to analyze + * Statistics report via CLI + * Various REST API endpoints + * CLI tool + +- **Simple configuration** - :baby: single configuration file in YAML format + + * Simple to maintain + * Simple to backup + +- **Simple installation/configuration** - :cloud: blocky was designed + + * Docker image with Multi-arch support + * Single binary + * Supports x86-64 and ARM architectures -> runs fine on Raspberry PI + * Community supported Helm chart for k8s deployment + + +## Contribution + +Issues, feature suggestions and pull requests are welcome! Blocky lives on :material-github:[GitHub](https://github.com/0xERR0R/blocky). + +--8<-- "docs/includes/abbreviations.md" diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 00000000..5ef122ec --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,131 @@ +# Installation + +You can choose one of the following installation options: + +* Run as standalone binary +* Run as docker container +* Kubernetes with helm chart + +## Prepare your configuration + +Blocky uses one YAML file as configuration. Create new `config.yaml` with your configuration ( +see [Configuration](configuration.md) for more details and all configuration options). + +Simple configuration file, which enables only basic features: + +```yaml +upstream: + externalResolvers: + - 46.182.19.48 + - 80.241.218.68 + - tcp-tls:fdns1.dismail.de:853 + - https://dns.digitale-gesellschaft.ch/dns-query +blocking: + blackLists: + ads: + - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts + clientGroupsBlock: + default: + - ads +port: 53 +httpPort: 4000 +``` + +## Run as standalone binary + +Download the binary file from [GitHub](https://github.com/0xERR0R/blocky/releases) 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). + +## Run with docker + +### Alternative registry + +Blocky docker images are deployed to DockerHub (`spx01/blocky`) and GitHub Container Registry (`ghcr.io/0xerr0r/blocky`) +. + +### Docker from command line + +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 +``` + +### Run with docker-compose + +Create following `docker-compose.yml` file + +```yaml +version: "2.1" +services: + blocky: + image: spx01/blocky + container_name: blocky + restart: unless-stopped + ports: + - "53:53/tcp" + - "53:53/udp" + - "4000:4000/tcp" + environment: + - TZ=Europe/Berlin # Optional to synchronize the log timestamp with host + volumes: + # config file + - ./config.yml:/app/config.yml +``` + +and start docker container with + +``` +docker-compose up -d +``` + +### Advanced setup + +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 + +```yaml +version: "2.1" +services: + blocky: + image: spx01/blocky + container_name: blocky + restart: unless-stopped + ports: + - "53:53/tcp" + - "53:53/udp" + - "4000:4000/tcp" # Prometheus stats (if enabled). + environment: + - TZ=Europe/Berlin + volumes: + # config file + - ./config.yml:/app/config.yml + # write query logs in this volume + - queryLogs:/logs + # put your custom white and blacklists in these directories + - ./blacklists:/app/blacklists/ + - ./whitelists:/app/whitelists/ + +volumes: + queryLogs: + driver: local + driver_opts: + type: cifs + o: username=USER,password=PASSWORD,rw + device: //NAS_HOSTNAME/blocky +``` + +## Run with helm chart on Kubernetes + +See [this repo](https://github.com/k8s-at-home/charts/tree/master/charts/blocky) +or [artifacthub](https://hub.helm.sh/charts/k8s-at-home/blocky) for details about running blocky via helm in kubernetes. + +--8<-- "docs/includes/abbreviations.md" \ No newline at end of file diff --git a/docs/interfaces.md b/docs/interfaces.md new file mode 100644 index 00000000..b1b134cc --- /dev/null +++ b/docs/interfaces.md @@ -0,0 +1,27 @@ +# Interfaces + +## REST API + +If http listener is enabled, blocky provides REST API. You can browse the API documentation (Swagger) documentation +under [https://0xERR0R.github.io/blocky/swagger.html](https://0xERR0R.github.io/blocky/swagger.html). + +## CLI + +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 + +- `./blocky blocking enable` to enable blocking +- `./blocky blocking disable` to disable blocking +- `./blocky blocking disable --duration [duration]` to disable blocking for a certain amount of time (30s, 5m, 10m30s, + ...) +- `./blocky blocking status` to print current status of blocking +- `./blocky query ` execute DNS query (A) (simple replacement for dig, useful for debug purposes) +- `./blocky query --type ` execute DNS query with passed query type (A, AAAA, MX, ...) +- `./blocky lists refresh` reloads all white and blacklists + +!!! tip + + To run this inside docker run `docker exec blocky ./blocky blocking status` + +--8<-- "docs/includes/abbreviations.md" diff --git a/docs/network_configuration.md b/docs/network_configuration.md new file mode 100644 index 00000000..4c96a52e --- /dev/null +++ b/docs/network_configuration.md @@ -0,0 +1,56 @@ +# Network configuration + +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. + +## Transparent configuration with DHCP + +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. + +``` +┌──────────────┐ ┌─────────────────┐ +│ │ │ Raspberry PI │ +│ Router │ │ blocky │ +│ │ │ 192.168.178.2 │ +└─▲─────┬──────┘ └────▲────────────┘ + │1 │ │ 3 + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ │ + │ │ ┌─────────────┴──────┐ + │ │ 2 │ │ + │ └───────► Network device │ + │ │ Android │ + └─────────────┤ │ + └────────────────────┘ +``` + +**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** :smile: + +!!! warning + + It is necessary to assign the server which runs blocky (e.g. Raspberry PI) a fix IP address. + +### Example configuration with FritzBox + +To configure the DNS server in the FritzBox, please open in the FritzBox web interface: + +* in navigation menu on the left side: Home Network -> Network +* Network Settings tab on the top +* "IPv4 Configuration" Button at the bottom op the page +* Enter the IP address of blocky under "Local DNS server", see screenshot + +![FritzBox DNS configuration](fb_dns_config.png "Logo Title Text 1") + +--8<-- "docs/includes/abbreviations.md" \ No newline at end of file diff --git a/docs/prometheus_grafana.md b/docs/prometheus_grafana.md new file mode 100644 index 00000000..9f1b75f6 --- /dev/null +++ b/docs/prometheus_grafana.md @@ -0,0 +1,42 @@ +# Integration in Prometheus / Grafana + +## Prometheus export + +Blocky can optionally export metrics for [Prometheus](https://prometheus.io/). + +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 | Counter for internal errors | +| 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 | + +## Grafana dashboard + +Example [Grafana](https://grafana.com/) dashboard +definition [as JSON](https://github.com/0xERR0R/blocky/blob/master/docs/blocky-grafana.json) +or [at grafana.com](https://grafana.com/grafana/dashboards/13768) +![grafana-dashboard](https://github.com/0xERR0R/blocky/raw/master/docs/grafana-dashboard.png). + +This dashboard shows all relevant statistics and allows enabling and disabling the blocking status. + +## Grafana configuration + +Please install `grafana-piechart-panel` and +set [disable-sanitize-html](https://grafana.com/docs/grafana/latest/installation/configuration/#disable-sanitize-html) +in config or as env to use control buttons to enable/disable the blocking status. + +## Grafana and Prometheus example project + +This [repo](https://github.com/0xERR0R/blocky-grafana-prometheus-example) contains example docker-compose.yml with +blocky, prometheus (with configured scraper for blocky) and grafana with prometheus datasource. + +--8<-- "docs/includes/abbreviations.md" diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..94f07c09 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,34 @@ +site_name: blocky +site_description: blocky Documentation +theme: + name: material + palette: + # scheme: slate + primary: teal + accent: teal +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/0xERR0R/blocky + - icon: fontawesome/brands/docker + link: https://hub.docker.com/r/spx01/blocky +repo_url: https://github.com/0xERR0R/blocky + +markdown_extensions: + - abbr + - pymdownx.snippets + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + - pymdownx.highlight + - pymdownx.superfences + - admonition + +nav: + - 'Welcome': 'index.md' + - 'Configuration': 'configuration.md' + - 'Installation': 'installation.md' + - 'Prometheus / Grafana': 'prometheus_grafana.md' + - 'Interfaces': 'interfaces.md' + - 'Network configuration': 'network_configuration.md' + - 'Additional information': 'additional_information.md'