DNS server with per-client targeted responses

GeoDNS servers

This is the DNS server powering the NTP Pool system and other similar services. Build Status

Questions or suggestions?

For bug reports or feature requests, please create an issue. For questions or discussion, you can post to the GeoDNS category on the NTP Pool forum.

Installation

If you already have go installed, just run go get to install the Go dependencies. GeoDNS requires Go 1.13 or later.

If you don't have Go installed the easiest way to build geodns from source is to download Go from https://golang.org/dl/ and untar'ing it in /usr/local/go and then run the following from a regular user account:

export PATH=$PATH:/usr/local/go/bin
export GOPATH=~/go
go get github.com/abh/geodns
cd ~/go/src/github.com/abh/geodns
go test
go build
./geodns -h

Sample configuration

There's a sample configuration file in dns/example.com.json. This is currently derived from the test.example.com data used for unit tests and not an example of a "best practices" configuration.

For testing there's also a bigger test file at:

mkdir -p dns
curl -o dns/test.ntppool.org.json http://tmp.askask.com/2012/08/dns/ntppool.org.json.big

Run it

After building the server you can run it with:

./geodns -log -interface 127.1 -port 5053

To test the responses run

dig -t a test.example.com @127.1 -p 5053

or

dig -t ptr 2.1.168.192.IN-ADDR.ARPA. @127.1 -p 5053

or more simply put

dig -x 192.168.1.2 @127.1 -p 5053

The binary can be moved to /usr/local/bin, /opt/geodns/ or wherever you find appropriate.

Command options

Notable command line parameters (and their defaults)

  • -config="./dns/"

Directory of zone files (and configuration named geodns.conf).

  • -checkconfig=false

Check configuration file, parse zone files and exit

  • -interface="*"

Comma separated IPs to listen on for DNS requests.

  • -port="53"

Port number for DNS requests (UDP and TCP)

  • -http=":8053"

Listen address for HTTP interface. Specify as 127.0.0.1:8053 to only listen on localhost.

  • -identifier=""

Identifier for this instance (hostname, pop name or similar).

It can also be a comma separated list of identifiers where the first is the "server id" and subsequent ones are "group names", for example region of the server, name of anycast cluster the server is part of, etc. This is used in (future) reporting/statistics features.

  • -log=false

Enable to get lots of extra logging, only useful for testing and debugging. Absolutely not recommended in production unless you get very few queries (less than 1-200/second).

  • -cpus=1

Maximum number of CPUs to use. Set to 0 to match the number of CPUs available on the system. Only "1" (the default) has been extensively tested.

WebSocket interface

geodns runs a WebSocket server on port 8053 that outputs various performance metrics. The WebSocket URL is /monitor. There's a "companion program" that can use this across a cluster to show aggregate statistics, email for more information.

Runtime status

There's a page with various runtime information (queries per second, queries and most frequently requested labels per zone, etc) at /status.

StatHat integration

GeoDNS can post runtime data to StatHat. (Documentation)

Country and continent lookups

See zone targeting options below.

Weighted records

Most records can have a 'weight' assigned. If any records of a particular type for a particular name have a weight, the system will return max_hosts records (default 2).

If the weight for all records is 0, all matching records will be returned. The weight for a label can be any integer as long as the weights for a label and record type is less than 2 billion.

As an example, if you configure

10.0.0.1, weight 10
10.0.0.2, weight 20
10.0.0.3, weight 30
10.0.0.4, weight 40

with max_hosts 2 then .4 will be returned about 4 times more often than .1.

Configuration file

The geodns.conf file allows you to specify a specific directory for the GeoIP data files and other options. See the geodns.conf.sample file for example configuration.

The global configuration file is not reloaded at runtime.

Most of the configuration is "per zone" and done in the zone .json files. The zone configuration files are automatically reloaded when they change.

Zone format

In the zone configuration file the whole zone is a big hash (associative array). At the top level you can (optionally) set some options with the keys serial, ttl and max_hosts.

The actual zone data (dns records) is in a hash under the key "data". The keys in the hash are hostnames and the value for each hostname is yet another hash where the keys are record types (lowercase) and the values an array of records.

For example to setup an MX record at the zone apex and then have a different A record for users in Europe than anywhere else, use:

