turbot/net_insights

Query: dns_ns_report

Usage

powerpipe query net_insights.query.dns_ns_report

Steampipe Tables

SQL

with domain_list as (
select
distinct domain,
substring(
domain
from
'^(?:[^/:]*:[^/@]*@)?(?:[^/:.]*\.)+([^:/]+)'
) as tld
from
net_dns_record
where
domain = $1
),
domain_parent_server as (
select
l.domain,
d.domain as tld,
d.target as parent_server
from
net_dns_record as d
inner join domain_list as l on d.domain = l.tld
where
d.type = 'SOA'
order by
l.domain
),
domain_parent_server_ip as (
select
*
from
net_dns_record
where
domain in (
select
parent_server
from
domain_parent_server
)
order by
domain
),
domain_parent_server_with_ip as (
select
domain_parent_server.domain,
host(domain_parent_server_ip.ip) as ip_text
from
domain_parent_server
inner join domain_parent_server_ip on domain_parent_server.parent_server = domain_parent_server_ip.domain
where
domain_parent_server_ip.type = 'A'
order by
domain_parent_server.domain
),
domain_parent_server_ns_list as (
select
net_dns_record.domain,
net_dns_record.target
from
net_dns_record
inner join domain_parent_server_with_ip on net_dns_record.domain = domain_parent_server_with_ip.domain
and net_dns_record.dns_server = domain_parent_server_with_ip.ip_text
and net_dns_record.type = 'NS'
order by
net_dns_record.domain
),
parent_server_ns_count_by_domain as (
select
net_dns_record.domain,
count(net_dns_record.target)
from
net_dns_record
inner join domain_parent_server_with_ip on net_dns_record.domain = domain_parent_server_with_ip.domain
and net_dns_record.dns_server = domain_parent_server_with_ip.ip_text
and net_dns_record.type = 'NS'
group by
net_dns_record.domain
order by
net_dns_record.domain
),
domain_ns_count as (
select
count(*)
from
net_dns_record
where
domain = $1
and type = 'NS'
group by
domain
),
domain_ns_records as (
select
*
from
net_dns_record
where
domain in ($1)
and type = 'NS'
),
ns_ips as (
select
domain,
type,
ip,
host(ip) as ip_text
from
net_dns_record
where
domain in (
select
target
from
domain_ns_records
)
and type = 'A'
),
ns_with_ip as (
select
domain_ns_records.domain,
host(ns_ips.ip) as ip_text
from
domain_ns_records
inner join ns_ips on domain_ns_records.target = ns_ips.domain
where
ns_ips.type = 'A'
order by
domain_ns_records.domain
),
ns_with_name_server_record as (
select
domain_parent_server_ns_list.domain,
domain_parent_server_ns_list.target,
(
select
count as parent_server_ns_record_count
from
parent_server_ns_count_by_domain
where
domain = domain_parent_server_ns_list.domain
),
(
select
count(*) as name_server_record_count
from
net_dns_record
where
domain = domain_parent_server_ns_list.domain
and dns_server = ns_ips.ip_text
and type = 'NS'
group by
domain
)
from
domain_parent_server_ns_list
left join ns_ips on domain_parent_server_ns_list.target = ns_ips.domain
where
ns_ips.ip is not null
order by
domain_parent_server_ns_list.domain
),
ns_with_different_ns_count as (
select
distinct domain
from
ns_with_name_server_record
where
parent_server_ns_record_count <> name_server_record_count
),
ns_record_with_ip as (
select
domain_ns_records.domain,
domain_ns_records.target,
ns_ips.ip,
(
ns_ips.ip << '10.0.0.0/8' :: inet
or ns_ips.ip << '100.64.0.0/10' :: inet
or ns_ips.ip << '172.16.0.0/12' :: inet
or ns_ips.ip << '192.0.0.0/24' :: inet
or ns_ips.ip << '192.168.0.0/16' :: inet
or ns_ips.ip << '198.18.0.0/15' :: inet
) as is_private
from
domain_ns_records
inner join ns_ips on domain_ns_records.target = ns_ips.domain
),
ns_record_with_private_ip as (
select
distinct domain
from
ns_record_with_ip
where
is_private
),
invalid_ns_count as (
select
domain,
count(*)
from
net_dns_record
where
domain in ($1)
and type = 'NS'
and not target ~ '^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}\.?$'
group by
domain
),
check_ips as (
select
distinct array_to_string(
array_remove(
string_to_array(text(ns_ips.ip), '.'),
split_part(text(ns_ips.ip), '.', 4)
),
'.'
),
domain_ns_records.domain as domain
from
domain_ns_records
inner join ns_ips on domain_ns_records.target = ns_ips.domain
where
ns_ips.type = 'A'
and domain_ns_records.type = 'NS'
),
dns_record_count as (
select
domain,
count(*)
from
net_dns_record
where
domain in (
select
domain
from
domain_list
)
group by
domain
),
dns_cname_count as (
select
domain,
count(*)
from
net_dns_record
where
domain in (
select
domain
from
domain_list
)
and type = 'CNAME'
group by
domain
),
count_stats as (
select
domain,
(
select
count
from
dns_record_count
where
domain = domain_list.domain
) as all_record_count,
(
select
count
from
dns_cname_count
where
domain = domain_list.domain
) as cname_record_count
from
domain_list
)
select
'Multiple name servers' as "Recommendation",
case
when count < 2 then '❌'
else '✅'
end as "Status",
count || ' NS record(s) found. As per RFC2182 section 5 domain record must have at least 3 name servers, and no more than 7.' as "Result"
from
domain_ns_count
UNION
select
'Name of name servers are valid' as "Recommendation",
case
when r.domain is null
or r.count = 0 then '✅'
else '❌'
end as "Status",
case
when r.domain is null
or r.count = 0 then 'Name servers have valid name format.'
else 'At least one name server with invalid name format.'
end || ' The names can contain only alphabetical characters (A-Z), numeric characters (0-9), the minus sign (-), and the period (.). Period characters are allowed only when they are used to delimit the components of domain style names.' as "Result"
from
domain_list as d
left join invalid_ns_count as r on d.domain = r.domain
UNION
select
'Missing name servers reported by parent' as "Recommendation",
case
when ns_with_different_ns_count.domain is null then '✅'
else '❌'
end as "Status",
case
when ns_with_different_ns_count.domain is null then 'NS records returned by parent server is same as the one reported by your name servers.'
else 'Name server records returned by parent server doesn''t match with your name servers [' || (
select
string_agg(target, ', ')
from
ns_with_name_server_record
where
parent_server_ns_record_count <> name_server_record_count
) || '].'
end || ' Unmatched NS records can cause delays when resolving domain records, as it tries to contact a name server that is either non-existent or non-authoritative.' as "Result"
from
domain_list
left join ns_with_different_ns_count on domain_list.domain = ns_with_different_ns_count.domain
UNION
select
'No CNAME record if an NS (or any other) record is present' as "Recommendation",
case
when all_record_count > 0
and (
cname_record_count is null
or cname_record_count < 1
) then '✅'
when cname_record_count > 0
and all_record_count = cname_record_count then '✅'
else '❌'
end as "Status",
case
when all_record_count > 0
and (
cname_record_count is null
or cname_record_count < 1
) then 'No CNAME record found.'
when cname_record_count > 0
and all_record_count = cname_record_count then 'CNAME record(s) [' || (
select
string_agg(target, ', ')
from
net_dns_record
where
domain = count_stats.domain
) || '].'
else domain || ' has CNAME record along with NS (or any other) record.'
end || ' A CNAME record is not allowed to coexist with any other data. This is often attempted by inexperienced administrators as an obvious way to allow your domain name to also be a host. However, DNS servers like BIND will see the CNAME and refuse to add any other resources for that name. Since no other records are allowed to coexist with a CNAME, the NS entries are ignored.' as "Result"
from
count_stats
UNION
select
'Different subnets' as "Recommendation",
case
when count(*) = 1 then '❌'
else '✅'
end as "Status",
case
when count(*) = 1 then 'Name servers are on the same subnet.'
else 'Name servers appear to be dispersed.'
end || ' As per RFC2182 section 3.1, it is recommended that the secondary servers must be placed at both topologically and geographically dispersed locations on the Internet, to minimize the likelihood of a single failure disabling all of them.' as "Result"
from
check_ips
group by
domain
UNION
select
'IPs of name servers are public' as "Recommendation",
case
when ns_record_with_private_ip.domain is null then '✅'
else '❌'
end as "Status",
case
when ns_record_with_private_ip.domain is null then 'All NS records appear to use public IPs.'
else domain_list.domain || ' has NS records using private IPs [' || (
select
host(ip)
from
ns_record_with_ip
where
domain = domain_list.domain
and is_private
) || '].'
end || ' For a server to be accessible on the public internet, it needs a public DNS record, and its IP address needs to be reachable on the internet.' as "Result"
from
domain_list
left join ns_record_with_private_ip on domain_list.domain = ns_record_with_private_ip.domain
UNION
select
'Different autonomous systems' as "Recommendation",
case
when count(*) = 1 then '❌'
else '✅'
end as "Status",
case
when count(*) = 1 then 'Name servers are in same location.'
else 'Name servers are located in different location.'
end || ' As per RFC2182 section 3.1, it is recommended that the secondary servers must be placed at both topologically and geographically dispersed locations on the Internet, to minimize the likelihood of a single failure disabling all of them.' as "Result"
from
check_ips
group by
domain

Params

ArgsNameDefaultDescriptionVariable
$1domain_name_input

    Dashboards

    The query is used in the dashboards: