#if defined(HAVE_YAML_CONFIGURATION)
#include "base64.hh"
#include "dolog.hh"
+#include "dnscrypt.hh"
#include "dnsdist-actions-factory.hh"
#include "dnsdist-backend.hh"
#include "dnsdist-cache.hh"
}
for (const auto& bind : globalConfig.binds) {
- ComboAddress listeningAddress(std::string(bind.listen_address), 53);
- updateImmutableConfiguration([&bind, listeningAddress](ImmutableConfiguration& config) {
+ updateImmutableConfiguration([&bind](ImmutableConfiguration& config) {
auto protocol = boost::to_lower_copy(std::string(bind.protocol));
+ uint16_t defaultPort = 53;
+ if (protocol == "dot" || protocol == "doq") {
+ defaultPort = 853;
+ }
+ else if (protocol == "doh" || protocol == "dnscrypt" || protocol == "doh3") {
+ defaultPort = 443;
+ }
+ ComboAddress listeningAddress(std::string(bind.listen_address), defaultPort);
auto cpus = getCPUPiningFromStr("binds", std::string(bind.cpus));
for (size_t idx = 0; idx < bind.threads; idx++) {
+#if defined(HAVE_DNSCRYPT)
+ std::shared_ptr<DNSCryptContext> dnsCryptContext;
+#endif /* defined(HAVE_DNSCRYPT) */
+
auto state = std::make_shared<ClientState>(listeningAddress, protocol != "doq" && protocol != "doh3", bind.reuseport, bind.tcp.fast_open_queue_size, std::string(bind.interface), cpus, false);
+
if (bind.tcp.listen_queue_size > 0) {
state->tcpListenQueueSize = bind.tcp.listen_queue_size;
}
}
}
- if (protocol != "do53") {
+ if (protocol == "dnscrypt") {
+#if defined(HAVE_DNSCRYPT)
+ std::vector<DNSCryptContext::CertKeyPaths> certKeys;
+ for (const auto& pair : bind.dnscrypt.certificates) {
+ certKeys.push_back({std::string(pair.certificate), std::string(pair.key)});
+ }
+ dnsCryptContext = std::make_shared<DNSCryptContext>(std::string(bind.dnscrypt.provider_name), certKeys);
+ state->dnscryptCtx = dnsCryptContext;
+#endif /* defined(HAVE_DNSCRYPT) */
+ }
+ else if (protocol != "do53") {
if (!handleTLSConfiguration(bind, *state)) {
continue;
}
}
config.d_frontends.emplace_back(std::move(state));
- if (protocol == "do53") {
+ if (protocol == "do53" || protocol == "dnscrypt") {
/* also create the UDP listener */
- state = std::make_shared<ClientState>(ComboAddress(std::string(bind.listen_address), 53), false, bind.reuseport, bind.tcp.fast_open_queue_size, std::string(bind.interface), cpus, false);
+ state = std::make_shared<ClientState>(ComboAddress(std::string(bind.listen_address), defaultPort), false, bind.reuseport, bind.tcp.fast_open_queue_size, std::string(bind.interface), cpus, false);
+#if defined(HAVE_DNSCRYPT)
+ state->dnscryptCtx = dnsCryptContext;
+#endif /* defined(HAVE_DNSCRYPT) */
config.d_frontends.emplace_back(std::move(state));
}
}
internal_pipe_buffer_size: u32,
}
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct IncomingDnscryptCertificateKeyPairConfiguration {
+ certificate: String,
+ key: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct IncomingDnscryptConfiguration {
+ #[serde(rename = "provider-name", default, skip_serializing_if = "crate::is_default")]
+ provider_name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ certificates: Vec<IncomingDnscryptCertificateKeyPairConfiguration>,
+ }
+
#[derive(Deserialize, Serialize, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
struct OutgoingDohConfiguration {
doq: IncomingDoqConfiguration,
#[serde(default, skip_serializing_if = "crate::is_default")]
quic: IncomingQuicConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ dnscrypt: IncomingDnscryptConfiguration,
#[serde(rename = "additional-addresses", default, skip_serializing_if = "crate::is_default")]
additional_addresses: Vec<String>,
}
}
+impl Default for dnsdistsettings::IncomingDnscryptCertificateKeyPairConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::IncomingDnscryptCertificateKeyPairConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::IncomingDnscryptConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::IncomingDnscryptConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
// DEFAULT HANDLING for outgoing_doh_path
fn default_value_outgoing_doh_path() -> String {
String::from("/dns-query")
Ok(())
}
}
+impl dnsdistsettings::IncomingDnscryptCertificateKeyPairConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::IncomingDnscryptConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.certificates {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
impl dnsdistsettings::OutgoingDohConfiguration {
fn validate(&self) -> Result<(), ValidationError> {
Ok(())
self.doh.validate()?;
self.doq.validate()?;
self.quic.validate()?;
+ self.dnscrypt.validate()?;
Ok(())
}
}
type: "u32"
default: 1048576
+incoming-dnscrypt-certificate-key-pair:
+ parameters:
+ - name: "certificate"
+ type: "String"
+ - name: "key"
+ type: "String"
+
+incoming-dnscrypt:
+ parameters:
+ - name: "provider-name"
+ type: "String"
+ default: ""
+ - name: "certificates"
+ type: "Vec<IncomingDnscryptCertificateKeyPairConfiguration>"
+ default: true
+
outgoing-doh:
parameters:
- name: "path"
- name: "quic"
type: "IncomingQuicConfiguration"
default: true
+ - name: "dnscrypt"
+ type: "IncomingDnscryptConfiguration"
+ default: true
- name: "additional-addresses"
type: "Vec<String>"
default: true
- **doh**: :ref:`IncomingDohConfiguration <yaml-settings-IncomingDohConfiguration>`
- **doq**: :ref:`IncomingDoqConfiguration <yaml-settings-IncomingDoqConfiguration>`
- **quic**: :ref:`IncomingQuicConfiguration <yaml-settings-IncomingQuicConfiguration>`
+- **dnscrypt**: :ref:`IncomingDnscryptConfiguration <yaml-settings-IncomingDnscryptConfiguration>`
- **additional-addresses**: Sequence of String
- **headers**: Sequence of :ref:`HttpCustomResponseHeaderConfiguration <yaml-settings-HttpCustomResponseHeaderConfiguration>`
+.. _yaml-settings-IncomingDnscryptCertificateKeyPairConfiguration:
+
+IncomingDnscryptCertificateKeyPairConfiguration
+-----------------------------------------------
+
+- **certificate**: String
+- **key**: String
+
+
+.. _yaml-settings-IncomingDnscryptConfiguration:
+
+IncomingDnscryptConfiguration
+-----------------------------
+
+- **provider-name**: String ``("")``
+- **certificates**: Sequence of :ref:`IncomingDnscryptCertificateKeyPairConfiguration <yaml-settings-IncomingDnscryptCertificateKeyPairConfiguration>`
+
+
.. _yaml-settings-IncomingDohConfiguration:
IncomingDohConfiguration
self.doDNSCryptQuery(client, query, response, True)
+class TestDNSCryptYaml(TestDNSCrypt):
+ _config_template = """
+ function checkDNSCryptUDP(dq)
+ if dq:getProtocol() ~= "DNSCrypt UDP" then
+ return DNSAction.Spoof, '1.2.3.4'
+ end
+ return DNSAction.None
+ end
+
+ function checkDNSCryptTCP(dq)
+ if dq:getProtocol() ~= "DNSCrypt TCP" then
+ return DNSAction.Spoof, '1.2.3.4'
+ end
+ return DNSAction.None
+ end
+"""
+ _yaml_config_template = """
+console:
+ key: "%s"
+ listen-address: "127.0.0.1:%d"
+ acl:
+ - 127.0.0.0/8
+binds:
+ - listen-address: "127.0.0.1:%d"
+ protocol: "DNSCrypt"
+ dnscrypt:
+ provider-name: "%s"
+ certificates:
+ - certificate: "DNSCryptResolver.cert"
+ key: "DNSCryptResolver.key"
+backends:
+ - address: "127.0.0.1:%d"
+ protocol: Do53
+query-rules:
+ - selector:
+ type: "QName"
+ qname: "udp.protocols.dnscrypt.tests.powerdns.com."
+ action:
+ type: "Lua"
+ function: "checkDNSCryptUDP"
+ - selector:
+ type: "QName"
+ qname: "tcp.protocols.dnscrypt.tests.powerdns.com."
+ action:
+ type: "Lua"
+ function: "checkDNSCryptTCP"
+"""
+ _config_params = []
+ _yaml_config_params = ['_consoleKeyB64', '_consolePort', '_dnsDistPortDNSCrypt', '_providerName', '_testServerPort']
+
class TestDNSCryptWithCache(DNSCryptTest):
_config_params = ['_resolverCertificateSerial', '_resolverCertificateValidFrom', '_resolverCertificateValidUntil', '_dnsDistPortDNSCrypt', '_providerName', '_testServerPort']