Merge pull request #26 from WKobes/update-2026

Update toolbox wiki to 2026 releases
This commit is contained in:
WKobes
2026-07-15 14:18:13 +02:00
committed by GitHub
14 changed files with 415 additions and 269 deletions
+102 -22
View File
@@ -56,6 +56,11 @@ This how-to is created by the Dutch Internet Standards Platform (the organizatio
* [Generic configuration](#generic-configuration-1) * [Generic configuration](#generic-configuration-1)
+ [Configure the use of DANE on the domain level](#configure-the-use-of-dane-on-the-domain-level) + [Configure the use of DANE on the domain level](#configure-the-use-of-dane-on-the-domain-level)
+ [Logging](#logging-1) + [Logging](#logging-1)
- [Implementing DANE for SMTP on Stalwart SMTP (outbound e-mail traffic)](#implementing-dane-for-smtp-on-stalwart-smtp-outbound-e-mail-traffic)
- [Outbound](#outbound)
- [DANE TLS Reporting](#dane-tls-reporting)
- [Outbound reports](#outbound-reports)
- [Inbound report analysis](#inbound-report-analysis)
- [Special thanks](#special-thanks) - [Special thanks](#special-thanks)
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small> <small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
@@ -63,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 plaintext 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:
@@ -93,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.
@@ -121,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))
@@ -133,7 +138,7 @@ The illustration below shows two TLS capable mail servers without using DANE. Th
![](images/dane-example-1-no-dane.png) ![](images/dane-example-1-no-dane.png)
## 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.
@@ -150,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.
![](images/dane-example-1-with-dane.png) ![](images/dane-example-1-with-dane.png)
@@ -161,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.
@@ -188,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.
@@ -202,24 +207,26 @@ This section describes several pionts for attention when implementing DANE for S
* See also this [example of Let's Encrypt](https://mail.sys4.de/pipermail/dane-users/2019-December/000545.html). In this case the issuer certificate was changed, but the public key was not. As a result a "2 1 1" roll-over record would still validate, but a "2 0 1" roll-over record would not and requires an update. * See also this [example of Let's Encrypt](https://mail.sys4.de/pipermail/dane-users/2019-December/000545.html). In this case the issuer certificate was changed, but the public key was not. As a result a "2 1 1" roll-over record would still validate, but a "2 0 1" roll-over record would not and requires an update.
* An issuer certificate (usage type "2") validates only when the full certificate chain is offered by the receiving mail server. * An issuer certificate (usage type "2") validates only when the full certificate chain is offered by the receiving mail server.
* Mail servers by default don't validate certificates and therefore don't have their own certificate store. That's why DANE for SMTP only supports usage type "2" (DANE-TA) and usage type "3" (DANE-EE). Usage type "0" (PKIX-TA) and usage type "1" (PKIX-EE) are not supported. * Mail servers by default don't validate certificates and therefore don't have their own certificate store. That's why DANE for SMTP only supports usage type "2" (DANE-TA) and usage type "3" (DANE-EE). Usage type "0" (PKIX-TA) and usage type "1" (PKIX-EE) are not supported.
* When using 2 x x TLSA records, you should be aware when and how your CA replaces intermediate certificates. For some CA's, it might be advisable to include a 2 x x record for all intermediates, if you have no control over which intermediate certificate is used.
* Make sure the TTL (time-to-live) of your TLSA records is not too high. This makes it possible to apply changes relatively fast in case of problems. A TTL between 30 minutes (1800) and 1 hour (3600) is recommended. * Make sure the TTL (time-to-live) of your TLSA records is not too high. This makes it possible to apply changes relatively fast in case of problems. A TTL between 30 minutes (1800) and 1 hour (3600) is recommended.
* The refresh value of your full DNS zone should be in accordance with the TTL setting of your TLSA record, to make sure all name servers give the same information when (after expiration of the TLSA TTL) being queried. * The refresh value of your full DNS zone should be in accordance with the TTL setting of your TLSA record, to make sure all name servers give the same information when (after expiration of the TLSA TTL) being queried.
* In case of roll-over scheme "current + issuer", the use of the root certificate is preferred because in some contexts ([PKIoverheid](https://en.wikipedia.org/wiki/PKIoverheid)) this makes it easier to switch supplier / certificate without impacting DANE. (Remember [DigiNotar](https://en.wikipedia.org/wiki/DigiNotar)). * In case of roll-over scheme "current + issuer", the use of the root certificate is preferred because in some contexts ([PKIoverheid](https://en.wikipedia.org/wiki/PKIoverheid)) this makes it easier to switch supplier / certificate without impacting DANE. (Remember [DigiNotar](https://en.wikipedia.org/wiki/DigiNotar)).
* 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 theres 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 theres 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.
* You can set up SMTP TLS Reporting (TLSRPT, see [RFC 8460](https://www.rfc-editor.org/info/rfc8460/) to receive reports concerning TLS connections. These reports may help you to debug issues concerning DANE and TLS.
# 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)**
@@ -319,11 +326,11 @@ This setting tells Postfix to perform DNS lookups using DNSSEC. This is an impor
`smtp_tls_security_level = dane` `smtp_tls_security_level = dane`
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 plaintext 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 plaintext 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 plaintext 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.
`smtp_host_lookup = dns` `smtp_host_lookup = dns`
@@ -547,6 +554,78 @@ tls: cert: /C=NL/ST=Zuid-Holland/L=Den Haag/XXXXXXX; issuer=/C=NL/O=XXXXXXX; ver
tls: DANE match: /C=NL/ST=Zuid-Holland/L=XXXXXX; issuer=XXXXX; depth=0 tls: DANE match: /C=NL/ST=Zuid-Holland/L=XXXXXX; issuer=XXXXX; depth=0
``` ```
# Implementing DANE for SMTP on Stalwart SMTP (outbound e-mail traffic)
Stalwart SMTP includes built-in support for strong transport security mechanisms such as DANE, MTA-STS (Mail Transfer Agent Strict Transport Security) and SMTP TLS Reporting.
**Specifics for this setup**
* Stalwart SMTP v0.1 (or greater)
**Assumptions**
* Basic configuration of Stalwart SMTP
## Outbound
DANE can be enabled in Stalwart SMTP with the `queue.outbound.tls.dane` property which accepts the following values:
- `optional`: Use DANE only if TLSA records for the domain are available.
- `require`: Require DANE and do not perform delivery unless a valid TLSA record is available (not recommended unless used under a custom rule).
- `disable`: Never use DANE.
Example:
```
[queue.outbound.tls]
dane = "optional"
```
## DANE TLS Reporting
SMTP TLS Reporting is a mechanism for reporting on the certificate and DANE validation outcomes performed by a mail transfer agent (MTA), such as Stalwart SMTP. It allows the recipient of an email to receive reports on DANE policies and the validity of the certificate used to secure the transport of the email, including information such as whether the certificate was valid, expired, or revoked.
### Outbound reports
Stalwart SMTP can generate TLS aggregate reports to inform other hosts about the results of DANE validation. Outgoing TLS reports are configured under the `report.tls.aggregate` key using the following options:
- `from-name`: The name that will be used in the `From` header of the TLS report email.
- `from-address`: The email address that will be used in the `From` header of the TLS report email.
- `org-name`: The name of the organization to be included in the report.
- `send`: The frequency at which the TLS reports will be sent. The options are `hourly`, `daily`, `weekly`, or `never` to disable reporting.
- `max-size`: The maximum size of the TLS report in bytes.
- `sign`: The list of DKIM signatures to use when signing the TLS report.
Example:
```
[report.tls.aggregate]
from-name = "TLS Report"
from-address = "noreply-tls@foobar.org"
org-name = "The Foobar Organization"
contact-info = "jane@foobar.org"
send = "daily"
max-size = 26214400 # 25 mb
sign = ["rsa"]
```
### Inbound report analysis
Stalwart SMTP has the ability to automatically analyze incoming TLS reports including DANE authentication results that are sent by other domains, which eliminates the need for manual intervention and saves time and effort for the system administrator. In case any DANE authentication issues are found, an event is recorded in the log file or sent to OpenTelemetry. By turning reports into actionable events, system administrators can quickly detect and respond to configuration errors and any instances of abuse, such as spam or phishing, which helps to maintain the integrity of the email system.
The configuration for report analysis can be found under the `report.analysis` key and includes the following attributes:
- `addresses`: A list of addresses (which may include wildcards) from which reports will be intercepted and analyzed.
- `forward`: Whether reports should be forwarded to their final recipient after analysis.
- `store`: The location where incoming reports will be stored. If no path is specified, the reports will not be stored.
Example:
```
[report.analysis]
addresses = ["dmarc@*", "abuse@*"]
forward = true
store = "/usr/local/stalwart-smtp/incoming"
```
# Special thanks # Special thanks
Our infinite gratitude goes out to the following people for their support in building this how-to for DANE. Our infinite gratitude goes out to the following people for their support in building this how-to for DANE.
@@ -555,6 +634,7 @@ Alwin de Bruin
Anders Berggren Anders Berggren
Marc van de Geijn Marc van de Geijn
Mark Scholten Mark Scholten
[mdecimus](https://github.com/mdecimus)
Patrick Koetter Patrick Koetter
Simon Besteman Simon Besteman
Tom van Leeuwen Tom van Leeuwen
+16 -16
View File
@@ -32,7 +32,7 @@ DKIM stands for **D**omain**K**eys **I**dentified **M**ail and is described in [
A common used technique used by spammers is to trick the receiving party into believing an e-mail is legitimate by using a forged sender address. This is also known as e-mail spoofing. DKIM has been designed to protect against spoofing. If an incoming e-mail does not have a DKIM signature or when it's DKIM signature does not validate, the receiving e-mail server should consider the e-mail to be SPAM. A common used technique used by spammers is to trick the receiving party into believing an e-mail is legitimate by using a forged sender address. This is also known as e-mail spoofing. DKIM has been designed to protect against spoofing. If an incoming e-mail does not have a DKIM signature or when it's DKIM signature does not validate, the receiving e-mail server should consider the e-mail to be SPAM.
# Tips, tricks and notices for implementation # Tips, tricks and notices for implementation
* Use a DKIM key (RSA) of [at least 1024 bits](https://tools.ietf.org/html/rfc6376#section-3.3.3) to minimize the successrate of offline attacks. Don't go beyond a key size of 2048 bits since this is not mandatory according to the RFC. * Use a DKIM key (RSA) of [at least 1024 bits](https://tools.ietf.org/html/rfc6376#section-3.3.3) to minimize the success rate of offline attacks. Don't go beyond a key size of 2048 bits since this is not mandatory according to the RFC.
* Make sure to change your DKIM keys regularly. A rotation scheme of 6 months is recommended. * Make sure to change your DKIM keys regularly. A rotation scheme of 6 months is recommended.
* If a domain is not using e-mail (anymore), it is recommended to set an empty public key: "v=DKIM1; p=". * If a domain is not using e-mail (anymore), it is recommended to set an empty public key: "v=DKIM1; p=".
* When used with a specific selector, an empty public key means that e-mail signed with the associated public key must be considered unreliable since they public key was revoked. * When used with a specific selector, an empty public key means that e-mail signed with the associated public key must be considered unreliable since they public key was revoked.
@@ -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)
+10 -10
View File
@@ -23,26 +23,26 @@ This how-to is created by the Dutch Internet Standards Platform (the organizatio
# What is DMARC? # What is DMARC?
DMARC is short for **D**omain based **M**essage **A**uthentication, **R**eporting and **C**onformance and is described in [RFC 7489](https://tools.ietf.org/html/rfc7489). With DMARC the owner of a domain can, by means of a DNS record, publish a policy that states how to handle e-mail (deliver, quarantine, reject) which is not properly authenticated using SPF and/or DKIM. Because DMARC depends on the security of DNS, the use of DNSSEC is highly recommended. DMARC is short for **D**omain based **M**essage **A**uthentication, **R**eporting and **C**onformance and is described in [RFC 7489](https://tools.ietf.org/html/rfc7489). With DMARC the owner of a domain can, by means of a DNS record, publish a policy that states how to handle e-mail (deliver, quarantine, reject) which is not properly authenticated using SPF and/or DKIM. Because DMARC depends on the security of DNS, the use of DNSSEC is highly recommended.
At the same time DMARC also provides the means for receiving reports which allows a domain's administrator to detect whether their domainname 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.
* Parked domain: “DMARC p=reject”. Make sure to include rua and ruf addresses, since this allows monitoring of possible abuse attempts. Implement additional records (SPF, DKIM, NullMX) if possible, see also our [Parked domain how-to](https://github.com/internetstandards/toolbox-wiki/blob/master/parked-domain-how-to.md). * Parked domain: “DMARC p=reject”. Make sure to include rua and ruf addresses, since this allows monitoring of possible abuse attempts. Implement additional records (SPF, DKIM, NullMX) if possible, see also our [Parked domain how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/parked-domain-how-to.md).
* RFC 7489 [states](https://tools.ietf.org/html/rfc7489#section-6.4) that the tags dmarc-version ("v=") and dmarc-request ("p=") should be on the first and second position of the DMARC record. The order of the other tags does not matter: "components other than dmarc-version and dmarc-request may appear in any order". * RFC 7489 [states](https://tools.ietf.org/html/rfc7489#section-6.4) that the tags dmarc-version ("v=") and dmarc-request ("p=") should be on the first and second position of the DMARC record. The order of the other tags does not matter: "components other than dmarc-version and dmarc-request may appear in any order".
* The verified [erratum 5440 of RFC 7489](https://www.rfc-editor.org/errata_search.php?rfc=7489) states that a semicolon should be included in the DMARC version tag. Correct: "v=DMARC1;". Incorrect: "v=DMARC1". * The verified [erratum 5440 of RFC 7489](https://www.rfc-editor.org/errata_search.php?rfc=7489) states that a semicolon should be included in the DMARC version tag. Correct: "v=DMARC1;". Incorrect: "v=DMARC1".
* 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. |
@@ -2,44 +2,45 @@ This document lists the basic usage of commonly used DNS records. It can be used
# A # A
* Points to an IPv4 address. * Points to an IPv4 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 -.
# 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
* Points to an A and/or AAAA record. * Used to specify a mailserver.
* Preferrably does not point to other record types, but the use of CNAME records is seen in practice. RFC's are inconsistent on this. * Contains a hostname, which in turn points to one or multiple A and/or AAAA records.
* Has a priority value. * 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.
# CNAME # CNAME
* Points to other records (A, AAAA, CNAME). * Redirects to other DNS name with its own records (A, AAAA, CNAME).
* Be carefull with CNAME chaining; don't use too many CNAMEs in a row. * Be careful with CNAME chaining; don't use too many CNAMEs in a row.
* The end of a CNAME chain is always an A an/or AAAA record.
* **Can only be combined with NS / SOA records if left side is equal.** # CAA
* Used to allowlist Certification Authorities that may issue 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 _.
* Points to an A and/or AAAA record. * Points to an A and/or AAAA record.
* Has a priority value. * Has a priority value.
# NS # NS
* Points to an A and/or AAAA record. * Used to specify a nameserver.
* **Used to point to subzones.** * Contains a hostname, which in turn points to one or multiple A and/or AAAA records.
* **Used to indicate what is inside the parent zone.**
* **Each zone needs this to indicate what is inside the parent zone as a reference to this zone.**
# 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 primairy 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). * 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.
+14 -8
View File
@@ -1,18 +1,24 @@
<img align="right" src="images/logo-internetnl-en.svg"> <img align="right" src="images/logo-internetnl-en.svg">
# Welcome to the [Internet.nl](https://internet.nl) toolbox. # Welcome to the [Internet.nl](https://internet.nl) toolbox.
This GitHub repository contains several how-to's for providing practical information and guidance on implementing secure and modern Internet Standards. The how-to's are maintained by the Dutch Internet Standards Platform (the organization behind [Internet.nl](https://internet.nl)) and are created in cooperation with industry experts and enthusiasts (hosters, vendors, etc). This GitHub repository contains several how-to's for providing practical information and guidance on implementing secure and modern Internet Standards. The how-to's are maintained by the Dutch Internet Standards Platform (the organization behind [Internet.nl](https://internet.nl)) and are created in cooperation with industry experts and enthusiasts (hosters, vendors, etc).
Feedback and/or contributions are much appreciated and welcome through issues, pull requests or via question@internet.nl. Feedback and/or contributions are much appreciated and welcome through issues, pull requests or via [question@internet.nl](mailto:question@internet.nl).
This repository and all contributions to it are licensed under CC BY 4.0, with the exception of the Internet.nl trademark and logo.
# Quick access # Quick access
[DANE how-to](https://github.com/internetstandards/toolbox-wiki/blob/master/DANE-for-SMTP-how-to.md) [DANE how-to](/DANE-for-SMTP-how-to.md)
[DKIM how-to](https://github.com/internetstandards/toolbox-wiki/blob/master/DKIM-how-to.md) [DKIM how-to](/DKIM-how-to.md)
[SPF how-to](https://github.com/internetstandards/toolbox-wiki/blob/master/SPF-how-to.md) [SPF how-to](/SPF-how-to.md)
[DMARC how-to](https://github.com/internetstandards/toolbox-wiki/blob/master/DMARC-how-to.md) [STARTTLS how-to](/STARTTLS-how-to.md)
[Parked domain how-to](https://github.com/internetstandards/toolbox-wiki/blob/master/parked-domain-how-to.md) [DMARC how-to](/DMARC-how-to.md)
[Parked domain how-to](/parked-domain-how-to.md)
[DNS records overview](/DNS-records-overview.md)
[Example webserver configs](/example-configs/Webserver-100%-example-configs.md)
# Interesting external sources # Interesting external sources
[SIDN Hands-on guides](https://www.sidn.nl/en/cyber-security/modern-internet-standards) [SIDN Hands-on guides](https://www.sidn.nl/en/cyber-security/modern-internet-standards)
[The Internet Society's Open Standards Everywhere Project](https://github.com/InternetSociety/ose-documentation) [The Internet Society's Open Standards Everywhere Project](https://github.com/InternetSociety/ose-documentation)
+13 -13
View File
@@ -1,13 +1,13 @@
<img align="right" src="images/logo-internetnl-en.svg"> <img align="right" src="images/logo-internetnl-en.svg">
# SPF how-to # SPF how-to
This how-to is created by the Dutch Internet Standards Platform (the organization behind [internet.nl](https://internet.nl)) and is meant to provide practical information and guidance on implementing SPF. This how-to is created by the Dutch Internet Standards Platform (the organization behind [internet.nl](https://internet.nl)) and is meant to provide practical information and guidance on implementing SPF.
# Table of contents # Table of contents
- [What is SPF?](#what-is-spf-) - [What is SPF?](#what-is-spf)
- [Why use SPF?](#why-use-spf-) - [Why use SPF?](#why-use-spf)
- [Tips, tricks and notices for implementation](#tips--tricks-and-notices-for-implementation) - [Tips, tricks and notices for implementation](#tips-tricks-and-notices-for-implementation)
- [Outbound e-mail traffic (DNS records)](#outbound-e-mail-traffic--dns-records-) - [Outbound e-mail traffic (DNS records)](#outbound-e-mail-traffic--dns-records)
- [Inbound e-mail traffic](#inbound-e-mail-traffic) - [Inbound e-mail traffic](#inbound-e-mail-traffic)
* [Implementing SPF in Postfix with SpamAssassin](#implementing-spf-in-postfix-with-spamassassin) * [Implementing SPF in Postfix with SpamAssassin](#implementing-spf-in-postfix-with-spamassassin)
+ [Configuring Postfix](#configuring-postfix) + [Configuring Postfix](#configuring-postfix)
@@ -19,22 +19,22 @@ This how-to is created by the Dutch Internet Standards Platform (the organizatio
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small> <small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
# What is SPF? # What is SPF?
SPF is short for "**S**ender **P**olicy **F**ramework" and is described in [RFC 7208](https://tools.ietf.org/html/rfc7208). It offers domain owners that use their domains for sending e-mail, the possibility to use the DNSSEC infrastructure to publish which hosts (mail servers) are authorized to use their domain names in the "MAIL FROM" and "HELO" identities. So basically SPF is a whitelist which lists all servers that are allowed to send e-mail on behalf of a specific domain. The receiving mail server may use the information (a SPF record) published in the DNS zone of a specific mail sending domain. SPF is short for "**S**ender **P**olicy **F**ramework" and is described in [RFC 7208](https://tools.ietf.org/html/rfc7208). It offers domain owners that use their domains for sending e-mail, the possibility to use the DNS infrastructure to publish which hosts (mail servers) are authorized to use their domain names in the "MAIL FROM" and "HELO" identities. So basically SPF is an allowlist which lists all servers that are allowed to send e-mail on behalf of a specific domain. The receiving mail server may use the information (a SPF record) published in the DNS zone of a specific mail sending domain.
# Why use SPF? # Why use SPF?
Our current e-mail infrastructure was originally designed for any mail sending host to use any DNS domain name it wants. The authenticity of the sending mail server cannot be deterimined, which makes it easy for random third parties to make use of a domain name with possibly a malicious intent. This increases the risk of processing e-mail since the intentions of the sender (host) are uncertain. SPF can help the fight against spam and other kinds of unwanted e-mail be offering a way of authenticating the sending mail server. Our current e-mail infrastructure was originally designed for any mail sending host to use any DNS domain name it wants. The authenticity of the sending mail server cannot be determined, which makes it easy for random third parties to make use of a domain name with possibly a malicious intent. This increases the risk of processing e-mail since the intentions of the sender (host) are uncertain. SPF can help the fight against spam and other kinds of unwanted e-mail be offering a way of authenticating the sending mail server.
# Tips, tricks and notices for implementation # Tips, tricks and notices for implementation
* The sender address shown to the user ("RFC5322.From") is not used when authenticating. SPF uses the invisible "RFC5321.MailFrom" header. Combining SPF with DMARC removes this disadvantage. * The sender address shown to the user ("RFC5322.From") is not used when authenticating. SPF uses the invisible "RFC5321.MailFrom" header. Combining SPF with DMARC removes this disadvantage.
* E-mail forwarding is not supported, since the e-mail is often forwarded by another e-mail server. * E-mail forwarding is not supported, since the e-mail is often forwarded by another e-mail server.
* SPF does not work between domains that use the same e-mail server. * SPF does not work between domains that use the same e-mail server.
* Parked domains should be explicitly configured to not use e-mail. For SPF this is done with an empty policy (not mentioning any ip-adresses or hostnames which are allowed to send mail) and a hard fail: "v=spf1 all". * Parked domains should be explicitly configured to not use e-mail. See the [Parked domain how-to](https://github.com/internetstandards/toolbox-wiki/blob/main/parked-domain-how-to.md).
* 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 evaluating the DMARC policy before the 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, even when SPF fails.
* 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 make a hard fail (-all) to go into effect early in handling and skip DMARC operations.
* As stated in [section 5.2 of the RFC](https://tools.ietf.org/html/rfc7208#section-5.2) the _include_ mechanism is not applicable to the _all_ mechanism within the referenced record. This means that an SPF record's default policy is not 'inherited' upon inclusion. When including one or more SPF records from other domains, a default policy (~all or -all) is still required. For fully 'inheriting' another domain's SPF record, consider using the [_redirect_ modifier](https://tools.ietf.org/html/rfc7208#section-6.1). * As stated in [section 5.2 of the RFC](https://tools.ietf.org/html/rfc7208#section-5.2) the _include_ mechanism is not applicable to the _all_ mechanism within the referenced record. This means that an SPF record's default policy is not 'inherited' upon inclusion. When including one or more SPF records from other domains, a default policy (~all or -all) is still required. For fully 'inheriting' another domain's SPF record, consider using the [_redirect_ modifier](https://tools.ietf.org/html/rfc7208#section-6.1).
# Outbound e-mail traffic (DNS records) # Outbound e-mail traffic (DNS records)
SPF for outbound e-mail traffic is limited to publishing an SPF policy as a TXT-record in a domain name's DNS zone. This enables other parties to use SPF for validating the authenticity of e-mail servers sending e-mail on behalf of your domain name. SPF for outbound e-mail traffic is limited to publishing an SPF policy as a TXT-record in a domain name's DNS zone. This enables other parties to use SPF for validating the authenticity of e-mail servers sending e-mail on behalf of your domain name.
The example below shows an SPF record with a **hard fail**. The example below shows an SPF record with a **hard fail**.
> v=spf1 mx ip4:192.168.1.1/32 ip6:fd12:3456:789a:1::/64 a:mail.example.com a:mail2.example.com -all" > v=spf1 mx ip4:192.168.1.1/32 ip6:fd12:3456:789a:1::/64 a:mail.example.com a:mail2.example.com -all"
@@ -44,7 +44,7 @@ Although a soft fail (~all) is recommended in order to prevent false positives,
# Inbound e-mail traffic # Inbound e-mail traffic
Ideally incoming e-mail is processed by making a **single decision** based on a collective evaluation of all relevant e-mail standards (SPF, DKIM, DMARC). Although this would be the most elegant way of processing incoming e-mail, most e-mail servers process e-mail standards in a sequential order. This should be taken into consideration when configuring your own e-mail environment; depending on a domain owner's preferences it is also possible to implement a "single decision" e-mail environment. Ideally incoming e-mail is processed by making a **single decision** based on a collective evaluation of all relevant e-mail standards (SPF, DKIM, DMARC). Although this would be the most elegant way of processing incoming e-mail, most e-mail servers process e-mail standards in a sequential order. This should be taken into consideration when configuring your own e-mail environment; depending on a domain owner's preferences it is also possible to implement a "single decision" e-mail environment.
Thereafter, it is [stated in the DMARC RFC](https://tools.ietf.org/html/rfc7489#section-10.1) that some receiver architectures might implement SPF in advance of any DMARC operations. This means that a "-" prefix on a sender's SPF mechanism, such as "-all", could cause that rejection to go into effect early in handling, causing message rejection before any DMARC processing takes place. While operators choosing to use "-all" should be aware of this, we advise to favor a DMARC policy over an SPF policy. As also [stated in the DMARC RFC](https://tools.ietf.org/html/rfc7489#section-6.7), the final diposition of a message is always a matter of local policy. With this in mind we feel that operators should not configure SPF rejection to go into effect early in handling, and thus disregarding DMARC. At the cost of processing the entire message body, we advise to always evaluate all relevant standards before coming to a decision. If SPF fails, DKIM might still pass resulting in a satisfying DMARC evaluation. Thereafter, it is [stated in the DMARC RFC](https://tools.ietf.org/html/rfc7489#section-10.1) that some receiver architectures might implement SPF in advance of any DMARC operations. This means that a "-" prefix on a sender's SPF mechanism, such as "-all", could cause that rejection to go into effect early in handling, causing message rejection before any DMARC processing takes place. While operators choosing to use "-all" should be aware of this, we advise to favor a DMARC policy over an SPF policy. As also [stated in the DMARC RFC](https://tools.ietf.org/html/rfc7489#section-6.7), the final disposition of a message is always a matter of local policy. With this in mind we feel that operators should not configure SPF rejection to go into effect early in handling, and thus disregarding DMARC. At the cost of processing the entire message body, we advise to always evaluate all relevant standards before coming to a decision. If SPF fails, DKIM might still pass resulting in a satisfying DMARC evaluation.
## Implementing SPF in Postfix with SpamAssassin ## Implementing SPF in Postfix with SpamAssassin
**Specifics for this setup** **Specifics for this setup**
+77
View File
@@ -0,0 +1,77 @@
<img align="right" src="/images/logo-internetnl-en.svg">
# UNDER CONSTRUCTION!!!
# STARTTLS how-to
This how-to is created by the Dutch Internet Standards Platform (the organization behind [internet.nl](https://internet.nl)) and is meant to provide practical information and guidance on implementing STARTTLS.
# Table of contents
Under construction
# What is STARTTLS?
Under construction
# Why use STARTTLS?
Under construction
# Tips, tricks and notices for implementation
* Use the RFC 7919 defined DH groups: https://raw.githubusercontent.com/internetstandards/dhe_groups/main/ffdhe4096.pem)
## Implementing STARTTLS in Postfix
**Specifics for this setup**
* Ubuntu 24.04
* Postfix 3.10.x
* OpenSSL 3.0.3
**Assumptions**
* Mail server is using DANE
* Software packages are already installed
### Configuring Postfix
/etc/postfix/main.cf
tls_high_cipherlist = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-CCM:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256
tls_config_name = postfix
tls_preempt_cipherlist = yes
smtpd_tls_cert_file=...
smtpd_tls_key_file=...
smtpd_tls_security_level=may
smtpd_tls_auth_only=yes
smtpd_tls_protocols = >=TLSv1.2
smtpd_tls_mandatory_protocols = >=TLSv1.2
smtpd_tls_ciphers = high
smtpd_tls_mandatory_ciphers = high
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache
smtpd_tls_received_header = yes
smtp_tls_note_starttls_offer = yes
smtp_tls_protocols = >=TLSv1.2
smtp_tls_mandatory_protocols = >=TLSv1.2
smtp_tls_ciphers = high
smtp_tls_mandatory_ciphers = high
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_tls_session_cache
smtp_dns_support_level = dnssec
smtp_tls_security_level = dane
/etc/ssl/openssl.cnf
postfix = postfix_settings
....
[postfix_settings]
ssl_conf = postfix_ssl_settings
[postfix_ssl_settings]
system_default = baseline_postfix_settings
[baseline_postfix_settings]
SignatureAlgorithms = ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA512:RSA+SHA256:RSA+SHA384
To enable PQC:
tls_eecdh_auto_curves =
tls_ffdhe_auto_groups =
@@ -0,0 +1,44 @@
<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.
* Internet.nl expects HTTP security headers to be set, even when a domain/URL is merely a redirect to another domain. This is considered a defense-in-depth measure and should not affect the redirect.
## nginx
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`
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 31 KiB

+13 -6
View File
@@ -21,18 +21,18 @@ This how-to is created by the Dutch Internet Standards Platform (the organizatio
If a domain is not using e-mail it is recommended to use the following settings. If a domain is not using e-mail it is recommended to use the following settings.
## Null MX ## Null MX
Explicitly configure an 'empty' MX record according to [RFC7505 ](https://tools.ietf.org/html/rfc7505). Explicitly configure an 'empty' MX record according to [RFC 7505](https://tools.ietf.org/html/rfc7505). This indicates you do not accept any inbound e-mail. Note that some MTA's also block outgoing e-mail when no mailserver/a Null MX is specified.
`example.nl. IN MX 0 .` `example.nl. IN MX 0 .`
## DMARC ## DMARC
Set DMARC policy to reject mails, but allow reporting to take place. This helps detecting activity related to your domain. Set DMARC policy to reject mails, but allow reporting to take place. This helps detecting activity related to your domain.
`_dmarc.example.nl. IN TXT "v=DMARC1; p=reject; rua=mailto:rua@example.nl; ruf=mailto:ruf@example.nl"` `_dmarc.example.nl. IN TXT "v=DMARC1; p=reject; psd=n; rua=mailto:rua@example.nl"`
If the domain itself does not receive email (such as when the domain has been configured with NULL MX), then the RUA and RUF must point to another domain that does receive emails, such as: If the domain itself does not receive email (such as when the domain has been configured with Null MX), then the RUA must point to another domain that does receive emails, such as:
`_dmarc.example.nl. TXT "v=DMARC1; p=reject; rua=mailto:rua@example.net; ruf=mailto:ruf@example.net"` `_dmarc.example.nl. TXT "v=DMARC1; p=reject; psd=n; rua=mailto:rua@example.net"`
On the other domain (that does receive e-mail), add an authorization record for the parked domain: On the other domain (that does receive e-mail), add an authorization record for the parked domain:
@@ -44,10 +44,17 @@ 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. This record should also be added for any specified subdomain (e.g., the www subdomain).
`example.nl. IN TXT "v=spf1 -all"` `example.nl. IN TXT "v=spf1 -all"`
You can add a wildcard record to protect all non-existing subdomains with SPF. For full protection, you should also add this for subdomains _under_ a specific subdomain (e.g., add it for *.www if www exists).
`*.example.nl TXT "v=spf1 -all"`
## DNSSEC
Using DNSSEC guarantees that the above DNS records are coming from the correct source.
# Domain without a website # Domain without a website
Apply the following settings to domains not using a website. Apply the following settings to domains not using a website.
@@ -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;
}
}
-75
View File
@@ -1,75 +0,0 @@
<img align="right" src="/images/logo-internetnl-en.svg">
# UNDER CONSTRUCTION!!!
# STARTTLS how-to
This how-to is created by the Dutch Internet Standards Platform (the organization behind [internet.nl](https://internet.nl)) and is meant to provide practical information and guidance on implementing STARTTLS.
# Table of contents
Under construction
# What is STARTTLS?
Under construction
# Why use STARTTLS?
Under construction
# Tips, tricks and notices for implementation
* http://postfix.1071664.n5.nabble.com/Disable-SSL-TLS-renegotiation-td96864.html#a96871
* Use the RFC 7919 defined DH groups: https://raw.githubusercontent.com/internetstandards/dhe_groups/master/ffdhe4096.pem)
## Implementing STARTTLS in Postfix
**Specifics for this setup**
* Linux Debian 10 (Buster)
* Postfix 3.4.5
* OpenSSL 1.1.1d
**Assumptions**
* Mail server is using DANE
* Software packages are already installed
### Configuring Postfix
# use DANE (when acting as a client)
smtp_dns_support_level = dnssec
smtp_tls_security_level = dane
smtp_host_lookup = dns
smtp_tls_note_starttls_offer = yes
# --- TLS settings ---
smtpd_tls_security_level = may
smtpd_tls_key_file = /etc/postfix/ssl/example.nl.key
smtpd_tls_cert_file = /etc/postfix/ssl/example.nl.crt
smtpd_tls_CAfile = /etc/postfix/ssl/example.nl-cabundle.crt
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
# --- TLS protocol config ---
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
lmtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
# --- TLS cipher config ---
smtpd_tls_mandatory_ciphers=high
smtpd_tls_ciphers=high
# disable compression and client-initiated renegotiation
tls_ssl_options = NO_COMPRESSION, 0x40000000
# disable unsecure ciphers
smtpd_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, ADH, AECDH, kRSA, DSS, RC4, DES, IDEA, SEED, ARIA, AESCCM8, 3DES, MD5
smtp_tls_exclude_ciphers = EXP, LOW, MEDIUM, aNULL, eNULL, SRP, PSK, kDH, ADH, AECDH, kRSA, DSS, RC4, DES, IDEA, SEED, ARIA, AESCCM8, 3DES, MD5
# Enable server cipher-suite preferences
tls_preempt_cipherlist = yes
# Forward secrecy
smtpd_tls_eecdh_grade=ultra
smtpd_tls_dh1024_param_file = /etc/postfix/ssl/ffdhe4096.pem
# --- TLS logging ---
smtp_tls_loglevel = 1
smtpd_tls_loglevel = 1