Compare commits

..

23 Commits

Author SHA1 Message Date
Star Brilliant
1c321be49c Release 2.1.1 2019-06-24 10:19:03 +08:00
Star Brilliant
852d0f6767 Fix a typo 2019-06-14 17:47:10 +08:00
Star Brilliant
a2d65bc89a Include DNS.SB's resolver in example configuration 2019-05-27 15:17:03 +08:00
Star Brilliant
6d8efe0939 Merge pull request #47 from rwv/master
slightly optimize the order of instructions in Dockerfile
2019-05-20 13:02:13 +08:00
seedgou
7e35e18164 optimize the order of instructions in Dockerfile 2019-05-20 11:17:40 +08:00
Star Brilliant
f40a7160b8 Merge pull request #46 from jangrewe/master
Add Dockerfiles
2019-05-17 22:50:33 +08:00
Jan Grewe
c8c22873bb Build separate Docker image for doh-server and doh-client
Make doh-client also listen on both IPv4 and IPv6
2019-05-16 20:47:40 +02:00
Star Brilliant
cb64f6694b Update the sample configuration to teach users how to listen on both IPv4 and IPv6 2019-05-17 02:37:52 +08:00
Jan Grewe
5c27ae02c0 Update Dockerfile to make doh-server listen on IPv4 and IPv6 2019-05-16 20:31:03 +02:00
Jan Grewe
f5ba377d2a Add Dockerfile 2019-05-16 00:28:46 +02:00
Star Brilliant
1ec9548ff1 Release 2.1.0 2019-05-14 01:39:46 +08:00
Star Brilliant
81f1cfba5d Disable static linking to Swift standard libraries
According to Apple: Swift compiler no longer supports statically linking the Swift libraries. They're included in the OS by default starting with macOS Mojave 10.14.4. For macOS Mojave 10.14.3 and earlier, there's an optional Swift library package that can be downloaded from "More Downloads" for Apple Developers at https://developer.apple.com/download/more/
2019-05-14 01:36:10 +08:00
Star Brilliant
ebba9c8ef5 Explain why ECS is disabled by some servers 2019-05-14 01:13:06 +08:00
Star Brilliant
6a2f2cea22 Merge pull request #44 from modib/quad9-dns-config
Added Quad9 servers in config.
2019-05-14 01:01:07 +08:00
B. Modi
63f07d20af Updated Quad9 config with ECS, DNSSEC info. 2019-05-13 09:55:20 -07:00
Star Brilliant
f0dec57e1a Merge pull request #45 from wsquasher/master
Use TCP when appropriate for the given query type/response
2019-05-13 11:40:26 +08:00
Wesley Squasher
f6b52a653a Use TCP when appropriate for the given query type/response 2019-05-12 08:17:52 +00:00
B. Modi
9a07f5b856 Added Quad9 servers in config. Good for malware threat prevention. 2019-05-10 13:50:17 -07:00
Star Brilliant
8787921faf Merge pull request #43 from modib/macos-build-error-fix
Make Makefile compatible with swift5 and older swift versions
2019-05-11 02:13:12 +08:00
B. Modi
1642730af0 Make Makefile compatible with swift5 and older swift versions 2019-05-10 11:02:07 -07:00
Ming Aldrich-Gan
2332d9b7c1 Add local_addr configuration for doh-server (#39)
* Add local_addr configuration for doh-server

This commit adds a `local_addr` string value to `doh-server.conf`, specifying the IP address and port from which outgoing calls to upstream DNS resolvers should originate. This value is set as the `udpClient`'s and `tcpClient`'s `Dialer.LocalAddr` when initializing a `NewServer`. If the value is left empty in `doh-server.conf`, it defaults to the first `listen` address (which in turn defaults to `"127.0.0.1:8053"`).

One use case for this would be if `doh-server` is proxying requests to a local DNS resolver (e.g. `unbound` or Pi-hole). Up to version 2.0.0, all DNS queries from `doh-server` are sent from `127.0.0.1` (even if the `listen` address is set to a different loopback IP address), making it hard to distinguish them from all other local DNS queries from the same machine in the query logs.

* Revert defaulting of local_addr to listen address

This commit reverts to the existing behavior when `conf.LocalAddr == ""`, i.e. letting `dns.Client` instantiate its own `Dialer` with the default local address.

* Fixup comment in configuration file

* Log errors from Dialer instantiation (e.g. if LocalAddr port is missing)

* Fixup other comment in configuration file

* Return error and log fatal
2019-03-25 04:01:32 +08:00
Star Brilliant
7f5a23584f Release 2.0.1 2019-03-24 19:11:12 +08:00
Sherlock Holo
17e5848178 Fix random selector (#41)
* Fix a bug: when only have one upstream, random selector will panic

Signed-off-by: Sherlock Holo <sherlockya@gmail.com>
2019-03-24 09:13:14 +08:00
15 changed files with 155 additions and 48 deletions

View File

@@ -4,6 +4,22 @@ This Changelog records major changes between versions.
Not all changes are recorded. Please check git log for details.
## Version 2.1.1
- Add a set of Dockerfile contributed by the community
- Include DNS.SB's resolver in example configuration
## Version 2.1.0
- Add `local_addr` configuration for doh-server (#39)
- Fix a problem when compiling on macOS 10.14.4 or newer
- Add Quad9 DoH server to the example `doh-client.conf`
- Use TCP when appropriate for the given query type/response (AXFR/IXFR)
## Version 2.0.1
- Fix a crash with the random load balancing algorithm.
## Version 2.0.0
**This is a breaking change!** Please update the configuration file after upgrading.

22
Dockerfile.client Normal file
View File

@@ -0,0 +1,22 @@
FROM golang:alpine AS build-env
RUN apk add --no-cache git make
WORKDIR /src
ADD . /src
RUN make doh-client/doh-client
FROM alpine:latest
COPY --from=build-env /src/doh-client/doh-client /doh-client
ADD doh-client/doh-client.conf /doh-client.conf
RUN sed -i '$!N;s/"127.0.0.1:53",.*"127.0.0.1:5380",/":53",/;P;D' /doh-client.conf
RUN sed -i '$!N;s/"\[::1\]:53",.*"\[::1\]:5380",/":5380",/;P;D' /doh-client.conf
EXPOSE 53
EXPOSE 5380
ENTRYPOINT ["/doh-client"]
CMD ["-conf", "/doh-client.conf"]

20
Dockerfile.server Normal file
View File

@@ -0,0 +1,20 @@
FROM golang:alpine AS build-env
RUN apk add --no-cache git make
WORKDIR /src
ADD . /src
RUN make doh-server/doh-server
FROM alpine:latest
COPY --from=build-env /src/doh-server/doh-server /doh-server
ADD doh-server/doh-server.conf /doh-server.conf
RUN sed -i '$!N;s/"127.0.0.1:8053",\s*"\[::1\]:8053",/":8053",/;P;D' /doh-server.conf
EXPOSE 8053
ENTRYPOINT ["/doh-server"]
CMD ["-conf", "/doh-server.conf"]

View File

@@ -6,7 +6,7 @@ PREFIX = /usr/local
all: doh-logger
doh-logger: doh-logger.swift
$(SWIFTC) -o $@ -O -static-stdlib $<
$(SWIFTC) -o $@ -O $<
clean:
rm -f doh-logger

View File

@@ -155,7 +155,7 @@ func NewClient(conf *config.Config) (c *Client, err error) {
switch c.conf.Upstream.UpstreamSelector {
case config.NginxWRR:
if c.conf.Other.Verbose {
log.Println(config.NginxWRR, " mode start")
log.Println(config.NginxWRR, "mode start")
}
s := selector.NewNginxWRRSelector(time.Duration(c.conf.Other.Timeout) * time.Second)
@@ -175,7 +175,7 @@ func NewClient(conf *config.Config) (c *Client, err error) {
case config.LVSWRR:
if c.conf.Other.Verbose {
log.Println(config.LVSWRR, " mode start")
log.Println(config.LVSWRR, "mode start")
}
s := selector.NewLVSWRRSelector(time.Duration(c.conf.Other.Timeout) * time.Second)
@@ -195,7 +195,7 @@ func NewClient(conf *config.Config) (c *Client, err error) {
default:
if c.conf.Other.Verbose {
log.Println(config.Random, " mode start")
log.Println(config.Random, "mode start")
}
// if selector is invalid or random, use random selector, or should we stop program and let user knows he is wrong?

View File

@@ -4,6 +4,9 @@ listen = [
"127.0.0.1:5380",
"[::1]:53",
"[::1]:5380",
## To listen on both 0.0.0.0:53 and [::]:53, use the following line
# ":53",
]
# HTTP path for upstream resolver
@@ -21,25 +24,30 @@ upstream_selector = "random"
# weight = 50
## CloudFlare's resolver, bad ECS, good DNSSEC
#[[upstream.upstream_google]]
# url = "https://cloudflare-dns.com/dns-query"
# weight = 50
## CloudFlare's resolver, bad ECS, good DNSSEC
#[[upstream.upstream_google]]
# url = "https://1.1.1.1/dns-query"
# weight = 50
# CloudFlare's resolver, bad ECS, good DNSSEC
## ECS is disabled for privacy by design: https://developers.cloudflare.com/1.1.1.1/nitty-gritty-details/#edns-client-subnet
[[upstream.upstream_ietf]]
url = "https://cloudflare-dns.com/dns-query"
weight = 50
## CloudFlare's resolver, bad ECS, good DNSSEC
## ECS is disabled for privacy by design: https://developers.cloudflare.com/1.1.1.1/nitty-gritty-details/#edns-client-subnet
## Note that some ISPs have problems connecting to 1.1.1.1, try 1.0.0.1 if problems happen.
#[[upstream.upstream_ietf]]
# url = "https://1.1.1.1/dns-query"
# weight = 50
## DNS.SB's resolver, good ECS, good DNSSEC
## The provider claims no logging: https://dns.sb/doh/
#[[upstream.upstream_ietf]]
# url = "https://doh.dns.sb/dns-query"
# weight = 50
## Quad9's resolver, bad ECS, good DNSSEC
## ECS is disabled for privacy by design: https://www.quad9.net/faq/#What_is_EDNS_Client-Subnet
#[[upstream.upstream_ietf]]
# url = "https://9.9.9.9/dns-query"
# weight = 50
## Google's experimental resolver, good ECS, good DNSSEC
#[[upstream.upstream_ietf]]
# url = "https://dns.google.com/experimental"

View File

@@ -42,7 +42,7 @@ func (rs *RandomSelector) Add(url string, upstreamType UpstreamType) (err error)
}
func (rs *RandomSelector) Get() *Upstream {
return rs.upstreams[rand.Intn(len(rs.upstreams)-1)]
return rs.upstreams[rand.Intn(len(rs.upstreams))]
}
func (rs *RandomSelector) StartEvaluate() {}

View File

@@ -24,6 +24,6 @@
package main
const (
VERSION = "2.0.0"
VERSION = "2.1.1"
USER_AGENT = "DNS-over-HTTPS/" + VERSION + " (+https://github.com/m13253/dns-over-https)"
)

View File

@@ -31,6 +31,7 @@ import (
type config struct {
Listen []string `toml:"listen"`
LocalAddr string `toml:"local_addr"`
Cert string `toml:"cert"`
Key string `toml:"key"`
Path string `toml:"path"`

View File

@@ -2,8 +2,15 @@
listen = [
"127.0.0.1:8053",
"[::1]:8053",
## To listen on both 0.0.0.0:8053 and [::]:8053, use the following line
# ":8053",
]
# Local address and port for upstream DNS
# If left empty, a local address is automatically chosen.
local_addr = ""
# TLS certification file
# If left empty, plain-text HTTP will be used.
# You are recommended to leave empty and to use a server load balancer (e.g.

View File

@@ -110,6 +110,9 @@ func main() {
conf.Verbose = true
}
server := NewServer(conf)
server, err := NewServer(conf)
if err != nil {
log.Fatalln(err)
}
_ = server.Start()
}

View File

@@ -56,22 +56,41 @@ type DNSRequest struct {
errtext string
}
func NewServer(conf *config) (s *Server) {
s = &Server{
func NewServer(conf *config) (*Server, error) {
timeout := time.Duration(conf.Timeout) * time.Second
s := &Server{
conf: conf,
udpClient: &dns.Client{
Net: "udp",
UDPSize: dns.DefaultMsgSize,
Timeout: time.Duration(conf.Timeout) * time.Second,
Timeout: timeout,
},
tcpClient: &dns.Client{
Net: "tcp",
Timeout: time.Duration(conf.Timeout) * time.Second,
Timeout: timeout,
},
servemux: http.NewServeMux(),
}
if conf.LocalAddr != "" {
udpLocalAddr, err := net.ResolveUDPAddr("udp", conf.LocalAddr)
if err != nil {
return nil, err
}
tcpLocalAddr, err := net.ResolveTCPAddr("tcp", conf.LocalAddr)
if err != nil {
return nil, err
}
s.udpClient.Dialer = &net.Dialer{
Timeout: timeout,
LocalAddr: udpLocalAddr,
}
s.tcpClient.Dialer = &net.Dialer{
Timeout: timeout,
LocalAddr: tcpLocalAddr,
}
}
s.servemux.HandleFunc(conf.Path, s.handlerFunc)
return
return s, nil
}
func (s *Server) Start() error {
@@ -244,19 +263,38 @@ func (s *Server) patchRootRD(req *DNSRequest) *DNSRequest {
return req
}
// Return the position index for the question of qtype from a DNS msg, otherwise return -1
func (s *Server) indexQuestionType(msg *dns.Msg, qtype uint16) int {
for i, question := range msg.Question {
if question.Qtype == qtype {
return i
}
}
return -1
}
func (s *Server) doDNSQuery(ctx context.Context, req *DNSRequest) (resp *DNSRequest, err error) {
// TODO(m13253): Make ctx work. Waiting for a patch for ExchangeContext from miekg/dns.
numServers := len(s.conf.Upstream)
for i := uint(0); i < s.conf.Tries; i++ {
req.currentUpstream = s.conf.Upstream[rand.Intn(numServers)]
if !s.conf.TCPOnly {
// Use TCP if always configured to or if the Query type dictates it (AXFR)
if s.conf.TCPOnly || (s.indexQuestionType(req.request, dns.TypeAXFR) > -1) {
req.response, _, err = s.tcpClient.Exchange(req.request, req.currentUpstream)
} else {
req.response, _, err = s.udpClient.Exchange(req.request, req.currentUpstream)
if err == nil && req.response != nil && req.response.Truncated {
log.Println(err)
req.response, _, err = s.tcpClient.Exchange(req.request, req.currentUpstream)
}
} else {
req.response, _, err = s.tcpClient.Exchange(req.request, req.currentUpstream)
// Retry with TCP if this was an IXFR request and we only received an SOA
if (s.indexQuestionType(req.request, dns.TypeIXFR) > -1) &&
(len(req.response.Answer) == 1) &&
(req.response.Answer[0].Header().Rrtype == dns.TypeSOA) {
req.response, _, err = s.tcpClient.Exchange(req.request, req.currentUpstream)
}
}
if err == nil {
return req, nil

View File

@@ -24,6 +24,6 @@
package main
const (
VERSION = "2.0.0"
VERSION = "2.1.1"
USER_AGENT = "DNS-over-HTTPS/" + VERSION + " (+https://github.com/m13253/dns-over-https)"
)

9
go.mod
View File

@@ -5,9 +5,8 @@ go 1.12
require (
github.com/BurntSushi/toml v0.3.1
github.com/gorilla/handlers v1.4.0
github.com/miekg/dns v1.1.6
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
golang.org/x/net v0.0.0-20190311183353-d8887717615a
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // indirect
golang.org/x/sys v0.0.0-20190312061237-fead79001313 // indirect
github.com/miekg/dns v1.1.14
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 // indirect
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
golang.org/x/sys v0.0.0-20190621203818-d432491b9138 // indirect
)

27
go.sum
View File

@@ -2,24 +2,17 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/gorilla/handlers v1.4.0 h1:XulKRWSQK5uChr4pEgSE4Tc/OcmnU9GJuSwdog/tZsA=
github.com/gorilla/handlers v1.4.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0=
github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.6 h1:jVwb4GDwD65q/gtItR/lIZHjNH93QfeGxZUkzJcW9mc=
github.com/miekg/dns v1.1.6/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
github.com/miekg/dns v1.1.14 h1:wkQWn9wIp4mZbwW8XV6Km6owkvRPbOiV004ZM2CkGvA=
github.com/miekg/dns v1.1.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95 h1:fY7Dsw114eJN4boqzVSbpVHO6rTdhq6/GnXeu+PKnzU=
golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190308023053-584f3b12f43e h1:K7CV15oJ823+HLXQ+M7MSMrUg8LjfqY7O3naO+8Pp/I=
golang.org/x/sys v0.0.0-20190308023053-584f3b12f43e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190621203818-d432491b9138 h1:t8BZD9RDjkm9/h7yYN6kE8oaeov5r9aztkB7zKA5Tkg=
golang.org/x/sys v0.0.0-20190621203818-d432491b9138/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=