Esempio n. 1
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
}
Esempio n. 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())
		}
	}
}
Esempio n. 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
}
Esempio n. 4
0
// 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
}