{
    "serial": 1,
    "data": {
        "": {
            "ns": [ "ns.example.net", "ns2.example.net" ],
            "txt": "Example zone",
            "spf": [ { "spf": "v=spf1 ~all", "weight": 1 } ],
            "mx": { "mx": "mail.example.com", "preference": 10 }
        },
        "mail": { "a": [ ["192.168.0.1", 100], ["192.168.10.1", 50] ] },
        "mail.europe": { "a": [ ["192.168.255.1", 0] ] },
        "smtp": { "alias": "mail" }
    }
}

The configuration files are automatically reloaded when they're updated. If a file can't be read (invalid JSON, for example) the previous configuration for that zone will be kept.

Zone options

  • serial

GeoDNS doesn't support zone transfers (AXFR), so the serial number is only used for debugging and monitoring. The default is the 'last modified' timestamp of the zone file.

  • ttl

Set the default TTL for the zone (default 120).

  • targeting

  • max_hosts

  • contact

Set the soa 'contact' field (default is "hostmaster.$domain").

Zone targeting options

@

country continent

region and regiongroup

Supported record types

Each label has a hash (object/associative array) of record data, the keys are the type. The supported types and their options are listed below.

Adding support for more record types is relatively straight forward, please open a ticket in the issue tracker with what you are missing.

A

Each record has the format of a short array with the first element being the IP address and the second the weight.

[ [ "192.168.0.1", 10], ["192.168.2.1", 5] ]

See above for how the weights work.

AAAA

Same format as A records (except the record type is "aaaa").

Alias

Internally resolved cname, of sorts. Only works internally in a zone.

"foo"

CNAME

"target.example.com."
"www"

The target will have the current zone name appended if it's not a FQDN (since v2.2.0).

MX

MX records support a weight similar to A records to indicate how often the particular record should be returned.

The preference is the MX record preference returned to the client.

{ "mx": "foo.example.com" }
{ "mx": "foo.example.com", "weight": 100 }
{ "mx": "foo.example.com", "weight": 100, "preference": 10 }

weight and preference are optional.

NS

NS records for the label, use it on the top level empty label ("") to specify the nameservers for the domain.

[ "ns1.example.com", "ns2.example.com" ]

There's an alternate legacy syntax that has space for glue records (IPv4 addresses), but in GeoDNS the values in the object are ignored so the list syntax above is recommended.

{ "ns1.example.net.": null, "ns2.example.net.": null }

TXT

Simple syntax

"Some text"

Or with weights

{ "txt": "Some text", "weight": 10 }

SPF

An SPF record is semantically identical to a TXT record with the exception that the label is set to 'spf'. An example of an spf record with weights:

{ "spf": "v=spf1 ~all]", "weight": 1 }

An spf record is typically at the root of a zone, and a label can have an array of SPF records, e.g

  "spf": [ { "spf": "v=spf1 ~all", "weight": 1 } , "spf": "v=spf1 10.0.0.1", "weight": 100]

SRV

An SRV record has four components: the weight, priority, port and target. The keys for these are "srv_weight", "priority", "target" and "port". Note the difference between srv_weight (the weight key for the SRV qtype) and "weight".

An example srv record definition for the _sip._tcp service:

"_sip._tcp": {
    "srv": [ { "port": 5060, "srv_weight": 100, "priority": 10, "target": "sipserver.example.com."} ]
},

Much like MX records, SRV records can have multiple targets, eg:

"_http._tcp": {
    "srv": [
        { "port": 80, "srv_weight": 10, "priority": 10, "target": "www.example.com."},
        { "port": 8080, "srv_weight": 10, "priority": 20, "target": "www2.example.com."}
    ]
},

License and Copyright

This software is Copyright 2012-2015 Ask Bjørn Hansen. For licensing information please see the file called LICENSE.

