11 Commits

12 changed files with 125 additions and 112 deletions

24
Cargo.lock generated
View File

@ -281,9 +281,9 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.81" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0" checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -1344,18 +1344,18 @@ dependencies = [
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.1.2" version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
dependencies = [ dependencies = [
"pin-project-internal", "pin-project-internal",
] ]
[[package]] [[package]]
name = "pin-project-internal" name = "pin-project-internal"
version = "1.1.2" version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1364,9 +1364,9 @@ dependencies = [
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.10" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c"
[[package]] [[package]]
name = "pin-utils" name = "pin-utils"
@ -1707,18 +1707,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.181" version = "1.0.183"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d3e73c93c3240c0bda063c239298e633114c69a888c3e37ca8bb33f343e9890" checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.181" version = "1.0.183"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be02f6cb0cd3a5ec20bbcfbcbd749f57daddb1a0882dc2e46a6c236c90b977ed" checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -72,7 +72,7 @@ This configuration option will not be exposed over the webinterface.
By default echoip-slatecave uses the system configuration for dns like most other programs. By default echoip-slatecave uses the system configuration for dns like most other programs.
In case this is undesired one can difable it by setting `enable_system_resolver` to false. In case this is undesired one can disable it by setting `enable_system_resolver` to false.
```toml ```toml
[dns] [dns]
@ -90,10 +90,6 @@ In case you want to use the system resolver and customize it.
`system_resolver_weight` `system_resolver_weight`
: Equivalent to the `weight` of a custom resolver, default: 1000 : Equivalent to the `weight` of a custom resolver, default: 1000
### `search`
This is for a work in progress feature that allows confiuring search domains for all custom dns resolvers.
### Custom resolvers ### Custom resolvers
It is possible to confgure custom resolvers in plce of or in addition to the default system resolver. It is possible to confgure custom resolvers in plce of or in addition to the default system resolver.

View File

@ -67,9 +67,9 @@ The default configuration is pretty liberal so that the average human probably w
## TODO ## TODO
* [ ] Investigate why search isn't working for global TLDs
* [ ] Add a way to configure just the dns server addresses and derive the port from the protocol. * [ ] Add a way to configure just the dns server addresses and derive the port from the protocol.
* [ ] Add an about page for the system resolver * [ ] Add an about page for the system resolver
* [ ] Expose DNS responses from the additional on the web interface
## License ## License

View File

@ -28,9 +28,6 @@ allow_reverse_lookup = true
# that end with one of these suffixes don't exist # that end with one of these suffixes don't exist
hidden_suffixes = [".com"] hidden_suffixes = [".com"]
# doesn't really work 🙁
search = ["org","net"]
[geoip] [geoip]
# Path to geoip databses # Path to geoip databses
# Currently only the mmdb format is supported # Currently only the mmdb format is supported
@ -116,7 +113,7 @@ tls_dns_name = "cloudflare-dns.com"
[dns.resolver.google] [dns.resolver.google]
display_name = "Google" display_name = "Google"
info_url = "https://www.cloudflare.com/dns/" info_url = "https://developers.google.com/speed/public-dns/docs/using"
aliases = ["goo","8888"] aliases = ["goo","8888"]
weight = 440 weight = 440

View File

@ -1,6 +1,5 @@
use serde::{Deserialize,Serialize}; use serde::{Deserialize,Serialize};
use trust_dns_resolver::config::Protocol; use trust_dns_resolver::config::Protocol;
use trust_dns_resolver::Name;
use std::collections::HashMap; use std::collections::HashMap;
use std::net::SocketAddr; use std::net::SocketAddr;
@ -11,7 +10,6 @@ pub struct DnsConfig {
pub allow_forward_lookup: bool, pub allow_forward_lookup: bool,
pub allow_reverse_lookup: bool, pub allow_reverse_lookup: bool,
pub hidden_suffixes: Vec<String>, pub hidden_suffixes: Vec<String>,
pub search: Vec<String>,
pub resolver: HashMap<String,DnsResolverConfig>, pub resolver: HashMap<String,DnsResolverConfig>,
pub enable_system_resolver: bool, pub enable_system_resolver: bool,
@ -40,8 +38,6 @@ pub struct DnsResolverConfig {
#[serde(default="zero")] #[serde(default="zero")]
pub weight: i32, pub weight: i32,
pub servers: Vec<SocketAddr>, pub servers: Vec<SocketAddr>,
#[serde(default)]
pub search: Vec<String>,
pub protocol: DnsProtocol, pub protocol: DnsProtocol,
pub tls_dns_name: Option<String>, pub tls_dns_name: Option<String>,
#[serde(skip_serializing)] //Don't leak our bind address to the outside #[serde(skip_serializing)] //Don't leak our bind address to the outside
@ -65,7 +61,6 @@ impl Default for DnsConfig {
allow_reverse_lookup: false, allow_reverse_lookup: false,
hidden_suffixes: Vec::new(), hidden_suffixes: Vec::new(),
resolver: Default::default(), resolver: Default::default(),
search: Vec::new(),
enable_system_resolver: true, enable_system_resolver: true,
system_resolver_name: "System".to_string(), system_resolver_name: "System".to_string(),
@ -89,8 +84,7 @@ impl Into<Protocol> for DnsProtocol {
impl DnsResolverConfig { impl DnsResolverConfig {
pub fn to_trust_resolver_config( pub fn to_trust_resolver_config(
&self, &self
additional_search: &Vec<String>,
) -> trust_dns_resolver::config::ResolverConfig { ) -> trust_dns_resolver::config::ResolverConfig {
let mut resolver = trust_dns_resolver::config::ResolverConfig::new(); let mut resolver = trust_dns_resolver::config::ResolverConfig::new();
for server in &self.servers { for server in &self.servers {
@ -103,16 +97,10 @@ impl DnsResolverConfig {
bind_addr: self.bind_address, bind_addr: self.bind_address,
}); });
} }
for search in &self.search { // Not configuring domain search here because searching
if let Ok(name) = Name::from_str_relaxed(search) { // on the resolver level is a bad idea unless we are
resolver.add_search(name); // taling about the system resolver which we
} // can't tell what to do (which is good!)
}
for search in additional_search {
if let Ok(name) = Name::from_str_relaxed(search) {
resolver.add_search(name);
}
}
return resolver; return resolver;
} }
} }

View File

@ -22,6 +22,7 @@ use serde::{Deserialize,Serialize};
use tera::Tera; use tera::Tera;
use tower::ServiceBuilder; use tower::ServiceBuilder;
use tower_http::services::ServeDir; use tower_http::services::ServeDir;
use trust_dns_resolver::Name;
use trust_dns_resolver::TokioAsyncResolver; use trust_dns_resolver::TokioAsyncResolver;
use tokio::signal::unix::{ use tokio::signal::unix::{
@ -258,7 +259,7 @@ async fn main() {
for (key, resolver_config) in &config.dns.resolver { for (key, resolver_config) in &config.dns.resolver {
println!("Initalizing {} resolver ...", key); println!("Initalizing {} resolver ...", key);
let resolver = TokioAsyncResolver::tokio( let resolver = TokioAsyncResolver::tokio(
resolver_config.to_trust_resolver_config(&config.dns.search), resolver_config.to_trust_resolver_config(),
Default::default() Default::default()
).unwrap(); ).unwrap();
dns_resolver_map.insert(key.clone(), resolver); dns_resolver_map.insert(key.clone(), resolver);
@ -679,32 +680,48 @@ async fn get_dig_result(
let name = &dig_query.trim().trim_end_matches(".").to_string(); let name = &dig_query.trim().trim_end_matches(".").to_string();
let idna_name = IdnaName::from_string(&name); let idna_name = IdnaName::from_string(&name);
if let Some(dns_resolver) = &state.dns_resolvers.get(dns_resolver_name) { if let Some(dns_resolver) = &state.dns_resolvers.get(dns_resolver_name) {
if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) { if let Ok(domain_name) = Name::from_str_relaxed(name.to_owned()+".") {
// Try to hide the fact that we didn't do dns resolution at all if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
// We resolve example.org as basic avoidance of timing sidechannels. // Try to hide the fact that we didn't do dns resolution at all
// WARNING: this timing sidechannel avoidance is very crude. // We resolve example.org as basic avoidance of timing sidechannels.
simple_dns::lookup( // WARNING: this timing sidechannel avoidance is very crude.
simple_dns::lookup(
&dns_resolver,
&Name::from_ascii("example.org.").expect("Static Dummy Name"),
do_full_lookup).await;
return DigResult {
records: DnsLookupResult{ nxdomain: true , ..Default::default() },
idn: idna_name,
partial_lookup: !do_full_lookup,
used_dns_resolver: dns_resolver_name.clone(),
}
} else {
return DigResult {
records: simple_dns::lookup(
&dns_resolver, &dns_resolver,
&("example.org.".to_string()), &domain_name,
do_full_lookup).await; do_full_lookup).await,
DigResult { idn: idna_name,
records: DnsLookupResult{ nxdomain: true , ..Default::default() }, partial_lookup: !do_full_lookup,
idn: idna_name, used_dns_resolver: dns_resolver_name.clone(),
partial_lookup: !do_full_lookup, }
used_dns_resolver: dns_resolver_name.clone(),
} }
} else { } else {
DigResult { return DigResult {
records: simple_dns::lookup( records: DnsLookupResult{
&dns_resolver, invalid_name: true,
&(idna_name.idn.clone().unwrap_or(name.to_owned())+"."), .. Default::default()
do_full_lookup).await, },
idn: idna_name, .. Default::default()
partial_lookup: !do_full_lookup,
used_dns_resolver: dns_resolver_name.clone(),
} }
} }
} else { } else {
return Default::default(); return DigResult {
records: DnsLookupResult{
unkown_resolver: true,
.. Default::default()
},
.. Default::default()
}
} }
} }

View File

@ -15,6 +15,7 @@ use trust_dns_resolver::{
error::ResolveError, error::ResolveError,
error::ResolveErrorKind, error::ResolveErrorKind,
lookup::Lookup, lookup::Lookup,
Name,
TokioAsyncResolver, TokioAsyncResolver,
}; };
@ -37,10 +38,12 @@ pub struct DnsLookupResult {
pub txt: Option<Vec<String>>, pub txt: Option<Vec<String>>,
pub srv: Option<Vec<SrvRecord>>, pub srv: Option<Vec<SrvRecord>>,
pub caa: Option<Vec<String>>, pub caa: Option<Vec<String>>,
pub other_error: bool, pub other_error: bool,
pub dns_error: bool, pub dns_error: bool,
pub nxdomain: bool, pub nxdomain: bool,
pub timeout: bool, pub timeout: bool,
pub invalid_name: bool,
pub unkown_resolver: bool,
} }
#[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq)] #[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq)]
@ -171,8 +174,14 @@ pub fn integrate_lookup_result(dig_result: &mut DnsLookupResult, lookup_result:
RecordType::TXT => set_default_if_none(&mut dig_result.txt), RecordType::TXT => set_default_if_none(&mut dig_result.txt),
_ => { /* This should not happen */ }, _ => { /* This should not happen */ },
}; };
for record in lookup.iter() { let name = lookup.query().name();
add_record_to_lookup_result(dig_result, record); for record in lookup.record_iter() {
if name == record.name() {
if let Some(data) = record.data() {
add_record_to_lookup_result(dig_result, data);
}
}
//TODO: handle additional responses
} }
}, },
Err(e) => { Err(e) => {
@ -210,7 +219,7 @@ pub fn integrate_lookup_result(dig_result: &mut DnsLookupResult, lookup_result:
// records will be fetched. // records will be fetched.
pub async fn lookup( pub async fn lookup(
resolver: &TokioAsyncResolver, resolver: &TokioAsyncResolver,
name: &String, name: &Name,
do_full_lookup: bool, do_full_lookup: bool,
) -> DnsLookupResult { ) -> DnsLookupResult {
let ( let (
@ -219,10 +228,10 @@ pub async fn lookup(
cname_lookup_res, cname_lookup_res,
aname_lookup_res aname_lookup_res
) = join!( ) = join!(
resolver.lookup(name, RecordType::A), resolver.lookup(name.clone(), RecordType::A),
resolver.lookup(name, RecordType::AAAA), resolver.lookup(name.clone(), RecordType::AAAA),
resolver.lookup(name, RecordType::CNAME), resolver.lookup(name.clone(), RecordType::CNAME),
resolver.lookup(name, RecordType::ANAME), resolver.lookup(name.clone(), RecordType::ANAME),
); );
// initlize an empty lookup result // initlize an empty lookup result
@ -243,12 +252,12 @@ pub async fn lookup(
srv_lookup_res, srv_lookup_res,
txt_lookup_res txt_lookup_res
) = join!( ) = join!(
resolver.lookup(name, RecordType::MX), resolver.lookup(name.clone(), RecordType::MX),
resolver.lookup(name, RecordType::NS), resolver.lookup(name.clone(), RecordType::NS),
resolver.lookup(name, RecordType::SOA), resolver.lookup(name.clone(), RecordType::SOA),
resolver.lookup(name, RecordType::CAA), resolver.lookup(name.clone(), RecordType::CAA),
resolver.lookup(name, RecordType::SRV), resolver.lookup(name.clone(), RecordType::SRV),
resolver.lookup(name, RecordType::TXT), resolver.lookup(name.clone(), RecordType::TXT),
); );
integrate_lookup_result(&mut dig_result, mx_lookup_res); integrate_lookup_result(&mut dig_result, mx_lookup_res);

View File

@ -26,8 +26,16 @@
<section> <section>
<h2>DNS Records</h2> <h2>DNS Records</h2>
{% if r.nxdomain %} {% set show_nonpresent = true %}
<p class="error box">Our DNS-Server claims that this domain doesn't exist, there shouldn't be any results.</p> {% if r.unkown_resolver %}
<p class="error box">The resolver you chose is not one of the available ones, if you can reproduce this error by just using the UI <a href="https://codeberg.org/slatian/service.echoip-slatecave/issues/new">please report it</a>.</p>
{% set show_nonpresent = false %}
{% elif r.invalid_name %}
<p class="error box">This domain name does not conform to <a href="https://www.rfc-editor.org/info/std3">the dns specification (std3)</a> rules and was therefore not resolved.</p>
{% set show_nonpresent = false %}
{% elif r.nxdomain %}
<p class="error box">The DNS-Server claims that this domain doesn't exist, there shouldn't be any results.</p>
{% set show_nonpresent = false %}
{% elif r.timeout %} {% elif r.timeout %}
<p class="error box">There was at least one timeout error while resolving this domain, the results below are incomplete.</p> <p class="error box">There was at least one timeout error while resolving this domain, the results below are incomplete.</p>
{% elif r.other_error %} {% elif r.other_error %}
@ -66,7 +74,7 @@
<li>{{ helper::ip(extra=extra, ip=address) }}</li> <li>{{ helper::ip(extra=extra, ip=address) }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% elif not r.nxdomain %} {% elif show_nonpresent %}
<p>No <code>A</code> (IPv4) Records.</p> <p>No <code>A</code> (IPv4) Records.</p>
{% endif %} {% endif %}
@ -77,7 +85,7 @@
<li>{{ helper::ip(extra=extra, ip=address) }}</li> <li>{{ helper::ip(extra=extra, ip=address) }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% elif not r.nxdomain %} {% elif show_nonpresent %}
<p>No <code>AAAA</code> (IPv6) Records.</p> <p>No <code>AAAA</code> (IPv6) Records.</p>
{% endif %} {% endif %}
@ -90,7 +98,7 @@
<li>{{ helper::dig(extra=extra, name=mx.exchange, fqdn=true, prefix=mx.preference) }}</li> <li>{{ helper::dig(extra=extra, name=mx.exchange, fqdn=true, prefix=mx.preference) }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% elif not r.nxdomain %} {% elif show_nonpresent %}
<p id="mx">No <code>MX</code> (Mail Exchange) records.</p> <p id="mx">No <code>MX</code> (Mail Exchange) records.</p>
{% endif %} {% endif %}
@ -116,7 +124,7 @@
</dl></li> </dl></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% elif not r.nxdomain %} {% elif show_nonpresent %}
<p id="soa">No <code>SOA</code> records.</p> <p id="soa">No <code>SOA</code> records.</p>
{% endif %} {% endif %}
@ -129,7 +137,7 @@
<li>{{ helper::dig(extra=extra, name=ns) }}</li> <li>{{ helper::dig(extra=extra, name=ns) }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% elif not r.nxdomain %} {% elif show_nonpresent %}
<p id="ns">No <code>NS</code> (Name Server) records.</p> <p id="ns">No <code>NS</code> (Name Server) records.</p>
{% endif %} {% endif %}
@ -141,7 +149,7 @@
<li><code>{{caa}}</code></li> <li><code>{{caa}}</code></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% elif not r.nxdomain %} {% elif show_nonpresent %}
<p id="caa">No <code>CAA</code> (<a target="_blank" href="https://de.wikipedia.org/wiki/DNS_Certification_Authority_Authorization">Certification Authority Authorization</a>) records.</p> <p id="caa">No <code>CAA</code> (<a target="_blank" href="https://de.wikipedia.org/wiki/DNS_Certification_Authority_Authorization">Certification Authority Authorization</a>) records.</p>
{% endif %} {% endif %}
@ -152,7 +160,7 @@
<li><code>{{txt}}</code></li> <li><code>{{txt}}</code></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% elif not r.nxdomain %} {% elif show_nonpresent %}
<p id="txt">No <code>TXT</code> records.</p> <p id="txt">No <code>TXT</code> records.</p>
{% endif %} {% endif %}
@ -172,7 +180,7 @@
</dl></li> </dl></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% elif not r.nxdomain %} {% elif show_nonpresent %}
<p id="srv">No <code>SRV</code> records.</p> <p id="srv">No <code>SRV</code> records.</p>
<p><code>SRV</code> or Service records usually live on their own subdomains like {{ helper::dig(extra=extra, name="_xmpp-client._tcp."~data.query) }}. <p><code>SRV</code> or Service records usually live on their own subdomains like {{ helper::dig(extra=extra, name="_xmpp-client._tcp."~data.query) }}.
{% endif %} {% endif %}

View File

@ -2,7 +2,8 @@
{% block path %}dig/{{ data.query | urlencode_strict }}{% endblock %} {% block path %}dig/{{ data.query | urlencode_strict }}{% endblock %}
{% block content -%} {% set r = data.result.records %}
{%- block content -%}
# dig {{data.query}} via {{ data.result.used_dns_resolver }} # dig {{data.query}} via {{ data.result.used_dns_resolver }}
{% if data.result.idn -%} {% if data.result.idn -%}
@ -25,7 +26,16 @@ Your IDN would decode to
{% set r = data.result.records -%} {% set r = data.result.records -%}
## DNS Records ## DNS Records
{% if r.nxdomain %} {% if r.unkown_resolver %}
{%- set show_nonpresent = false %}
The resolver you chose is not one of the available ones.
=> {{ extra.base_url }}/dns_resolver
{% elif r.invalid_name %}
{%- set show_nonpresent = false %}
This domain name does not conform to the dns specification (std3) rules and was therefore not resolved.
=> https://www.rfc-editor.org/info/std3
{% elif r.nxdomain %}
{%- set show_nonpresent = false %}
Our DNS-Server claims that this domain doesn't exist, there shouldn't be any results. Our DNS-Server claims that this domain doesn't exist, there shouldn't be any results.
{%- elif r.timeout -%} {%- elif r.timeout -%}
There was at least one timeout error while resolving this domain, the results below are incomplete. There was at least one timeout error while resolving this domain, the results below are incomplete.
@ -61,7 +71,7 @@ A (IPv4) records:
{% for address in r.a -%} {% for address in r.a -%}
* {{ address }} * {{ address }}
{% endfor %} {% endfor %}
{%- elif not r.nxdomain %} {%- elif show_nonpresent %}
No A (IPv4) Records. No A (IPv4) Records.
{% endif -%} {% endif -%}
@ -70,7 +80,7 @@ AAAA (IPv6) records:
{% for address in r.aaaa -%} {% for address in r.aaaa -%}
* {{ address }} * {{ address }}
{% endfor %} {% endfor %}
{%- elif not r.nxdomain %} {%- elif show_nonpresent %}
No AAAA (IPv6) Records. No AAAA (IPv6) Records.
{% endif -%} {% endif -%}
@ -81,7 +91,7 @@ MX (Mail Exchange) records:
{% for mx in r.mx | sort(attribute="preference") | reverse -%} {% for mx in r.mx | sort(attribute="preference") | reverse -%}
* {{ mx.preference }} {{ mx.exchange }} * {{ mx.preference }} {{ mx.exchange }}
{% endfor %} {% endfor %}
{%- elif not r.nxdomain %} {%- elif show_nonpresent %}
No MX (Mail Exchange) records. No MX (Mail Exchange) records.
{% endif %} {% endif %}
@ -96,7 +106,7 @@ SOA (Source Of Authority) records:
* expire: {{soa.expire / 3600 | round(precision=2)}}h * expire: {{soa.expire / 3600 | round(precision=2)}}h
* minimum: {{soa.minimum / 60 | round(precision=2)}}m TTL * minimum: {{soa.minimum / 60 | round(precision=2)}}m TTL
{% endfor %} {% endfor %}
{%- elif not r.nxdomain %} {%- elif show_nonpresent %}
No SOA (Source Of Authority) records. No SOA (Source Of Authority) records.
{% endif %} {% endif %}
@ -105,7 +115,7 @@ NS (Name Server) records:
{% for ns in r.ns -%} {% for ns in r.ns -%}
* {{ns}} * {{ns}}
{% endfor %} {% endfor %}
{%- elif not r.nxdomain %} {%- elif show_nonpresent %}
No NS (Name Server) records. No NS (Name Server) records.
{% endif %} {% endif %}
@ -114,7 +124,7 @@ CAA (Certification Authority Authorization) records:
{% for caa in r.caa -%} {% for caa in r.caa -%}
* {{caa}} * {{caa}}
{% endfor %} {% endfor %}
{%- elif not r.nxdomain %} {%- elif show_nonpresent %}
No CAA (Certification Authority Authorization) records. No CAA (Certification Authority Authorization) records.
{% endif %} {% endif %}
@ -123,7 +133,7 @@ TXT records:
{% for txt in r.txt -%} {% for txt in r.txt -%}
* {{txt}} * {{txt}}
{% endfor %} {% endfor %}
{%- elif not r.nxdomain %} {%- elif show_nonpresent %}
No TXT records. No TXT records.
{% endif %} {% endif %}
@ -135,7 +145,7 @@ SRV records:
* Port: {{srv.port}} * Port: {{srv.port}}
* Target: {{srv.target}} * Target: {{srv.target}}
{% endfor %} {% endfor %}
{%- elif not r.nxdomain %} {%- elif show_nonpresent %}
No SRV records. No SRV records.
SRV or Service records usually live on their own subdomains like {{ "_xmpp-client._tcp."~data.query }}. SRV or Service records usually live on their own subdomains like {{ "_xmpp-client._tcp."~data.query }}.

View File

@ -31,12 +31,6 @@
<dd>{{ helper::dig(extra=extra, name=c.tls_dns_name) }}</dd> <dd>{{ helper::dig(extra=extra, name=c.tls_dns_name) }}</dd>
{%- endif %} {%- endif %}
{%- if c.search | length > 0 %}
<dt>Search</dt>
{%- for s in c.search %}
<dd>{{s}}</dd>
{%- endfor %}
{%- endif %}
</dl> </dl>
{%- if c.info_url %} {%- if c.info_url %}
<p class="button-paragraph"><a href="{{c.info_url}}">More about the {{c.display_name}} DNS Server <small>(external link)</small></a></p> <p class="button-paragraph"><a href="{{c.info_url}}">More about the {{c.display_name}} DNS Server <small>(external link)</small></a></p>

View File

@ -16,14 +16,6 @@ Protocol: {{ c.protocol }}
{%-if c.tls_dns_name %} {%-if c.tls_dns_name %}
DNS Name: {{ c.tls_dns_name }} DNS Name: {{ c.tls_dns_name }}
{%- endif %} {%- endif %}
{%- if c.search | length == 1 %}
Search: {{ c.search | first }}
{%- elif c.search | length > 1 %}
Search:
{%- for s in c.search %}
* {{s}}
{%- endfor %}
{%- endif %}
{%- if c.aliases | length == 1 %} {%- if c.aliases | length == 1 %}
Alias: {{ c.aliases | first }} Alias: {{ c.aliases | first }}
{%- elif c.aliases | length > 1 %} {%- elif c.aliases | length > 1 %}

View File

@ -380,6 +380,8 @@ a:visited {
color: var(--page-link-visited); color: var(--page-link-visited);
} }
a.sitename { display: inline-block; }
h1, a.sitename { h1, a.sitename {
margin: var(--heading-mg); margin: var(--heading-mg);
padding: var(--heading-pad); padding: var(--heading-pad);