Skip to content

Commit

Permalink
Create gfc.go
Browse files Browse the repository at this point in the history
  • Loading branch information
sumkincpp committed Jul 6, 2015
1 parent 892a578 commit 328b603
Showing 1 changed file with 149 additions and 0 deletions.
149 changes: 149 additions & 0 deletions golang/dns/gfc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
golang
package main

import (
"github.com/miekg/dns"
"log"
"math/rand"
"strings"
"os"
"fmt"
"time"
"flag"
"regexp"
)

const (
DEFAULT_PORT = 53
DEFAULT_TIMEOUT = time.Minute
DEFAULT_PROTO = "tcp"
)

var (
LOG *log.Logger
PROTO string
TIMEOUT time.Duration
DEBUG bool
TCP_REGEX *regexp.Regexp

DEFAULT_SERVERS = []string { "8.8.8.8",
"8.8.4.4",
"156.154.70.1",
"156.154.71.1",
"208.67.222.222",
"208.67.220.220",
"198.153.192.1",
"198.153.194.1" }


)

func init () {
LOG = log.New (os.Stderr, "[DNS PROXY] ", log.LstdFlags)

var proto, pattern string
var timeout int

flag.BoolVar (&DEBUG, "d", false, "Enable debug mode")
flag.StringVar (&proto, "p", "", "Which proto use for lookup domain")
flag.IntVar (&timeout, "t", 0, "How many seconds to timeout")
flag.StringVar (&pattern, "r", "", "Regex pattern for match domain to use tcp proto")
flag.Parse ()

switch proto {
case "tcp" :
PROTO = "tcp"
case "udp" :
PROTO = "udp"
default:
PROTO = DEFAULT_PROTO
}

if timeout > 5 {
TIMEOUT = time.Duration(timeout) * time.Second
} else {
TIMEOUT = DEFAULT_TIMEOUT
}

if len(pattern) > 0 {
if re, err := regexp.Compile (pattern); err != nil {
LOG.Fatalf ("Compiling pattern [%s] was %s", pattern, err)
} else {
TCP_REGEX = re
}
}

LOG.Printf ("Use %s proto to lookup domain", PROTO)
LOG.Printf ("Timeout duration: %s", TIMEOUT)
if TCP_REGEX != nil {
LOG.Printf ("Compiling tcp regex pattern [%s]", TCP_REGEX)
}
}

type Proxy struct {
Servers []string
}

func ( p Proxy ) ServeDNS (w dns.ResponseWriter, r *dns.Msg) {
c := dns.NewClient ()

c.Net = PROTO
if TCP_REGEX != nil {
for _, q := range r.Question {
if TCP_REGEX.MatchString (q.Name) {
LOG.Printf ("Tcp proto regex match: %s", q.Name)
c.Net = "tcp"
break
}
}
}

c.ReadTimeout = TIMEOUT
c.WriteTimeout = TIMEOUT

if rs, err := c.Exchange (r, p.Server()); err == nil {
if DEBUG {
LOG.Printf ("DEBUG %s\n%v", w.RemoteAddr(), rs)
}
w.Write (rs)
} else {
dns.Refused (w, r)
LOG.Printf ("%s %s", w.RemoteAddr(), err)
}
}

func ( p Proxy ) Server () string {
sl := len(p.Servers)
if sl > 0 {
i := rand.Intn (sl)
s := p.Servers[i]
if strings.Index (s, ":") == -1 {
s = fmt.Sprintf ("%s:%d", s, DEFAULT_PORT)
}
return s
}
return "8.8.8.8:53"
}

func main () {

var servers []string
args := flag.Args ()

if len(args) > 0 {
servers = append (servers, args...)
} else {
servers = DEFAULT_SERVERS
}

LOG.Printf ("Servers: %s", servers)

proxyer := Proxy{servers}

if err := dns.ListenAndServe ("127.0.0.1:53", "udp", proxyer); err != nil {
LOG.Fatal (err)
}
}

// see: https://github.com/newblue/juhua.dns (i'm testing long code snips)
// https://koding.com/Activity/little-go-dns-proxy-for-our-chinese-users

0 comments on commit 328b603

Please sign in to comment.