Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start proxy rewrite dns server as a goroutine for nse-istio-proxy #4

Open
denis-tingaikin opened this issue May 12, 2022 · 0 comments

Comments

@denis-tingaikin
Copy link
Member

denis-tingaikin commented May 12, 2022

Motivation

See at DNS Perspective diagram from https://drive.google.com/file/d/1k0hWlgdapko50vI3BQ2rOA0FgQiWxQa6/view

We should support rewriting of A/AAAA for positive answers (for a first iteration is required suport for A responses)

Solution

To avoid extra dependecies or proc management that comes from the using Coredns we could simply write our own simple DNS server based on the core coredns libary.

  1. Create a new internal pkg in cmd-nse-istio-proxy
  2. Put the next code into the new pkg
package dns

import (
	"context"
	"errors"
	"fmt"
	"net"
	"sync"

	"github.com/miekg/dns"
)

type ProxyRewriteServer struct {
	RewriteTO       net.IP
	ListenOn        string
	ResolveConfPath string
}

func (p *ProxyRewriteServer) ListenAndServe(ctx context.Context) <-chan error {
	var networks = []string{"tcp", "udp"}
	var result = make(chan error, len(networks))

	if p.RewriteTO == nil {
		result <- errors.New("RewriteTO is not set")
	}
	if p.ResolveConfPath == "" {
		p.ResolveConfPath = "/etc/resolv.conf"
	}
	for _, network := range networks {
		server := &dns.Server{Addr: p.ListenOn, Net: network}
		go func() {
			server.Handler = p
			defer server.Shutdown()
			select {
			case result <- server.ListenAndServe():
			case <-ctx.Done():
			}

		}()
	}

	return result
}

func (p *ProxyRewriteServer) ServeDNS(rw dns.ResponseWriter, m *dns.Msg) {
	config, err := dns.ClientConfigFromFile(p.ResolveConfPath)
	if err != nil {
		dns.HandleFailed(rw, m)
		return
	}
	var networks = []string{"tcp", "udp"}

	for _, network := range networks {
		var client = dns.Client{
			Net: network,
		}
		for _, addr := range config.Servers {
			var msg *dns.Msg
			fmt.Println(addr)
			fmt.Println(network)
			if msg, _, err = client.Exchange(m, fmt.Sprintf("%v:%v", addr, config.Port)); err != nil {
				fmt.Println(err.Error())
				continue
			}
			for _, answer := range msg.Answer {
				p.rewriteIP(answer)
			}
			if err := rw.WriteMsg(msg); err == nil {
				return
			}
		}
	}

	dns.HandleFailed(rw, m)

}
func (p *ProxyRewriteServer) rewriteIP(rr dns.RR) {
	switch rr.Header().Rrtype {
	case dns.TypeAAAA:
		if p.RewriteTO.To16() != nil {
			rr.(*dns.AAAA).AAAA = p.RewriteTO.To16()
		}
	case dns.TypeA:
		if p.RewriteTO.To4() != nil {
			rr.(*dns.A).A = p.RewriteTO.To4()
		}
	}
}
  1. Start code in the main of the nse-istio-proxy (note: RewriteTO should be $dstIP(can be passed just a cidr), listenOn is :53)
  2. Add dnsconfig based on the DSTIP into context (there should be provded only nameserver ip (can be passed from a cidr))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant