mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-31 10:13:14 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			108 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package etcd
 | |
| 
 | |
| import (
 | |
| 	"net"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/miekg/dns"
 | |
| )
 | |
| 
 | |
| // hasStubEdns0 checks if the message is carrying our special
 | |
| // edns0 zero option.
 | |
| func hasStubEdns0(m *dns.Msg) bool {
 | |
| 	option := m.IsEdns0()
 | |
| 	if option == nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	for _, o := range option.Option {
 | |
| 		if o.Option() == ednsStubCode && len(o.(*dns.EDNS0_LOCAL).Data) == 1 &&
 | |
| 			o.(*dns.EDNS0_LOCAL).Data[0] == 1 {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // addStubEdns0 adds our special option to the message's OPT record.
 | |
| func addStubEdns0(m *dns.Msg) *dns.Msg {
 | |
| 	option := m.IsEdns0()
 | |
| 	// Add a custom EDNS0 option to the packet, so we can detect loops
 | |
| 	// when 2 stubs are forwarding to each other.
 | |
| 	if option != nil {
 | |
| 		option.Option = append(option.Option, &dns.EDNS0_LOCAL{ednsStubCode, []byte{1}})
 | |
| 	} else {
 | |
| 		m.Extra = append(m.Extra, ednsStub)
 | |
| 	}
 | |
| 	return m
 | |
| }
 | |
| 
 | |
| // Look in .../dns/stub/<zone>/xx for msg.Services. Loop through them
 | |
| // extract <zone> and add them as forwarders (ip:port-combos) for
 | |
| // the stub zones. Only numeric (i.e. IP address) hosts are used.
 | |
| // TODO(miek): makes this Startup Function.
 | |
| func (e Etcd) UpdateStubZones(zone string) error {
 | |
| 	stubmap := make(map[string][]string)
 | |
| 
 | |
| 	services, err := e.Records("stub.dns."+zone, false)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	for _, serv := range services {
 | |
| 		if serv.Port == 0 {
 | |
| 			serv.Port = 53
 | |
| 		}
 | |
| 		ip := net.ParseIP(serv.Host)
 | |
| 		if ip == nil {
 | |
| 			//logf("stub zone non-address %s seen for: %s", serv.Key, serv.Host)
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		domain := e.Domain(serv.Key)
 | |
| 		labels := dns.SplitDomainName(domain)
 | |
| 
 | |
| 		// If the remaining name equals any of the zones we have, we ignore it.
 | |
| 		for _, z := range e.Zones {
 | |
| 			// Chop of left most label, because that is used as the nameserver place holder
 | |
| 			// and drop the right most labels that belong to zone.
 | |
| 			domain = dns.Fqdn(strings.Join(labels[1:len(labels)-dns.CountLabel(z)], "."))
 | |
| 			if domain == z {
 | |
| 				continue
 | |
| 			}
 | |
| 			stubmap[domain] = append(stubmap[domain], net.JoinHostPort(serv.Host, strconv.Itoa(serv.Port)))
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// TODO(miek): add to etcd structure and startup with a StartFunction
 | |
| 	//	e.stub = &stubmap
 | |
| 	// stubmap contains proxy is best way forward... I think.
 | |
| 	// TODO(miek): setup a proxy that forward to these
 | |
| 	// StubProxy type?
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func ServeDNSStubForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg {
 | |
| 	if !hasStubEdns0(req) {
 | |
| 		return nil
 | |
| 	}
 | |
| 	req = addStubEdns0(req)
 | |
| 	// proxy woxy
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // ednsStub is the EDNS0 record we add to stub queries. Queries which have this record are
 | |
| // not forwarded again.
 | |
| var ednsStub = func() *dns.OPT {
 | |
| 	o := new(dns.OPT)
 | |
| 	o.Hdr.Name = "."
 | |
| 	o.Hdr.Rrtype = dns.TypeOPT
 | |
| 
 | |
| 	e := new(dns.EDNS0_LOCAL)
 | |
| 	e.Code = ednsStubCode
 | |
| 	e.Data = []byte{1}
 | |
| 	o.Option = append(o.Option, e)
 | |
| 	return o
 | |
| }()
 | |
| 
 | |
| const ednsStubCode = dns.EDNS0LOCALSTART + 10
 |