Owner
Ask Bjørn Hansen
Ask Bjørn Hansen
Comments
  • Add healthtest feature to dynamically add/remove DNS entries

    Add healthtest feature to dynamically add/remove DNS entries

    This is an experimental feature to add/remove DNS entries depending on whether servers/services are up/down. Initially NTP testing and TCP port testing are supported.

    This is an experimental lightly tested patch. It's based on top of the other 3 merge requests I have submitted recently, but is pretty easily separated.

    From the commit message:

    commit 049d4acdfd1b5941feb501ddb1353a27e464047d
    Author: Alex Bligh <[email protected]>
    Date:   Mon Aug 17 15:32:26 2015 +0100
    
    Add healthtest functionality to automatically exclude down hosts
    
    Add a healthtest function activated by setting the 'test' attribute on a label.
    When a test is specified, each RR within the label (A and AAAA only at this
    stage) is polled regularly with a configurable test. Current configurable
    tests are that a tcp port can be opened, or that an NTP response within a
    given stratum range is achieved. RRs that fail the test will be excluded
    from any results.
    
    Health tests can be configured as follows:
    
         "test" :  {
             "type" : "ntp",
             "frequency" : 30,
             "retry_time" : 5,
             "retries" : 3,
             "timeout" : 5,
             "max_stratum" : "3"
          }
    
    or
    
         "test" :  {
             "type" : "tcp",
             "frequency" : 30,
             "retry_time" : 5,
             "retries" : 3,
             "timeout" : 5,
         "port" : 80
          }
    
    Attributes are as follows:
    
    * type: specifies type of test (currently "ntp" or "tcp")
    
    * frequency: specifies time in seconds between polls if the server is up
    
    * retry_time: specifies time in seconds between polls if a poll fails
    
    * retries: number of failed polls required to consider a server as down
    
    * timeout: timeout on each of the polls
    
    * max_stratum: (ntp only) maximum ntp stratum number for the poll
      to be considered successful
    
    * port: (tcp only) tcp port number to connect to
    
    Signed-off-by: Alex Bligh <[email protected]>
    
  • Add closest flag and automatic geographic load balancing

    Add closest flag and automatic geographic load balancing

    This is an experimental feature to provide automatic geographic loadbalancing by choosing the group of servers with the lowest geographic distance to the query originator.

    This is lightly tested. However, it should not affect normal operation unless you turn it on.

    Information from the commit:

    Add 'closest' flag
    
    This changeset adds a new boolean option 'closest' to the zone options
    and to the label options. The label option defaults to the zone option
    for 'closest'.
    
    When closest is set on a label within a zone, each A record has its
    location determined and stored in memory. When a query is received,
    after the targeting process is performed, the geographically closest
    group of A records are selected prior to the weight algorithm being
    applied.
    
    In practice this means you can use a simple technique (set 'closest'
    to be "true") to choose the geographically closest servers. Note
    that geographic proximity may not correlate perfectly to topological
    proximity.
    
    Note that when 'closest' is selected on any label within the zone,
    the GEOIP_CITY_EDITION_REV1 geoip data is required, as that is what
    contains latitude and longitude data.
    
    No provision is currently made for servers that change longitude
    and latitude (most likely due to a geoip data change) during the
    runtime life of the server.
    
    Signed-off-by: Alex Bligh <[email protected]>
    
  • Panic on deletion of broken zonefile

    Panic on deletion of broken zonefile

    geodns panics if a broken zone file is created then deleted.

    To replicate, create a broken zonefile:

    $ echo a > dns/x.com.json
    

    Wait until the zone file fails to load:

    geodns 13:25:19.160763 log.go:7: Reading new file x.com.json
    geodns 13:25:19.160889 zones.go:69: Caught an error error parsing JSON object in config file dns/x.com.json:
    Error at line 1, column 1 (file offset 1):
        1: a
          ^
    invalid character 'a' looking for beginning of value
    

    Then delete the zone file

    $ rm dns/x.com.json
    

    And wait a few minutes

    geodns 13:25:29.163572 zones.go:91: Removing zone
    panic: runtime error: invalid memory address or nil pointer dereference
    [signal 0xb code=0x1 addr=0x0 pc=0x400fe45]
    
    goroutine 29 [running]:
    main.(*Zone).Close(0xc20805e6e0)
        /Users/amb/go/src/github.com/abh/geodns/zone.go:98 +0x1a5
    main.zonesReadDir(0x4489e70, 0x6, 0xc20803de30, 0x0, 0x0)
        /Users/amb/go/src/github.com/abh/geodns/zones.go:92 +0x78b
    main.zonesReader(0x4489e70, 0x6, 0xc20803de30)
        /Users/amb/go/src/github.com/abh/geodns/zones.go:26 +0x3c
    created by main.main
        /Users/amb/go/src/github.com/abh/geodns/geodns.go:173 +0xd41
     ... (snipped) ...
    

    The problem is this line:

    func (z *Zone) Close() {
        metrics.Unregister(z.Origin + " queries")
        metrics.Unregister(z.Origin + " EDNS queries")
        z.Metrics.LabelStats.Close() // <-------------------- HERE
        z.Metrics.ClientStats.Close()
    }
    

    As the zone file never existed, it has been incompletely loaded, and the metrics were not set up. Deleting it attempts to Close() the zone file and this fails with a nil pointer dereference as z.Metrics is nil.

    I would suggest zone files that are not present prior to loading and fail to load leave the zones map unchanged and do nothing. I will submit a changeset to fix this.

  • geoip2: watch and update

    geoip2: watch and update

    Add goroutine to watch file modification time each minute. Lock and update the files independently if the modification time is newer than the last time it was loaded.

    Also ancillary fixes for type signatures, and formatting test files.

    Fixes #116, #16

  • Add option to make debugging queries private

    Add option to make debugging queries private

    Add an option to make debugging queries private, meaning only accepted from the loopback address. The debugging queries (i.e. _status, _health and possibly _country) contain information which may be either commercially sensitive or security sensitive. Therefore provide an option (-privatedebug) which if set does not return these unless the query comes from the loopback address.

  • Add a health RR

    Add a health RR

    Add a RR which returns the health status of a record, for debugging purposes. This returns in JSON format the health record of all the records associated with a label if a health test is running.

    Example follows.

    $ dig -p 10053 TXT _health.foo.example2.com @127.0.0.1
    
    ; <<>> DiG 9.8.3-P1 <<>> -p 10053 TXT _health.foo.example2.com @127.0.0.1
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59545
    ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
    ;; WARNING: recursion requested but not available
    
    ;; QUESTION SECTION:
    ;_health.foo.example2.com.  IN      TXT
    
    ;; ANSWER SECTION:
    _health.foo.example2.com. 1 IN      TXT     "{\"A\":{\"192.168.1.2\":false,\"192.168.1.3\":false,\"192.168.1.4\":false},\"AAAA\":{\"fd06:c1d3:e902:202:a5ff:fecd:13a6:a\":false,\"fd06:c1d3:e902::2\":false,\"fd06:c1d3:e902::4\":false}}"
    
    ;; Query time: 1 msec
    ;; SERVER: 127.0.0.1#10053(127.0.0.1)
    ;; WHEN: Wed Sep  2 19:24:01 2015
    ;; MSG SIZE  rcvd: 251
    

    Decoding that JSON:

    {
       "A" : {
          "192.168.1.4" : false,
          "192.168.1.3" : false,
          "192.168.1.2" : false
       },
       "AAAA" : {
          "fd06:c1d3:e902:202:a5ff:fecd:13a6:a" : false,
          "fd06:c1d3:e902::4" : false,
          "fd06:c1d3:e902::2" : false
       }
    }
    
  • Can you do some support to make it work on ubuntu?

    Can you do some support to make it work on ubuntu?

    I tried install geodns on ubuntu a number of times, but failed. It seems there are some problems in terms of packages dependencies. Besides, I also got the error message:

    /usr/lib/go/src/pkg/github.com/abh/dns/edns.go:230: function ends without a return statement

    without a clue

    The steps I tried: sudo apt-get install golang sudo apt-get install mercurial sudo apt-get install libgeoip-dev export GOPATH=/usr/lib/go sudo go get github.com/abh/geodns

    I haven't tried to install it on centos, so I cannot tell if I tried to install it in wrong way.

    Thanks

  • Remove minimum ns ttl

    Remove minimum ns ttl

    geodns adopted a seemingly arbitrary minimum TTL for NS records of 86400 seconds (one day). I can find no reason for this in the RFCs. Setting a lower TTL is useful e.g. when NS records are to be changed, for instance removal of a nameserver. This patch removes this arbitrary limit.

  • Domain geo record clarification

    Domain geo record clarification

    I'm planning to migrate my dns from pgeodns to this version. But When I look into the sample configuration of ntp , the entries are making me some confusion on geo record.

    What is difference between the below record for country Malaysia

    3.my , 1.my , 0.my ,2.my from ntppool.org.json

  • HEAD doesn't build with abh/go-metrics

    HEAD doesn't build with abh/go-metrics

    ./metrics.go:26: cannot use metrics.NewHistogram(metrics.NewUniformSample(1800)) (type metrics.Histogram) as type *metrics.StandardHistogram in assignment: need type assertion ./metrics.go:29: cannot use metrics.NewHistogram(metrics.NewExpDecaySample(600, 0.015)) (type metrics.Histogram) as type *metrics.StandardHistogram in assignment: need type assertion ./metrics.go:32: cannot use metrics.NewGauge() (type metrics.Gauge) as type *metrics.StandardGauge in assignment: need type assertion ./zone.go:85: cannot use metrics.NewMeter() (type metrics.Meter) as type *metrics.StandardMeter in assignment: need type assertion

  • Closes UDP socket randomly(?)

    Closes UDP socket randomly(?)

    This is a followup to miekg/dns#21 (which really was about something else).

    I ran dnsbench against the geodns server today to reproduce the "hang" where it just stops listening on UDP. After 4 hours of 1000qps it was still working fine and it's "only" doubled memory usage from 15MB to 30MB.

    Running lsof on the process shows it's doesn't have the UDP server open anymore.

    I've added some monitoring code in 70b6e4e413f8751678c2999e8a6d124c954676d3 and an attempt at logging if ListenAndServe returns: 98020a3f63515b4a

  • Need help for an example config file

    Need help for an example config file

    Here are following dns domains that have A/NS records :

    EUROPE:

    eu-1.internet.dedyn.io eu-2.internet.dedyn.io eu-3.internet.dedyn.io

    AMERICA:

    us-1.internet.dedyn.io us-2.internet.dedyn.io

    ASIA (not tested):

    as-1.internet.dedyn.io

    I wanted to do this kind of stuff (like CDN) as a fun project and i may use it for my websites in the future. (the goal is that it opens one of these websites according to location)

  • Bug) Incorrect GSLB result for Cloudflare DNS ( 1.1.1.1 )

    Bug) Incorrect GSLB result for Cloudflare DNS ( 1.1.1.1 )

    Hello,

    I think geodns doesn't work when clients are querying DNS records via 1.1.1.1 dns

    Test results

    root@localhost:~# which dig
    /usr/bin/dig
    root@localhost:~# dig pool.ntp.org @1.1.1.1
    
    ; <<>> DiG 9.16.1-Ubuntu <<>> pool.ntp.org @1.1.1.1
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34920
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 1232
    ;; QUESTION SECTION:
    ;pool.ntp.org.                  IN      A
    
    ;; ANSWER SECTION:
    pool.ntp.org.           133     IN      A       213.231.5.55
    pool.ntp.org.           133     IN      A       200.89.75.197
    pool.ntp.org.           133     IN      A       109.74.192.97
    pool.ntp.org.           133     IN      A       211.233.84.186
    
    ;; Query time: 0 msec
    ;; SERVER: 1.1.1.1#53(1.1.1.1)
    ;; WHEN: Fri Apr 08 23:19:57 UTC 2022
    ;; MSG SIZE  rcvd: 105
    
    root@localhost:~# ping 213.231.5.55
    PING 213.231.5.55 (213.231.5.55) 56(84) bytes of data.
    64 bytes from 213.231.5.55: icmp_seq=1 ttl=53 time=250 ms
    64 bytes from 213.231.5.55: icmp_seq=2 ttl=53 time=250 ms
    ^C
    --- 213.231.5.55 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1001ms
    rtt min/avg/max/mdev = 249.610/249.961/250.313/0.351 ms
    root@localhost:~# ping 200.89.75.197
    PING 200.89.75.197 (200.89.75.197) 56(84) bytes of data.
    64 bytes from 200.89.75.197: icmp_seq=1 ttl=56 time=267 ms
    ^C
    --- 200.89.75.197 ping statistics ---
    2 packets transmitted, 1 received, 50% packet loss, time 1001ms
    rtt min/avg/max/mdev = 266.621/266.621/266.621/0.000 ms
    root@localhost:~# ping 109.74.192.97
    PING 109.74.192.97 (109.74.192.97) 56(84) bytes of data.
    64 bytes from 109.74.192.97: icmp_seq=1 ttl=55 time=236 ms
    ^C
    --- 109.74.192.97 ping statistics ---
    2 packets transmitted, 1 received, 50% packet loss, time 1002ms
    rtt min/avg/max/mdev = 236.298/236.298/236.298/0.000 ms
    root@localhost:~# ping 211.233.84.186
    PING 211.233.84.186 (211.233.84.186) 56(84) bytes of data.
    64 bytes from 211.233.84.186: icmp_seq=1 ttl=54 time=33.3 ms
    64 bytes from 211.233.84.186: icmp_seq=2 ttl=54 time=33.2 ms
    ^C
    --- 211.233.84.186 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1002ms
    rtt min/avg/max/mdev = 33.228/33.249/33.270/0.021 ms
    root@localhost:~# dig pool.ntp.org
    
    ; <<>> DiG 9.16.1-Ubuntu <<>> pool.ntp.org
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32438
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 65494
    ;; QUESTION SECTION:
    ;pool.ntp.org.                  IN      A
    
    ;; ANSWER SECTION:
    pool.ntp.org.           75      IN      A       162.159.200.1
    pool.ntp.org.           75      IN      A       203.112.25.169
    pool.ntp.org.           75      IN      A       194.0.5.123
    pool.ntp.org.           75      IN      A       133.243.238.163
    
    ;; Query time: 7 msec
    ;; SERVER: 127.0.0.53#53(127.0.0.53)
    ;; WHEN: Fri Apr 08 23:21:08 UTC 2022
    ;; MSG SIZE  rcvd: 105
    

    Querying from japan region server would return incorrect answers when the records are returned by 1.1.1.1,

    while it just works normally with the default DNS server provided by ISP.

  • How to correctly distinguish normal subrecords from country codes when subrecords are the same as country codes

    How to correctly distinguish normal subrecords from country codes when subrecords are the same as country codes

    Hi

    I looked at this sample configuration and I had a question https://github.com/abh/geodns/blob/main/dns/test.example.com.json

    When I set up the following record for example.com

    {
        "": {
            "a": [
                [
                    "192.168.1.1",
                    10
                ]
            ]
        },
        "my": {
            "a": [
                [
                    "192.168.1.2",
                    10
                ]
            ]
        },
        "se": {
            "a": [
                [
                    "192.168.1.3",
                    10
                ]
            ]
        }
    }
    

    Attempts to request records from Sweden for example.com will return 192.168.1.3 A request from Malaysia will return 192.168.1.2

    But my here stands formyself se here stands for Special Edition

    https://github.com/abh/geodns/issues/50

    I found other similar questions in issues but no solution

    How to distinguish between geo records and normal records?

  • Match by IP Prefix/24 or /32

    Match by IP Prefix/24 or /32

    Hi Team

    I am unsuccessful in getting domain resolved by matching IP address or IP prefix. I think it is supported. Could you please give me some example config for the same.

  • Matching by ip-addresses/networks

    Matching by ip-addresses/networks

    Thank you for that awesome software. However, there's a small draw I've been unable to solve by now: A number of popular open dns-providers (Cloudflare) do not pass client's source network via edns. It'd be really helpful to match by source ip-address (networks) to build a list of exclusions in addition to matching by countries/regions. Of course, one can edit mmdb-databases directly but this feature would greatly improve flexibility.

