Skip to content

Repository files navigation

blocker - Domain blocker plugin for CoreDNS

blocker is a CoreDNS plugin which can be used to block a list of domains provided in the AdBlock Plus syntax format. The blocklist will be loaded into memory at start-up and the file’s modified time will be checked periodically. When the blocklist file is updated, the in-memory blocklist will be updated by scanning the blocklist file line-by-line.

Updating the blocklist file itself is beyond the scope of this plugin. I recommend a bash script which downloads commonblocklists and updates them into a format without comments. The script blocklist-file-preparer.sh included with this repository is an example of how this can be done using bash and common GNU utilities.

Example blocklist file: (AdBlock Plus syntax)

||buyer.revsci.net^
||ww92.impfr.tradedoubler.com^
||next.chartboost.com^
||pl16442154.alternativecpmgate.com^
||denturesauaid.com^
||pdx-p-con-336.saas.appdynamics.com^
||cdn.ad.citynews.it^
||xxxxxxxamob.acs86.com^
||www.globalhotsale.su^
||zipuploads.com^

Usage

CoreDNS Binary

You can include blocker in the CoreDNS code just as you would include any other CoreDNS plugin.

# Clone coredns to a local location
$ git clone git@github.com:coredns/coredns.git ~/dns-server/coredns
# Clone blocker plugin to a close location
$ git clone git@github.com:icyflame/blocker.git ~/dns-server/blocker
# Symlink blocker location into coredns/plugin/blocker
$ cd~/dns-server/coredns/plugin
$ ln -s ../blocker ./blocker
# Update plugin.cfg and put the line "blocker:blocker" before the "forward:forward" line# Build CoreDNS
$ cd~/dns-server/coredns
$ go generate
$ make
$ ./coredns -conf Corefile

Corefile

The blocker directive inside Corefile requires four arguments. The first argument is the absolute path to the blocklist file. The second argument is the frequency at which the blocklist file is checked for updates. The third argument is the type of blocklist file (hosts and abp are the only two values which are supported at this time.) The fourth argument is the response type from the plugin, either empty for a valid DNS response with 0.0.0.0 or ::6 or nxdomain to respond with a DNS empty response.

The frequency is specified as a string and the value should be a valid argument of the time.ParseDuration function.

blocker /home/user/blocklist_file 1h abp empty

The following is a sample Corefile including the blocker directive. It will block domains that are specified in the blocklist and forward everything else to a full DNS server.

 .:53 {
metadata
# prometheus records metrics regarding incoming requests
prometheus
# log writes 1 line to the log for every DNS request# The last word in the log line will be YES if the request was blocked and NO if it was not# blocked.# This behaviour is supported by the metadata plugin.
log . "{common} {/blocker/request-blocked}"# blocker blocks domains which are specified in the blocklist
blocker /home/user/blocklist_file 1h abp empty
# forward handles any request that is not blocked by blocker
forward . 127.0.0.1:9053
}

plugin.cfg

This is a sample middleware configuration file. The order of plugins here is important. This is the order in which plugins will be executed for incoming requests.

metadata:metadata
prometheus:metrics
log:log
blocker:blocker
forward:forward

Interaction with Other CoreDNS Plugins

metadata

The blocker plugin will write a metadata value with the label blocker/request-blocked. This is a boolean value whose value will be either YES (if the request was blocked) or NO when the request was not blocked.

prometheus (metrics)

When the prometheusplugin is enabled, the blocker plugin will record 2 Counter metrics, representing the allowed and blocked DNS request count. These metrics can be fetched by setting up Prometheus to scrape from port 9153 on the interface where CoreDNS is running.

Metric values can be verified by making a HTTP request to the /metrics endpoint:

$ curl -s 127.0.0.1:9153/metrics | rg requests_total
# HELP coredns_blocker_allowed_requests_total Counter of DNS requests being allowed.# TYPE coredns_blocker_allowed_requests_total counter
coredns_blocker_allowed_requests_total 2
# HELP coredns_blocker_blocked_requests_total Counter of DNS requests being blocked.# TYPE coredns_blocker_blocked_requests_total counter
coredns_blocker_blocked_requests_total 3

Release Binaries

For tags which are published to this repository, the GitHub Actions workflow ./.github/workflows/build-binary.yml builds binaries using the latest Go version for Linux under the three most popular architectures: AMD64, ARM (32 bit), and ARM64. The tar.gz files contain a Checksum file which can be used together with sha256sum to verify the integrity of the binary.

$ wget https://github.com/icyflame/blocker/releases/download/v0.0.1-alpha/coredns-linux-amd64.tar.gz
...
coredns-linux-amd64.tar.gz 100%[=======================================================================>] 5.16M 610KB/s in 14s
2024-07-13 12:26:05 (390 KB/s) - ‘coredns-linux-amd64.tar.gz’ saved [5414731/5414731]
$ tar tvf coredns-linux-amd64.tar.gz
-rwxr-xr-x runner/docker 14110872 2024-07-13 12:26 coredns-linux-amd64
-rw-r--r-- runner/docker 86 2024-07-13 12:26 coredns-linux-amd64.checksum
$ tar zxf coredns-linux-amd64.tar.gz
$ sha256sum -c coredns-linux-amd64.checksum
coredns-linux-amd64: OK
$ ./coredns-linux-amd64 -version
CoreDNS-1.11.1
linux/amd64, go1.22.5, Blocker plugin refs/tags/v0.0.1-alpha 1e6061ee8b7d2ad2ee5c632d3b91851c00481453

Development

Running Tests

This plugin contains unit tests. These unit tests are run as part of the unit tests for CoreDNS. The following process should be followed to run these unit tests:

# Clone CoreDNS
$ git clone git@github.com:coredns/coredns.git /tmp/dns-server/coredns
# Clone this plugin
git clone git@github.com:icyflame/blocker.git /tmp/dns-server/blocker
# Link this plugin into CoreDNS
ln -s /tmp/dns-server/blocker /tmp/dns-server/coredns/plugin/blocker
# Run tests for this plugincd /tmp/dns-server/coredns
go test -v -count=1 ./plugin/blocker
=== RUN TestIsDomainBlocked_ABP
=== RUN TestIsDomainBlocked_ABP/base_case
[snip]
PASS
ok github.com/coredns/coredns/plugin/blocker 0.005s

During development, making changes to the blocker plugin, after the above process, makes it easier to run tests and use the Go language server features such as jumping to definition.

Testing the DNS server

Apart from unit tests, benchmarking tools can be used to verify whether CoreDNS works with a large volume of DNS requests. This is the setup that I use to run benchmarks using dnsbench.

First, follow the process in the Usage > CoreDNS Binary section to create a CoreDNS binary which contains the blocker plugin.

Second, start the CoreDNS server using the following configuration:

$ cat Corefile.benchmark.conf
.:5335 {
metadata
log . "{common} {/blocker/request-blocked}"
blocker /home/siddharth/code/open-source/coredns/blocklist.benchmark 1s abp nxdomain
forward . 8.8.8.8
}
$ touch blocklist.benchmark
$ ./coredns -conf Corefile.benchmark.conf
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[INFO] plugin/blocker: updated blocklist; blocked domains: before: 0, after: 0; last updated: before: 0001-01-01 00:00:00 +0000 UTC, after: 2025-08-09 12:10:31.479348779 +0900 JST m=+0.026230377
.:5335
CoreDNS-1.12.3
linux/amd64, go1.24.5, 463fd1c1b-dirty

Third, run the following one liner which simulates updating the block list:

$ truncate --size 0 blocklist.benchmark;foriin`seq 101 10000`;do sleep 1;echo"||baddomain-$i.example.com^">> blocklist.benchmark;echo"$(date): Iteration $i DONE";done;
Sat 09 Aug 2025 12:11:30 PM JST: Iteration 1 DONE
Sat 09 Aug 2025 12:11:31 PM JST: Iteration 2 DONE
Sat 09 Aug 2025 12:11:32 PM JST: Iteration 3 DONE
[snip]

A new domain will be written to the blocklist file every second, and the Blocker plugin will constantly update this file, printing logs such as this one:

[INFO] plugin/blocker: updated blocklist; blocked domains: before: 58, after: 59; last updated: before: 2025-08-09 12:12:28.480451154 +0900 JST m=+117.027332732, after: 2025-08-09 12:12:29.47975636 +0900 JST m=+118.026637938

Finally, install and run the dnsbench tool against this CoreDNS server:

