Commit Graph

286 Commits

Author SHA1 Message Date
Miek Gieben fef7963e99 remove newlines
Signed-off-by: Miek Gieben <miek@miek.nl>
2018-11-28 22:32:50 +00:00
Miek Gieben ab67d69d9b review
Signed-off-by: Miek Gieben <miek@miek.nl>
2018-11-28 22:25:28 +00:00
Miek Gieben 74dbfccc11 Code Review
Signed-off-by: Miek Gieben <miek@miek.nl>
2018-11-28 18:42:48 +00:00
Miek Gieben 2c18e7259a Add MsgAcceptFunc in server
Generalize the srv.Unsafe and make it pluggeable. Also add a default
accept function that allows to discard malformed DNS messages very early
on. Before we allocate and parse anything furher.

Also re-use the client's message when sending a reply.

Signed-off-by: Miek Gieben <miek@miek.nl>
2018-11-28 18:42:48 +00:00
Tom Thorogood ec3443f85d Fix TCP connection tracking memory leak (#808)
* Add test that srv.conns is empty in checkInProgressQueriesAtShutdownServer

* Track ResponseWriter Close without nil-ing tcp

* Remove LocalAddr and RemoteAddr panic after Close

This is no longer needed as the tcp field is no longer set to nil in
Close.

* Add more explicit WriteMsg panic after Close

Previously this would panic with `dns: Write called after Close` which
is obviously less clear.

* Panic if Hijack is called after Close

Previously this worked, but later calls to Write would panic. This is
more explicit.

* Return an error if Close called multiple times

Neither io.Closer, nor ResponseWriter, provide any guarantees about the
behaviour of multiple calls to Close. This was made explicit in
https://golang.org/cl/8575043 and in practice implementations differ
wildly.

This matches ShutdownContext which returns an error if called multiple
times.

* Check map len under lock in checkInProgressQueriesAtShutdownServer

* Correct error message in checkInProgressQueriesAtShutdownServer

* Remove panic-after-Close from Hijack

* Return errors, not panic, on Write after Close
2018-11-03 09:44:07 +00:00
Tom Thorogood a3f088363b Hold srv.lock while calling SetReadDeadline (#780)
* Hold srv.lock while calling SetReadDeadline

* Only hold the read lock in readTCP and readUDP
2018-10-09 18:46:15 +01:00
Tom Thorogood 36ffedf7d0
Avoid overriding aLongTimeAgo read deadline (#774)
* Avoid overriding aLongTimeAgo read deadline

The (*Server).readTCP and (*Server).readUDP methods both call
SetReadDeadline. If they race with ShutdownContext, they can override
the aLongTimeAgo read deadline that is set in ShutdownContext. That
will cause ShutdownContext to hang or timeout.

* Reword readTCP comment
2018-10-06 01:46:28 +09:30
Tom Thorogood 008c8ca764 Explicitly panic after (*response).Close (#769)
* Explicitly panic after (*response).Close

* Prefix panics with package name

* Harden TestResponseAfterClose by comparing panic message
2018-10-04 07:39:21 +01:00
Tom Thorogood 7f61c6631b
Fix dominikh/go-tools nits (#758)
* Remove unused functions and consts

* Address gosimple nits

* Address staticcheck nits

This excludes several that were intentional or weren't actual errors.

* Reduce size of lex struct

This reduces the size of the lex struct by 8 bytes from:
  lex.token string: 0-16 (size 16, align 8)
  lex.tokenUpper string: 16-32 (size 16, align 8)
  lex.length int: 32-40 (size 8, align 8)
  lex.err bool: 40-41 (size 1, align 1)
  lex.value uint8: 41-42 (size 1, align 1)
  padding: 42-48 (size 6, align 0)
  lex.line int: 48-56 (size 8, align 8)
  lex.column int: 56-64 (size 8, align 8)
  lex.torc uint16: 64-66 (size 2, align 2)
  padding: 66-72 (size 6, align 0)
  lex.comment string: 72-88 (size 16, align 8)
to:
  lex.token string: 0-16 (size 16, align 8)
  lex.tokenUpper string: 16-32 (size 16, align 8)
  lex.length int: 32-40 (size 8, align 8)
  lex.err bool: 40-41 (size 1, align 1)
  lex.value uint8: 41-42 (size 1, align 1)
  lex.torc uint16: 42-44 (size 2, align 2)
  padding: 44-48 (size 4, align 0)
  lex.line int: 48-56 (size 8, align 8)
  lex.column int: 56-64 (size 8, align 8)
  lex.comment string: 64-80 (size 16, align 8)

* Reduce size of response struct

This reduces the size of the response struct by 8 bytes from:
  response.msg []byte: 0-24 (size 24, align 8)
  response.hijacked bool: 24-25 (size 1, align 1)
  padding: 25-32 (size 7, align 0)
  response.tsigStatus error: 32-48 (size 16, align 8)
  response.tsigTimersOnly bool: 48-49 (size 1, align 1)
  padding: 49-56 (size 7, align 0)
  response.tsigRequestMAC string: 56-72 (size 16, align 8)
  response.tsigSecret map[string]string: 72-80 (size 8, align 8)
  response.udp *net.UDPConn: 80-88 (size 8, align 8)
  response.tcp net.Conn: 88-104 (size 16, align 8)
  response.udpSession *github.com/tmthrgd/dns.SessionUDP: 104-112 (size 8, align 8)
  response.writer github.com/tmthrgd/dns.Writer: 112-128 (size 16, align 8)
  response.wg *sync.WaitGroup: 128-136 (size 8, align 8)
to:
  response.msg []byte: 0-24 (size 24, align 8)
  response.hijacked bool: 24-25 (size 1, align 1)
  response.tsigTimersOnly bool: 25-26 (size 1, align 1)
  padding: 26-32 (size 6, align 0)
  response.tsigStatus error: 32-48 (size 16, align 8)
  response.tsigRequestMAC string: 48-64 (size 16, align 8)
  response.tsigSecret map[string]string: 64-72 (size 8, align 8)
  response.udp *net.UDPConn: 72-80 (size 8, align 8)
  response.tcp net.Conn: 80-96 (size 16, align 8)
  response.udpSession *github.com/tmthrgd/dns.SessionUDP: 96-104 (size 8, align 8)
  response.writer github.com/tmthrgd/dns.Writer: 104-120 (size 16, align 8)
  response.wg *sync.WaitGroup: 120-128 (size 8, align 8)
2018-09-27 04:02:05 +09:30
Tom Thorogood 60d113313c Move ServeMux into seperate file (#753)
This reduces the clutter in server.go.
2018-09-26 10:20:48 +01:00
Daniel Selifonov ab16005053 Bugfix for miekg/dns#748 (#749)
* Bugfix for miekg/dns#748

w.msg was being prematurely cleared prior to use by TsigVerify

* Modified patch after feedback from tmthrgd

Added a disposeBuffer method to the server that's passed a response. This wipes the reference to and frees the buffer used to store the message after TSIG validation has occured, not before. Since the pool is an attribute of the server (and the logic refers to a server UDPSize attribute), it made sense to make this a function of the server rather than a function of the response.

* Added TestServerRoundtripTsig to server_test.go

This test generates a TSIG signed query, and makes sure that server TSIG validation does not produce an error.

* Fixed data races introduced by TestServerRoundtripTsig

* Simplified error signalling in TestServerRoundtripTsig

* RunLocalUDPServerWithFinChan variadic closure argument added

This (clever hack suggested by tmthrgd) allows specifying field values (like TsigSecret) on Server instances at test time without making the race detector grouchy, but is backwards compatible with existing invocations of RunLocalUDPServerWithFinChan.
2018-09-26 09:19:35 +01:00
chantra 833bf76c28 [tls] Carry TLS state within (possibly) response writer (#728)
* [tls] Carry TLS state within (possibly) response writer

This allows a server to make decision wether or not the link used to
connect to the DNS server is using TLS.
This can be used by the handler for instance to (but not limited to):
- log that the request was TLS vs TCP
- craft specific responsed knowing that the link is secured
- return custom answers based on client cert (if provided)
...

Fixes #711

* Address @tmthrgd comments:
- do not check whether w.tcp is nil
- create RR after setting txt value

* Address @miekg comments.

Attempt to make a TLS connection state specific test, it goes over
testing each individual server types (TLS, TCP, UDP) and validate that
tls.Connectionstate is only accessible when expected.

* ConnectionState() returns value instead of pointer

* * make ConnectionStater.ConnectionState() return a pointer again
* rename interface ConnectionState to ConnectionStater
* fix nits pointed by @tmthrgd

* @tmthrgd comment: Do not use concret type in `ConnectionState`
2018-09-22 18:34:55 +01:00
Tom Thorogood b0dc93d276
Make Shutdown wait for connections to terminate gracefully (#717)
* Make Shutdown wait for connections to terminate gracefully

* Add graceful shutdown test files from #713

* Tidy up graceful shutdown tests

* Call t.Error directly in checkInProgressQueriesAtShutdownServer

* Remove timeout arguments from RunLocal*ServerWithFinChan

* Merge defers together in (*Server).serve

This removes the defer from the UDP path, in favour of directly
calling (*sync.WaitGroup).Done after (*Serve).serveDNS has
returned.

* Replace checkInProgressQueriesAtShutdownServer implementation

This performs dialing, writing and reading as three seperate steps.

* Add sleep after writing shutdown test messages

* Avoid race condition when setting server timeouts

Server timeouts cannot be set after the server has started without
triggering the race detector. The timeout's are not strictly needed, so
remove them.

* Use a sync.Cond for testShutdownNotify

Using a chan erroneously triggered the race detector, using a sync.Cond
avoids that problem.

* Remove TestShutdownUDPWithContext

This doesn't really add anything.

* Move shutdown and conn into (*Server).init

* Only log ResponseWriter.WriteMsg error once

* Test that ShutdownContext waits for the reply

* Remove stray newline from diff

* Rename err to ctxErr in ShutdownContext

* Reword testShutdownNotify comment
2018-09-13 23:06:28 +09:30
Tom Thorogood e875a31a5c
Add SO_REUSEPORT support (#736)
* Use strings.TrimSuffix in ListenAndServe for TLS

This replaces the if/else statements with something simpler.

Interestingly, the first pull request I submitted to this library was
to fix the tcp6-tls case way back in 4744e915eb.

* Add SO_REUSEPORT implementation

Fixes #654

* Rename Reuseport field to ReusePort

* Rename supportsReuseport to match ReusePort

* Rename listenUDP and listenTCP file to listen_*.go
2018-09-10 20:12:54 +09:30
Tom Thorogood bf6da3a5bd Reduce UDP server memory usage (#735)
* Clear the response.msg field after unpacking

The allocated buffer cannot be freed by the garbage collector while the
response is alive, by clearing msg here, the GC can collect the buffer
sooner.

* Use a sync.Pool for UDP message buffers

* Return UDP message buffer to pool in all paths

* Move udpPool.New closure out of (*Server).init

The closure used to capture the *Server which would cause a reference
loop and prevent it from ever being released by the garbage collector.

This also gives the closure a more obvious name in memory profiles:
  github.com/miekg/dns.makeUDPBuffer.func1 rather than
  github.com/miekg/dns.(*Server).init.func1.
2018-09-08 17:15:17 +01:00
Tom Thorogood 4bda1db839 Improve documentation of maxWorkersCount const (#726)
While I'm here, rename it to maxIdleWorkersCount so it's purpose is
clearer.

Updates #722
Updates #725
2018-08-16 17:10:20 +01:00
Tom Thorogood c9b812d1d9 Remove redundant parenthesis (#727)
* Remove redundant parenthesis

These were caught with:
    gofmt -r '(a) -> a' -w *.go

This commit only includes the changes where the formatting makes the
ordering of operations clear.

* Remove more redundant parenthesis

These were caught with:
    gofmt -r '(a) -> a' -w *.go

This commit includes the remaining changes where the formatting does not
make the ordering of operations as clear as the previous commit.
2018-08-16 17:05:27 +01:00
Tom Thorogood 208cd1e89e Simplify unlocking dance in *Serve functions (#719) 2018-08-10 22:50:48 +01:00
Tom Thorogood b559d43c31 Abstract shutdown checking into seperate function (#716) 2018-07-28 13:47:30 +01:00
Uladzimir Trehubenka 621df0907e Make MaxTCPQueries configurable (#673) 2018-05-14 20:12:20 +01:00
Uladzimir Trehubenka 98a1ef4565 Use workers instead spawning goroutines for each incoming DNS request (#664)
* Use workers instead spawning goroutines for each incoming DNS request

* Replace count (int) with inUse (bool)
2018-05-09 16:44:32 +01:00
Tom Thorogood 01d59357d4 Cleanup serve function (reland) (#667)
* Split central ServeDNS code out of (*Server).serve

* Add UDP and TCP specific (*Server).serve wrappers

* Move UDP serve functionality into serveUDPPacket

* Merge serve into serveTCPConn

* Cleanup serveTCPConn replacing goto with for

* defer Close in serveTCPConn

* Remove remoteAddr field from response struct

* Fix broken tsigSecret check in serveDNS

* Reorder serveDNS arguments

This makes it consistent with the ordering of arguments to
serveUDPPacket and serveTCPConn.
2018-04-06 16:09:55 +01:00
Miek Gieben 7fdfb0141b Revert "Cleanup serve function (#653)"
This reverts commit d174bbf0a5.
2018-04-01 12:27:36 +01:00
Tom Thorogood d174bbf0a5 Cleanup serve function (#653)
* Split central ServeDNS code out of (*Server).serve

* Add UDP and TCP specific (*Server).serve wrappers

* Move UDP serve functionality into serveUDPPacket

* Merge serve into serveTCPConn

* Cleanup serveTCPConn replacing goto with for

* defer Close in serveTCPConn

* Remove remoteAddr field from response struct

* Fix broken tsigSecret check in serveDNS

* Reorder serveDNS arguments

This makes it consistent with the ordering of arguments to
serveUDPPacket and serveTCPConn.
2018-03-30 14:50:27 +01:00
Miek Gieben 43913f2f4f
Fix for CVE-2017-15133 TCP DOS (#631)
serveTCP calls reader.ReadTCP in the accept loop rather than in
the per-connection goroutine. If an attacker opens a connection
and leaves it idle, this will block the accept loop until the
connection times out (2s by default). During this time no other
incoming connections will succeed, preventing legitimate queries
from being answered.

This commit moves the call to reader.ReadTCP into the per-connection
goroutine. It also adds a missing call to Close whose absence allowed
file-descirptors to leak in select cases.

This attack and fix have no impact on serving UDP queries.
2018-01-25 10:36:19 +00:00
Tom Thorogood f5ac34d755 Fix TCP Shutdown 'use of closed network connection' (#623)
The check for srv.started being false is in the wrong place, it should
be after Accept not after ReadTCP. If Shutdown is called, serveTCP will
currently return a 'use of closed network connection' error, which is
undesired.

This commit mirrors the behaviour of serveUDP with respect to Shutdown.
2018-01-10 13:37:59 +00:00
Tom Thorogood ddd8477be2 Ignore malformed UDP datagrams without headers (#622)
Ignore malformed UDP datagrams with incomplete DNS headers
2018-01-10 07:51:00 +00:00
Tom Thorogood 69d25e845f Fixes #613 & #619 (#621)
* Do not reutrn ErrShortRead in readUDP

A read of zero bytes indicates a peer shutdown for TCP sockets -- and
thus returning ErrShortRead is fine in readTCP -- but not for UDP
sockets. For UDP sockets a read of zero bytes literally indicates a
zero-byte datagram, and is a valid return value not indicating an error.

Removing this case will cause readUDP to correctly return a zero-byte
message.

* Return non-temporary error from serveUDP loop

Fixes #613
2018-01-09 13:57:26 +00:00
Miek Gieben e2db8456df
Revert "Fixes #613 (#617)" (#620)
This reverts commit ac8cd7878c.
2018-01-09 08:03:27 +00:00
Twitch ac8cd7878c Fixes #613 (#617)
* Fixes #613

* use net.Error interface for detecting temporary errors
2018-01-06 16:01:19 +00:00
Matthijs Mekking 99c447f9f6 TSIG name must be presented in canonical form (#574)
* TSIG name must be presented in canonical form

Update the documentation to make clear that the zonename in the
TsigSecret map must be in canonical form.

* Reference RFC 4034 for canonical form
2017-11-17 13:17:47 +00:00
Miek Gieben 9fc4eb252e
Server: drop inflight waitgroup (#561)
* Server: drop inflight waitgroup

This drops the waitgroup in Server, the suspicion is this can make the server
fail to stop; doing this make graceful shutdown not work.

Add test that tries to find a race between starting on stopping race;
there was a data race on srv.Inflight.

The coredns' TestReadme doesn't race anymore with this as it did with
the more evasive PR #546.
2017-11-10 10:33:17 +00:00
Miek Gieben 4bb60ce4d8
Revert "server: drop graceful handling (#546)" (#560)
This reverts commit 8223ae840e.
2017-11-09 21:01:09 +00:00
Miek Gieben 8223ae840e
server: drop graceful handling (#546)
Drop all graceful handling. There is just too much locking in
waitgrouping going on for very little gain; deal with it.

Make the error handling between serve{TCP,UDP} identical.
2017-11-09 09:38:14 +00:00
Tom Thorogood 4744e915eb Fix tcp6-tls support in (*Server).ListenAndServe(). (#427)
In the switch statement srv.Net is matched for tcp6-tls but
then compared against tcp6 within the case statement. This
causes tcp6-tls to be equivalent to tcp-tls and not specific
to tcp6. The `network = "tcp6"` line was previously unreachable.

This change corrects this and ensures tcp6-tls listens on IPv6
only.
2016-12-09 07:38:01 +00:00
Santhosh Manohar 271c58e0c1 Add nil check for interface value in ActivateAndServe (#419)
Signed-off-by: Santhosh Manohar <santhosh@docker.com>
2016-11-22 06:12:14 +00:00
Preet Bhinder 3f1f7c8ec9 Fix a couple of comments (#386) 2016-10-03 19:18:08 +01:00
Michael Haro 1be7320498 Use t.Errorf in tests and make the error variable naming more consistent. (#367)
* Make the error variable always named err.

Sometimes the error variable was named 'err' sometimes 'e'.  Sometimes
'e' refered to an EDNS or string and not an error type.

* Use t.Errorf instead of t.Logf & t.Fail.
2016-06-09 07:00:08 +01:00
Michael Haro a465e84f54 Use encoding/binary's conversion functions when possible. (#364)
* Remove {un,}packUint{16,32}Msg functions.

unpackUint16Msg unpackUint32Msg packUint16Msg packUint32Msg implemented
functionality that is part of the encoding/binary package.

* Use encoding/binary's encoding in more places.
2016-06-08 16:38:42 +01:00
Miek Gieben 475ab80867 Remove (most) reflection
Remove the use of reflection when packing and unpacking, instead
generate all the pack and unpack functions using msg_generate.
This will generate zmsg.go which in turn calls the helper functions from
msg_helper.go.

This increases the speed by about ~30% while cutting back on memory
usage. Not all RRs are using it, but that will be rectified in upcoming
PR.

Most of the speed increase is in the header/question section parsing.
These functions *are* not generated, but straight forward enough. The
implementation can be found in msg.go.

The new code has been fuzzed by go-fuzz, which turned up some issues.

All files that started with 'z', and not autogenerated were renamed,
i.e. zscan.go is now scan.go.

Reflection is still used, in subsequent PRs it will be removed entirely.
2016-06-03 12:45:22 +01:00
Nick Galbreath 5cbabd2322 spelling 2016-01-19 14:23:11 -08:00
Rafael Dantas Justo ad79b3f5fb Change documentation based on @miekg comments
See #297
2016-01-11 08:40:14 -02:00
Rafael Dantas Justo 72c041d2f5 Create new function ListenAndServeTLS to easy run a DNS server with TLS support
Using the ListenAndServe with network as "tcp-tls" will cause an error, as the
certificates weren't informed. To solve that we created the function
ListenAndServeTLS that will configure a DNS server listening TCP and handling
requests on incoming TLS connections.

See #297
2016-01-08 13:20:22 -02:00
Rafael Dantas Justo 6fe70412bc Add option in server to allow DNS over TLS
We should allow the server to receive requests of an encrypted connection. This
is proposed on the document draft-ietf-dprive-dns-over-tls [1].

Now it is possible to initialize the DNS server to listen with TLS using
"tcp-tls" value in network parameter of ListenAndServe function, or passing a
listener initialized with tls.Listen to ActivateAndServe.

There's also an option in Server type to change the TLS confirguration, to
inform the certificates that are going to be used, or to change any other
desired option of tls.Config.

See #297

[1] http://tools.ietf.org/html/draft-ietf-dprive-dns-over-tls-02
2016-01-08 11:26:13 -02:00
Andrew Tunnell-Jones 3062dcb751 Check server TCP conn exists before reading
w.tcp could be nil if the conn has been closed by a handler.
2015-11-26 08:10:55 +00:00
Bryan Boreham e54a6cf1bc Only re-try AcceptTCP() if the error is temporary 2015-10-30 17:08:27 +00:00
Filippo Valsorda a58e9c7a9e Refactor server shutdown to call Close() on conn and sync on srv.started
Remove the necessity for the hackish (and unreliable) fake packet.
Fix a couple races and unclutter the start/stop internal state.
2015-10-07 00:13:40 +01:00
Miek Gieben 3c158e6e74 Correct set srv.started to false on error
Unlock the lock and set started to false when we return an error
during the startup.

Fixes #263
2015-09-23 22:00:38 +01:00
Miek Gieben 540899743c Handle the last TCP connection
We currently close the connection after 128 TCP queries. But the
when the last query comes in, we close the connection immediately.
Fix this by moving the check to before we read data from the TCP
socket.

Fixes: #218.
2015-08-31 17:40:56 +01:00
Miek Gieben 114b68f41b go vet fixes 2015-08-23 07:24:08 +01:00