A DNS client in Go that supports Google DNS over HTTPS

dingo A DNS client (stub resolver) implemented in Go for the Google DNS-over-HTTPS. It effectively encrypts all your DNS traffic. It also supports Ope

Nov 9, 2022
A smol DNS server (<100 loc) that's configured with a static JSON file. Useful for split-dns.

A smol DNS server (<100 loc) that's configured with a static JSON file. Useful for split-dns.

Jul 27, 2022
dnscrypt-proxy 2 - A flexible DNS proxy, with support for encrypted DNS protocols.
dnscrypt-proxy 2 - A flexible DNS proxy, with support for encrypted DNS protocols.

Overview A flexible DNS proxy, with support for modern encrypted DNS protocols such as DNSCrypt v2, DNS-over-HTTPS and Anonymized DNSCrypt. dnscrypt-p

Jan 3, 2023
🐶 Command-line DNS Client for Humans. Written in Golang
🐶 Command-line DNS Client for Humans. Written in Golang

doggo ?? Command-line DNS client for humans doggo is a modern command-line DNS client (like dig) written in Golang. It outputs information in a neat c

Dec 29, 2022
GRONG is a DNS (Domain Name System) authoritative name server.It is more a research project than a production-ready program.

GRONG (Gross and ROugh Nameserver written in Go) is a DNS (Domain Name System) authoritative name server. It is intended as a research project and is