# Prepare a list of domain names
$ truncate --size 0 domain-names.benchmark;foriin`seq 1 200`;doecho"baddomain-$i.example.com">> domain-names.benchmark;done;
$ dnsbench run --nameserver '127.0.0.1:5335' --names domain-names.benchmark --count=10000
# requests errors min [ p50 p95 p99 p999] max qps
1421 382 4.71 [6.23 265.95 523.76 809.50] 809.50 284.20
1550 422 4.91 [6.09 253.89 475.27 740.82] 740.82 310.00
1562 426 4.84 [6.11 254.54 476.32 738.72] 738.72 312.40
1293 353 4.93 [6.14 268.30 529.53 771.23] 771.23 258.60
1403 383 4.81 [6.09 263.98 525.34 786.96] 786.96 280.60
1539 419 4.87 [6.06 263.19 508.82 743.96] 743.96 307.80
Finished 10000 requests
# latency summary
10000 2727 4.71 [6.11 264.90 493.09 809.50] 809.50 290.18
Concurrency level: 10
Time taken for tests: 34.464370221s
Completed Requests: 7273
Failed Requests: 2727
Requests per second: -0.0000 [#/sec] (mean)
Time per request: 34.04 [ms] (mean)
Fastest request: 4.71 [ms]
Slowest request: 809.50 [ms]

About

Domain blocker plugin for CoreDNS

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - icyflame/blocker: Domain blocker plugin for CoreDNS · GitHub
Skip to content

Repository files navigation

blocker - Domain blocker plugin for CoreDNS

blocker is a CoreDNS plugin which can be used to block a list of domains provided in the AdBlock Plus syntax format. The blocklist will be loaded into memory at start-up and the file’s modified time will be checked periodically. When the blocklist file is updated, the in-memory blocklist will be updated by scanning the blocklist file line-by-line.

Updating the blocklist file itself is beyond the scope of this plugin. I recommend a bash script which downloads commonblocklists and updates them into a format without comments. The script blocklist-file-preparer.sh included with this repository is an example of how this can be done using bash and common GNU utilities.

Example blocklist file: (AdBlock Plus syntax)

||buyer.revsci.net^
||ww92.impfr.tradedoubler.com^
||next.chartboost.com^
||pl16442154.alternativecpmgate.com^
||denturesauaid.com^
||pdx-p-con-336.saas.appdynamics.com^
||cdn.ad.citynews.it^
||xxxxxxxamob.acs86.com^
||www.globalhotsale.su^
||zipuploads.com^

Usage

CoreDNS Binary

You can include blocker in the CoreDNS code just as you would include any other CoreDNS plugin.

# Clone coredns to a local location
$ git clone git@github.com:coredns/coredns.git ~/dns-server/coredns
# Clone blocker plugin to a close location
$ git clone git@github.com:icyflame/blocker.git ~/dns-server/blocker
# Symlink blocker location into coredns/plugin/blocker
$ cd~/dns-server/coredns/plugin
$ ln -s ../blocker ./blocker
# Update plugin.cfg and put the line "blocker:blocker" before the "forward:forward" line# Build CoreDNS
$ cd~/dns-server/coredns
$ go generate
$ make
$ ./coredns -conf Corefile

Corefile

The blocker directive inside Corefile requires four arguments. The first argument is the absolute path to the blocklist file. The second argument is the frequency at which the blocklist file is checked for updates. The third argument is the type of blocklist file (hosts and abp are the only two values which are supported at this time.) The fourth argument is the response type from the plugin, either empty for a valid DNS response with 0.0.0.0 or ::6 or nxdomain to respond with a DNS empty response.

The frequency is specified as a string and the value should be a valid argument of the time.ParseDuration function.

blocker /home/user/blocklist_file 1h abp empty

The following is a sample Corefile including the blocker directive. It will block domains that are specified in the blocklist and forward everything else to a full DNS server.

 .:53 {
metadata
# prometheus records metrics regarding incoming requests
prometheus
# log writes 1 line to the log for every DNS request# The last word in the log line will be YES if the request was blocked and NO if it was not# blocked.# This behaviour is supported by the metadata plugin.
log . "{common} {/blocker/request-blocked}"# blocker blocks domains which are specified in the blocklist
blocker /home/user/blocklist_file 1h abp empty
# forward handles any request that is not blocked by blocker
forward . 127.0.0.1:9053
}

plugin.cfg

This is a sample middleware configuration file. The order of plugins here is important. This is the order in which plugins will be executed for incoming requests.

metadata:metadata
prometheus:metrics
log:log
blocker:blocker
forward:forward

Interaction with Other CoreDNS Plugins

metadata

The blocker plugin will write a metadata value with the label blocker/request-blocked. This is a boolean value whose value will be either YES (if the request was blocked) or NO when the request was not blocked.

prometheus (metrics)

When the prometheusplugin is enabled, the blocker plugin will record 2 Counter metrics, representing the allowed and blocked DNS request count. These metrics can be fetched by setting up Prometheus to scrape from port 9153 on the interface where CoreDNS is running.

Metric values can be verified by making a HTTP request to the /metrics endpoint:

$ curl -s 127.0.0.1:9153/metrics | rg requests_total
# HELP coredns_blocker_allowed_requests_total Counter of DNS requests being allowed.# TYPE coredns_blocker_allowed_requests_total counter
coredns_blocker_allowed_requests_total 2
# HELP coredns_blocker_blocked_requests_total Counter of DNS requests being blocked.# TYPE coredns_blocker_blocked_requests_total counter
coredns_blocker_blocked_requests_total 3

Release Binaries

For tags which are published to this repository, the GitHub Actions workflow ./.github/workflows/build-binary.yml builds binaries using the latest Go version for Linux under the three most popular architectures: AMD64, ARM (32 bit), and ARM64. The tar.gz files contain a Checksum file which can be used together with sha256sum to verify the integrity of the binary.

$ wget https://github.com/icyflame/blocker/releases/download/v0.0.1-alpha/coredns-linux-amd64.tar.gz
...
coredns-linux-amd64.tar.gz 100%[=======================================================================>] 5.16M 610KB/s in 14s
2024-07-13 12:26:05 (390 KB/s) - ‘coredns-linux-amd64.tar.gz’ saved [5414731/5414731]
$ tar tvf coredns-linux-amd64.tar.gz
-rwxr-xr-x runner/docker 14110872 2024-07-13 12:26 coredns-linux-amd64
-rw-r--r-- runner/docker 86 2024-07-13 12:26 coredns-linux-amd64.checksum
$ tar zxf coredns-linux-amd64.tar.gz
$ sha256sum -c coredns-linux-amd64.checksum
coredns-linux-amd64: OK
$ ./coredns-linux-amd64 -version
CoreDNS-1.11.1
linux/amd64, go1.22.5, Blocker plugin refs/tags/v0.0.1-alpha 1e6061ee8b7d2ad2ee5c632d3b91851c00481453

Development

Running Tests

This plugin contains unit tests. These unit tests are run as part of the unit tests for CoreDNS. The following process should be followed to run these unit tests:

# Clone CoreDNS
$ git clone git@github.com:coredns/coredns.git /tmp/dns-server/coredns
# Clone this plugin
git clone git@github.com:icyflame/blocker.git /tmp/dns-server/blocker
# Link this plugin into CoreDNS
ln -s /tmp/dns-server/blocker /tmp/dns-server/coredns/plugin/blocker
# Run tests for this plugincd /tmp/dns-server/coredns
go test -v -count=1 ./plugin/blocker
=== RUN TestIsDomainBlocked_ABP
=== RUN TestIsDomainBlocked_ABP/base_case
[snip]
PASS
ok github.com/coredns/coredns/plugin/blocker 0.005s

During development, making changes to the blocker plugin, after the above process, makes it easier to run tests and use the Go language server features such as jumping to definition.

Testing the DNS server

Apart from unit tests, benchmarking tools can be used to verify whether CoreDNS works with a large volume of DNS requests. This is the setup that I use to run benchmarks using dnsbench.

First, follow the process in the Usage > CoreDNS Binary section to create a CoreDNS binary which contains the blocker plugin.

Second, start the CoreDNS server using the following configuration:

$ cat Corefile.benchmark.conf
.:5335 {
metadata
log . "{common} {/blocker/request-blocked}"
blocker /home/siddharth/code/open-source/coredns/blocklist.benchmark 1s abp nxdomain
forward . 8.8.8.8
}
$ touch blocklist.benchmark
$ ./coredns -conf Corefile.benchmark.conf
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[INFO] plugin/blocker: updated blocklist; blocked domains: before: 0, after: 0; last updated: before: 0001-01-01 00:00:00 +0000 UTC, after: 2025-08-09 12:10:31.479348779 +0900 JST m=+0.026230377
.:5335
CoreDNS-1.12.3
linux/amd64, go1.24.5, 463fd1c1b-dirty

Third, run the following one liner which simulates updating the block list:

$ truncate --size 0 blocklist.benchmark;foriin`seq 101 10000`;do sleep 1;echo"||baddomain-$i.example.com^">> blocklist.benchmark;echo"$(date): Iteration $i DONE";done;
Sat 09 Aug 2025 12:11:30 PM JST: Iteration 1 DONE
Sat 09 Aug 2025 12:11:31 PM JST: Iteration 2 DONE
Sat 09 Aug 2025 12:11:32 PM JST: Iteration 3 DONE
[snip]

A new domain will be written to the blocklist file every second, and the Blocker plugin will constantly update this file, printing logs such as this one:

[INFO] plugin/blocker: updated blocklist; blocked domains: before: 58, after: 59; last updated: before: 2025-08-09 12:12:28.480451154 +0900 JST m=+117.027332732, after: 2025-08-09 12:12:29.47975636 +0900 JST m=+118.026637938

Finally, install and run the dnsbench tool against this CoreDNS server:

# Prepare a list of domain names
$ truncate --size 0 domain-names.benchmark;foriin`seq 1 200`;doecho"baddomain-$i.example.com">> domain-names.benchmark;done;
$ dnsbench run --nameserver '127.0.0.1:5335' --names domain-names.benchmark --count=10000
# requests errors min [ p50 p95 p99 p999] max qps
1421 382 4.71 [6.23 265.95 523.76 809.50] 809.50 284.20
1550 422 4.91 [6.09 253.89 475.27 740.82] 740.82 310.00
1562 426 4.84 [6.11 254.54 476.32 738.72] 738.72 312.40
1293 353 4.93 [6.14 268.30 529.53 771.23] 771.23 258.60
1403 383 4.81 [6.09 263.98 525.34 786.96] 786.96 280.60
1539 419 4.87 [6.06 263.19 508.82 743.96] 743.96 307.80
Finished 10000 requests
# latency summary
10000 2727 4.71 [6.11 264.90 493.09 809.50] 809.50 290.18
Concurrency level: 10
Time taken for tests: 34.464370221s
Completed Requests: 7273
Failed Requests: 2727
Requests per second: -0.0000 [#/sec] (mean)
Time per request: 34.04 [ms] (mean)
Fastest request: 4.71 [ms]
Slowest request: 809.50 [ms]

About

Domain blocker plugin for CoreDNS

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - icyflame/blocker: Domain blocker plugin for CoreDNS · GitHub
Skip to content

Repository files navigation

blocker - Domain blocker plugin for CoreDNS

blocker is a CoreDNS plugin which can be used to block a list of domains provided in the AdBlock Plus syntax format. The blocklist will be loaded into memory at start-up and the file’s modified time will be checked periodically. When the blocklist file is updated, the in-memory blocklist will be updated by scanning the blocklist file line-by-line.

Updating the blocklist file itself is beyond the scope of this plugin. I recommend a bash script which downloads commonblocklists and updates them into a format without comments. The script blocklist-file-preparer.sh included with this repository is an example of how this can be done using bash and common GNU utilities.

Example blocklist file: (AdBlock Plus syntax)

||buyer.revsci.net^
||ww92.impfr.tradedoubler.com^
||next.chartboost.com^
||pl16442154.alternativecpmgate.com^
||denturesauaid.com^
||pdx-p-con-336.saas.appdynamics.com^
||cdn.ad.citynews.it^
||xxxxxxxamob.acs86.com^
||www.globalhotsale.su^
||zipuploads.com^

Usage

CoreDNS Binary

You can include blocker in the CoreDNS code just as you would include any other CoreDNS plugin.

# Clone coredns to a local location
$ git clone git@github.com:coredns/coredns.git ~/dns-server/coredns
# Clone blocker plugin to a close location
$ git clone git@github.com:icyflame/blocker.git ~/dns-server/blocker
# Symlink blocker location into coredns/plugin/blocker
$ cd~/dns-server/coredns/plugin
$ ln -s ../blocker ./blocker
# Update plugin.cfg and put the line "blocker:blocker" before the "forward:forward" line# Build CoreDNS
$ cd~/dns-server/coredns
$ go generate
$ make
$ ./coredns -conf Corefile

Corefile

The blocker directive inside Corefile requires four arguments. The first argument is the absolute path to the blocklist file. The second argument is the frequency at which the blocklist file is checked for updates. The third argument is the type of blocklist file (hosts and abp are the only two values which are supported at this time.) The fourth argument is the response type from the plugin, either empty for a valid DNS response with 0.0.0.0 or ::6 or nxdomain to respond with a DNS empty response.

The frequency is specified as a string and the value should be a valid argument of the time.ParseDuration function.

blocker /home/user/blocklist_file 1h abp empty

The following is a sample Corefile including the blocker directive. It will block domains that are specified in the blocklist and forward everything else to a full DNS server.

 .:53 {
metadata
# prometheus records metrics regarding incoming requests
prometheus
# log writes 1 line to the log for every DNS request# The last word in the log line will be YES if the request was blocked and NO if it was not# blocked.# This behaviour is supported by the metadata plugin.
log . "{common} {/blocker/request-blocked}"# blocker blocks domains which are specified in the blocklist
blocker /home/user/blocklist_file 1h abp empty
# forward handles any request that is not blocked by blocker
forward . 127.0.0.1:9053
}

plugin.cfg

This is a sample middleware configuration file. The order of plugins here is important. This is the order in which plugins will be executed for incoming requests.

metadata:metadata
prometheus:metrics
log:log
blocker:blocker
forward:forward

Interaction with Other CoreDNS Plugins

metadata

The blocker plugin will write a metadata value with the label blocker/request-blocked. This is a boolean value whose value will be either YES (if the request was blocked) or NO when the request was not blocked.

prometheus (metrics)

When the prometheusplugin is enabled, the blocker plugin will record 2 Counter metrics, representing the allowed and blocked DNS request count. These metrics can be fetched by setting up Prometheus to scrape from port 9153 on the interface where CoreDNS is running.

Metric values can be verified by making a HTTP request to the /metrics endpoint:

$ curl -s 127.0.0.1:9153/metrics | rg requests_total
# HELP coredns_blocker_allowed_requests_total Counter of DNS requests being allowed.# TYPE coredns_blocker_allowed_requests_total counter
coredns_blocker_allowed_requests_total 2
# HELP coredns_blocker_blocked_requests_total Counter of DNS requests being blocked.# TYPE coredns_blocker_blocked_requests_total counter
coredns_blocker_blocked_requests_total 3

Release Binaries

For tags which are published to this repository, the GitHub Actions workflow ./.github/workflows/build-binary.yml builds binaries using the latest Go version for Linux under the three most popular architectures: AMD64, ARM (32 bit), and ARM64. The tar.gz files contain a Checksum file which can be used together with sha256sum to verify the integrity of the binary.

$ wget https://github.com/icyflame/blocker/releases/download/v0.0.1-alpha/coredns-linux-amd64.tar.gz
...
coredns-linux-amd64.tar.gz 100%[=======================================================================>] 5.16M 610KB/s in 14s
2024-07-13 12:26:05 (390 KB/s) - ‘coredns-linux-amd64.tar.gz’ saved [5414731/5414731]
$ tar tvf coredns-linux-amd64.tar.gz
-rwxr-xr-x runner/docker 14110872 2024-07-13 12:26 coredns-linux-amd64
-rw-r--r-- runner/docker 86 2024-07-13 12:26 coredns-linux-amd64.checksum
$ tar zxf coredns-linux-amd64.tar.gz
$ sha256sum -c coredns-linux-amd64.checksum
coredns-linux-amd64: OK
$ ./coredns-linux-amd64 -version
CoreDNS-1.11.1
linux/amd64, go1.22.5, Blocker plugin refs/tags/v0.0.1-alpha 1e6061ee8b7d2ad2ee5c632d3b91851c00481453

Development

Running Tests

This plugin contains unit tests. These unit tests are run as part of the unit tests for CoreDNS. The following process should be followed to run these unit tests:

# Clone CoreDNS
$ git clone git@github.com:coredns/coredns.git /tmp/dns-server/coredns
# Clone this plugin
git clone git@github.com:icyflame/blocker.git /tmp/dns-server/blocker
# Link this plugin into CoreDNS
ln -s /tmp/dns-server/blocker /tmp/dns-server/coredns/plugin/blocker
# Run tests for this plugincd /tmp/dns-server/coredns
go test -v -count=1 ./plugin/blocker
=== RUN TestIsDomainBlocked_ABP
=== RUN TestIsDomainBlocked_ABP/base_case
[snip]
PASS
ok github.com/coredns/coredns/plugin/blocker 0.005s

During development, making changes to the blocker plugin, after the above process, makes it easier to run tests and use the Go language server features such as jumping to definition.

Testing the DNS server

Apart from unit tests, benchmarking tools can be used to verify whether CoreDNS works with a large volume of DNS requests. This is the setup that I use to run benchmarks using dnsbench.

First, follow the process in the Usage > CoreDNS Binary section to create a CoreDNS binary which contains the blocker plugin.

Second, start the CoreDNS server using the following configuration:

$ cat Corefile.benchmark.conf
.:5335 {
metadata
log . "{common} {/blocker/request-blocked}"
blocker /home/siddharth/code/open-source/coredns/blocklist.benchmark 1s abp nxdomain
forward . 8.8.8.8
}
$ touch blocklist.benchmark
$ ./coredns -conf Corefile.benchmark.conf
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[INFO] plugin/blocker: updated blocklist; blocked domains: before: 0, after: 0; last updated: before: 0001-01-01 00:00:00 +0000 UTC, after: 2025-08-09 12:10:31.479348779 +0900 JST m=+0.026230377
.:5335
CoreDNS-1.12.3
linux/amd64, go1.24.5, 463fd1c1b-dirty

Third, run the following one liner which simulates updating the block list:

$ truncate --size 0 blocklist.benchmark;foriin`seq 101 10000`;do sleep 1;echo"||baddomain-$i.example.com^">> blocklist.benchmark;echo"$(date): Iteration $i DONE";done;
Sat 09 Aug 2025 12:11:30 PM JST: Iteration 1 DONE
Sat 09 Aug 2025 12:11:31 PM JST: Iteration 2 DONE
Sat 09 Aug 2025 12:11:32 PM JST: Iteration 3 DONE
[snip]

A new domain will be written to the blocklist file every second, and the Blocker plugin will constantly update this file, printing logs such as this one:

[INFO] plugin/blocker: updated blocklist; blocked domains: before: 58, after: 59; last updated: before: 2025-08-09 12:12:28.480451154 +0900 JST m=+117.027332732, after: 2025-08-09 12:12:29.47975636 +0900 JST m=+118.026637938

Finally, install and run the dnsbench tool against this CoreDNS server:

# Prepare a list of domain names
$ truncate --size 0 domain-names.benchmark;foriin`seq 1 200`;doecho"baddomain-$i.example.com">> domain-names.benchmark;done;
$ dnsbench run --nameserver '127.0.0.1:5335' --names domain-names.benchmark --count=10000
# requests errors min [ p50 p95 p99 p999] max qps
1421 382 4.71 [6.23 265.95 523.76 809.50] 809.50 284.20
1550 422 4.91 [6.09 253.89 475.27 740.82] 740.82 310.00
1562 426 4.84 [6.11 254.54 476.32 738.72] 738.72 312.40
1293 353 4.93 [6.14 268.30 529.53 771.23] 771.23 258.60
1403 383 4.81 [6.09 263.98 525.34 786.96] 786.96 280.60
1539 419 4.87 [6.06 263.19 508.82 743.96] 743.96 307.80
Finished 10000 requests
# latency summary
10000 2727 4.71 [6.11 264.90 493.09 809.50] 809.50 290.18
Concurrency level: 10
Time taken for tests: 34.464370221s
Completed Requests: 7273
Failed Requests: 2727
Requests per second: -0.0000 [#/sec] (mean)
Time per request: 34.04 [ms] (mean)
Fastest request: 4.71 [ms]
Slowest request: 809.50 [ms]

About

Domain blocker plugin for CoreDNS

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - icyflame/blocker: Domain blocker plugin for CoreDNS · GitHub
Skip to content

Repository files navigation

blocker - Domain blocker plugin for CoreDNS

blocker is a CoreDNS plugin which can be used to block a list of domains provided in the AdBlock Plus syntax format. The blocklist will be loaded into memory at start-up and the file’s modified time will be checked periodically. When the blocklist file is updated, the in-memory blocklist will be updated by scanning the blocklist file line-by-line.

Updating the blocklist file itself is beyond the scope of this plugin. I recommend a bash script which downloads commonblocklists and updates them into a format without comments. The script blocklist-file-preparer.sh included with this repository is an example of how this can be done using bash and common GNU utilities.

Example blocklist file: (AdBlock Plus syntax)

||buyer.revsci.net^
||ww92.impfr.tradedoubler.com^
||next.chartboost.com^
||pl16442154.alternativecpmgate.com^
||denturesauaid.com^
||pdx-p-con-336.saas.appdynamics.com^
||cdn.ad.citynews.it^
||xxxxxxxamob.acs86.com^
||www.globalhotsale.su^
||zipuploads.com^

Usage

CoreDNS Binary

You can include blocker in the CoreDNS code just as you would include any other CoreDNS plugin.

# Clone coredns to a local location
$ git clone git@github.com:coredns/coredns.git ~/dns-server/coredns
# Clone blocker plugin to a close location
$ git clone git@github.com:icyflame/blocker.git ~/dns-server/blocker
# Symlink blocker location into coredns/plugin/blocker
$ cd~/dns-server/coredns/plugin
$ ln -s ../blocker ./blocker
# Update plugin.cfg and put the line "blocker:blocker" before the "forward:forward" line# Build CoreDNS
$ cd~/dns-server/coredns
$ go generate
$ make
$ ./coredns -conf Corefile

Corefile

The blocker directive inside Corefile requires four arguments. The first argument is the absolute path to the blocklist file. The second argument is the frequency at which the blocklist file is checked for updates. The third argument is the type of blocklist file (hosts and abp are the only two values which are supported at this time.) The fourth argument is the response type from the plugin, either empty for a valid DNS response with 0.0.0.0 or ::6 or nxdomain to respond with a DNS empty response.

The frequency is specified as a string and the value should be a valid argument of the time.ParseDuration function.

blocker /home/user/blocklist_file 1h abp empty

The following is a sample Corefile including the blocker directive. It will block domains that are specified in the blocklist and forward everything else to a full DNS server.

 .:53 {
metadata
# prometheus records metrics regarding incoming requests
prometheus
# log writes 1 line to the log for every DNS request# The last word in the log line will be YES if the request was blocked and NO if it was not# blocked.# This behaviour is supported by the metadata plugin.
log . "{common} {/blocker/request-blocked}"# blocker blocks domains which are specified in the blocklist
blocker /home/user/blocklist_file 1h abp empty
# forward handles any request that is not blocked by blocker
forward . 127.0.0.1:9053
}

plugin.cfg

This is a sample middleware configuration file. The order of plugins here is important. This is the order in which plugins will be executed for incoming requests.

metadata:metadata
prometheus:metrics
log:log
blocker:blocker
forward:forward

Interaction with Other CoreDNS Plugins

metadata

The blocker plugin will write a metadata value with the label blocker/request-blocked. This is a boolean value whose value will be either YES (if the request was blocked) or NO when the request was not blocked.

prometheus (metrics)

When the prometheusplugin is enabled, the blocker plugin will record 2 Counter metrics, representing the allowed and blocked DNS request count. These metrics can be fetched by setting up Prometheus to scrape from port 9153 on the interface where CoreDNS is running.

Metric values can be verified by making a HTTP request to the /metrics endpoint:

$ curl -s 127.0.0.1:9153/metrics | rg requests_total
# HELP coredns_blocker_allowed_requests_total Counter of DNS requests being allowed.# TYPE coredns_blocker_allowed_requests_total counter
coredns_blocker_allowed_requests_total 2
# HELP coredns_blocker_blocked_requests_total Counter of DNS requests being blocked.# TYPE coredns_blocker_blocked_requests_total counter
coredns_blocker_blocked_requests_total 3

Release Binaries

For tags which are published to this repository, the GitHub Actions workflow ./.github/workflows/build-binary.yml builds binaries using the latest Go version for Linux under the three most popular architectures: AMD64, ARM (32 bit), and ARM64. The tar.gz files contain a Checksum file which can be used together with sha256sum to verify the integrity of the binary.

$ wget https://github.com/icyflame/blocker/releases/download/v0.0.1-alpha/coredns-linux-amd64.tar.gz
...
coredns-linux-amd64.tar.gz 100%[=======================================================================>] 5.16M 610KB/s in 14s
2024-07-13 12:26:05 (390 KB/s) - ‘coredns-linux-amd64.tar.gz’ saved [5414731/5414731]
$ tar tvf coredns-linux-amd64.tar.gz
-rwxr-xr-x runner/docker 14110872 2024-07-13 12:26 coredns-linux-amd64
-rw-r--r-- runner/docker 86 2024-07-13 12:26 coredns-linux-amd64.checksum
$ tar zxf coredns-linux-amd64.tar.gz
$ sha256sum -c coredns-linux-amd64.checksum
coredns-linux-amd64: OK
$ ./coredns-linux-amd64 -version
CoreDNS-1.11.1
linux/amd64, go1.22.5, Blocker plugin refs/tags/v0.0.1-alpha 1e6061ee8b7d2ad2ee5c632d3b91851c00481453

Development

Running Tests

This plugin contains unit tests. These unit tests are run as part of the unit tests for CoreDNS. The following process should be followed to run these unit tests:

# Clone CoreDNS
$ git clone git@github.com:coredns/coredns.git /tmp/dns-server/coredns
# Clone this plugin
git clone git@github.com:icyflame/blocker.git /tmp/dns-server/blocker
# Link this plugin into CoreDNS
ln -s /tmp/dns-server/blocker /tmp/dns-server/coredns/plugin/blocker
# Run tests for this plugincd /tmp/dns-server/coredns
go test -v -count=1 ./plugin/blocker
=== RUN TestIsDomainBlocked_ABP
=== RUN TestIsDomainBlocked_ABP/base_case
[snip]
PASS
ok github.com/coredns/coredns/plugin/blocker 0.005s

During development, making changes to the blocker plugin, after the above process, makes it easier to run tests and use the Go language server features such as jumping to definition.

Testing the DNS server

Apart from unit tests, benchmarking tools can be used to verify whether CoreDNS works with a large volume of DNS requests. This is the setup that I use to run benchmarks using dnsbench.

First, follow the process in the Usage > CoreDNS Binary section to create a CoreDNS binary which contains the blocker plugin.

Second, start the CoreDNS server using the following configuration:

$ cat Corefile.benchmark.conf
.:5335 {
metadata
log . "{common} {/blocker/request-blocked}"
blocker /home/siddharth/code/open-source/coredns/blocklist.benchmark 1s abp nxdomain
forward . 8.8.8.8
}
$ touch blocklist.benchmark
$ ./coredns -conf Corefile.benchmark.conf
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[INFO] plugin/blocker: updated blocklist; blocked domains: before: 0, after: 0; last updated: before: 0001-01-01 00:00:00 +0000 UTC, after: 2025-08-09 12:10:31.479348779 +0900 JST m=+0.026230377
.:5335
CoreDNS-1.12.3
linux/amd64, go1.24.5, 463fd1c1b-dirty

Third, run the following one liner which simulates updating the block list:

$ truncate --size 0 blocklist.benchmark;foriin`seq 101 10000`;do sleep 1;echo"||baddomain-$i.example.com^">> blocklist.benchmark;echo"$(date): Iteration $i DONE";done;
Sat 09 Aug 2025 12:11:30 PM JST: Iteration 1 DONE
Sat 09 Aug 2025 12:11:31 PM JST: Iteration 2 DONE
Sat 09 Aug 2025 12:11:32 PM JST: Iteration 3 DONE
[snip]

A new domain will be written to the blocklist file every second, and the Blocker plugin will constantly update this file, printing logs such as this one:

[INFO] plugin/blocker: updated blocklist; blocked domains: before: 58, after: 59; last updated: before: 2025-08-09 12:12:28.480451154 +0900 JST m=+117.027332732, after: 2025-08-09 12:12:29.47975636 +0900 JST m=+118.026637938

Finally, install and run the dnsbench tool against this CoreDNS server:

# Prepare a list of domain names
$ truncate --size 0 domain-names.benchmark;foriin`seq 1 200`;doecho"baddomain-$i.example.com">> domain-names.benchmark;done;
$ dnsbench run --nameserver '127.0.0.1:5335' --names domain-names.benchmark --count=10000
# requests errors min [ p50 p95 p99 p999] max qps
1421 382 4.71 [6.23 265.95 523.76 809.50] 809.50 284.20
1550 422 4.91 [6.09 253.89 475.27 740.82] 740.82 310.00
1562 426 4.84 [6.11 254.54 476.32 738.72] 738.72 312.40
1293 353 4.93 [6.14 268.30 529.53 771.23] 771.23 258.60
1403 383 4.81 [6.09 263.98 525.34 786.96] 786.96 280.60
1539 419 4.87 [6.06 263.19 508.82 743.96] 743.96 307.80
Finished 10000 requests
# latency summary
10000 2727 4.71 [6.11 264.90 493.09 809.50] 809.50 290.18
Concurrency level: 10
Time taken for tests: 34.464370221s
Completed Requests: 7273
Failed Requests: 2727
Requests per second: -0.0000 [#/sec] (mean)
Time per request: 34.04 [ms] (mean)
Fastest request: 4.71 [ms]
Slowest request: 809.50 [ms]

About

Domain blocker plugin for CoreDNS

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - icyflame/blocker: Domain blocker plugin for CoreDNS · GitHub
Skip to content

Repository files navigation

blocker - Domain blocker plugin for CoreDNS

blocker is a CoreDNS plugin which can be used to block a list of domains provided in the AdBlock Plus syntax format. The blocklist will be loaded into memory at start-up and the file’s modified time will be checked periodically. When the blocklist file is updated, the in-memory blocklist will be updated by scanning the blocklist file line-by-line.

Updating the blocklist file itself is beyond the scope of this plugin. I recommend a bash script which downloads commonblocklists and updates them into a format without comments. The script blocklist-file-preparer.sh included with this repository is an example of how this can be done using bash and common GNU utilities.

Example blocklist file: (AdBlock Plus syntax)

||buyer.revsci.net^
||ww92.impfr.tradedoubler.com^
||next.chartboost.com^
||pl16442154.alternativecpmgate.com^
||denturesauaid.com^
||pdx-p-con-336.saas.appdynamics.com^
||cdn.ad.citynews.it^
||xxxxxxxamob.acs86.com^
||www.globalhotsale.su^
||zipuploads.com^

Usage

CoreDNS Binary

You can include blocker in the CoreDNS code just as you would include any other CoreDNS plugin.

# Clone coredns to a local location
$ git clone git@github.com:coredns/coredns.git ~/dns-server/coredns
# Clone blocker plugin to a close location
$ git clone git@github.com:icyflame/blocker.git ~/dns-server/blocker
# Symlink blocker location into coredns/plugin/blocker
$ cd~/dns-server/coredns/plugin
$ ln -s ../blocker ./blocker
# Update plugin.cfg and put the line "blocker:blocker" before the "forward:forward" line# Build CoreDNS
$ cd~/dns-server/coredns
$ go generate
$ make
$ ./coredns -conf Corefile

Corefile

The blocker directive inside Corefile requires four arguments. The first argument is the absolute path to the blocklist file. The second argument is the frequency at which the blocklist file is checked for updates. The third argument is the type of blocklist file (hosts and abp are the only two values which are supported at this time.) The fourth argument is the response type from the plugin, either empty for a valid DNS response with 0.0.0.0 or ::6 or nxdomain to respond with a DNS empty response.

The frequency is specified as a string and the value should be a valid argument of the time.ParseDuration function.

blocker /home/user/blocklist_file 1h abp empty

The following is a sample Corefile including the blocker directive. It will block domains that are specified in the blocklist and forward everything else to a full DNS server.

 .:53 {
metadata
# prometheus records metrics regarding incoming requests
prometheus
# log writes 1 line to the log for every DNS request# The last word in the log line will be YES if the request was blocked and NO if it was not# blocked.# This behaviour is supported by the metadata plugin.
log . "{common} {/blocker/request-blocked}"# blocker blocks domains which are specified in the blocklist
blocker /home/user/blocklist_file 1h abp empty
# forward handles any request that is not blocked by blocker
forward . 127.0.0.1:9053
}

plugin.cfg

This is a sample middleware configuration file. The order of plugins here is important. This is the order in which plugins will be executed for incoming requests.

metadata:metadata
prometheus:metrics
log:log
blocker:blocker
forward:forward

Interaction with Other CoreDNS Plugins

metadata

The blocker plugin will write a metadata value with the label blocker/request-blocked. This is a boolean value whose value will be either YES (if the request was blocked) or NO when the request was not blocked.

prometheus (metrics)

When the prometheusplugin is enabled, the blocker plugin will record 2 Counter metrics, representing the allowed and blocked DNS request count. These metrics can be fetched by setting up Prometheus to scrape from port 9153 on the interface where CoreDNS is running.

Metric values can be verified by making a HTTP request to the /metrics endpoint:

$ curl -s 127.0.0.1:9153/metrics | rg requests_total
# HELP coredns_blocker_allowed_requests_total Counter of DNS requests being allowed.# TYPE coredns_blocker_allowed_requests_total counter
coredns_blocker_allowed_requests_total 2
# HELP coredns_blocker_blocked_requests_total Counter of DNS requests being blocked.# TYPE coredns_blocker_blocked_requests_total counter
coredns_blocker_blocked_requests_total 3

Release Binaries

For tags which are published to this repository, the GitHub Actions workflow ./.github/workflows/build-binary.yml builds binaries using the latest Go version for Linux under the three most popular architectures: AMD64, ARM (32 bit), and ARM64. The tar.gz files contain a Checksum file which can be used together with sha256sum to verify the integrity of the binary.

$ wget https://github.com/icyflame/blocker/releases/download/v0.0.1-alpha/coredns-linux-amd64.tar.gz
...
coredns-linux-amd64.tar.gz 100%[=======================================================================>] 5.16M 610KB/s in 14s
2024-07-13 12:26:05 (390 KB/s) - ‘coredns-linux-amd64.tar.gz’ saved [5414731/5414731]
$ tar tvf coredns-linux-amd64.tar.gz
-rwxr-xr-x runner/docker 14110872 2024-07-13 12:26 coredns-linux-amd64
-rw-r--r-- runner/docker 86 2024-07-13 12:26 coredns-linux-amd64.checksum
$ tar zxf coredns-linux-amd64.tar.gz
$ sha256sum -c coredns-linux-amd64.checksum
coredns-linux-amd64: OK
$ ./coredns-linux-amd64 -version
CoreDNS-1.11.1
linux/amd64, go1.22.5, Blocker plugin refs/tags/v0.0.1-alpha 1e6061ee8b7d2ad2ee5c632d3b91851c00481453

Development

Running Tests

This plugin contains unit tests. These unit tests are run as part of the unit tests for CoreDNS. The following process should be followed to run these unit tests:

# Clone CoreDNS
$ git clone git@github.com:coredns/coredns.git /tmp/dns-server/coredns
# Clone this plugin
git clone git@github.com:icyflame/blocker.git /tmp/dns-server/blocker
# Link this plugin into CoreDNS
ln -s /tmp/dns-server/blocker /tmp/dns-server/coredns/plugin/blocker
# Run tests for this plugincd /tmp/dns-server/coredns
go test -v -count=1 ./plugin/blocker
=== RUN TestIsDomainBlocked_ABP
=== RUN TestIsDomainBlocked_ABP/base_case
[snip]
PASS
ok github.com/coredns/coredns/plugin/blocker 0.005s

During development, making changes to the blocker plugin, after the above process, makes it easier to run tests and use the Go language server features such as jumping to definition.

Testing the DNS server

Apart from unit tests, benchmarking tools can be used to verify whether CoreDNS works with a large volume of DNS requests. This is the setup that I use to run benchmarks using dnsbench.

First, follow the process in the Usage > CoreDNS Binary section to create a CoreDNS binary which contains the blocker plugin.

Second, start the CoreDNS server using the following configuration:

$ cat Corefile.benchmark.conf
.:5335 {
metadata
log . "{common} {/blocker/request-blocked}"
blocker /home/siddharth/code/open-source/coredns/blocklist.benchmark 1s abp nxdomain
forward . 8.8.8.8
}
$ touch blocklist.benchmark
$ ./coredns -conf Corefile.benchmark.conf
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[INFO] plugin/blocker: updated blocklist; blocked domains: before: 0, after: 0; last updated: before: 0001-01-01 00:00:00 +0000 UTC, after: 2025-08-09 12:10:31.479348779 +0900 JST m=+0.026230377
.:5335
CoreDNS-1.12.3
linux/amd64, go1.24.5, 463fd1c1b-dirty

Third, run the following one liner which simulates updating the block list:

$ truncate --size 0 blocklist.benchmark;foriin`seq 101 10000`;do sleep 1;echo"||baddomain-$i.example.com^">> blocklist.benchmark;echo"$(date): Iteration $i DONE";done;
Sat 09 Aug 2025 12:11:30 PM JST: Iteration 1 DONE
Sat 09 Aug 2025 12:11:31 PM JST: Iteration 2 DONE
Sat 09 Aug 2025 12:11:32 PM JST: Iteration 3 DONE
[snip]

A new domain will be written to the blocklist file every second, and the Blocker plugin will constantly update this file, printing logs such as this one:

[INFO] plugin/blocker: updated blocklist; blocked domains: before: 58, after: 59; last updated: before: 2025-08-09 12:12:28.480451154 +0900 JST m=+117.027332732, after: 2025-08-09 12:12:29.47975636 +0900 JST m=+118.026637938

Finally, install and run the dnsbench tool against this CoreDNS server:

# Prepare a list of domain names
$ truncate --size 0 domain-names.benchmark;foriin`seq 1 200`;doecho"baddomain-$i.example.com">> domain-names.benchmark;done;
$ dnsbench run --nameserver '127.0.0.1:5335' --names domain-names.benchmark --count=10000
# requests errors min [ p50 p95 p99 p999] max qps
1421 382 4.71 [6.23 265.95 523.76 809.50] 809.50 284.20
1550 422 4.91 [6.09 253.89 475.27 740.82] 740.82 310.00
1562 426 4.84 [6.11 254.54 476.32 738.72] 738.72 312.40
1293 353 4.93 [6.14 268.30 529.53 771.23] 771.23 258.60
1403 383 4.81 [6.09 263.98 525.34 786.96] 786.96 280.60
1539 419 4.87 [6.06 263.19 508.82 743.96] 743.96 307.80
Finished 10000 requests
# latency summary
10000 2727 4.71 [6.11 264.90 493.09 809.50] 809.50 290.18
Concurrency level: 10
Time taken for tests: 34.464370221s
Completed Requests: 7273
Failed Requests: 2727
Requests per second: -0.0000 [#/sec] (mean)
Time per request: 34.04 [ms] (mean)
Fastest request: 4.71 [ms]
Slowest request: 809.50 [ms]

About

Domain blocker plugin for CoreDNS

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - icyflame/blocker: Domain blocker plugin for CoreDNS · GitHub
Skip to content

Repository files navigation

blocker - Domain blocker plugin for CoreDNS

blocker is a CoreDNS plugin which can be used to block a list of domains provided in the AdBlock Plus syntax format. The blocklist will be loaded into memory at start-up and the file’s modified time will be checked periodically. When the blocklist file is updated, the in-memory blocklist will be updated by scanning the blocklist file line-by-line.

Updating the blocklist file itself is beyond the scope of this plugin. I recommend a bash script which downloads commonblocklists and updates them into a format without comments. The script blocklist-file-preparer.sh included with this repository is an example of how this can be done using bash and common GNU utilities.

Example blocklist file: (AdBlock Plus syntax)

||buyer.revsci.net^
||ww92.impfr.tradedoubler.com^
||next.chartboost.com^
||pl16442154.alternativecpmgate.com^
||denturesauaid.com^
||pdx-p-con-336.saas.appdynamics.com^
||cdn.ad.citynews.it^
||xxxxxxxamob.acs86.com^
||www.globalhotsale.su^
||zipuploads.com^

Usage

CoreDNS Binary

You can include blocker in the CoreDNS code just as you would include any other CoreDNS plugin.

# Clone coredns to a local location
$ git clone git@github.com:coredns/coredns.git ~/dns-server/coredns
# Clone blocker plugin to a close location
$ git clone git@github.com:icyflame/blocker.git ~/dns-server/blocker
# Symlink blocker location into coredns/plugin/blocker
$ cd~/dns-server/coredns/plugin
$ ln -s ../blocker ./blocker
# Update plugin.cfg and put the line "blocker:blocker" before the "forward:forward" line# Build CoreDNS
$ cd~/dns-server/coredns
$ go generate
$ make
$ ./coredns -conf Corefile

Corefile

The blocker directive inside Corefile requires four arguments. The first argument is the absolute path to the blocklist file. The second argument is the frequency at which the blocklist file is checked for updates. The third argument is the type of blocklist file (hosts and abp are the only two values which are supported at this time.) The fourth argument is the response type from the plugin, either empty for a valid DNS response with 0.0.0.0 or ::6 or nxdomain to respond with a DNS empty response.

The frequency is specified as a string and the value should be a valid argument of the time.ParseDuration function.

blocker /home/user/blocklist_file 1h abp empty

The following is a sample Corefile including the blocker directive. It will block domains that are specified in the blocklist and forward everything else to a full DNS server.

 .:53 {
metadata
# prometheus records metrics regarding incoming requests
prometheus
# log writes 1 line to the log for every DNS request# The last word in the log line will be YES if the request was blocked and NO if it was not# blocked.# This behaviour is supported by the metadata plugin.
log . "{common} {/blocker/request-blocked}"# blocker blocks domains which are specified in the blocklist
blocker /home/user/blocklist_file 1h abp empty
# forward handles any request that is not blocked by blocker
forward . 127.0.0.1:9053
}

plugin.cfg

This is a sample middleware configuration file. The order of plugins here is important. This is the order in which plugins will be executed for incoming requests.

metadata:metadata
prometheus:metrics
log:log
blocker:blocker
forward:forward

Interaction with Other CoreDNS Plugins

metadata

The blocker plugin will write a metadata value with the label blocker/request-blocked. This is a boolean value whose value will be either YES (if the request was blocked) or NO when the request was not blocked.

prometheus (metrics)

When the prometheusplugin is enabled, the blocker plugin will record 2 Counter metrics, representing the allowed and blocked DNS request count. These metrics can be fetched by setting up Prometheus to scrape from port 9153 on the interface where CoreDNS is running.

Metric values can be verified by making a HTTP request to the /metrics endpoint:

$ curl -s 127.0.0.1:9153/metrics | rg requests_total
# HELP coredns_blocker_allowed_requests_total Counter of DNS requests being allowed.# TYPE coredns_blocker_allowed_requests_total counter
coredns_blocker_allowed_requests_total 2
# HELP coredns_blocker_blocked_requests_total Counter of DNS requests being blocked.# TYPE coredns_blocker_blocked_requests_total counter
coredns_blocker_blocked_requests_total 3

Release Binaries

For tags which are published to this repository, the GitHub Actions workflow ./.github/workflows/build-binary.yml builds binaries using the latest Go version for Linux under the three most popular architectures: AMD64, ARM (32 bit), and ARM64. The tar.gz files contain a Checksum file which can be used together with sha256sum to verify the integrity of the binary.

$ wget https://github.com/icyflame/blocker/releases/download/v0.0.1-alpha/coredns-linux-amd64.tar.gz
...
coredns-linux-amd64.tar.gz 100%[=======================================================================>] 5.16M 610KB/s in 14s
2024-07-13 12:26:05 (390 KB/s) - ‘coredns-linux-amd64.tar.gz’ saved [5414731/5414731]
$ tar tvf coredns-linux-amd64.tar.gz
-rwxr-xr-x runner/docker 14110872 2024-07-13 12:26 coredns-linux-amd64
-rw-r--r-- runner/docker 86 2024-07-13 12:26 coredns-linux-amd64.checksum
$ tar zxf coredns-linux-amd64.tar.gz
$ sha256sum -c coredns-linux-amd64.checksum
coredns-linux-amd64: OK
$ ./coredns-linux-amd64 -version
CoreDNS-1.11.1
linux/amd64, go1.22.5, Blocker plugin refs/tags/v0.0.1-alpha 1e6061ee8b7d2ad2ee5c632d3b91851c00481453

Development

Running Tests

This plugin contains unit tests. These unit tests are run as part of the unit tests for CoreDNS. The following process should be followed to run these unit tests:

# Clone CoreDNS
$ git clone git@github.com:coredns/coredns.git /tmp/dns-server/coredns
# Clone this plugin
git clone git@github.com:icyflame/blocker.git /tmp/dns-server/blocker
# Link this plugin into CoreDNS
ln -s /tmp/dns-server/blocker /tmp/dns-server/coredns/plugin/blocker
# Run tests for this plugincd /tmp/dns-server/coredns
go test -v -count=1 ./plugin/blocker
=== RUN TestIsDomainBlocked_ABP
=== RUN TestIsDomainBlocked_ABP/base_case
[snip]
PASS
ok github.com/coredns/coredns/plugin/blocker 0.005s

During development, making changes to the blocker plugin, after the above process, makes it easier to run tests and use the Go language server features such as jumping to definition.

Testing the DNS server

Apart from unit tests, benchmarking tools can be used to verify whether CoreDNS works with a large volume of DNS requests. This is the setup that I use to run benchmarks using dnsbench.

First, follow the process in the Usage > CoreDNS Binary section to create a CoreDNS binary which contains the blocker plugin.

Second, start the CoreDNS server using the following configuration:

$ cat Corefile.benchmark.conf
.:5335 {
metadata
log . "{common} {/blocker/request-blocked}"
blocker /home/siddharth/code/open-source/coredns/blocklist.benchmark 1s abp nxdomain
forward . 8.8.8.8
}
$ touch blocklist.benchmark
$ ./coredns -conf Corefile.benchmark.conf
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[INFO] plugin/blocker: updated blocklist; blocked domains: before: 0, after: 0; last updated: before: 0001-01-01 00:00:00 +0000 UTC, after: 2025-08-09 12:10:31.479348779 +0900 JST m=+0.026230377
.:5335
CoreDNS-1.12.3
linux/amd64, go1.24.5, 463fd1c1b-dirty

Third, run the following one liner which simulates updating the block list:

$ truncate --size 0 blocklist.benchmark;foriin`seq 101 10000`;do sleep 1;echo"||baddomain-$i.example.com^">> blocklist.benchmark;echo"$(date): Iteration $i DONE";done;
Sat 09 Aug 2025 12:11:30 PM JST: Iteration 1 DONE
Sat 09 Aug 2025 12:11:31 PM JST: Iteration 2 DONE
Sat 09 Aug 2025 12:11:32 PM JST: Iteration 3 DONE
[snip]

A new domain will be written to the blocklist file every second, and the Blocker plugin will constantly update this file, printing logs such as this one:

[INFO] plugin/blocker: updated blocklist; blocked domains: before: 58, after: 59; last updated: before: 2025-08-09 12:12:28.480451154 +0900 JST m=+117.027332732, after: 2025-08-09 12:12:29.47975636 +0900 JST m=+118.026637938

Finally, install and run the dnsbench tool against this CoreDNS server:

# Prepare a list of domain names
$ truncate --size 0 domain-names.benchmark;foriin`seq 1 200`;doecho"baddomain-$i.example.com">> domain-names.benchmark;done;
$ dnsbench run --nameserver '127.0.0.1:5335' --names domain-names.benchmark --count=10000
# requests errors min [ p50 p95 p99 p999] max qps
1421 382 4.71 [6.23 265.95 523.76 809.50] 809.50 284.20
1550 422 4.91 [6.09 253.89 475.27 740.82] 740.82 310.00
1562 426 4.84 [6.11 254.54 476.32 738.72] 738.72 312.40
1293 353 4.93 [6.14 268.30 529.53 771.23] 771.23 258.60
1403 383 4.81 [6.09 263.98 525.34 786.96] 786.96 280.60
1539 419 4.87 [6.06 263.19 508.82 743.96] 743.96 307.80
Finished 10000 requests
# latency summary
10000 2727 4.71 [6.11 264.90 493.09 809.50] 809.50 290.18
Concurrency level: 10
Time taken for tests: 34.464370221s
Completed Requests: 7273
Failed Requests: 2727
Requests per second: -0.0000 [#/sec] (mean)
Time per request: 34.04 [ms] (mean)
Fastest request: 4.71 [ms]
Slowest request: 809.50 [ms]

About

Domain blocker plugin for CoreDNS

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - icyflame/blocker: Domain blocker plugin for CoreDNS · GitHub
Skip to content

Repository files navigation

blocker - Domain blocker plugin for CoreDNS

blocker is a CoreDNS plugin which can be used to block a list of domains provided in the AdBlock Plus syntax format. The blocklist will be loaded into memory at start-up and the file’s modified time will be checked periodically. When the blocklist file is updated, the in-memory blocklist will be updated by scanning the blocklist file line-by-line.

Updating the blocklist file itself is beyond the scope of this plugin. I recommend a bash script which downloads commonblocklists and updates them into a format without comments. The script blocklist-file-preparer.sh included with this repository is an example of how this can be done using bash and common GNU utilities.

Example blocklist file: (AdBlock Plus syntax)

||buyer.revsci.net^
||ww92.impfr.tradedoubler.com^
||next.chartboost.com^
||pl16442154.alternativecpmgate.com^
||denturesauaid.com^
||pdx-p-con-336.saas.appdynamics.com^
||cdn.ad.citynews.it^
||xxxxxxxamob.acs86.com^
||www.globalhotsale.su^
||zipuploads.com^

Usage

CoreDNS Binary

You can include blocker in the CoreDNS code just as you would include any other CoreDNS plugin.

# Clone coredns to a local location
$ git clone git@github.com:coredns/coredns.git ~/dns-server/coredns
# Clone blocker plugin to a close location
$ git clone git@github.com:icyflame/blocker.git ~/dns-server/blocker
# Symlink blocker location into coredns/plugin/blocker
$ cd~/dns-server/coredns/plugin
$ ln -s ../blocker ./blocker
# Update plugin.cfg and put the line "blocker:blocker" before the "forward:forward" line# Build CoreDNS
$ cd~/dns-server/coredns
$ go generate
$ make
$ ./coredns -conf Corefile

Corefile

The blocker directive inside Corefile requires four arguments. The first argument is the absolute path to the blocklist file. The second argument is the frequency at which the blocklist file is checked for updates. The third argument is the type of blocklist file (hosts and abp are the only two values which are supported at this time.) The fourth argument is the response type from the plugin, either empty for a valid DNS response with 0.0.0.0 or ::6 or nxdomain to respond with a DNS empty response.

The frequency is specified as a string and the value should be a valid argument of the time.ParseDuration function.

blocker /home/user/blocklist_file 1h abp empty

The following is a sample Corefile including the blocker directive. It will block domains that are specified in the blocklist and forward everything else to a full DNS server.

 .:53 {
metadata
# prometheus records metrics regarding incoming requests
prometheus
# log writes 1 line to the log for every DNS request# The last word in the log line will be YES if the request was blocked and NO if it was not# blocked.# This behaviour is supported by the metadata plugin.
log . "{common} {/blocker/request-blocked}"# blocker blocks domains which are specified in the blocklist
blocker /home/user/blocklist_file 1h abp empty
# forward handles any request that is not blocked by blocker
forward . 127.0.0.1:9053
}

plugin.cfg

This is a sample middleware configuration file. The order of plugins here is important. This is the order in which plugins will be executed for incoming requests.

metadata:metadata
prometheus:metrics
log:log
blocker:blocker
forward:forward

Interaction with Other CoreDNS Plugins

metadata

The blocker plugin will write a metadata value with the label blocker/request-blocked. This is a boolean value whose value will be either YES (if the request was blocked) or NO when the request was not blocked.

prometheus (metrics)

When the prometheusplugin is enabled, the blocker plugin will record 2 Counter metrics, representing the allowed and blocked DNS request count. These metrics can be fetched by setting up Prometheus to scrape from port 9153 on the interface where CoreDNS is running.

Metric values can be verified by making a HTTP request to the /metrics endpoint:

$ curl -s 127.0.0.1:9153/metrics | rg requests_total
# HELP coredns_blocker_allowed_requests_total Counter of DNS requests being allowed.# TYPE coredns_blocker_allowed_requests_total counter
coredns_blocker_allowed_requests_total 2
# HELP coredns_blocker_blocked_requests_total Counter of DNS requests being blocked.# TYPE coredns_blocker_blocked_requests_total counter
coredns_blocker_blocked_requests_total 3

Release Binaries

For tags which are published to this repository, the GitHub Actions workflow ./.github/workflows/build-binary.yml builds binaries using the latest Go version for Linux under the three most popular architectures: AMD64, ARM (32 bit), and ARM64. The tar.gz files contain a Checksum file which can be used together with sha256sum to verify the integrity of the binary.

$ wget https://github.com/icyflame/blocker/releases/download/v0.0.1-alpha/coredns-linux-amd64.tar.gz
...
coredns-linux-amd64.tar.gz 100%[=======================================================================>] 5.16M 610KB/s in 14s
2024-07-13 12:26:05 (390 KB/s) - ‘coredns-linux-amd64.tar.gz’ saved [5414731/5414731]
$ tar tvf coredns-linux-amd64.tar.gz
-rwxr-xr-x runner/docker 14110872 2024-07-13 12:26 coredns-linux-amd64
-rw-r--r-- runner/docker 86 2024-07-13 12:26 coredns-linux-amd64.checksum
$ tar zxf coredns-linux-amd64.tar.gz
$ sha256sum -c coredns-linux-amd64.checksum
coredns-linux-amd64: OK
$ ./coredns-linux-amd64 -version
CoreDNS-1.11.1
linux/amd64, go1.22.5, Blocker plugin refs/tags/v0.0.1-alpha 1e6061ee8b7d2ad2ee5c632d3b91851c00481453

Development

Running Tests

This plugin contains unit tests. These unit tests are run as part of the unit tests for CoreDNS. The following process should be followed to run these unit tests:

# Clone CoreDNS
$ git clone git@github.com:coredns/coredns.git /tmp/dns-server/coredns
# Clone this plugin
git clone git@github.com:icyflame/blocker.git /tmp/dns-server/blocker
# Link this plugin into CoreDNS
ln -s /tmp/dns-server/blocker /tmp/dns-server/coredns/plugin/blocker
# Run tests for this plugincd /tmp/dns-server/coredns
go test -v -count=1 ./plugin/blocker
=== RUN TestIsDomainBlocked_ABP
=== RUN TestIsDomainBlocked_ABP/base_case
[snip]
PASS
ok github.com/coredns/coredns/plugin/blocker 0.005s

During development, making changes to the blocker plugin, after the above process, makes it easier to run tests and use the Go language server features such as jumping to definition.

Testing the DNS server

Apart from unit tests, benchmarking tools can be used to verify whether CoreDNS works with a large volume of DNS requests. This is the setup that I use to run benchmarks using dnsbench.

First, follow the process in the Usage > CoreDNS Binary section to create a CoreDNS binary which contains the blocker plugin.

Second, start the CoreDNS server using the following configuration:

$ cat Corefile.benchmark.conf
.:5335 {
metadata
log . "{common} {/blocker/request-blocked}"
blocker /home/siddharth/code/open-source/coredns/blocklist.benchmark 1s abp nxdomain
forward . 8.8.8.8
}
$ touch blocklist.benchmark
$ ./coredns -conf Corefile.benchmark.conf
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[INFO] plugin/blocker: updated blocklist; blocked domains: before: 0, after: 0; last updated: before: 0001-01-01 00:00:00 +0000 UTC, after: 2025-08-09 12:10:31.479348779 +0900 JST m=+0.026230377
.:5335
CoreDNS-1.12.3
linux/amd64, go1.24.5, 463fd1c1b-dirty

Third, run the following one liner which simulates updating the block list:

$ truncate --size 0 blocklist.benchmark;foriin`seq 101 10000`;do sleep 1;echo"||baddomain-$i.example.com^">> blocklist.benchmark;echo"$(date): Iteration $i DONE";done;
Sat 09 Aug 2025 12:11:30 PM JST: Iteration 1 DONE
Sat 09 Aug 2025 12:11:31 PM JST: Iteration 2 DONE
Sat 09 Aug 2025 12:11:32 PM JST: Iteration 3 DONE
[snip]

A new domain will be written to the blocklist file every second, and the Blocker plugin will constantly update this file, printing logs such as this one:

[INFO] plugin/blocker: updated blocklist; blocked domains: before: 58, after: 59; last updated: before: 2025-08-09 12:12:28.480451154 +0900 JST m=+117.027332732, after: 2025-08-09 12:12:29.47975636 +0900 JST m=+118.026637938

Finally, install and run the dnsbench tool against this CoreDNS server:

# Prepare a list of domain names
$ truncate --size 0 domain-names.benchmark;foriin`seq 1 200`;doecho"baddomain-$i.example.com">> domain-names.benchmark;done;
$ dnsbench run --nameserver '127.0.0.1:5335' --names domain-names.benchmark --count=10000
# requests errors min [ p50 p95 p99 p999] max qps
1421 382 4.71 [6.23 265.95 523.76 809.50] 809.50 284.20
1550 422 4.91 [6.09 253.89 475.27 740.82] 740.82 310.00
1562 426 4.84 [6.11 254.54 476.32 738.72] 738.72 312.40
1293 353 4.93 [6.14 268.30 529.53 771.23] 771.23 258.60
1403 383 4.81 [6.09 263.98 525.34 786.96] 786.96 280.60
1539 419 4.87 [6.06 263.19 508.82 743.96] 743.96 307.80
Finished 10000 requests
# latency summary
10000 2727 4.71 [6.11 264.90 493.09 809.50] 809.50 290.18
Concurrency level: 10
Time taken for tests: 34.464370221s
Completed Requests: 7273
Failed Requests: 2727
Requests per second: -0.0000 [#/sec] (mean)
Time per request: 34.04 [ms] (mean)
Fastest request: 4.71 [ms]
Slowest request: 809.50 [ms]

About

Domain blocker plugin for CoreDNS

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - icyflame/blocker: Domain blocker plugin for CoreDNS · GitHub
Skip to content

Repository files navigation

blocker - Domain blocker plugin for CoreDNS

blocker is a CoreDNS plugin which can be used to block a list of domains provided in the AdBlock Plus syntax format. The blocklist will be loaded into memory at start-up and the file’s modified time will be checked periodically. When the blocklist file is updated, the in-memory blocklist will be updated by scanning the blocklist file line-by-line.

Updating the blocklist file itself is beyond the scope of this plugin. I recommend a bash script which downloads commonblocklists and updates them into a format without comments. The script blocklist-file-preparer.sh included with this repository is an example of how this can be done using bash and common GNU utilities.

Example blocklist file: (AdBlock Plus syntax)

||buyer.revsci.net^
||ww92.impfr.tradedoubler.com^
||next.chartboost.com^
||pl16442154.alternativecpmgate.com^
||denturesauaid.com^
||pdx-p-con-336.saas.appdynamics.com^
||cdn.ad.citynews.it^
||xxxxxxxamob.acs86.com^
||www.globalhotsale.su^
||zipuploads.com^

Usage

CoreDNS Binary

You can include blocker in the CoreDNS code just as you would include any other CoreDNS plugin.

# Clone coredns to a local location
$ git clone git@github.com:coredns/coredns.git ~/dns-server/coredns
# Clone blocker plugin to a close location
$ git clone git@github.com:icyflame/blocker.git ~/dns-server/blocker
# Symlink blocker location into coredns/plugin/blocker
$ cd~/dns-server/coredns/plugin
$ ln -s ../blocker ./blocker
# Update plugin.cfg and put the line "blocker:blocker" before the "forward:forward" line# Build CoreDNS
$ cd~/dns-server/coredns
$ go generate
$ make
$ ./coredns -conf Corefile

Corefile

The blocker directive inside Corefile requires four arguments. The first argument is the absolute path to the blocklist file. The second argument is the frequency at which the blocklist file is checked for updates. The third argument is the type of blocklist file (hosts and abp are the only two values which are supported at this time.) The fourth argument is the response type from the plugin, either empty for a valid DNS response with 0.0.0.0 or ::6 or nxdomain to respond with a DNS empty response.

The frequency is specified as a string and the value should be a valid argument of the time.ParseDuration function.

blocker /home/user/blocklist_file 1h abp empty

The following is a sample Corefile including the blocker directive. It will block domains that are specified in the blocklist and forward everything else to a full DNS server.

 .:53 {
metadata
# prometheus records metrics regarding incoming requests
prometheus
# log writes 1 line to the log for every DNS request# The last word in the log line will be YES if the request was blocked and NO if it was not# blocked.# This behaviour is supported by the metadata plugin.
log . "{common} {/blocker/request-blocked}"# blocker blocks domains which are specified in the blocklist
blocker /home/user/blocklist_file 1h abp empty
# forward handles any request that is not blocked by blocker
forward . 127.0.0.1:9053
}

plugin.cfg

This is a sample middleware configuration file. The order of plugins here is important. This is the order in which plugins will be executed for incoming requests.

metadata:metadata
prometheus:metrics
log:log
blocker:blocker
forward:forward

Interaction with Other CoreDNS Plugins

metadata

The blocker plugin will write a metadata value with the label blocker/request-blocked. This is a boolean value whose value will be either YES (if the request was blocked) or NO when the request was not blocked.

prometheus (metrics)

When the prometheusplugin is enabled, the blocker plugin will record 2 Counter metrics, representing the allowed and blocked DNS request count. These metrics can be fetched by setting up Prometheus to scrape from port 9153 on the interface where CoreDNS is running.

Metric values can be verified by making a HTTP request to the /metrics endpoint:

$ curl -s 127.0.0.1:9153/metrics | rg requests_total
# HELP coredns_blocker_allowed_requests_total Counter of DNS requests being allowed.# TYPE coredns_blocker_allowed_requests_total counter
coredns_blocker_allowed_requests_total 2
# HELP coredns_blocker_blocked_requests_total Counter of DNS requests being blocked.# TYPE coredns_blocker_blocked_requests_total counter
coredns_blocker_blocked_requests_total 3

Release Binaries

For tags which are published to this repository, the GitHub Actions workflow ./.github/workflows/build-binary.yml builds binaries using the latest Go version for Linux under the three most popular architectures: AMD64, ARM (32 bit), and ARM64. The tar.gz files contain a Checksum file which can be used together with sha256sum to verify the integrity of the binary.

$ wget https://github.com/icyflame/blocker/releases/download/v0.0.1-alpha/coredns-linux-amd64.tar.gz
...
coredns-linux-amd64.tar.gz 100%[=======================================================================>] 5.16M 610KB/s in 14s
2024-07-13 12:26:05 (390 KB/s) - ‘coredns-linux-amd64.tar.gz’ saved [5414731/5414731]
$ tar tvf coredns-linux-amd64.tar.gz
-rwxr-xr-x runner/docker 14110872 2024-07-13 12:26 coredns-linux-amd64
-rw-r--r-- runner/docker 86 2024-07-13 12:26 coredns-linux-amd64.checksum
$ tar zxf coredns-linux-amd64.tar.gz
$ sha256sum -c coredns-linux-amd64.checksum
coredns-linux-amd64: OK
$ ./coredns-linux-amd64 -version
CoreDNS-1.11.1
linux/amd64, go1.22.5, Blocker plugin refs/tags/v0.0.1-alpha 1e6061ee8b7d2ad2ee5c632d3b91851c00481453

Development

Running Tests

This plugin contains unit tests. These unit tests are run as part of the unit tests for CoreDNS. The following process should be followed to run these unit tests:

# Clone CoreDNS
$ git clone git@github.com:coredns/coredns.git /tmp/dns-server/coredns
# Clone this plugin
git clone git@github.com:icyflame/blocker.git /tmp/dns-server/blocker
# Link this plugin into CoreDNS
ln -s /tmp/dns-server/blocker /tmp/dns-server/coredns/plugin/blocker
# Run tests for this plugincd /tmp/dns-server/coredns
go test -v -count=1 ./plugin/blocker
=== RUN TestIsDomainBlocked_ABP
=== RUN TestIsDomainBlocked_ABP/base_case
[snip]
PASS
ok github.com/coredns/coredns/plugin/blocker 0.005s

During development, making changes to the blocker plugin, after the above process, makes it easier to run tests and use the Go language server features such as jumping to definition.

Testing the DNS server

Apart from unit tests, benchmarking tools can be used to verify whether CoreDNS works with a large volume of DNS requests. This is the setup that I use to run benchmarks using dnsbench.

First, follow the process in the Usage > CoreDNS Binary section to create a CoreDNS binary which contains the blocker plugin.

Second, start the CoreDNS server using the following configuration:

$ cat Corefile.benchmark.conf
.:5335 {
metadata
log . "{common} {/blocker/request-blocked}"
blocker /home/siddharth/code/open-source/coredns/blocklist.benchmark 1s abp nxdomain
forward . 8.8.8.8
}
$ touch blocklist.benchmark
$ ./coredns -conf Corefile.benchmark.conf
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
[INFO] plugin/blocker: updated blocklist; blocked domains: before: 0, after: 0; last updated: before: 0001-01-01 00:00:00 +0000 UTC, after: 2025-08-09 12:10:31.479348779 +0900 JST m=+0.026230377
.:5335
CoreDNS-1.12.3
linux/amd64, go1.24.5, 463fd1c1b-dirty

Third, run the following one liner which simulates updating the block list:

$ truncate --size 0 blocklist.benchmark;foriin`seq 101 10000`;do sleep 1;echo"||baddomain-$i.example.com^">> blocklist.benchmark;echo"$(date): Iteration $i DONE";done;
Sat 09 Aug 2025 12:11:30 PM JST: Iteration 1 DONE
Sat 09 Aug 2025 12:11:31 PM JST: Iteration 2 DONE
Sat 09 Aug 2025 12:11:32 PM JST: Iteration 3 DONE
[snip]

A new domain will be written to the blocklist file every second, and the Blocker plugin will constantly update this file, printing logs such as this one:

[INFO] plugin/blocker: updated blocklist; blocked domains: before: 58, after: 59; last updated: before: 2025-08-09 12:12:28.480451154 +0900 JST m=+117.027332732, after: 2025-08-09 12:12:29.47975636 +0900 JST m=+118.026637938

Finally, install and run the dnsbench tool against this CoreDNS server:

# Prepare a list of domain names
$ truncate --size 0 domain-names.benchmark;foriin`seq 1 200`;doecho"baddomain-$i.example.com">> domain-names.benchmark;done;
$ dnsbench run --nameserver '127.0.0.1:5335' --names domain-names.benchmark --count=10000
# requests errors min [ p50 p95 p99 p999] max qps
1421 382 4.71 [6.23 265.95 523.76 809.50] 809.50 284.20
1550 422 4.91 [6.09 253.89 475.27 740.82] 740.82 310.00
1562 426 4.84 [6.11 254.54 476.32 738.72] 738.72 312.40
1293 353 4.93 [6.14 268.30 529.53 771.23] 771.23 258.60
1403 383 4.81 [6.09 263.98 525.34 786.96] 786.96 280.60
1539 419 4.87 [6.06 263.19 508.82 743.96] 743.96 307.80
Finished 10000 requests
# latency summary
10000 2727 4.71 [6.11 264.90 493.09 809.50] 809.50 290.18
Concurrency level: 10
Time taken for tests: 34.464370221s
Completed Requests: 7273
Failed Requests: 2727
Requests per second: -0.0000 [#/sec] (mean)
Time per request: 34.04 [ms] (mean)
Fastest request: 4.71 [ms]
Slowest request: 809.50 [ms]

About

Domain blocker plugin for CoreDNS

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages