mirror of
https://github.com/Li4n0/revsuit.git
synced 2026-09-21 22:30:46 +08:00
68 lines
1.5 KiB
Go
68 lines
1.5 KiB
Go
package newdns
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
// Accept will return a dns.MsgAcceptFunc that only accepts normal queries.
|
|
func Accept(logger Logger) dns.MsgAcceptFunc {
|
|
return func(dh dns.Header) dns.MsgAcceptAction {
|
|
// check if request
|
|
if dh.Bits&(1<<15) != 0 {
|
|
log(logger, Ignored, nil, nil, "not a request")
|
|
return dns.MsgIgnore
|
|
}
|
|
|
|
// check opcode
|
|
if int(dh.Bits>>11)&0xF != dns.OpcodeQuery {
|
|
log(logger, Ignored, nil, nil, "not a query")
|
|
return dns.MsgIgnore
|
|
}
|
|
|
|
// check question count
|
|
if dh.Qdcount != 1 {
|
|
log(logger, Ignored, nil, nil, fmt.Sprintf("invalid question count: %d", dh.Qdcount))
|
|
return dns.MsgIgnore
|
|
}
|
|
|
|
return dns.MsgAccept
|
|
}
|
|
}
|
|
|
|
// Run will start a UDP and TCP listener to serve the specified handler with the
|
|
// specified accept function until the provided close channel is closed. It will
|
|
// return the first error of a listener.
|
|
func Run(addr string, handler dns.Handler, accept dns.MsgAcceptFunc, close <-chan struct{}) error {
|
|
// prepare servers
|
|
udp := &dns.Server{Addr: addr, Net: "udp", Handler: handler, MsgAcceptFunc: accept}
|
|
tcp := &dns.Server{Addr: addr, Net: "tcp", Handler: handler, MsgAcceptFunc: accept}
|
|
|
|
// prepare errors
|
|
errs := make(chan error, 2)
|
|
|
|
// run udp server
|
|
go func() {
|
|
errs <- udp.ListenAndServe()
|
|
}()
|
|
|
|
// run tcp server
|
|
go func() {
|
|
errs <- tcp.ListenAndServe()
|
|
}()
|
|
|
|
// await first error
|
|
var err error
|
|
select {
|
|
case err = <-errs:
|
|
case <-close:
|
|
}
|
|
|
|
// shutdown servers
|
|
_ = udp.Shutdown()
|
|
_ = tcp.Shutdown()
|
|
|
|
return err
|
|
}
|