mirror of
https://github.com/nadoo/glider.git
synced 2025-02-24 01:45:39 +08:00
dns: change parseAnswers function to return error
This commit is contained in:
parent
e91d4bcb6e
commit
ff632f23a6
130
dns.go
130
dns.go
@ -44,11 +44,11 @@ const DNSQTypeAAAA = 28
|
|||||||
// | Authority | RRs pointing toward an authority
|
// | Authority | RRs pointing toward an authority
|
||||||
// +---------------------+
|
// +---------------------+
|
||||||
// | Additional | RRs holding additional information
|
// | Additional | RRs holding additional information
|
||||||
type DNSMsg struct {
|
// type DNSMsg struct {
|
||||||
DNSHeader
|
// DNSHeader
|
||||||
Questions []*DNSQuestion
|
// Questions []DNSQuestion
|
||||||
Answers []*DNSRR
|
// Answers []DNSRR
|
||||||
}
|
// }
|
||||||
|
|
||||||
// DNSHeader format
|
// DNSHeader format
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.1.1
|
// https://tools.ietf.org/html/rfc1035#section-4.1.1
|
||||||
@ -70,9 +70,9 @@ type DNSMsg struct {
|
|||||||
// | ARCOUNT |
|
// | ARCOUNT |
|
||||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
//
|
//
|
||||||
type DNSHeader struct {
|
// type DNSHeader struct {
|
||||||
ID uint16
|
// ID uint16
|
||||||
}
|
// }
|
||||||
|
|
||||||
// DNSQuestion format
|
// DNSQuestion format
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.1.2
|
// https://tools.ietf.org/html/rfc1035#section-4.1.2
|
||||||
@ -134,8 +134,8 @@ type DNSRR struct {
|
|||||||
IP string
|
IP string
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSAnswerHandler .
|
// DNSAnswerHandler function handles the dns TypeA or TypeAAAA answer
|
||||||
type DNSAnswerHandler func(domain, ip string) error
|
type DNSAnswerHandler func(Domain, ip string) error
|
||||||
|
|
||||||
// DNS .
|
// DNS .
|
||||||
type DNS struct {
|
type DNS struct {
|
||||||
@ -191,22 +191,26 @@ func (s *DNS) ListenAndServeUDP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reqLen := uint16(n)
|
reqLen := uint16(n)
|
||||||
if reqLen <= DNSHeaderLen {
|
// TODO: check here
|
||||||
|
if reqLen <= DNSHeaderLen+2 {
|
||||||
logf("proxy-dns not enough data")
|
logf("proxy-dns not enough data")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
reqMsg := b[:n]
|
reqMsg := b[:n]
|
||||||
go func() {
|
go func() {
|
||||||
_, respMsg := s.Exchange(reqLen, reqMsg)
|
_, respMsg, err := s.Exchange(reqLen, reqMsg, clientAddr.String())
|
||||||
|
if err != nil {
|
||||||
|
logf("proxy-dns error in exchange: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
_, err = c.WriteTo(respMsg, clientAddr)
|
_, err = c.WriteTo(respMsg, clientAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("proxy-dns error in local write: %s", err)
|
logf("proxy-dns error in local write: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// logf("proxy-dns %s <-> %s, type: %d, %s: %s", clientAddr.String(), dnsServer, query.QueryType, domain, ip)
|
|
||||||
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,11 +245,12 @@ func (s *DNS) ServeTCP(c net.Conn) {
|
|||||||
|
|
||||||
var reqLen uint16
|
var reqLen uint16
|
||||||
if err := binary.Read(c, binary.BigEndian, &reqLen); err != nil {
|
if err := binary.Read(c, binary.BigEndian, &reqLen); err != nil {
|
||||||
logf("proxy-dns-tcp failed to read request length: %v", err)
|
logf("proxy-dns-tcp failed to get request length: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if reqLen <= DNSHeaderLen {
|
// TODO: check here
|
||||||
|
if reqLen <= DNSHeaderLen+2 {
|
||||||
logf("proxy-dns-tcp not enough data")
|
logf("proxy-dns-tcp not enough data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -257,29 +262,34 @@ func (s *DNS) ServeTCP(c net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
respLen, respMsg := s.Exchange(reqLen, reqMsg)
|
respLen, respMsg, err := s.Exchange(reqLen, reqMsg, c.RemoteAddr().String())
|
||||||
if err := binary.Write(c, binary.BigEndian, respLen); err != nil {
|
|
||||||
logf("proxy-dns-tcp error in local write respLen: %s\n", err)
|
|
||||||
}
|
|
||||||
if err := binary.Write(c, binary.BigEndian, respMsg); err != nil {
|
|
||||||
logf("proxy-dns-tcp error in local write respMsg: %s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// logf("proxy-dns-tcp %s <-> %s, type: %d, %s: %s", c.RemoteAddr(), dnsServer, query.QueryType, domain, ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exchange handles request msg and return response msg
|
|
||||||
func (s *DNS) Exchange(reqLen uint16, reqMsg []byte) (respLen uint16, respMsg []byte) {
|
|
||||||
// fmt.Printf("\ndns req len %d:\n%s\n", reqLen, hex.Dump(reqMsg[:]))
|
|
||||||
query, err := parseQuestion(reqMsg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("proxy-dns error in parseQuestion reqMsg %s", err)
|
logf("proxy-dns-tcp error in exchange: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsServer := s.GetServer(query.QNAME)
|
if err := binary.Write(c, binary.BigEndian, respLen); err != nil {
|
||||||
if s.Tunnel {
|
logf("proxy-dns-tcp error in local write respLen: %s", err)
|
||||||
dnsServer = s.DNSServer
|
return
|
||||||
|
}
|
||||||
|
if err := binary.Write(c, binary.BigEndian, respMsg); err != nil {
|
||||||
|
logf("proxy-dns-tcp error in local write respMsg: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exchange handles request msg and returns response msg
|
||||||
|
func (s *DNS) Exchange(reqLen uint16, reqMsg []byte, addr string) (respLen uint16, respMsg []byte, err error) {
|
||||||
|
// fmt.Printf("\ndns req len %d:\n%s\n", reqLen, hex.Dump(reqMsg[:]))
|
||||||
|
query, err := parseQuestion(reqMsg)
|
||||||
|
if err != nil {
|
||||||
|
logf("proxy-dns error in parseQuestion reqMsg: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsServer := s.DNSServer
|
||||||
|
if !s.Tunnel {
|
||||||
|
dnsServer = s.GetServer(query.QNAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := s.sDialer.NextDialer(query.QNAME+":53").Dial("tcp", dnsServer)
|
rc, err := s.sDialer.NextDialer(query.QNAME+":53").Dial("tcp", dnsServer)
|
||||||
@ -289,16 +299,16 @@ func (s *DNS) Exchange(reqLen uint16, reqMsg []byte) (respLen uint16, respMsg []
|
|||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
if err := binary.Write(rc, binary.BigEndian, reqLen); err != nil {
|
if err = binary.Write(rc, binary.BigEndian, reqLen); err != nil {
|
||||||
logf("proxy-dns failed to write req length: %v", err)
|
logf("proxy-dns failed to write req length: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := binary.Write(rc, binary.BigEndian, reqMsg); err != nil {
|
if err = binary.Write(rc, binary.BigEndian, reqMsg); err != nil {
|
||||||
logf("proxy-dns failed to write req message: %v", err)
|
logf("proxy-dns failed to write req message: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(rc, binary.BigEndian, &respLen); err != nil {
|
if err = binary.Read(rc, binary.BigEndian, &respLen); err != nil {
|
||||||
logf("proxy-dns failed to read response length: %v", err)
|
logf("proxy-dns failed to read response length: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -313,30 +323,35 @@ func (s *DNS) Exchange(reqLen uint16, reqMsg []byte) (respLen uint16, respMsg []
|
|||||||
// fmt.Printf("\ndns resp len %d:\n%s\n", respLen, hex.Dump(respMsg[:]))
|
// fmt.Printf("\ndns resp len %d:\n%s\n", respLen, hex.Dump(respMsg[:]))
|
||||||
|
|
||||||
var ip string
|
var ip string
|
||||||
if respLen > 0 {
|
respReq, err := parseQuestion(respMsg)
|
||||||
query, err := parseQuestion(respMsg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("proxy-dns error in parseQuestion respMsg %s", err)
|
logf("proxy-dns error in parseQuestion respMsg: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.QTYPE == DNSQTypeA || query.QTYPE == DNSQTypeAAAA) &&
|
if (respReq.QTYPE == DNSQTypeA || respReq.QTYPE == DNSQTypeAAAA) &&
|
||||||
len(respMsg) > query.Offset {
|
len(respMsg) > respReq.Offset {
|
||||||
|
|
||||||
|
var answers []*DNSRR
|
||||||
|
answers, err = parseAnswers(respMsg[respReq.Offset:])
|
||||||
|
if err != nil {
|
||||||
|
logf("proxy-dns error in parseAnswers: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
answers := parseAnswers(respMsg[query.Offset:])
|
|
||||||
for _, answer := range answers {
|
for _, answer := range answers {
|
||||||
|
for _, h := range s.AnswerHandlers {
|
||||||
|
h(respReq.QNAME, answer.IP)
|
||||||
|
}
|
||||||
|
|
||||||
if answer.IP != "" {
|
if answer.IP != "" {
|
||||||
ip += answer.IP + ","
|
ip += answer.IP + ","
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, h := range s.AnswerHandlers {
|
|
||||||
h(query.QNAME, answer.IP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logf("proxy-dns %s <-> %s, type: %d, %s: %s", addr, dnsServer, query.QTYPE, query.QNAME, ip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,9 +404,13 @@ func parseQuestion(p []byte) (*DNSQuestion, error) {
|
|||||||
i = i + l + 1
|
i = i + l + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(domain) == 0 {
|
||||||
|
return nil, errors.New("no QNAME")
|
||||||
|
}
|
||||||
|
|
||||||
q.QNAME = string(domain[:len(domain)-1])
|
q.QNAME = string(domain[:len(domain)-1])
|
||||||
|
|
||||||
if len(p) < i+4 {
|
if lenP < i+4 {
|
||||||
return nil, errors.New("not enough data")
|
return nil, errors.New("not enough data")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,10 +421,11 @@ func parseQuestion(p []byte) (*DNSQuestion, error) {
|
|||||||
return q, nil
|
return q, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAnswers(p []byte) []*DNSRR {
|
func parseAnswers(p []byte) ([]*DNSRR, error) {
|
||||||
var answers []*DNSRR
|
var answers []*DNSRR
|
||||||
|
lenP := len(p)
|
||||||
|
|
||||||
for i := 0; i < len(p); {
|
for i := 0; i < lenP; {
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.1.4
|
// https://tools.ietf.org/html/rfc1035#section-4.1.4
|
||||||
// "Message compression",
|
// "Message compression",
|
||||||
@ -420,6 +440,10 @@ func parseAnswers(p []byte) []*DNSRR {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if lenP <= i+10 {
|
||||||
|
return nil, errors.New("not enough data")
|
||||||
|
}
|
||||||
|
|
||||||
answer := &DNSRR{}
|
answer := &DNSRR{}
|
||||||
|
|
||||||
answer.TYPE = binary.BigEndian.Uint16(p[i:])
|
answer.TYPE = binary.BigEndian.Uint16(p[i:])
|
||||||
@ -439,5 +463,5 @@ func parseAnswers(p []byte) []*DNSRR {
|
|||||||
i = i + 10 + int(answer.RDLENGTH)
|
i = i + 10 + int(answer.RDLENGTH)
|
||||||
}
|
}
|
||||||
|
|
||||||
return answers
|
return answers, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user