-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #93 in DNS/adguard-dns from fix/414 to master
* commit '914eb612cd0da015b98c151b7ac603fb4126a2c3': Add bootstrap DNS to readme Fix review comments Close test upstream Added bootstrap DNS to the config file DNS healthcheck now uses the upstream package methods goimports files Added CoreDNS plugin setup and replaced forward Added factory method for creating DNS upstreams Added health-check method Added persistent connections cache Upstream plugin prototype
- Loading branch information
Showing
13 changed files
with
955 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package upstream | ||
|
||
import ( | ||
"crypto/tls" | ||
"time" | ||
|
||
"github.com/miekg/dns" | ||
"golang.org/x/net/context" | ||
) | ||
|
||
// DnsUpstream is a very simple upstream implementation for plain DNS | ||
type DnsUpstream struct { | ||
endpoint string // IP:port | ||
timeout time.Duration // Max read and write timeout | ||
proto string // Protocol (tcp, tcp-tls, or udp) | ||
transport *Transport // Persistent connections cache | ||
} | ||
|
||
// NewDnsUpstream creates a new DNS upstream | ||
func NewDnsUpstream(endpoint string, proto string, tlsServerName string) (Upstream, error) { | ||
|
||
u := &DnsUpstream{ | ||
endpoint: endpoint, | ||
timeout: defaultTimeout, | ||
proto: proto, | ||
} | ||
|
||
var tlsConfig *tls.Config | ||
|
||
if proto == "tcp-tls" { | ||
tlsConfig = new(tls.Config) | ||
tlsConfig.ServerName = tlsServerName | ||
} | ||
|
||
// Initialize the connections cache | ||
u.transport = NewTransport(endpoint) | ||
u.transport.tlsConfig = tlsConfig | ||
u.transport.Start() | ||
|
||
return u, nil | ||
} | ||
|
||
// Exchange provides an implementation for the Upstream interface | ||
func (u *DnsUpstream) Exchange(ctx context.Context, query *dns.Msg) (*dns.Msg, error) { | ||
|
||
resp, err := u.exchange(u.proto, query) | ||
|
||
// Retry over TCP if response is truncated | ||
if err == dns.ErrTruncated && u.proto == "udp" { | ||
resp, err = u.exchange("tcp", query) | ||
} else if err == dns.ErrTruncated && resp != nil { | ||
// Reassemble something to be sent to client | ||
m := new(dns.Msg) | ||
m.SetReply(query) | ||
m.Truncated = true | ||
m.Authoritative = true | ||
m.Rcode = dns.RcodeSuccess | ||
return m, nil | ||
} | ||
|
||
if err != nil { | ||
resp = &dns.Msg{} | ||
resp.SetRcode(resp, dns.RcodeServerFailure) | ||
} | ||
|
||
return resp, err | ||
} | ||
|
||
// Clear resources | ||
func (u *DnsUpstream) Close() error { | ||
|
||
// Close active connections | ||
u.transport.Stop() | ||
return nil | ||
} | ||
|
||
// Performs a synchronous query. It sends the message m via the conn | ||
// c and waits for a reply. The conn c is not closed. | ||
func (u *DnsUpstream) exchange(proto string, query *dns.Msg) (r *dns.Msg, err error) { | ||
|
||
// Establish a connection if needed (or reuse cached) | ||
conn, err := u.transport.Dial(proto) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Write the request with a timeout | ||
conn.SetWriteDeadline(time.Now().Add(u.timeout)) | ||
if err = conn.WriteMsg(query); err != nil { | ||
conn.Close() // Not giving it back | ||
return nil, err | ||
} | ||
|
||
// Write response with a timeout | ||
conn.SetReadDeadline(time.Now().Add(u.timeout)) | ||
r, err = conn.ReadMsg() | ||
if err != nil { | ||
conn.Close() // Not giving it back | ||
} else if err == nil && r.Id != query.Id { | ||
err = dns.ErrId | ||
conn.Close() // Not giving it back | ||
} | ||
|
||
if err == nil { | ||
// Return it back to the connections cache if there were no errors | ||
u.transport.Yield(conn) | ||
} | ||
return r, err | ||
} |
Oops, something went wrong.