mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 17:35:40 +08:00
dns: add tcp support
This commit is contained in:
parent
99ad1eb762
commit
050489806c
@ -44,8 +44,7 @@ func DialerFromURL(s string, cDialer Dialer) (Dialer, error) {
|
|||||||
case "socks5":
|
case "socks5":
|
||||||
return NewSOCKS5(addr, user, pass, cDialer, nil)
|
return NewSOCKS5(addr, user, pass, cDialer, nil)
|
||||||
case "ss":
|
case "ss":
|
||||||
p, err := NewSS(addr, user, pass, cDialer, nil)
|
return NewSS(addr, user, pass, cDialer, nil)
|
||||||
return p, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("unknown schema '" + u.Scheme + "'")
|
return nil, errors.New("unknown schema '" + u.Scheme + "'")
|
||||||
|
118
dns.go
118
dns.go
@ -77,21 +77,27 @@ func NewDNS(addr, raddr string, sDialer Dialer) (*DNS, error) {
|
|||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
func (s *DNS) ListenAndServe() {
|
func (s *DNS) ListenAndServe() {
|
||||||
|
go s.ListenAndServeTCP()
|
||||||
|
s.ListenAndServeUDP()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenAndServeUDP .
|
||||||
|
func (s *DNS) ListenAndServeUDP() {
|
||||||
c, err := net.ListenPacket("udp", s.addr)
|
c, err := net.ListenPacket("udp", s.addr)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
logf("listening UDP on %s", s.addr)
|
logf("proxy-dns listening UDP on %s", s.addr)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
data := make([]byte, DNSUDPMaxLen)
|
data := make([]byte, DNSUDPMaxLen)
|
||||||
|
|
||||||
n, clientAddr, err := c.ReadFrom(data)
|
n, clientAddr, err := c.ReadFrom(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("DNS local read error: %v", err)
|
logf("proxy-dns DNS local read error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,11 +107,14 @@ func (s *DNS) ListenAndServe() {
|
|||||||
query := parseQuery(data)
|
query := parseQuery(data)
|
||||||
domain := query.DomainName
|
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)
|
rc, err := s.sDialer.NextDialer(domain+":53").Dial("tcp", dnsServer)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
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 .
|
// SetServer .
|
||||||
func (s *DNS) SetServer(domain, server string) {
|
func (s *DNS) SetServer(domain, server string) {
|
||||||
s.dnsServerMap[domain] = server
|
s.dnsServerMap[domain] = server
|
||||||
|
13
dnstun.go
13
dnstun.go
@ -9,7 +9,7 @@ type DNSTun struct {
|
|||||||
|
|
||||||
raddr string
|
raddr string
|
||||||
|
|
||||||
udp *DNS
|
dns *DNS
|
||||||
tcp *TCPTun
|
tcp *TCPTun
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,19 +22,14 @@ func NewDNSTun(addr, raddr string, sDialer Dialer) (*DNSTun, error) {
|
|||||||
raddr: raddr,
|
raddr: raddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.udp, _ = NewDNS(addr, raddr, sDialer)
|
s.dns, _ = NewDNS(addr, raddr, sDialer)
|
||||||
s.tcp, _ = NewTCPTun(addr, raddr, sDialer)
|
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
func (s *DNSTun) ListenAndServe() {
|
func (s *DNSTun) ListenAndServe() {
|
||||||
if s.udp != nil {
|
if s.dns != nil {
|
||||||
go s.udp.ListenAndServe()
|
go s.dns.ListenAndServe()
|
||||||
}
|
|
||||||
|
|
||||||
if s.tcp != nil {
|
|
||||||
s.tcp.ListenAndServe()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,7 @@ func ServerFromURL(s string, sDialer Dialer) (Server, error) {
|
|||||||
case "socks5":
|
case "socks5":
|
||||||
return NewSOCKS5(addr, user, pass, nil, sDialer)
|
return NewSOCKS5(addr, user, pass, nil, sDialer)
|
||||||
case "ss":
|
case "ss":
|
||||||
p, err := NewSS(addr, user, pass, nil, sDialer)
|
return NewSS(addr, user, pass, nil, sDialer)
|
||||||
return p, err
|
|
||||||
case "redir":
|
case "redir":
|
||||||
return NewRedirProxy(addr, sDialer)
|
return NewRedirProxy(addr, sDialer)
|
||||||
case "tcptun":
|
case "tcptun":
|
||||||
|
Loading…
Reference in New Issue
Block a user