github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/cmd/geph-client/dnsproxy.go (about) 1 package main 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "io/ioutil" 7 "math/rand" 8 "net" 9 "net/http" 10 "strings" 11 "sync" 12 "time" 13 14 log "github.com/sirupsen/logrus" 15 16 "github.com/miekg/dns" 17 "golang.org/x/net/proxy" 18 ) 19 20 func doDNS() { 21 log.Println("DNS on", dnsAddr) 22 if fakeDNS { 23 doDNSFaker() 24 } else { 25 doDNSProxy() 26 } 27 } 28 29 func doDNSProxy() { 30 tunProx, err := proxy.SOCKS5("tcp", socksAddr, nil, proxy.Direct) 31 if err != nil { 32 panic(err) 33 } 34 hclient := &http.Client{ 35 Transport: &http.Transport{ 36 Dial: tunProx.Dial, 37 IdleConnTimeout: time.Minute * 30, 38 }, 39 } 40 socket, err := net.ListenPacket("udp", dnsAddr) 41 if err != nil { 42 panic(err) 43 } 44 log.Println("DNS listening at", socket.LocalAddr()) 45 reqbuf := make([]byte, 512) 46 for { 47 n, addr, err := socket.ReadFrom(reqbuf) 48 if err != nil { 49 panic(err) 50 } 51 smabuf := make([]byte, n) 52 copy(smabuf, reqbuf) 53 go func() { 54 burl := base64.RawURLEncoding.EncodeToString(smabuf) 55 rsp, err := hclient.Get("https://cloudflare-dns.com/dns-query?dns=" + burl) 56 if err != nil { 57 return 58 } 59 response, err := ioutil.ReadAll(rsp.Body) 60 if err != nil { 61 log.Println("error from Cloudflare reader:", err) 62 return 63 } 64 socket.WriteTo(response, addr) 65 }() 66 } 67 } 68 69 func doDNSFaker() { 70 // our server 71 serv := &dns.Server{ 72 Net: "udp", 73 Addr: dnsAddr, 74 Handler: dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Msg) { 75 q := r.Question[0] 76 // we can't do anything if not A or CNAME 77 if q.Qtype == dns.TypeA || q.Qtype == dns.TypeCNAME { 78 ans := nameToFakeIP(q.Name) 79 ip, _ := net.ResolveIPAddr("ip4", ans) 80 m := new(dns.Msg) 81 m.SetReply(r) 82 m.Answer = append(m.Answer, &dns.A{ 83 Hdr: dns.RR_Header{ 84 Name: q.Name, 85 Rrtype: dns.TypeA, 86 Class: dns.ClassINET, 87 Ttl: 1, 88 }, 89 A: ip.IP, 90 }) 91 w.WriteMsg(m) 92 } else if q.Qtype == dns.TypeAAAA { 93 // we claim that we don't have AAAA records 94 m := new(dns.Msg) 95 m.SetReply(r) 96 w.WriteMsg(m) 97 } 98 dns.HandleFailed(w, r) 99 }), 100 } 101 err := serv.ListenAndServe() 102 if err != nil { 103 log.Println("Uh oh!") 104 panic(err.Error()) 105 } 106 } 107 108 var fakeIPCache struct { 109 mapping map[string]string 110 revmap map[string]string 111 lock sync.Mutex 112 } 113 114 func init() { 115 fakeIPCache.mapping = make(map[string]string) 116 fakeIPCache.revmap = make(map[string]string) 117 } 118 119 func nameToFakeIP(name string) string { 120 fakeIPCache.lock.Lock() 121 defer fakeIPCache.lock.Unlock() 122 if fakeIPCache.mapping[name] != "" { 123 return fakeIPCache.mapping[name] 124 } 125 genFakeIP := func() string { 126 return fmt.Sprintf("100.%v.%v.%v", rand.Int()%64+64, rand.Int()%256, rand.Int()%256) 127 } 128 // find an unallocated name 129 retval := genFakeIP() 130 for fakeIPCache.revmap[retval] != "" { 131 retval = genFakeIP() 132 } 133 log.Debugf("mapped fake IP %v => %v", retval, name) 134 fakeIPCache.revmap[retval] = strings.Trim(name, ".") 135 fakeIPCache.mapping[name] = retval 136 return retval 137 } 138 139 func fakeIPToName(ip string) string { 140 fakeIPCache.lock.Lock() 141 defer fakeIPCache.lock.Unlock() 142 return fakeIPCache.revmap[ip] 143 }