Oct 17, 2020
CoreDNS is a DNS server that chains plugins
CoreDNS is a DNS server that chains plugins

CoreDNS is a DNS server/forwarder, written in Go, that chains plugins. Each plugin performs a (DNS) function. CoreDNS is a Cloud Native Computing Foun

Jan 3, 2023
Are you forwarding DNS traffic to another server for some reason, but want to make sure only queries for certain names are passed? Say no more.

DNSFWD Redirect DNS traffic to an upstream. Get Latest: wget https://github.com/C-Sto/dnsfwd/releases/latest/download/dnsfwd_linux (replace linux with

Dec 16, 2022
cert-manager webhook & CoreDNS plugin for solving DNS01 challenge on self-hosted authoritative DNS server.
cert-manager webhook & CoreDNS plugin for solving DNS01 challenge on self-hosted authoritative DNS server.

cert-manager webhook & CoreDNS plugin This repo exists for a niche case scenario in which we are running cert-manager on one or multiple Kubernetes cl

Feb 4, 2022
Free and open source, powerful network-wide ads & trackers blocking DNS server
Free and open source, powerful network-wide ads & trackers blocking DNS server

Privacy protection center for you and your devices Free and open source, powerful network-wide ads & trackers blocking DNS server. AdGuard.com | Wiki

