mirror of
https://github.com/internetstandards/toolbox-wiki.git
synced 2026-07-21 19:47:40 +02:00
Fixed typos, updated example configs
This commit is contained in:
+18
-18
@@ -68,12 +68,12 @@ This how-to is created by the Dutch Internet Standards Platform (the organizatio
|
|||||||
# What is DANE?
|
# What is DANE?
|
||||||
DANE is short for "**D**NS-based **A**uthentication of **N**amed **E**ntities" and is described in [RFC 6698](https://tools.ietf.org/html/rfc6698) with "updates and operational guidance" in [RFC 7671](https://tools.ietf.org/html/rfc7671). DANE establishes a downgrade-resistant method to verify an SMTP servers identity **before** it starts to transport an email message over a STARTTLS encrypted layer. In order to achieve this it uses verification information retrieved from the recipients DNSSEC signed DNS zone. DANE does not rely on additional trusted parties outside the delegation chain in DNS.
|
DANE is short for "**D**NS-based **A**uthentication of **N**amed **E**ntities" and is described in [RFC 6698](https://tools.ietf.org/html/rfc6698) with "updates and operational guidance" in [RFC 7671](https://tools.ietf.org/html/rfc7671). DANE establishes a downgrade-resistant method to verify an SMTP servers identity **before** it starts to transport an email message over a STARTTLS encrypted layer. In order to achieve this it uses verification information retrieved from the recipients DNSSEC signed DNS zone. DANE does not rely on additional trusted parties outside the delegation chain in DNS.
|
||||||
|
|
||||||
DANE, as a method, has been designed to work with any TLS service. DANE for SMTP (which is described in [RFC 7672](https://tools.ietf.org/html/rfc7672)) implements the DANE method for SMTP. It is used increasingly and adds active attack (man-in-the-middle) resistance to SMTP transport encryption [RFC 7672 Section 1.3](https://tools.ietf.org/rfc7672#section-1.3). DANE for SMTP uses the presence of DNS TLSA ressource records to **securely signal TLS support** and to publish the means by which SMTP clients can successfully **authenticate legitimate SMTP servers**. The result is called "opportunistic DANE TLS", and resists downgrade and man-in-the-middle (MITM) attacks when the destination domain and its MX hosts are DNSSEC signed, and TLSA records are published for each MX host. While possible, DANE for HTTP is not presently supported by the major browsers and so has seen little deployment.
|
DANE, as a method, has been designed to work with any TLS service. DANE for SMTP (which is described in [RFC 7672](https://tools.ietf.org/html/rfc7672)) implements the DANE method for SMTP. It is used increasingly and adds active attack (man-in-the-middle) resistance to SMTP transport encryption [RFC 7672 Section 1.3](https://tools.ietf.org/rfc7672#section-1.3). DANE for SMTP uses the presence of DNS TLSA resource records to **securely signal TLS support** and to publish the means by which SMTP clients can successfully **authenticate legitimate SMTP servers**. The result is called "opportunistic DANE TLS", and resists downgrade and man-in-the-middle (MITM) attacks when the destination domain and its MX hosts are DNSSEC signed, and TLSA records are published for each MX host. While possible, DANE for HTTP is not presently supported by the major browsers and so has seen little deployment.
|
||||||
|
|
||||||
# Why use DANE for SMTP?
|
# Why use DANE for SMTP?
|
||||||
At this time it is not possible to require **mandatory** transport encryption (TLS) in public mail transport. A mail server might not support transporting messages using encryption. Today only plain text or **opportunistic** transport encryption are applicable – opportunistic because it is up to the receiving server to decide if it wants to and is able to send messages using TLS (via STARTTLS).
|
At this time it is not possible to require **mandatory** transport encryption (TLS) in public mail transport. A mail server might not support transporting messages using encryption. Today only plain text or **opportunistic** transport encryption are applicable – opportunistic because it is up to the receiving server to decide if it wants to and is able to send messages using TLS (via STARTTLS).
|
||||||
|
|
||||||
DANE offers several advantages by binding X.509 certificates to domains using DNSSEC. In an SMTP context this allows **a)** sending mail servers to securely signal TLS support by the receiving domain's mail server, and **b)** sending mail servers to verify the autenticity of the offered certificate by the receiving domain's mail server. This helps to address risks that occur when using oppurtunistic TLS connections between mail servers.
|
DANE offers several advantages by binding X.509 certificates to domains using DNSSEC. In an SMTP context this allows **a)** sending mail servers to securely signal TLS support by the receiving domain's mail server, and **b)** sending mail servers to verify the authenticity of the offered certificate by the receiving domain's mail server. This helps to address risks that occur when using opportunistic TLS connections between mail servers.
|
||||||
|
|
||||||
## Risks of SMTP with opportunistic TLS
|
## Risks of SMTP with opportunistic TLS
|
||||||
The way SMTP was designed including the usage of opportunistic TLS (via STARTTLS) is not without risks:
|
The way SMTP was designed including the usage of opportunistic TLS (via STARTTLS) is not without risks:
|
||||||
@@ -98,14 +98,14 @@ In short: DANE allows sending mail servers to unconditionally require STARTTLS w
|
|||||||
## How about MTA-STS?
|
## How about MTA-STS?
|
||||||
Internet.nl currently does not include MTA-STS in its tests. This paragraph explains why this is the case.
|
Internet.nl currently does not include MTA-STS in its tests. This paragraph explains why this is the case.
|
||||||
|
|
||||||
First you need to understand that, as [explained on our website](https://en.internet.nl/faqs/report/), the selection and development of tests performed by internet.nl is primairily based on:
|
First you need to understand that, as [explained on our website](https://en.internet.nl/faqs/report/), the selection and development of tests performed by internet.nl is primarily based on:
|
||||||
* the [‘comply-or-explain’ list](https://www.forumstandaardisatie.nl/open-standaarden) of the Dutch Standardisation Forum which is mandatory for all Dutch government agencies;
|
* the [‘comply-or-explain’ list](https://www.forumstandaardisatie.nl/open-standaarden) of the Netherlands Standardisation Forum which is mandatory for all Dutch government agencies;
|
||||||
* security advice of the Dutch NCSC;
|
* security advice of the Dutch NCSC;
|
||||||
* relevant RFCs of IETF.
|
* relevant RFCs of IETF.
|
||||||
|
|
||||||
Final decisions in this area are made by our steering committee.
|
Final decisions in this area are made by our steering committee.
|
||||||
|
|
||||||
MTA-STS is a fairly new standard for enforcing authenticated transport encryption between mail servers. The standard was developed primarily by the big cloud mail providers and seems to especially meet their specific needs. We have seen [quite some uptake of DANE](https://github.com/baknu/DANE-for-SMTP/wiki/4.-Adoption-statistics) (e.g. by Comcast, Protonmail and Cisco), but until now not by the major cloud mail providers. MTA-STS is relatively complex because it needs an extra HTTPS interface (including certificate validation) to function, and it is also considered to be less secure than DANE due to trust on first use and caching.
|
MTA-STS is a fairly new standard for enforcing authenticated transport encryption between mail servers. The standard was developed primarily by the big cloud mail providers and seems to especially meet their specific needs. We have seen [quite some uptake of DANE](https://github.com/baknu/DANE-for-SMTP/wiki/4.-Adoption-statistics) (e.g. by Comcast, Protonmail, Microsoft 365 and Cisco). MTA-STS is relatively complex because it needs an extra HTTPS interface (including certificate validation) to function, and it is also considered to be less secure than DANE due to trust on first use and caching.
|
||||||
|
|
||||||
MTA-STS relies on trust on first use (TOFU) and policy caching. So the initial connection is just STARTTLS (without authentication of the receiving mail server and without enforcing encryption). During that first connection the MTA-STS policy will be cached by the sending mail server and subsequent encrypted connections will be enforced and authenticated (until the policy cache time expires). This caching mechanism means the larger and more up up-to-date the cache, the better MTA-STS will work. Basically big (cloud) mail providers (that contact about every mail server worldwide each day) will have a large up-to-date policy cache, but smaller mail providers will not and therefore will run more often into trust on first use (i.e. initial less secure connection). So basically MTA-STS seems to offer better security to big players than to the smaller ones. In fact, the MTA-STS RFC [states](https://tools.ietf.org/html/rfc8461#section-10) that DANE offers better downgrade resistance.
|
MTA-STS relies on trust on first use (TOFU) and policy caching. So the initial connection is just STARTTLS (without authentication of the receiving mail server and without enforcing encryption). During that first connection the MTA-STS policy will be cached by the sending mail server and subsequent encrypted connections will be enforced and authenticated (until the policy cache time expires). This caching mechanism means the larger and more up up-to-date the cache, the better MTA-STS will work. Basically big (cloud) mail providers (that contact about every mail server worldwide each day) will have a large up-to-date policy cache, but smaller mail providers will not and therefore will run more often into trust on first use (i.e. initial less secure connection). So basically MTA-STS seems to offer better security to big players than to the smaller ones. In fact, the MTA-STS RFC [states](https://tools.ietf.org/html/rfc8461#section-10) that DANE offers better downgrade resistance.
|
||||||
|
|
||||||
@@ -126,8 +126,8 @@ Note that MTA-STA and DANE can co-exists next to each other. They intentionally
|
|||||||
0: fingerprint with regard to the full certificate (not recommended / [to be avoided](http://dnssec-stats.ant.isi.edu/~viktor/x3hosts.html))
|
0: fingerprint with regard to the full certificate (not recommended / [to be avoided](http://dnssec-stats.ant.isi.edu/~viktor/x3hosts.html))
|
||||||
1: fingerprint with regard to the public key (recommended)
|
1: fingerprint with regard to the public key (recommended)
|
||||||
|
|
||||||
**Matching-Type**: information about the hashing mechanism used for fingeeprint regarding this TLSA record.
|
**Matching-Type**: information about the hashing mechanism used for fingerprint regarding this TLSA record.
|
||||||
0: no hasing, full information (not recommended / [to be avoided](https://tools.ietf.org/html/rfc7672#section-3.1.2))
|
0: no hashing, full information (not recommended / [to be avoided](https://tools.ietf.org/html/rfc7672#section-3.1.2))
|
||||||
1: SHA2-256 hash ([recommended](https://tools.ietf.org/html/rfc7672#section-3.1.1))
|
1: SHA2-256 hash ([recommended](https://tools.ietf.org/html/rfc7672#section-3.1.1))
|
||||||
2: SHA2-512 hash (not recommended / [less supported](https://www.rfc-editor.org/rfc/rfc6698.html#section-6))
|
2: SHA2-512 hash (not recommended / [less supported](https://www.rfc-editor.org/rfc/rfc6698.html#section-6))
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ The illustration below shows two TLS capable mail servers without using DANE. Th
|
|||||||

|

|
||||||
|
|
||||||
## Mail delivery: TLS with MITM stripping TLS
|
## Mail delivery: TLS with MITM stripping TLS
|
||||||
The illustration below shows what happens when an attacker performs a man in the middle (MITM) attack and forces an unsecure connection by stripping the TLS capability from the receiving e-mail server.
|
The illustration below shows what happens when an attacker performs a man in the middle (MITM) attack and forces an insecure connection by stripping the TLS capability from the receiving e-mail server.
|
||||||
|
|
||||||
* When an attacker controls the network communication between the sending and receiving server it may downgrade the session by removing the information that indicates the receiving server supports encrypted transport. The sending server would proceed and transport the message unencrypted making all data contained in the message visible to the attacker.
|
* When an attacker controls the network communication between the sending and receiving server it may downgrade the session by removing the information that indicates the receiving server supports encrypted transport. The sending server would proceed and transport the message unencrypted making all data contained in the message visible to the attacker.
|
||||||
|
|
||||||
@@ -155,8 +155,8 @@ The illustration below shows what happens when an attacker performs a man in the
|
|||||||
## Mail delivery: TLS with DANE
|
## Mail delivery: TLS with DANE
|
||||||
The illustration below shows how the use of DANE can protect against man in the middle (MITM) attacks by addressing the shortcomings of TLS without DANE.
|
The illustration below shows how the use of DANE can protect against man in the middle (MITM) attacks by addressing the shortcomings of TLS without DANE.
|
||||||
|
|
||||||
* The operator of the receiving server publishes a TLSA record in its DNSSEC signed zone. The mere existence of the record indicates to the sending server that the recieving server **must** offer STARTTLS. Otherwise transport must not take place.
|
* The operator of the receiving server publishes a TLSA record in its DNSSEC signed zone. The mere existence of the record indicates to the sending server that the receiving server **must** offer STARTTLS. Otherwise transport must not take place.
|
||||||
* The receiving server's TLSA record contains policy information and a string that identifies the correct certificate. Only the good servers certiciate will match these verification criteria. Unless the attacker is also in possesion of the good servers certificate it cannot disguise as good and the man-in-the-middle server will be detected. It the verification data does not match the servers certificate the sending server will not transport the message.
|
* The receiving server's TLSA record contains policy information and a string that identifies the correct certificate. Only the good servers certificate will match these verification criteria. Unless the attacker is also in possession of the good servers certificate it cannot disguise as good and the man-in-the-middle server will be detected. It the verification data does not match the servers certificate the sending server will not transport the message.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -166,13 +166,13 @@ Although guaranteeing reliable DNS resolving is actually an advantage of DNSSEC,
|
|||||||
# Reliable certificate rollover
|
# Reliable certificate rollover
|
||||||
A TLSA record identifies a certificate. If the certificate is exchanged for a new one also the associated TLSA record needs to be updated. Otherwise there will be a mismatch, verification will fail and DANE aware servers will not send messages to the receiver's domain.
|
A TLSA record identifies a certificate. If the certificate is exchanged for a new one also the associated TLSA record needs to be updated. Otherwise there will be a mismatch, verification will fail and DANE aware servers will not send messages to the receiver's domain.
|
||||||
|
|
||||||
Usually this creates the intent not to exchange the certificate at all. But this collides with best-practices to replace crytographic material – certificates and keys – from time to time.
|
Usually this creates the intent not to exchange the certificate at all. But this collides with best-practices to replace cryptographic material – certificates and keys – from time to time.
|
||||||
|
|
||||||
To satisfy both requirements establish these maintenance procedures:
|
To satisfy both requirements establish these maintenance procedures:
|
||||||
* DANE allows to publish multiple TLSA records. As long as one matches the receving servers certificates everything is fine. Publish **two** sets of TLSA records like this:
|
* DANE allows to publish multiple TLSA records. As long as one matches the receiving servers certificates everything is fine. Publish **two** sets of TLSA records like this:
|
||||||
* One TLSA record matching the certificate currently in use.
|
* One TLSA record matching the certificate currently in use.
|
||||||
* A second TLSA record matching a fallback or future certificate to be used.
|
* A second TLSA record matching a fallback or future certificate to be used.
|
||||||
* Wait two rounds of **TTL** before you start using a new certicate. This allows clients to clear their DNS cache and pick up the new TLSA record.
|
* Wait two rounds of **TTL** before you start using a new certificate. This allows clients to clear their DNS cache and pick up the new TLSA record.
|
||||||
* Once the new certificate has been deployed, tested and all is well, the legacy TLSA records may be dropped. Notice that removing the legacy TLSA record too soon can cause an outage.
|
* Once the new certificate has been deployed, tested and all is well, the legacy TLSA records may be dropped. Notice that removing the legacy TLSA record too soon can cause an outage.
|
||||||
|
|
||||||
Two ways of handling certificate rollover are known to work well, in combination with automated monitoring to ensure that the TLSA records and certificates are always current and correct.
|
Two ways of handling certificate rollover are known to work well, in combination with automated monitoring to ensure that the TLSA records and certificates are always current and correct.
|
||||||
@@ -193,7 +193,7 @@ Two ways of handling certificate rollover are known to work well, in combination
|
|||||||
* Make sure that your servers support TLS 1.2, and offer STARTTLS to all clients, even those that have not sent you email in the past. Denying STARTTLS to clients with no IP "reputation" would lock them out indefinitely if they support DANE, since they then can never send any initial mail in the clear to establish their reputation.
|
* Make sure that your servers support TLS 1.2, and offer STARTTLS to all clients, even those that have not sent you email in the past. Denying STARTTLS to clients with no IP "reputation" would lock them out indefinitely if they support DANE, since they then can never send any initial mail in the clear to establish their reputation.
|
||||||
|
|
||||||
# Tips, tricks and notices for implementation
|
# Tips, tricks and notices for implementation
|
||||||
This section describes several pionts for attention when implementing DANE for SMTP.
|
This section describes several points for attention when implementing DANE for SMTP.
|
||||||
|
|
||||||
* DANE is meant to be used for the MX domain. So if you are using another domain's mail servers, make sure to ask the administrator of that domain (your mail provider) to support DANE by setting up a TLSA record.
|
* DANE is meant to be used for the MX domain. So if you are using another domain's mail servers, make sure to ask the administrator of that domain (your mail provider) to support DANE by setting up a TLSA record.
|
||||||
* When implementing DANE we advise to first publish DANE records on your MX domains, and then enable DANE verification on your sending mail servers.
|
* When implementing DANE we advise to first publish DANE records on your MX domains, and then enable DANE verification on your sending mail servers.
|
||||||
@@ -213,18 +213,18 @@ This section describes several pionts for attention when implementing DANE for S
|
|||||||
* Roll-over scheme "current + next" gives less flexibility but the highest form of certainty, because of "tight pinning".
|
* Roll-over scheme "current + next" gives less flexibility but the highest form of certainty, because of "tight pinning".
|
||||||
* Implement monitoring of your DANE records to be able to detect problems as soon as possible.
|
* Implement monitoring of your DANE records to be able to detect problems as soon as possible.
|
||||||
* Make sure your implementation supports the usage of a CNAME in your MX record. There are some inconsistencies between multiple RFCs. According to [RFC 2181](https://tools.ietf.org/html/rfc2181#section-10.3) a CNAME in MX records is not allowed, while [RFC 7671](https://tools.ietf.org/html/rfc7671#section-7) and [RFC 5321](https://tools.ietf.org/html/rfc5321#section-5.1) imply that the usage of a CNAME in MX records is allowed.
|
* Make sure your implementation supports the usage of a CNAME in your MX record. There are some inconsistencies between multiple RFCs. According to [RFC 2181](https://tools.ietf.org/html/rfc2181#section-10.3) a CNAME in MX records is not allowed, while [RFC 7671](https://tools.ietf.org/html/rfc7671#section-7) and [RFC 5321](https://tools.ietf.org/html/rfc5321#section-5.1) imply that the usage of a CNAME in MX records is allowed.
|
||||||
* Using Server Name Indication (SNI) in an e-mail environment (for matching the certificate offered by a recieving e-mail server) is only usefull when DANE and DNSSEC are used. DNSSEC to perform a reliable MX lookup and DANE to verify the authenticity of the certificate. Sending e-mail servers (the TLS client) usually don't use SNI, because some receiving e-mail servers (the TLS server) cannot handle this; in some cases the setting up of a TLS connection fails. For more information see [RFC 7672 section 8.1](https://tools.ietf.org/html/rfc7672#section-8.1) and [this blogpost by Filippo Valsorda](https://blog.filippo.io/the-sad-state-of-smtp-encryption/).
|
* Using Server Name Indication (SNI) in an e-mail environment (for matching the certificate offered by a receiving e-mail server) is only useful when DANE and DNSSEC are used. DNSSEC to perform a reliable MX lookup and DANE to verify the authenticity of the certificate. Sending e-mail servers (the TLS client) usually don't use SNI, because some receiving e-mail servers (the TLS server) cannot handle this; in some cases the setting up of a TLS connection fails. For more information see [RFC 7672 section 8.1](https://tools.ietf.org/html/rfc7672#section-8.1) and [this blog post by Filippo Valsorda](https://blog.filippo.io/the-sad-state-of-smtp-encryption/).
|
||||||
* Make sure you keep an eye on the logs of your sending mail server to see what domains fail DANE verification.
|
* Make sure you keep an eye on the logs of your sending mail server to see what domains fail DANE verification.
|
||||||
* Some software allows for a test mode. This means that DANE verification is done and logged but there’s no consequence for delivery if DANE verification fails.
|
* Some software allows for a test mode. This means that DANE verification is done and logged but there’s no consequence for delivery if DANE verification fails.
|
||||||
* Manually verify a mail server's certificate with the following commands:
|
* Manually verify a mail server's certificate with the following commands:
|
||||||
* get the DANE record: `dig tlsa _25._tcp.mail.example.nl`
|
* get the DANE record: `dig tlsa _25._tcp.mail.example.nl`
|
||||||
* verify certificate against TLSA record `openssl s_client -starttls smtp -connect mail.example.nl:25 -dane_tlsa_domain "mail.example.nl" -dane_tlsa_rrdata "3 1 1 29c8601cb562d00aa7190003b5c17e61a93dcbed3f61fd2f86bd35fbb461d084"`.
|
* verify certificate against TLSA record `openssl s_client -starttls smtp -connect mail.example.nl:25 -dane_tlsa_domain "mail.example.nl" -dane_tlsa_rrdata "3 1 1 29c8601cb562d00aa7190003b5c17e61a93dcbed3f61fd2f86bd35fbb461d084"`.
|
||||||
* Check if DANE TLSA records (_25._tcp.mail.example.nl) are properly DNSSEC signed. A regularly occuring mistake is the presence of "proof of non-existence" (NSEC3) for the ancestor domain (_tcp.mail.example.nl). If this happens then resolvers that use qname minimization (like the resolver used by [Internet.nl](https://internet.nl)) think that _25._tcp.mail.example.nl does not exist since _tcp.mail.example.nl does not exists. Therefore the resolver can't get the TLSA record which makes DANE fail.
|
* Check if DANE TLSA records (_25._tcp.mail.example.nl) are properly DNSSEC signed. A regularly occurring mistake is the presence of "proof of non-existence" (NSEC3) for the ancestor domain (_tcp.mail.example.nl). If this happens then resolvers that use QNAME minimization (like the resolver used by [Internet.nl](https://internet.nl)) think that _25._tcp.mail.example.nl does not exist since _tcp.mail.example.nl does not exists. Therefore the resolver can't get the TLSA record which makes DANE fail.
|
||||||
* Check your DNSSEC implementation on [DNSViz](https://dnsviz.net/). Enter "_25._tcp.mail.example.nl".
|
* Check your DNSSEC implementation on [DNSViz](https://dnsviz.net/). Enter "_25._tcp.mail.example.nl".
|
||||||
* You can also manually check for this error. `dig _25._tcp.mail.example.nl tlsa +dnssec` results in a NOERROR response, while `dig _tcp.mail.example.nl tlsa +dnssec` results in a NXDOMAIN response.
|
* You can also manually check for this error. `dig _25._tcp.mail.example.nl tlsa +dnssec` results in a NOERROR response, while `dig _tcp.mail.example.nl tlsa +dnssec` results in a NXDOMAIN response.
|
||||||
|
|
||||||
# Inbound e-mail traffic (publishing DANE DNS records)
|
# Inbound e-mail traffic (publishing DANE DNS records)
|
||||||
This part of the how-to describes the steps that should be taken with regard to your inbound e-mail traffic, which primairily involves publishing DANE DNS records. This enables other parties to use DANE for validating the certificates offered by your e-mail servers.
|
This part of the how-to describes the steps that should be taken with regard to your inbound e-mail traffic, which primarily involves publishing DANE DNS records. This enables other parties to use DANE for validating the certificates offered by your e-mail servers.
|
||||||
|
|
||||||
## Generating DANE records
|
## Generating DANE records
|
||||||
**Primary mail server (mail1.example.nl)**
|
**Primary mail server (mail1.example.nl)**
|
||||||
@@ -326,7 +326,7 @@ This setting tells Postfix to perform DNS lookups using DNSSEC. This is an impor
|
|||||||
|
|
||||||
By default Postfix uses opportunistic TLS (smtp_tls_security_level = may) which is susceptible to man in the middle attacks. You could tell Postfix to use mandatory TLS (smtp_tls_security_level = encrypt) but this breaks backwards compatibility with mail servers that don't support TLS (and only work with plain text delivery). However, when Postfix is configured to use the "dane" security level (smtp_tls_security_level = dane) it becomes resistant to man in the middle attacks, since Postfix will connect to other mail servers using "mandatory TLS" when TLSA records are found. This means that:
|
By default Postfix uses opportunistic TLS (smtp_tls_security_level = may) which is susceptible to man in the middle attacks. You could tell Postfix to use mandatory TLS (smtp_tls_security_level = encrypt) but this breaks backwards compatibility with mail servers that don't support TLS (and only work with plain text delivery). However, when Postfix is configured to use the "dane" security level (smtp_tls_security_level = dane) it becomes resistant to man in the middle attacks, since Postfix will connect to other mail servers using "mandatory TLS" when TLSA records are found. This means that:
|
||||||
* If TLSA records are found but are unusable, Postfix will NOT fallback to opportunistic TLS (STARTTLS) or ultimately plain text delivery.
|
* If TLSA records are found but are unusable, Postfix will NOT fallback to opportunistic TLS (STARTTLS) or ultimately plain text delivery.
|
||||||
* If no TLSA records are found (and thus DANE is not supported), Postfix will fallback to opportunistic TLS (STARTTLS) or ultimality plaintext delivery.
|
* If no TLSA records are found (and thus DANE is not supported), Postfix will fallback to opportunistic TLS (STARTTLS) or ultimately plain text delivery.
|
||||||
|
|
||||||
To enforce DANE you can use "smtp_tls_security_level = dane-only" (aka mandatory DANE). With this setting a sending mail server makes sure there is no fallback to opportunistic TLS (STARTTLS) or plain text when either the TLSA records are unusable or absent. It is possible to use mandatory DANE on a per domain basis. For example when you know a certain domain should support DANE and you want to be absolutely sure that a secure and validated delivery is used and want to prevent fallbacks to a less secure delivery method.
|
To enforce DANE you can use "smtp_tls_security_level = dane-only" (aka mandatory DANE). With this setting a sending mail server makes sure there is no fallback to opportunistic TLS (STARTTLS) or plain text when either the TLSA records are unusable or absent. It is possible to use mandatory DANE on a per domain basis. For example when you know a certain domain should support DANE and you want to be absolutely sure that a secure and validated delivery is used and want to prevent fallbacks to a less secure delivery method.
|
||||||
|
|
||||||
|
|||||||
+15
-15
@@ -47,7 +47,7 @@ DKIM software allows you to specify the canonicalization settings. The settings
|
|||||||
We currently advise against the "simple/simple" canonicalization setting because this (being the most strict setting) tolerates almost no modification of the header and body before signing, which is prone to cause problems when forwarding mail. This is confirmed in RFC 7960 [section 2.3](https://tools.ietf.org/html/rfc7960#section-2.3) and [section 4.1.1.2](https://tools.ietf.org/html/rfc7960#section-4.1.1.2). Therefore we recommend to use the "relaxed/relaxed" setting which tolerates common modifications of the header and body before signing.
|
We currently advise against the "simple/simple" canonicalization setting because this (being the most strict setting) tolerates almost no modification of the header and body before signing, which is prone to cause problems when forwarding mail. This is confirmed in RFC 7960 [section 2.3](https://tools.ietf.org/html/rfc7960#section-2.3) and [section 4.1.1.2](https://tools.ietf.org/html/rfc7960#section-4.1.1.2). Therefore we recommend to use the "relaxed/relaxed" setting which tolerates common modifications of the header and body before signing.
|
||||||
|
|
||||||
Notice:
|
Notice:
|
||||||
* When not specified DKIM canoncalization defaults to "strict/strict".
|
* When not specified DKIM canonicalization defaults to "strict/strict".
|
||||||
* "c=strict" equals "c=strict/strict", but "c=relaxed" equals "relaxed/strict".
|
* "c=strict" equals "c=strict/strict", but "c=relaxed" equals "relaxed/strict".
|
||||||
|
|
||||||
# Implementing DKIM with OpenDKIM for Postfix with SpamAssassin
|
# Implementing DKIM with OpenDKIM for Postfix with SpamAssassin
|
||||||
@@ -90,15 +90,15 @@ Create the the file **/etc/opendkim/trusted_hosts** and make sure it contains th
|
|||||||
example.nl
|
example.nl
|
||||||
mail.example.nl
|
mail.example.nl
|
||||||
|
|
||||||
Now create the directory **/etc/opendkim/keys/example.nl** and execute the following command with this directory and make sure to replace 'YYYYMM' with the number of the current year and month. For example: "selector201906". This makes it easier to determine the age of a specific key in a later stage.
|
Now create the directory **/etc/opendkim/keys/example.nl** and execute the following command with this directory and make sure to replace 'YYYYMM' with the number of the current year and month. For example: "selector202606". This makes it easier to determine the age of a specific key in a later stage.
|
||||||
|
|
||||||
`opendkim-genkey -s selectorYYYYMM -d example.nl`
|
`opendkim-genkey -s selectorYYYYMM -d example.nl`
|
||||||
|
|
||||||
There are now 2 files in **/etc/opendkim/keys/example.nl** (the key pair):
|
There are now 2 files in **/etc/opendkim/keys/example.nl** (the key pair):
|
||||||
* selector201906.txt: this file contains DNS complete DKIM DNS record including the public key.
|
* selector202606.txt: this file contains DNS complete DKIM DNS record including the public key.
|
||||||
> selector201906._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCooJQftNOg3wOqVW5wOpr1PhhzgeP1IE9dTOtpUOCENP+z1HwP+8fFp9aGo/EKHoDQRhDUxXlVfocmRjb0lyjHD5ax16BBKLAd8+AgHZt1er8fmm2cL+7nurv0vU5YBG9LGUklD9qO/zJrIz+Lp+YO7D2rt0qYAgGzUOLJBWLBNQIDAQAB" ; ----- DKIM key selector201906 for example.nl
|
> selector202606._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCooJQftNOg3wOqVW5wOpr1PhhzgeP1IE9dTOtpUOCENP+z1HwP+8fFp9aGo/EKHoDQRhDUxXlVfocmRjb0lyjHD5ax16BBKLAd8+AgHZt1er8fmm2cL+7nurv0vU5YBG9LGUklD9qO/zJrIz+Lp+YO7D2rt0qYAgGzUOLJBWLBNQIDAQAB" ; ----- DKIM key selector202606 for example.nl
|
||||||
|
|
||||||
* selector201906.private: this file contains the private key which is going to be used by Postfix to sign all outbound e-mails.
|
* selector202606.private: this file contains the private key which is going to be used by Postfix to sign all outbound e-mails.
|
||||||
|
|
||||||
> -----BEGIN RSA PRIVATE KEY-----
|
> -----BEGIN RSA PRIVATE KEY-----
|
||||||
> MIICXAIBAAKBgQCooJQftNOg3wOqVW5wOpr1PhhzgeP1IE9dTOtpUOCENP+z1HwP
|
> MIICXAIBAAKBgQCooJQftNOg3wOqVW5wOpr1PhhzgeP1IE9dTOtpUOCENP+z1HwP
|
||||||
@@ -118,15 +118,15 @@ There are now 2 files in **/etc/opendkim/keys/example.nl** (the key pair):
|
|||||||
|
|
||||||
Now make sure that the private key can only be read by the user opendkim by executing the following command:
|
Now make sure that the private key can only be read by the user opendkim by executing the following command:
|
||||||
|
|
||||||
`chown opendkim:opendkim selector201906.private`
|
`chown opendkim:opendkim selector202606.private`
|
||||||
|
|
||||||
The next step is to create the key table file **/etc/opendkim/key_table**. This file will tell opendkim about the domains that have been configured and where to find their keys. Add the following to configure example.nl:
|
The next step is to create the key table file **/etc/opendkim/key_table**. This file will tell opendkim about the domains that have been configured and where to find their keys. Add the following to configure example.nl:
|
||||||
|
|
||||||
> selector201906._domainkey.example.nl example.nl:selector201906:/etc/opendkim/keys/example.nl/selector201906.private
|
> selector202606._domainkey.example.nl example.nl:selector202606:/etc/opendkim/keys/example.nl/selector202606.private
|
||||||
|
|
||||||
Create the file **/etc/opendkim/signing_table** and add the following line:
|
Create the file **/etc/opendkim/signing_table** and add the following line:
|
||||||
|
|
||||||
> *@example.nl selector201906._domainkey.example.nl
|
> *@example.nl selector202606._domainkey.example.nl
|
||||||
|
|
||||||
Start OpenDKIM and check your logfiles for possible errors.
|
Start OpenDKIM and check your logfiles for possible errors.
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ OpenDKIM does not support the automated rotation of DKIM keys. This means that y
|
|||||||
### Publish the DNS record
|
### Publish the DNS record
|
||||||
|
|
||||||
Make sure to add the following lines to you domain's zone file:
|
Make sure to add the following lines to you domain's zone file:
|
||||||
> selector201906._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCooJQftNOg3wOqVW5wOpr1PhhzgeP1IE9dTOtpUOCENP+z1HwP+8fFp9aGo/EKHoDQRhDUxXlVfocmRjb0lyjHD5ax16BBKLAd8+AgHZt1er8fmm2cL+7nurv0vU5YBG9LGUklD9qO/zJrIz+Lp+YO7D2rt0qYAgGzUOLJBWLBNQIDAQAB"
|
> selector202606._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCooJQftNOg3wOqVW5wOpr1PhhzgeP1IE9dTOtpUOCENP+z1HwP+8fFp9aGo/EKHoDQRhDUxXlVfocmRjb0lyjHD5ax16BBKLAd8+AgHZt1er8fmm2cL+7nurv0vU5YBG9LGUklD9qO/zJrIz+Lp+YO7D2rt0qYAgGzUOLJBWLBNQIDAQAB"
|
||||||
|
|
||||||
> _adsp._domainkey IN TXT "dkim=all"
|
> _adsp._domainkey IN TXT "dkim=all"
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ The final step is to configure Postfix to actually sign outbound e-mail using Op
|
|||||||
smtpd_milters = inet:localhost:12301
|
smtpd_milters = inet:localhost:12301
|
||||||
non_smtpd_milters = inet:localhost:12301
|
non_smtpd_milters = inet:localhost:12301
|
||||||
|
|
||||||
When you are ready to start using DKIM restart Postfix, but make sure you waited long enough for the DKIM DNS record to succesfully propagate.
|
When you are ready to start using DKIM restart Postfix, but make sure you waited long enough for the DKIM DNS record to successfully propagate.
|
||||||
|
|
||||||
## Inbound e-mail
|
## Inbound e-mail
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ score DKIM_ADSP_NXDOMAIN 5.0
|
|||||||
# No valid author signature and from-domain does not exist
|
# No valid author signature and from-domain does not exist
|
||||||
```
|
```
|
||||||
|
|
||||||
This means that incoming e-mail is instantly classificied as spam if there is not a valid DKIM signature in the mail header and:
|
This means that incoming e-mail is instantly classified as spam if there is not a valid DKIM signature in the mail header and:
|
||||||
* the sending domain's DKIM ADSP record states that all e-mail should be signed and all unsigned mails should be discarded (DISCARD).
|
* the sending domain's DKIM ADSP record states that all e-mail should be signed and all unsigned mails should be discarded (DISCARD).
|
||||||
* the sending domain's DKIM ADSP record states that all e-mail should be signed (ALL).
|
* the sending domain's DKIM ADSP record states that all e-mail should be signed (ALL).
|
||||||
* the domain used in the "From"-header (a.k.a. RFC5322.From, Header From, Message From) does not exist.
|
* the domain used in the "From"-header (a.k.a. RFC5322.From, Header From, Message From) does not exist.
|
||||||
@@ -216,16 +216,16 @@ Navigate to `Configuration -> Code editor` select there the End of Data (EOD/EOD
|
|||||||
Before the `GetMailMessage()->queue()` add:
|
Before the `GetMailMessage()->queue()` add:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$dkimselector = "selector201909"; // Selector
|
$dkimselector = "selector202609"; // Selector
|
||||||
$dkimdomain = "example.nl"; // Header From:
|
$dkimdomain = "example.nl"; // Header From:
|
||||||
$dkimcertificate = "selector201909"; // certificate ID
|
$dkimcertificate = "selector202609"; // certificate ID
|
||||||
if (GetMailMessage()->signDKIM($dkimselector,$dkimdomain,"pki:".$dkimcertificate) == none)
|
if (GetMailMessage()->signDKIM($dkimselector,$dkimdomain,"pki:".$dkimcertificate) == none)
|
||||||
Defer("DKIM signing error, bla bla error message");
|
Defer("DKIM signing error, bla bla error message");
|
||||||
```
|
```
|
||||||
|
|
||||||
The following syslog message is visible in the logging if DKIM signing is successful.
|
The following syslog message is visible in the logging if DKIM signing is successful.
|
||||||
```
|
```
|
||||||
[6xxxxxxb-dxxf-1xx9-bxx5-0xxxxxxxxx4] [EOD] DKIM signed for example.nl (selector201909) with signature b=Yxxxxx9
|
[6xxxxxxb-dxxf-1xx9-bxx5-0xxxxxxxxx4] [EOD] DKIM signed for example.nl (selector202609) with signature b=Yxxxxx9
|
||||||
```
|
```
|
||||||
|
|
||||||
## Inbound email
|
## Inbound email
|
||||||
@@ -251,7 +251,7 @@ on success:
|
|||||||
|
|
||||||
on error, selector not found in DNS:
|
on error, selector not found in DNS:
|
||||||
[2xxxxxxc-dxx2-1xx9-axxv-xxxxxxxxxxxa] [EOD] Processing (dkimverify)
|
[2xxxxxxc-dxx2-1xx9-axxv-xxxxxxxxxxxa] [EOD] Processing (dkimverify)
|
||||||
[2xxxxxxc-dxx2-1xx9-axxv-xxxxxxxxxxxa] [EOD] DKIM(example.nl): Permanent error: No key for signature selector201909._domainkey.example.nl
|
[2xxxxxxc-dxx2-1xx9-axxv-xxxxxxxxxxxa] [EOD] DKIM(example.nl): Permanent error: No key for signature selector202609._domainkey.example.nl
|
||||||
|
|
||||||
on error, Mailbody has been manipulated:
|
on error, Mailbody has been manipulated:
|
||||||
[2xxxxxxc-dxx2-1xx9-axxv-xxxxxxxxxxxa] [EOD] Processing (dkimverify)
|
[2xxxxxxc-dxx2-1xx9-axxv-xxxxxxxxxxxa] [EOD] Processing (dkimverify)
|
||||||
|
|||||||
+8
-8
@@ -26,12 +26,12 @@ DMARC is short for **D**omain based **M**essage **A**uthentication, **R**eportin
|
|||||||
At the same time DMARC also provides the means for receiving reports which allows a domain's administrator to detect whether their domain name is used for phishing or spam.
|
At the same time DMARC also provides the means for receiving reports which allows a domain's administrator to detect whether their domain name is used for phishing or spam.
|
||||||
|
|
||||||
# Why use DMARC?
|
# Why use DMARC?
|
||||||
Before DMARC, organizations already took several measures to determine the authenticity of an e-mail (like SPF and DKIM) to reduce the received amount of SPAM to a minimum. This is basically a good thing, but if these measures fail to choose whether or not an email is SPAM with a high level of certainty, the choice is redirected to the addressee (receiving party). This methodology is prone to abuse, since users are generally not equiped with the knowledge and/or means to classify incoming emails.
|
Before DMARC, organizations already took several measures to determine the authenticity of an e-mail (like SPF and DKIM) to reduce the received amount of SPAM to a minimum. This is basically a good thing, but if these measures fail to choose whether or not an email is SPAM with a high level of certainty, the choice is redirected to the addressee (receiving party). This methodology is prone to abuse, since users are generally not equipped with the knowledge and/or means to classify incoming emails.
|
||||||
|
|
||||||
DMARC addresses this problem and enables the owner of a domain to take explicit responsiblity with regard to the actions taken by the sending party when the validity of an incoming email cannot be determined.
|
DMARC addresses this problem and enables the owner of a domain to take explicit responsibility with regard to the actions taken by the sending party when the validity of an incoming email cannot be determined.
|
||||||
|
|
||||||
# Tips, tricks and notices for implementation
|
# Tips, tricks and notices for implementation
|
||||||
* Interoperabily issues: https://tools.ietf.org/html/rfc7960
|
* Interoperability issues: https://tools.ietf.org/html/rfc7960
|
||||||
* DMARC does not require both DKIM or SPF. But implementation of both is strongly advised.
|
* DMARC does not require both DKIM or SPF. But implementation of both is strongly advised.
|
||||||
* DMARC is about aligning the domain in the DKIM header (the "d=" value) and SPF header (*a.k.a. RFC5321.MailFrom, Return-Path, Envelope Sender, Envelope From*) with the organizational domain in the message From header (*a.k.a. RFC5322.From, Header From, Message From*) which is visible to the user.
|
* DMARC is about aligning the domain in the DKIM header (the "d=" value) and SPF header (*a.k.a. RFC5321.MailFrom, Return-Path, Envelope Sender, Envelope From*) with the organizational domain in the message From header (*a.k.a. RFC5322.From, Header From, Message From*) which is visible to the user.
|
||||||
* If these values do not align this could mean for example, that an attacker placed a valid DKIM signature header in an email with a "d=" value that points to a domain the attacker controls, allowing DKIM to pass while still spoofing the From address to the user.
|
* If these values do not align this could mean for example, that an attacker placed a valid DKIM signature header in an email with a "d=" value that points to a domain the attacker controls, allowing DKIM to pass while still spoofing the From address to the user.
|
||||||
@@ -41,8 +41,8 @@ DMARC addresses this problem and enables the owner of a domain to take explicit
|
|||||||
* When using office 365, the forwarding of calendar appointments from a DMARC projected domain fails. This is a known issue. Read more on the [Office 365 UserVoice forum](https://office365.uservoice.com/forums/264636-general/suggestions/34012756-forwarding-of-calendar-appointments-from-a-dmarc-p) and don't forget to submit your vote!
|
* When using office 365, the forwarding of calendar appointments from a DMARC projected domain fails. This is a known issue. Read more on the [Office 365 UserVoice forum](https://office365.uservoice.com/forums/264636-general/suggestions/34012756-forwarding-of-calendar-appointments-from-a-dmarc-p) and don't forget to submit your vote!
|
||||||
* There is a workaround: Forward the appointment as an "iCalendar file" or as an attachment.
|
* There is a workaround: Forward the appointment as an "iCalendar file" or as an attachment.
|
||||||
* When processing incoming mail we advise to favor a DMARC policy over an SPF policy. Do not configure SPF rejection to go into effect early in handling, but take full advantage of the enhancements DMARC is offering. A message might still pass based on DKIM.
|
* When processing incoming mail we advise to favor a DMARC policy over an SPF policy. Do not configure SPF rejection to go into effect early in handling, but take full advantage of the enhancements DMARC is offering. A message might still pass based on DKIM.
|
||||||
* At the same time, be aware that some operaters still allow a hard fail (-all) to go into effect early in handling and skip DMARC operations.
|
* At the same time, be aware that some operators still allow a hard fail (-all) to go into effect early in handling and skip DMARC operations.
|
||||||
* When using a different domain for the rua and/or ruf address, make sure that the DMARC authorization records (example.nl._report._dmarc.differentdomain.nl) are properly DNSSEC signed. A regularly occuring mistake is the presence of "proof of non-existence" (NSEC3) for the ancestor domain (_report._dmarc.differentdomain.nl). If this happens then resolvers that use qname minimization (like the resolver used by [Internet.nl](https://internet.nl)) think that example.nl._report._dmarc.differentdomain.nl does not exists since _report._dmarc.differentdomain.nl does not exists. Therefore the resolver can't get the DMARC authorization record which makes DMARC fail.
|
* When using a different domain for the rua and/or ruf address, make sure that the DMARC authorization records (example.nl._report._dmarc.differentdomain.nl) are properly DNSSEC signed. A regularly occurring mistake is the presence of "proof of non-existence" (NSEC3) for the ancestor domain (_report._dmarc.differentdomain.nl). If this happens then resolvers that use QNAME minimization (like the resolver used by [Internet.nl](https://internet.nl)) think that example.nl._report._dmarc.differentdomain.nl does not exists since _report._dmarc.differentdomain.nl does not exists. Therefore the resolver can't get the DMARC authorization record which makes DMARC fail.
|
||||||
* Check your DNSSEC implementation on [DNSViz](https://dnsviz.net/). Enter "example.nl._report._dmarc.differentdomain.nl".
|
* Check your DNSSEC implementation on [DNSViz](https://dnsviz.net/). Enter "example.nl._report._dmarc.differentdomain.nl".
|
||||||
* You can also manually check for this error. `dig example.nl._report._dmarc.differentdomain.nl +dnssec` results in a NOERROR response, while `dig _report._dmarc.differentdomain.nl +dnssec` results in a NXDOMAIN response.
|
* You can also manually check for this error. `dig example.nl._report._dmarc.differentdomain.nl +dnssec` results in a NOERROR response, while `dig _report._dmarc.differentdomain.nl +dnssec` results in a NXDOMAIN response.
|
||||||
|
|
||||||
@@ -56,9 +56,9 @@ The DMARC policy is published by means of a DNS TXT record. A DMARC record can c
|
|||||||
| rua | optional | rua@example.nl | This field contains the email address used to send **aggregate** reports to |
|
| rua | optional | rua@example.nl | This field contains the email address used to send **aggregate** reports to |
|
||||||
| ruf | optional |ruf@example.nl | This field contains the email address used to send **forensic** reports to |
|
| ruf | optional |ruf@example.nl | This field contains the email address used to send **forensic** reports to |
|
||||||
| fo | mandatory | <br>0<br>1<br>s<br>d | Reporting options for failure reports. Generates a report if:<br>- both SPF and DKIM tests fail (0)<br>- either SPF or DKIM test fail (1)<br>- SPF test fails (s)<br>- DKIM test fails (d) |
|
| fo | mandatory | <br>0<br>1<br>s<br>d | Reporting options for failure reports. Generates a report if:<br>- both SPF and DKIM tests fail (0)<br>- either SPF or DKIM test fail (1)<br>- SPF test fails (s)<br>- DKIM test fails (d) |
|
||||||
| adkim | optional | s<br>r | Controls how strict the result of DKIM alignment checks should be intepreted. Strict or relaxed. |
|
| adkim | optional | s<br>r | Controls how strict the result of DKIM alignment checks should be interpreted. Strict or relaxed. |
|
||||||
| aspf | optional | s<br>r | Controls how strict the result of SPF alignment checks should be intepreted. Strict or relaxed. |
|
| aspf | optional | s<br>r | Controls how strict the result of SPF alignment checks should be interpreted. Strict or relaxed. |
|
||||||
| pct | optional | 0..100 | Determine percentage of mail from your domain to have the DMARC verificaton done by other mail providers. Default is 100. |
|
| pct | optional | 0..100 | Determine percentage of mail from your domain to have the DMARC verification done by other mail providers. Default is 100. |
|
||||||
| rf | optional | afrf<br>aodef | Preferred reporting format for forensic reports. Default is afrf. |
|
| rf | optional | afrf<br>aodef | Preferred reporting format for forensic reports. Default is afrf. |
|
||||||
| ri | optional | 60..86400 | Interval (in seconds) at which you want to receive DMARC reports. The DMARC RFC specifies that organizations should be able to send reports at least once every day (86400 seconds) and also states a minimum interval of one hour (60 seconds). Default is 86400. |
|
| ri | optional | 60..86400 | Interval (in seconds) at which you want to receive DMARC reports. The DMARC RFC specifies that organizations should be able to send reports at least once every day (86400 seconds) and also states a minimum interval of one hour (60 seconds). Default is 86400. |
|
||||||
| sp | optional | none<br>quarantine<br>reject | Subdomain policy. If not set the policy defined under "p=" will apply to all your subdomains. |
|
| sp | optional | none<br>quarantine<br>reject | Subdomain policy. If not set the policy defined under "p=" will apply to all your subdomains. |
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ This document lists the basic usage of commonly used DNS records. It can be used
|
|||||||
|
|
||||||
# AAAA
|
# AAAA
|
||||||
* Points to an IPv6 address.
|
* Points to an IPv6 address.
|
||||||
* Does not point to anyhting else.
|
* Does not point to anything else.
|
||||||
* Record does not start (left side) with _ or -.
|
* Record does not start (left side) with _ or -.
|
||||||
|
|
||||||
# MX
|
# MX
|
||||||
* Used to specify a mailserver.
|
* Used to specify a mailserver.
|
||||||
* Contains a hostname, which in turn points to one or multiple A and/or AAAA records.
|
* Contains a hostname, which in turn points to one or multiple A and/or AAAA records.
|
||||||
* Preferrably does not point to other record types, but the use of CNAME records is seen in practice. RFC's are inconsistent on this.
|
* Preferably does not point to other record types, but the use of CNAME records is seen in practice. RFC's are inconsistent on this.
|
||||||
* Has a priority value.
|
* Has a priority value.
|
||||||
|
|
||||||
# CNAME
|
# CNAME
|
||||||
@@ -22,7 +22,7 @@ This document lists the basic usage of commonly used DNS records. It can be used
|
|||||||
|
|
||||||
# CAA
|
# CAA
|
||||||
* Used to allowlist Certification Authorities that may issue certificates.
|
* Used to allowlist Certification Authorities that may issue certificates.
|
||||||
* May contain several policies, like issue, issuewild (wildcard), issuemail (S/MIME certificates) and issuevmc (BIMI certificates).
|
* May contain several policies, like issue, issuewild (wildcard, i.e. certificates valid for all subdomains), issuemail (S/MIME certificates) and issuevmc (BIMI certificates).
|
||||||
|
|
||||||
# SRV
|
# SRV
|
||||||
* Records starts (left side) with _.
|
* Records starts (left side) with _.
|
||||||
@@ -31,16 +31,16 @@ This document lists the basic usage of commonly used DNS records. It can be used
|
|||||||
|
|
||||||
# NS
|
# NS
|
||||||
* Used to specify a nameserver.
|
* Used to specify a nameserver.
|
||||||
* Contains a hostname, which in turn points tp one or multiple A and/or AAAA records.
|
* Contains a hostname, which in turn points to one or multiple A and/or AAAA records.
|
||||||
|
|
||||||
# SOA
|
# SOA
|
||||||
* Mandatory for every DNS zone.
|
* Mandatory for every DNS zone.
|
||||||
* Contains the following information (seperated by a single white space):
|
* Contains the following information (separated by a single white space):
|
||||||
* FQDN of the primary name server followed by a trailing dot.
|
* FQDN of the primary name server followed by a trailing dot.
|
||||||
* e-mail address of the DNS administrator (followed by a trailing dot, the @ replaced with a dot and other dots escaped using a backslash).
|
* e-mail address of the DNS administrator (followed by a trailing dot, the @ replaced with a dot and other dots escaped using a backslash).
|
||||||
* an opening round bracket "(".
|
* an opening round bracket "(".
|
||||||
* serial number that is changed (increased) on every zone change.
|
* serial number that is changed (increased) on every zone change.
|
||||||
* refresh time (in seconds) for a secondary name server to check the primairy name server for changes in the zone.
|
* refresh time (in seconds) for a secondary name server to check the primary name server for changes in the zone.
|
||||||
* retry time (in seconds) for a secondary name server for requesting the serial number when the primary name server did not respond on the previous request.
|
* retry time (in seconds) for a secondary name server for requesting the serial number when the primary name server did not respond on the previous request.
|
||||||
* expire time (in seconds) after which a secondary name server should stop answering requests if the primary name server is not responding.
|
* expire time (in seconds) after which a secondary name server should stop answering requests if the primary name server is not responding.
|
||||||
* Negative caching time to live (in seconds) which is the time a caching name server should cache a negative result (indicating that a name does not exist) coming from the authorative name server before trying again.
|
* Negative caching time to live (in seconds) which is the time a caching name server should cache a negative result (indicating that a name does not exist) coming from the authorative name server before trying again.
|
||||||
@@ -12,8 +12,11 @@ This repository and all contributions to it are licensed under CC BY 4.0, with t
|
|||||||
[DANE how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/DANE-for-SMTP-how-to.md)
|
[DANE how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/DANE-for-SMTP-how-to.md)
|
||||||
[DKIM how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/DKIM-how-to.md)
|
[DKIM how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/DKIM-how-to.md)
|
||||||
[SPF how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/SPF-how-to.md)
|
[SPF how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/SPF-how-to.md)
|
||||||
|
[STARTTLS how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/STARTTLS-how-to.md)
|
||||||
[DMARC how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/DMARC-how-to.md)
|
[DMARC how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/DMARC-how-to.md)
|
||||||
[Parked domain how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/parked-domain-how-to.md)
|
[Parked domain how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/parked-domain-how-to.md)
|
||||||
|
[DNS records overview](https://github.com/internetstandards/toolbox-wiki/blob/main/DNS-records-overview.md)
|
||||||
|
[Example webserver configs](https://github.com/internetstandards/toolbox-wiki/blob/main/example-configs/Webserver-100%-example-configs.md)
|
||||||
|
|
||||||
|
|
||||||
# Interesting external sources
|
# Interesting external sources
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
<img align="right" src="/images/logo-internetnl-en.svg">
|
|
||||||
|
|
||||||
# Ngnix example configuration
|
|
||||||
This example configuration was created by SIDN Labs and shows how to configure Ngnix in order to score 100% in the Website test on Internet.nl.
|
|
||||||
|
|
||||||
# Assumptions
|
|
||||||
* DNSSEC is used
|
|
||||||
* IPv6 is used
|
|
||||||
|
|
||||||
# Configuring Ngnix
|
|
||||||
|
|
||||||
server_tokens off;
|
|
||||||
add_header X-Frame-Options SAMEORIGIN;
|
|
||||||
add_header X-Content-Type-Options nosniff;
|
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
|
||||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
|
||||||
add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'none'" always;
|
|
||||||
add_header Referrer-Policy "strict-origin" always;
|
|
||||||
|
|
||||||
ssl_stapling on;
|
|
||||||
ssl_stapling_verify on;
|
|
||||||
ssl_trusted_certificate /etc/letsencrypt/live/example.nl/fullchain.pem;
|
|
||||||
|
|
||||||
# Rate limiting 20 requests/s
|
|
||||||
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=20r/s;
|
|
||||||
|
|
||||||
# http://example.nl -> https://example.nl
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
server_name example.nl;
|
|
||||||
|
|
||||||
location /.well-known/acme-challenge/ {
|
|
||||||
root /var/www/certbot;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
return 301 https://example.nl$request_uri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# http://(www|api).example.nl -> https://(www|api).example.nl
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
server_name www.example.nl api.example.nl;
|
|
||||||
|
|
||||||
return 301 https://$host$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://example.nl -> https://www.example.nl
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
listen [::]:443 ssl http2;
|
|
||||||
server_name example.nl;
|
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/example.nl/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/example.nl/privkey.pem;
|
|
||||||
|
|
||||||
ssl_session_cache shared:SSL:50m;
|
|
||||||
ssl_session_timeout 1d;
|
|
||||||
ssl_session_tickets on;
|
|
||||||
|
|
||||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
|
||||||
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
|
|
||||||
return 301 https://www.$host$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
# serve https://(www|api).example.nl
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
listen [::]:443 ssl http2;
|
|
||||||
server_name www.example.nl api.example.nl;
|
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/example.nl/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/example.nl/privkey.pem;
|
|
||||||
|
|
||||||
ssl_session_cache shared:SSL:50m;
|
|
||||||
ssl_session_timeout 1d;
|
|
||||||
ssl_session_tickets on;
|
|
||||||
|
|
||||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
|
||||||
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
|
|
||||||
# Example location for a Flask application running on port 8080
|
|
||||||
location / {
|
|
||||||
limit_req zone=mylimit burst=100 nodelay;
|
|
||||||
|
|
||||||
include uwsgi_params;
|
|
||||||
uwsgi_pass flask:8080;
|
|
||||||
uwsgi_ignore_client_abort on;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<img align="right" src="/images/logo-internetnl-en.svg">
|
||||||
|
|
||||||
|
# Webserver example configurations
|
||||||
|
|
||||||
|
## Common mistakes
|
||||||
|
|
||||||
|
For all webservers, we observe the following common mistakes:
|
||||||
|
|
||||||
|
* HTTPS redirect: our test demands an upgrade to HTTPS **first**, before redirecting. This means that when you want your website to be accessible over domain example.nl, we expect http://example.nl to redirect to https://example.nl, while http://www.example.nl should redirect first to https://www.example.nl, then to https://example.nl. The reason for this, is that HSTS will only work when the Strict-Transport-Security header is served over HTTPS. By redirecting directly, the initial domain is not protected by HSTS.
|
||||||
|
* SHA-1 as hash function for key exchange: this is a legacy hash function that is explicitly deprecated since 2021 by [RFC 9155](https://datatracker.ietf.org/doc/html/rfc9155) and insufficient according to the latest TLS guidelines. Note that this is a different setting than the accepted ciphers. Not all firmware (especially GUI firmware) allows you easily change this configuration.
|
||||||
|
|
||||||
|
## nginx example configuration
|
||||||
|
The most actual example configuration can be found within the source code of Internet.nl itself.
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
* DNSSEC is enabled
|
||||||
|
* IPv6 is used and working
|
||||||
|
* RPKI is used for all IPs
|
||||||
|
|
||||||
|
### Configuring nginx
|
||||||
|
|
||||||
|
The configuration used by Internet.nl is to be found in [this folder](https://github.com/internetstandards/Internet.nl/blob/main/docker/webserver/).
|
||||||
|
Parts of the configuration can be reused by your project to set up a 100% compliant webserver.
|
||||||
|
|
||||||
|
Most of the generic configuration can be found [here](https://github.com/internetstandards/Internet.nl/blob/main/docker/webserver/nginx_templates/default.conf.template). Most notable are
|
||||||
|
enabling HTTP3 and upgrading HTTP requests to HTTPS. Note that for the Internet.nl project specific configurations are made, for instance for the connection test.
|
||||||
|
You will not need this for an ordinary webserver configuration.
|
||||||
|
|
||||||
|
For the TLS configuration, check [this file](https://github.com/internetstandards/Internet.nl/blob/main/docker/webserver/nginx_templates/tls.conf.template).
|
||||||
|
Note that this allows TLS 1.2 and TLS 1.3, with all sufficient/good ciphers. `ssl_conf_command SignatureAlgorithms` ensures only sufficient signature
|
||||||
|
algorithms are accepted by the server (in case you got a 'SHA-1' finding in this test). Make sure to uncomment `ssl_stapling` and `ssl_stapling_verify` if your
|
||||||
|
CA/certificate still supports OCSP to enable OCSP-stapling.
|
||||||
|
|
||||||
|
For HTTP headers, [this configuration](https://github.com/internetstandards/Internet.nl/blob/main/docker/webserver/http.headers) includes general headers, [here](https://github.com/internetstandards/Internet.nl/blob/main/docker/webserver/hsts_h3.headers) HSTS (Strict-Transport-Security) and HTTP3 headers are included. [This file](https://github.com/internetstandards/Internet.nl/blob/main/docker/webserver/nginx_templates/csp.header.template) contains an example Content-Security-Policy (CSP) header, which should be adapted to your own website.
|
||||||
|
|
||||||
|
|
||||||
|
## Apache
|
||||||
|
|
||||||
|
We currently do not have a full example Apache configuration. Most settings are documented [here](https://httpd.apache.org/docs/current/mod/mod_ssl.html), for example the `SSLCipherSuite` setting to specify which cipher suites should be accepted.
|
||||||
|
|
||||||
|
To make sure only the allowed hash functions for key exchange are used, make use of the following setting:
|
||||||
|
|
||||||
|
`SSLOpenSSLConfCmd SignatureAlgorithms ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA256:RSA+SHA256:RSA+SHA384:RSA+SHA512`
|
||||||
@@ -44,7 +44,7 @@ When using a wildcard selector to set an empty public key, you indicate that all
|
|||||||
`*._domainkey.example.nl. IN TXT "v=DKIM1; p="`
|
`*._domainkey.example.nl. IN TXT "v=DKIM1; p="`
|
||||||
|
|
||||||
## SPF
|
## SPF
|
||||||
Set an an empty policy (not mentioning any ip-adresses or hostnames which are allowed to send mail) and a hard fail.
|
Set an an empty policy (not mentioning any IP addresses or hostnames which are allowed to send mail) and a hard fail.
|
||||||
|
|
||||||
`example.nl. IN TXT "v=spf1 -all"`
|
`example.nl. IN TXT "v=spf1 -all"`
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user