dns: add tcp support

This commit is contained in:
nadoo 2018-01-08 22:28:11 +08:00
parent 99ad1eb762
commit 050489806c
4 changed files with 119 additions and 18 deletions

View File

@ -44,8 +44,7 @@ func DialerFromURL(s string, cDialer Dialer) (Dialer, error) {
case "socks5":
return NewSOCKS5(addr, user, pass, cDialer, nil)
case "ss":
p, err := NewSS(addr, user, pass, cDialer, nil)
return p, err
return NewSS(addr, user, pass, cDialer, nil)
}
return nil, errors.New("unknown schema '" + u.Scheme + "'")

118
dns.go
View File

@ -77,21 +77,27 @@ func NewDNS(addr, raddr string, sDialer Dialer) (*DNS, error) {
// ListenAndServe .
func (s *DNS) ListenAndServe() {
go s.ListenAndServeTCP()
s.ListenAndServeUDP()
}
// ListenAndServeUDP .
func (s *DNS) ListenAndServeUDP() {
c, err := net.ListenPacket("udp", s.addr)
if err != nil {
logf("failed to listen on %s: %v", s.addr, err)
logf("proxy-dns failed to listen on %s: %v", s.addr, err)
return
}
defer c.Close()
logf("listening UDP on %s", s.addr)
logf("proxy-dns listening UDP on %s", s.addr)
for {
data := make([]byte, DNSUDPMaxLen)
n, clientAddr, err := c.ReadFrom(data)
if err != nil {
logf("DNS local read error: %v", err)
logf("proxy-dns DNS local read error: %v", err)
continue
}
@ -101,11 +107,14 @@ func (s *DNS) ListenAndServe() {
query := parseQuery(data)
domain := query.DomainName
dnsServer := s.GetServer(domain)
dnsServer := s.dnsServer
if dnsServer == "" {
dnsServer = s.GetServer(domain)
}
rc, err := s.sDialer.NextDialer(domain+":53").Dial("tcp", dnsServer)
if err != nil {
logf("failed to connect to server %v: %v", dnsServer, err)
logf("proxy-dns failed to connect to server %v: %v", dnsServer, err)
return
}
defer rc.Close()
@ -170,6 +179,105 @@ func (s *DNS) ListenAndServe() {
}
}
// ListenAndServeTCP .
func (s *DNS) ListenAndServeTCP() {
l, err := net.Listen("tcp", s.addr)
if err != nil {
logf("proxy-dns-tcp error: %v", err)
return
}
logf("proxy-dns-tcp listening TCP on %s", s.addr)
for {
c, err := l.Accept()
if err != nil {
logf("proxy-dns-tcp error: failed to accept: %v", err)
continue
}
go s.ServeTCP(c)
}
}
// ServeTCP .
func (s *DNS) ServeTCP(c net.Conn) {
defer c.Close()
if c, ok := c.(*net.TCPConn); ok {
c.SetKeepAlive(true)
}
var reqLen uint16
if err := binary.Read(c, binary.BigEndian, &reqLen); err != nil {
logf("proxy-dns-tcp failed to read request length: %v", err)
return
}
reqMsg := make([]byte, reqLen)
_, err := io.ReadFull(c, reqMsg)
if err != nil {
logf("proxy-dns-tcp error in read reqMsg %s\n", err)
return
}
query := parseQuery(reqMsg)
domain := query.DomainName
dnsServer := s.dnsServer
if dnsServer == "" {
dnsServer = s.GetServer(domain)
}
rc, err := s.sDialer.NextDialer(domain+":53").Dial("tcp", dnsServer)
if err != nil {
logf("proxy-dns failed to connect to server %v: %v", dnsServer, err)
return
}
defer rc.Close()
binary.Write(rc, binary.BigEndian, reqLen)
binary.Write(rc, binary.BigEndian, reqMsg)
var respLen uint16
if err := binary.Read(rc, binary.BigEndian, &respLen); err != nil {
logf("proxy-dns-tcp failed to read response length: %v", err)
return
}
respMsg := make([]byte, respLen)
_, err = io.ReadFull(rc, respMsg)
if err != nil {
logf("proxy-dns-tcp error in read respMsg %s\n", err)
return
}
var ip string
if respLen > 0 {
query := parseQuery(respMsg)
if (query.QueryType == DNSQueryTypeA || query.QueryType == DNSQueryTypeAAAA) &&
len(respMsg) > query.Offset {
answers := parseAnswers(respMsg[query.Offset:])
for _, answer := range answers {
if answer.IP != "" {
ip += answer.IP + ","
}
for _, h := range s.answerHandlers {
h(query.DomainName, answer.IP)
}
}
}
binary.Write(c, binary.BigEndian, respLen)
binary.Write(c, binary.BigEndian, respMsg)
}
logf("proxy-dns-tcp %s <-> %s, type: %d, %s: %s", c.RemoteAddr(), dnsServer, query.QueryType, domain, ip)
}
// SetServer .
func (s *DNS) SetServer(domain, server string) {
s.dnsServerMap[domain] = server

View File

@ -9,7 +9,7 @@ type DNSTun struct {
raddr string
udp *DNS
dns *DNS
tcp *TCPTun
}
@ -22,19 +22,14 @@ func NewDNSTun(addr, raddr string, sDialer Dialer) (*DNSTun, error) {
raddr: raddr,
}
s.udp, _ = NewDNS(addr, raddr, sDialer)
s.tcp, _ = NewTCPTun(addr, raddr, sDialer)
s.dns, _ = NewDNS(addr, raddr, sDialer)
return s, nil
}
// ListenAndServe .
func (s *DNSTun) ListenAndServe() {
if s.udp != nil {
go s.udp.ListenAndServe()
}
if s.tcp != nil {
s.tcp.ListenAndServe()
if s.dns != nil {
go s.dns.ListenAndServe()
}
}

View File

@ -44,8 +44,7 @@ func ServerFromURL(s string, sDialer Dialer) (Server, error) {
case "socks5":
return NewSOCKS5(addr, user, pass, nil, sDialer)
case "ss":
p, err := NewSS(addr, user, pass, nil, sDialer)
return p, err
return NewSS(addr, user, pass, nil, sDialer)
case "redir":
return NewRedirProxy(addr, sDialer)
case "tcptun":