Nov 20, 2021
DNS Server

运行: nohup ./server serve -c ../conf/confile 2<&1 & 使用: 修改dns-client的dns服务器地址为dns-server的ip即可 部署目录结构描述: . ├── bin │   ├── nohup.out │   └── server //二进

Dec 2, 2021
A minimalist-configuration reverse DNS name server

autoreverse autoreverse is a specialized authoritative DNS server whose goal is to make it as easy as possible to auto-answer reverse queries without

Feb 14, 2022
DNS server with Redis-cache

GoNS DNS server for home usage. Can resolve by global DNS (external dns) and internal by searching in private_domains list. Also, GoNS can use redis-c

Dec 28, 2021
DNS library in Go

Alternative (more granular) approach to a DNS library Less is more. Complete and usable DNS library. All Resource Records are supported, including the

Dec 26, 2022
DNS over HTTPS [mirror]

dnss dnss is a daemon for using DNS over HTTPS. It can act as a proxy, receiving DNS requests and resolving them using DNS-over-HTTPs (DoH). This can

Dec 26, 2022
Multicast DNS library for Go

Introduction This package allows Go processes to publish multicast DNS style records onto their local network segment. For more information about mDNS

Oct 23, 2022
Resolver (DNS) cache daemon.
Resolver (DNS) cache daemon.

RESCACHED(1) Manual Page NAME rescached - DNS resolver cache daemon. Table of Contents SYNOPSIS OPTIONS DESCRIPTION FEATURES BEHIND THE DNS HOW CACHE

Nov 17, 2022
CUP - Cloudflare (DNS) Updater Program

CUP The Cloudflare (DNS) Updater CUP is a tool to turn CloudFlare DNS into a Dynamic DNS service. Documentation Documentation can be found in the docs

Jun 6, 2022
Fast and lightweight DNS proxy as ad-blocker for local network with many features

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 w

Jan 1, 2023
Fast DNS implementation for Go

Fast DNS implementation for Go Features 0 Dependency Similar Interface with net/http Fast DoH Server Co-create with fasthttp Fast DNS Client with rich

Dec 27, 2022