예제 #1
0
func ExamplePrivateHandle() {
	dns.PrivateHandle("APAIR", TypeAPAIR, NewAPAIR)
	defer dns.PrivateHandleRemove(TypeAPAIR)

	rr, err := dns.NewRR("miek.nl. APAIR (1.2.3.4    1.2.3.5)")
	if err != nil {
		log.Fatal("could not parse APAIR record: ", err)
	}
	fmt.Println(rr)
	// Output: miek.nl.	3600	IN	APAIR	1.2.3.4 1.2.3.5

	m := new(dns.Msg)
	m.Id = 12345
	m.SetQuestion("miek.nl.", TypeAPAIR)
	m.Answer = append(m.Answer, rr)

	fmt.Println(m)
	// ;; opcode: QUERY, status: NOERROR, id: 12345
	// ;; flags: rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
	//
	// ;; QUESTION SECTION:
	// ;miek.nl.	IN	 APAIR
	//
	// ;; ANSWER SECTION:
	// miek.nl.	3600	IN	APAIR	1.2.3.4 1.2.3.5
}
예제 #2
0
// Retrieve the MX records for miek.nl.
func ExampleMX() {
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := new(dns.Client)
	m := new(dns.Msg)
	m.SetQuestion("miek.nl.", dns.TypeMX)
	m.RecursionDesired = true
	r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port)
	if err != nil {
		return
	}
	if r.Rcode != dns.RcodeSuccess {
		return
	}
	for _, a := range r.Answer {
		if mx, ok := a.(*dns.MX); ok {
			fmt.Printf("%s\n", mx.String())
		}
	}
}
예제 #3
0
// Verify the DNS configuration on the nameservers. This method will send a SOA request
// for each nameserver and verify the results. Returns true if nameserver is done checking
// and can be saved or false otherwise, that indicates that the domain was postponed
func (q *querier) checkNameserver(domain *model.Domain,
	index int, postponedDomains []postponedDomain) bool {

	nameserver := domain.Nameservers[index]
	domainNSPolicy := nspolicy.NewDomainNSPolicy(domain)

	// Build message to send the request
	var dnsRequestMessage dns.Msg
	dnsRequestMessage.SetQuestion(domain.FQDN, dns.TypeSOA)
	dnsRequestMessage.RecursionDesired = false

	host, err := getHost(domain.FQDN, nameserver)
	if err == ErrHostTimeout {
		domain.Nameservers[index].ChangeStatus(model.NameserverStatusTimeout)
		return true

	} else if err == ErrHostQPSExceeded {
		postponedDomains = append(postponedDomains, postponedDomain{
			domain: domain,
			index:  index,
		})
		return false
	}

	dnsResponseMessage, err := q.sendDNSRequest(host, &dnsRequestMessage)
	querierCache.Query(nameserver.Host)

	if status := domainNSPolicy.CheckNetworkError(err); status != model.NameserverStatusOK {
		if status == model.NameserverStatusTimeout {
			querierCache.Timeout(nameserver.Host)
		}

		domain.Nameservers[index].ChangeStatus(status)

	} else {
		domain.Nameservers[index].ChangeStatus(domainNSPolicy.Run(dnsResponseMessage))
	}

	return true
}
예제 #4
0
// Retrieve the DNSKEY records of a zone and convert them
// to DS records for SHA1, SHA256 and SHA384.
func ExampleDS(zone string) {
	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := new(dns.Client)
	m := new(dns.Msg)
	if zone == "" {
		zone = "miek.nl"
	}
	m.SetQuestion(dns.Fqdn(zone), dns.TypeDNSKEY)
	m.SetEdns0(4096, true)
	r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port)
	if err != nil {
		return
	}
	if r.Rcode != dns.RcodeSuccess {
		return
	}
	for _, k := range r.Answer {
		if key, ok := k.(*dns.DNSKEY); ok {
			for _, alg := range []uint8{dns.SHA1, dns.SHA256, dns.SHA384} {
				fmt.Printf("%s; %d\n", key.ToDS(alg).String(), key.Flags)
			}
		}
	}
}
예제 #5
0
// Check the DS with the domain DNSSEC keys and signatures. You need also to inform the
// UDP max package size supported to pass into firewalls. Many firewalls don't allow
// fragmented UDP packages or UDP packages bigger than 512 bytes. Returns true if DS set
// is done checking and can be saved or false otherwise, that indicates that the domain
// was postponed
func (q *querier) checkDS(domain *model.Domain, index int, udpMaxSize uint16,
	postponedDomains []postponedDomain) bool {

	// Check if the domain has DNSSEC, this system will work with both kinds of domain. So
	// when the domain don't have any DS record we assume that it does not have DNSSEC
	// configured and check only the DNS configuration
	if len(domain.DSSet) == 0 {
		return true
	}

	nameserver := domain.Nameservers[index]
	domainDSPolicy := dspolicy.NewDomainDSPolicy(domain)

	// We are going to request the DNSSEC keys to validate with the DS information that we
	// have from the domain
	var dnsRequestMessage dns.Msg
	dnsRequestMessage.SetQuestion(domain.FQDN, dns.TypeDNSKEY)
	dnsRequestMessage.RecursionDesired = false
	dnsRequestMessage.SetEdns0(udpMaxSize, true)

	host, err := getHost(domain.FQDN, nameserver)
	if err == ErrHostTimeout {
		for index, _ := range domain.DSSet {
			domain.DSSet[index].ChangeStatus(model.DSStatusTimeout)
		}
		return true

	} else if err == ErrHostQPSExceeded {
		postponedDomains = append(postponedDomains, postponedDomain{
			domain: domain,
			index:  index,
		})
		return false
	}

	dnsResponseMessage, err := q.sendDNSRequest(host, &dnsRequestMessage)
	querierCache.Query(nameserver.Host)

	if domainDSPolicy.CheckNetworkError(err) {
		domainDSPolicy.Run(dnsResponseMessage)
	}

	return true
}
예제 #6
0
파일: scan.go 프로젝트: rafaeljusto/shelter
// Send DNS requests to fill a domain object from the information found on the DNS authoritative
// nameservers. This is very usefull to make it easier for the user to fill forms with the domain
// information. The domain must be already delegated by a registry to this function works, because
// it uses a recursive DNS
func QueryDomain(fqdn string) (model.Domain, error) {
	domain := model.Domain{
		FQDN: fqdn,
	}

	querier := newQuerier(
		config.ShelterConfig.Scan.UDPMaxSize,
		time.Duration(config.ShelterConfig.Scan.Timeouts.DialSeconds)*time.Second,
		time.Duration(config.ShelterConfig.Scan.Timeouts.ReadSeconds)*time.Second,
		time.Duration(config.ShelterConfig.Scan.Timeouts.WriteSeconds)*time.Second,
		config.ShelterConfig.Scan.ConnectionRetries,
	)

	resolver := fmt.Sprintf("%s:%d",
		config.ShelterConfig.Scan.Resolver.Address,
		config.ShelterConfig.Scan.Resolver.Port,
	)

	var dnsRequestMessage dns.Msg
	dnsRequestMessage.SetQuestion(fqdn, dns.TypeNS)
	dnsRequestMessage.RecursionDesired = true

	// Allow retrieving domain information when there's a DNSSEC problem in the chain-of-trust
	dnsRequestMessage.CheckingDisabled = true

	dnsResponseMsg, err := querier.sendDNSRequest(resolver, &dnsRequestMessage)
	if err != nil {
		return domain, err
	}

	for _, answer := range dnsResponseMsg.Answer {
		nsRecord, ok := answer.(*dns.NS)
		if !ok {
			continue
		}

		domain.Nameservers = append(domain.Nameservers, model.Nameserver{
			Host: nsRecord.Ns,
		})
	}

	for index, nameserver := range domain.Nameservers {
		// Don't need to retrieve glue records if not necessary
		if !strings.HasSuffix(nameserver.Host, domain.FQDN) {
			continue
		}

		dnsRequestMessage.SetQuestion(nameserver.Host, dns.TypeA)
		dnsResponseMsg, err = querier.sendDNSRequest(resolver, &dnsRequestMessage)
		if err != nil {
			return domain, err
		}

		for _, answer := range dnsResponseMsg.Answer {
			ipv4Record, ok := answer.(*dns.A)
			if !ok {
				continue
			}

			domain.Nameservers[index].IPv4 = ipv4Record.A
		}

		dnsRequestMessage.SetQuestion(nameserver.Host, dns.TypeAAAA)
		dnsResponseMsg, err = querier.sendDNSRequest(resolver, &dnsRequestMessage)
		if err != nil {
			return domain, err
		}

		for _, answer := range dnsResponseMsg.Answer {
			ipv6Record, ok := answer.(*dns.AAAA)
			if !ok {
				continue
			}

			domain.Nameservers[index].IPv6 = ipv6Record.AAAA
		}
	}

	// We are going to retrieve the DNSKEYs from the user zone, and generate the DS records from it.
	// This is good if the user wants to use the Shelter project as a easy-to-fill domain registration
	// form
	dnsRequestMessage.SetQuestion(fqdn, dns.TypeDNSKEY)

	dnsResponseMsg, err = querier.sendDNSRequest(resolver, &dnsRequestMessage)
	if err != nil {
		return domain, err
	}

	for _, answer := range dnsResponseMsg.Answer {
		dnskeyRecord, ok := answer.(*dns.DNSKEY)
		if !ok {
			continue
		}

		// Only add DNSKEYs with bit SEP on
		if (dnskeyRecord.Flags & dns.SEP) == 0 {
			continue
		}

		dsRecord := dnskeyRecord.ToDS(uint8(DefaultDigestType))

		domain.DSSet = append(domain.DSSet, model.DS{
			Keytag:     dsRecord.KeyTag,
			Algorithm:  model.DSAlgorithm(dsRecord.Algorithm),
			DigestType: model.DSDigestType(dsRecord.DigestType),
			Digest:     dsRecord.Digest,
		})
	}

	return domain, nil
}