diff --git a/dns/dnsserver.go b/dns/dnsserver.go new file mode 100644 index 00000000..43d379c6 --- /dev/null +++ b/dns/dnsserver.go @@ -0,0 +1,66 @@ +package dns + +import ( + "fmt" + miekgdns "github.com/miekg/dns" + log "github.com/sirupsen/logrus" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/cache" + "strings" +) + +type server struct { + // todo using cache to speed up dns resolve process + dnsCache *cache.LRUExpireCache + forwardDNS string + namespace string +} + +func NewDNSServer(network, address, forwardDNS, namespace string) error { + if len(namespace) == 0 { + namespace = v1.NamespaceDefault + } + return miekgdns.ListenAndServe(address, network, &server{ + dnsCache: cache.NewLRUExpireCache(1000), forwardDNS: forwardDNS, namespace: namespace, + }) +} + +// ServeDNS consider using a cache +func (s *server) ServeDNS(w miekgdns.ResponseWriter, r *miekgdns.Msg) { + q := r.Question + r.Question = make([]miekgdns.Question, 0, len(q)) + question := q[0] + name := question.Name + switch strings.Count(question.Name, ".") { + case 1: + question.Name = question.Name + s.namespace + ".svc.cluster.local." + case 2: + question.Name = question.Name + "svc.cluster.local." + case 3: + question.Name = question.Name + "cluster.local." + case 4: + question.Name = question.Name + "local." + case 5: + } + r.Question = []miekgdns.Question{question} + fmt.Println(r.Question) + answer, err := miekgdns.Exchange(r, s.forwardDNS) + if err != nil { + log.Warnln(err) + err = w.WriteMsg(r) + if err != nil { + log.Warnln(err) + } + } else { + if len(answer.Answer) != 0 { + answer.Answer[0].Header().Name = name + } + if len(answer.Question) != 0 { + answer.Question[0].Name = name + } + err = w.WriteMsg(answer) + if err != nil { + log.Warnln(err) + } + } +} diff --git a/dns/dnsserver_test.go b/dns/dnsserver_test.go new file mode 100644 index 00000000..eab5983d --- /dev/null +++ b/dns/dnsserver_test.go @@ -0,0 +1,16 @@ +package dns + +import ( + log "github.com/sirupsen/logrus" + "strconv" + "testing" +) + +func TestName(t *testing.T) { + //port := util.GetAvailableUDPPortOrDie() + port := 58477 + err := NewDNSServer("udp", "127.0.0.1:"+strconv.Itoa(port), "172.20.135.131:53", "test") + if err != nil { + log.Warnln(err) + } +} diff --git a/util/util.go b/util/util.go index cf8ee401..7c947006 100644 --- a/util/util.go +++ b/util/util.go @@ -104,6 +104,19 @@ func GetAvailablePortOrDie() int { return listener.Addr().(*net.TCPAddr).Port } +func GetAvailableUDPPortOrDie() int { + address, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:0", "0.0.0.0")) + if err != nil { + log.Fatal(err) + } + listener, err := net.ListenUDP("udp", address) + if err != nil { + log.Fatal(err) + } + defer listener.Close() + return listener.LocalAddr().(*net.UDPAddr).Port +} + func WaitPod(clientset *kubernetes.Clientset, namespace string, list metav1.ListOptions, checker func(*v1.Pod) bool) error { return WaitResource( clientset,