X-Git-Url: https://git.exim.org/users/jgh/exim.git/blobdiff_plain/05c39afa86ea3d0dd619e7d75554c701f96d2da4..a713f9c58699e31cc76093c550dde2808563cd57:/doc/doc-txt/experimental-spec.txt?ds=inline diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 8d1ebef13..aae8338f1 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -6,94 +6,6 @@ about experimental features, all of which are unstable and liable to incompatible change. -PRDR support --------------------------------------------------------------- - -Per-Recipient Data Reponse is an SMTP extension proposed by Eric Hall -in a (now-expired) IETF draft from 2007. It's not hit mainstream -use, but has apparently been implemented in the META1 MTA. - -There is mention at http://mail.aegee.org/intern/sendmail.html -of a patch to sendmail "to make it PRDR capable". - - ref: http://www.eric-a-hall.com/specs/draft-hall-prdr-00.txt - -If Exim is built with EXPERIMENTAL_PRDR there is a new config -boolean "prdr_enable" which controls whether PRDR is advertised -as part of an EHLO response, a new "acl_data_smtp_prdr" ACL -(called for each recipient, after data arrives but before the -data ACL), and a new smtp transport option "hosts_try_prdr". - -PRDR may be used to support per-user content filtering. Without it -one must defer any recipient after the first that has a different -content-filter configuration. With PRDR, the RCPT-time check -for this can be disabled when the MAIL-time $smtp_command included -"PRDR". Any required difference in behaviour of the main DATA-time -ACL should however depend on the PRDR-time ACL having run, as Exim -will avoid doing so in some situations (eg. single-recipient mails). - - - -OCSP Stapling support --------------------------------------------------------------- - -X.509 PKI certificates expire and can be revoked; to handle this, the -clients need some way to determine if a particular certificate, from a -particular Certificate Authority (CA), is still valid. There are three -main ways to do so. - -The simplest way is to serve up a Certificate Revocation List (CRL) with -an ordinary web-server, regenerating the CRL before it expires. The -downside is that clients have to periodically re-download a potentially -huge file from every certificate authority it knows of. - -The way with most moving parts at query time is Online Certificate -Status Protocol (OCSP), where the client verifies the certificate -against an OCSP server run by the CA. This lets the CA track all -usage of the certs. This requires running software with access to the -private key of the CA, to sign the responses to the OCSP queries. OCSP -is based on HTTP and can be proxied accordingly. - -The only widespread OCSP server implementation (known to this writer) -comes as part of OpenSSL and aborts on an invalid request, such as -connecting to the port and then disconnecting. This requires -re-entering the passphrase each time some random client does this. - -The third way is OCSP Stapling; in this, the server using a certificate -issued by the CA periodically requests an OCSP proof of validity from -the OCSP server, then serves it up inline as part of the TLS -negotiation. This approach adds no extra round trips, does not let the -CA track users, scales well with number of certs issued by the CA and is -resilient to temporary OCSP server failures, as long as the server -starts retrying to fetch an OCSP proof some time before its current -proof expires. The downside is that it requires server support. - -If Exim is built with EXPERIMENTAL_OCSP and it was built with OpenSSL, -then it gains one new option: "tls_ocsp_file". - -The file specified therein is expected to be in DER format, and contain -an OCSP proof. Exim will serve it as part of the TLS handshake. This -option will be re-expanded for SNI, if the tls_certificate option -contains $tls_sni, as per other TLS options. - -Exim does not at this time implement any support for fetching a new OCSP -proof. The burden is on the administrator to handle this, outside of -Exim. The file specified should be replaced atomically, so that the -contents are always valid. Exim will expand the "tls_ocsp_file" option -on each connection, so a new file will be handled transparently on the -next connection. - -Exim will check for a valid next update timestamp in the OCSP proof; -if not present, or if the proof has expired, it will be ignored. - -At this point in time, we're gathering feedback on use, to determine if -it's worth adding complexity to the Exim daemon to periodically re-fetch -OCSP files and somehow handling multiple files. There is no client support -for OCSP in Exim, this is feature expected to be used by mail clients. - - - - Brightmail AntiSpam (BMI) suppport -------------------------------------------------------------- @@ -432,15 +344,21 @@ which the spf condition should succeed. Valid strings are: This means the queried domain has published a SPF record, but wants to allow outside servers to send mail under its domain as well. - o err_perm This indicates a syntax error in the SPF - record of the queried domain. This should be - treated like "none". - o err_temp This indicates a temporary error during all + This should be treated like "none". + o permerror This indicates a syntax error in the SPF + record of the queried domain. You may deny + messages when this occurs. (Changed in 4.83) + o temperror This indicates a temporary error during all processing, including Exim's SPF processing. You may defer messages when this occurs. + (Changed in 4.83) + o err_temp Same as permerror, deprecated in 4.83, will be + removed in a future release. + o err_perm Same as temperror, deprecated in 4.83, will be + removed in a future release. You can prefix each string with an exclamation mark to invert -is meaning, for example "!fail" will match all results but +its meaning, for example "!fail" will match all results but "fail". The string list is evaluated left-to-right, in a short-circuit fashion. When a string matches the outcome of the SPF check, the condition succeeds. If none of the listed @@ -490,8 +408,8 @@ variables. $spf_result This contains the outcome of the SPF check in string form, - one of pass, fail, softfail, none, neutral, err_perm or - err_temp. + one of pass, fail, softfail, none, neutral, permerror or + temperror. $spf_smtp_comment This contains a string that can be used in a SMTP response @@ -622,6 +540,698 @@ mout.gmx.net 212.227.15.16 Use a reasonable IP. eg. one the sending cluster acutally uses. +DMARC Support +-------------------------------------------------------------- + +DMARC combines feedback from SPF, DKIM, and header From: in order +to attempt to provide better indicators of the authenticity of an +email. This document does not explain the fundamentals, you +should read and understand how it works by visiting the website at +http://www.dmarc.org/. + +DMARC support is added via the libopendmarc library. Visit: + + http://sourceforge.net/projects/opendmarc/ + +to obtain a copy, or find it in your favorite rpm package +repository. If building from source, this description assumes +that headers will be in /usr/local/include, and that the libraries +are in /usr/local/lib. + +1. To compile Exim with DMARC support, you must first enable SPF. +Please read the above section on enabling the EXPERIMENTAL_SPF +feature. You must also have DKIM support, so you cannot set the +DISABLE_DKIM feature. Once both of those conditions have been met +you can enable DMARC in Local/Makefile: + +EXPERIMENTAL_DMARC=yes +LDFLAGS += -lopendmarc +# CFLAGS += -I/usr/local/include +# LDFLAGS += -L/usr/local/lib + +The first line sets the feature to include the correct code, and +the second line says to link the libopendmarc libraries into the +exim binary. The commented out lines should be uncommented if you +built opendmarc from source and installed in the default location. +Adjust the paths if you installed them elsewhere, but you do not +need to uncomment them if an rpm (or you) installed them in the +package controlled locations (/usr/include and /usr/lib). + + +2. Use the following global settings to configure DMARC: + +Required: +dmarc_tld_file Defines the location of a text file of valid + top level domains the opendmarc library uses + during domain parsing. Maintained by Mozilla, + the most current version can be downloaded + from a link at http://publicsuffix.org/list/. + +Optional: +dmarc_history_file Defines the location of a file to log results + of dmarc verification on inbound emails. The + contents are importable by the opendmarc tools + which will manage the data, send out DMARC + reports, and expire the data. Make sure the + directory of this file is writable by the user + exim runs as. + +dmarc_forensic_sender The email address to use when sending a + forensic report detailing alignment failures + if a sender domain's dmarc record specifies it + and you have configured Exim to send them. + Default: do-not-reply@$default_hostname + + +3. By default, the DMARC processing will run for any remote, +non-authenticated user. It makes sense to only verify DMARC +status of messages coming from remote, untrusted sources. You can +use standard conditions such as hosts, senders, etc, to decide that +DMARC verification should *not* be performed for them and disable +DMARC with a control setting: + + control = dmarc_disable_verify + +A DMARC record can also specify a "forensic address", which gives +exim an email address to submit reports about failed alignment. +Exim does not do this by default because in certain conditions it +results in unintended information leakage (what lists a user might +be subscribed to, etc). You must configure exim to submit forensic +reports to the owner of the domain. If the DMARC record contains a +forensic address and you specify the control statement below, then +exim will send these forensic emails. It's also advised that you +configure a dmarc_forensic_sender because the default sender address +construction might be inadequate. + + control = dmarc_forensic_enable + +(AGAIN: You can choose not to send these forensic reports by simply +not putting the dmarc_forensic_enable control line at any point in +your exim config. If you don't tell it to send them, it will not +send them.) + +There are no options to either control. Both must appear before +the DATA acl. + + +4. You can now run DMARC checks in incoming SMTP by using the +"dmarc_status" ACL condition in the DATA ACL. You are required to +call the spf condition first in the ACLs, then the "dmarc_status" +condition. Putting this condition in the ACLs is required in order +for a DMARC check to actually occur. All of the variables are set +up before the DATA ACL, but there is no actual DMARC check that +occurs until a "dmarc_status" condition is encountered in the ACLs. + +The dmarc_status condition takes a list of strings on its +right-hand side. These strings describe recommended action based +on the DMARC check. To understand what the policy recommendations +mean, refer to the DMARC website above. Valid strings are: + + o accept The DMARC check passed and the library recommends + accepting the email. + o reject The DMARC check failed and the library recommends + rejecting the email. + o quarantine The DMARC check failed and the library recommends + keeping it for further inspection. + o none The DMARC check passed and the library recommends + no specific action, neutral. + o norecord No policy section in the DMARC record for this + sender domain. + o nofrom Unable to determine the domain of the sender. + o temperror Library error or dns error. + o off The DMARC check was disabled for this email. + +You can prefix each string with an exclamation mark to invert its +meaning, for example "!accept" will match all results but +"accept". The string list is evaluated left-to-right in a +short-circuit fashion. When a string matches the outcome of the +DMARC check, the condition succeeds. If none of the listed +strings matches the outcome of the DMARC check, the condition +fails. + +Of course, you can also use any other lookup method that Exim +supports, including LDAP, Postgres, MySQL, etc, as long as the +result is a list of colon-separated strings. + +Several expansion variables are set before the DATA ACL is +processed, and you can use them in this ACL. The following +expansion variables are available: + + o $dmarc_status + This is a one word status indicating what the DMARC library + thinks of the email. It is a combination of the results of + DMARC record lookup and the SPF/DKIM/DMARC processing results + (if a DMARC record was found). The actual policy declared + in the DMARC record is in a separate expansion variable. + + o $dmarc_status_text + This is a slightly longer, human readable status. + + o $dmarc_used_domain + This is the domain which DMARC used to look up the DMARC + policy record. + + o $dmarc_domain_policy + This is the policy declared in the DMARC record. Valid values + are "none", "reject" and "quarantine". It is blank when there + is any error, including no DMARC record. + + o $dmarc_ar_header + This is the entire Authentication-Results header which you can + add using an add_header modifier. + + +5. How to enable DMARC advanced operation: +By default, Exim's DMARC configuration is intended to be +non-intrusive and conservative. To facilitate this, Exim will not +create any type of logging files without explicit configuration by +you, the admin. Nor will Exim send out any emails/reports about +DMARC issues without explicit configuration by you, the admin (other +than typical bounce messages that may come about due to ACL +processing or failure delivery issues). + +In order to log statistics suitable to be imported by the opendmarc +tools, you need to: +a. Configure the global setting dmarc_history_file. +b. Configure cron jobs to call the appropriate opendmarc history + import scripts and truncating the dmarc_history_file. + +In order to send forensic reports, you need to: +a. Configure the global setting dmarc_forensic_sender. +b. Configure, somewhere before the DATA ACL, the control option to + enable sending DMARC forensic reports. + + +6. Example usage: +(RCPT ACL) + warn domains = +local_domains + hosts = +local_hosts + control = dmarc_disable_verify + + warn !domains = +screwed_up_dmarc_records + control = dmarc_enable_forensic + + warn condition = (lookup if destined to mailing list) + set acl_m_mailing_list = 1 + +(DATA ACL) + warn dmarc_status = accept : none : off + !authenticated = * + log_message = DMARC DEBUG: $dmarc_status $dmarc_used_domain + add_header = $dmarc_ar_header + + warn dmarc_status = !accept + !authenticated = * + log_message = DMARC DEBUG: '$dmarc_status' for $dmarc_used_domain + + warn dmarc_status = quarantine + !authenticated = * + set $acl_m_quarantine = 1 + # Do something in a transport with this flag variable + + deny condition = ${if eq{$dmarc_domain_policy}{reject}} + condition = ${if eq{$acl_m_mailing_list}{1}} + message = Messages from $dmarc_used_domain break mailing lists + + deny dmarc_status = reject + !authenticated = * + message = Message from $domain_used_domain failed sender's DMARC policy, REJECT + + + +Event Actions +-------------------------------------------------------------- + +(Renamed from TPDA, Transport post-delivery actions) + +An arbitrary per-transport string can be expanded upon various transport events. +Additionally a main-section configuration option can be expanded on some +per-message events. +This feature may be used, for example, to write exim internal log information +(not available otherwise) into a database. + +In order to use the feature, you must compile with + +EXPERIMENTAL_EVENT=yes + +in your Local/Makefile + +and define one or both of +- the event_action option in the transport +- the event_action main option +to be expanded when the event fires. + +A new variable, $event_name, is set to the event type when the +expansion is done. The current list of events is: + + msg:complete after main per message + msg:delivery after transport per recipient + msg:host:defer after transport per attempt + msg:fail:delivery after main per recipient + msg:fail:internal after main per recipient + tcp:connect before transport per connection + tcp:close after transport per connection + tls:cert before both per certificate in verification chain + smtp:connect after transport per connection + +The expansion is called for all event types, and should use the $event_name +value to decide when to act. The variable data is a colon-separated +list, describing an event tree. + +There is an auxilary variable, $event_data, for which the +content is event_dependent: + + msg:delivery smtp confirmation mssage + msg:host:defer error string + tls:cert verification chain depth + smtp:connect smtp banner + +The msg:host:defer event populates one extra variable, $event_defer_errno. + +The following variables are likely to be useful depending on the event type: + + router_name, transport_name + local_part, domain + host, host_address, host_port + tls_out_peercert + lookup_dnssec_authenticated, tls_out_dane + sending_ip_address, sending_port + message_exim_id, verify_mode + + +An example might look like: + +event_action = ${if = {msg:delivery}{$event_name} \ +{${lookup pgsql {SELECT * FROM record_Delivery( \ + '${quote_pgsql:$sender_address_domain}',\ + '${quote_pgsql:${lc:$sender_address_local_part}}', \ + '${quote_pgsql:$domain}', \ + '${quote_pgsql:${lc:$local_part}}', \ + '${quote_pgsql:$host_address}', \ + '${quote_pgsql:${lc:$host}}', \ + '${quote_pgsql:$message_exim_id}')}} \ +} {}} + +The string is expanded when each of the supported events occur +and any side-effects of the expansion will happen. +Note that for complex operations an ACL expansion can be used. + + +The expansion of the event_action option should normally +return an empty string. Should it return anything else the +following will be forced: + + msg:delivery (ignored) + msg:host:defer (ignored) + msg:fail:delivery (ignored) + tcp:connect do not connect + tcp:close (ignored) + tls:cert refuse verification + smtp:connect close connection + +No other use is made of the result string. + + +Known issues: +- the tls:cert event is only called for the cert chain elements + received over the wire, with GnuTLS. OpenSSL gives the entire + chain including thse loaded locally. + + +Redis Lookup +-------------------------------------------------------------- + +Redis is open source advanced key-value data store. This document +does not explain the fundamentals, you should read and understand how +it works by visiting the website at http://www.redis.io/. + +Redis lookup support is added via the hiredis library. Visit: + + https://github.com/redis/hiredis + +to obtain a copy, or find it in your operating systems package repository. +If building from source, this description assumes that headers will be in +/usr/local/include, and that the libraries are in /usr/local/lib. + +1. In order to build exim with Redis lookup support add + +EXPERIMENTAL_REDIS=yes + +to your Local/Makefile. (Re-)build/install exim. exim -d should show +Experimental_Redis in the line "Support for:". + +EXPERIMENTAL_REDIS=yes +LDFLAGS += -lhiredis +# CFLAGS += -I/usr/local/include +# LDFLAGS += -L/usr/local/lib + +The first line sets the feature to include the correct code, and +the second line says to link the hiredis libraries into the +exim binary. The commented out lines should be uncommented if you +built hiredis from source and installed in the default location. +Adjust the paths if you installed them elsewhere, but you do not +need to uncomment them if an rpm (or you) installed them in the +package controlled locations (/usr/include and /usr/lib). + + +2. Use the following global settings to configure Redis lookup support: + +Required: +redis_servers This option provides a list of Redis servers + and associated connection data, to be used in + conjunction with redis lookups. The option is + only available if Exim is configured with Redis + support. + +For example: + +redis_servers = 127.0.0.1/10/ - using database 10 with no password +redis_servers = 127.0.0.1//password - to make use of the default database of 0 with a password +redis_servers = 127.0.0.1// - for default database of 0 with no password + +3. Once you have the Redis servers defined you can then make use of the +experimental Redis lookup by specifying ${lookup redis{}} in a lookup query. + +4. Example usage: + +(Host List) +hostlist relay_from_ips = <\n ${lookup redis{SMEMBERS relay_from_ips}} + +Where relay_from_ips is a Redis set which contains entries such as "192.168.0.0/24" "10.0.0.0/8" and so on. +The result set is returned as +192.168.0.0/24 +10.0.0.0/8 +.. +. + +(Domain list) +domainlist virtual_domains = ${lookup redis {HGET $domain domain}} + +Where $domain is a hash which includes the key 'domain' and the value '$domain'. + +(Adding or updating an existing key) +set acl_c_spammer = ${if eq{${lookup redis{SPAMMER_SET}}}{OK}} + +Where SPAMMER_SET is a macro and it is defined as + +"SET SPAMMER " + +(Getting a value from Redis) + +set acl_c_spam_host = ${lookup redis{GET...}} + + +Proxy Protocol Support +-------------------------------------------------------------- + +Exim now has Experimental "Proxy Protocol" support. It was built on +specifications from: +http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt +Above URL revised May 2014 to change version 2 spec: +http://git.1wt.eu/web?p=haproxy.git;a=commitdiff;h=afb768340c9d7e50d8e + +The purpose of this function is so that an application load balancer, +such as HAProxy, can sit in front of several Exim servers and Exim +will log the IP that is connecting to the proxy server instead of +the IP of the proxy server when it connects to Exim. It resets the +$sender_address_host and $sender_address_port to the IP:port of the +connection to the proxy. It also re-queries the DNS information for +this new IP address so that the original sender's hostname and IP +get logged in the Exim logfile. There is no logging if a host passes or +fails Proxy Protocol negotiation, but it can easily be determined and +recorded in an ACL (example is below). + +1. To compile Exim with Proxy Protocol support, put this in +Local/Makefile: + +EXPERIMENTAL_PROXY=yes + +2. Global configuration settings: + +proxy_required_hosts = HOSTLIST + +The proxy_required_hosts option will require any IP in that hostlist +to use Proxy Protocol. The specification of Proxy Protocol is very +strict, and if proxy negotiation fails, Exim will not allow any SMTP +command other than QUIT. (See end of this section for an example.) +The option is expanded when used, so it can be a hostlist as well as +string of IP addresses. Since it is expanded, specifying an alternate +separator is supported for ease of use with IPv6 addresses. + +To log the IP of the proxy in the incoming logline, add: + log_selector = +proxy + +A default incoming logline (wrapped for appearance) will look like this: + + 2013-11-04 09:25:06 1VdNti-0001OY-1V <= me@example.net + H=mail.example.net [1.2.3.4] P=esmtp S=433 + +With the log selector enabled, an email that was proxied through a +Proxy Protocol server at 192.168.1.2 will look like this: + + 2013-11-04 09:25:06 1VdNti-0001OY-1V <= me@example.net + H=mail.example.net [1.2.3.4] P=esmtp PRX=192.168.1.2 S=433 + +3. In the ACL's the following expansion variables are available. + +proxy_host_address The (internal) src IP of the proxy server + making the connection to the Exim server. +proxy_host_port The (internal) src port the proxy server is + using to connect to the Exim server. +proxy_target_address The dest (public) IP of the remote host to + the proxy server. +proxy_target_port The dest port the remote host is using to + connect to the proxy server. +proxy_session Boolean, yes/no, the connected host is required + to use Proxy Protocol. + +There is no expansion for a failed proxy session, however you can detect +it by checking if $proxy_session is true but $proxy_host is empty. As +an example, in my connect ACL, I have: + + warn condition = ${if and{ {bool{$proxy_session}} \ + {eq{$proxy_host_address}{}} } } + log_message = Failed required proxy protocol negotiation \ + from $sender_host_name [$sender_host_address] + + warn condition = ${if and{ {bool{$proxy_session}} \ + {!eq{$proxy_host_address}{}} } } + # But don't log health probes from the proxy itself + condition = ${if eq{$proxy_host_address}{$sender_host_address} \ + {false}{true}} + log_message = Successfully proxied from $sender_host_name \ + [$sender_host_address] through proxy protocol \ + host $proxy_host_address + + # Possibly more clear + warn logwrite = Remote Source Address: $sender_host_address:$sender_host_port + logwrite = Proxy Target Address: $proxy_target_address:$proxy_target_port + logwrite = Proxy Internal Address: $proxy_host_address:$proxy_host_port + logwrite = Internal Server Address: $received_ip_address:$received_port + + +4. Recommended ACL additions: + - Since the real connections are all coming from your proxy, and the + per host connection tracking is done before Proxy Protocol is + evaluated, smtp_accept_max_per_host must be set high enough to + handle all of the parallel volume you expect per inbound proxy. + - With the smtp_accept_max_per_host set so high, you lose the ability + to protect your server from massive numbers of inbound connections + from one IP. In order to prevent your server from being DOS'd, you + need to add a per connection ratelimit to your connect ACL. I + suggest something like this: + + # Set max number of connections per host + LIMIT = 5 + # Or do some kind of IP lookup in a flat file or database + # LIMIT = ${lookup{$sender_host_address}iplsearch{/etc/exim/proxy_limits}} + + defer message = Too many connections from this IP right now + ratelimit = LIMIT / 5s / per_conn / strict + + +5. Runtime issues to be aware of: + - The proxy has 3 seconds (hard-coded in the source code) to send the + required Proxy Protocol header after it connects. If it does not, + the response to any commands will be: + "503 Command refused, required Proxy negotiation failed" + - If the incoming connection is configured in Exim to be a Proxy + Protocol host, but the proxy is not sending the header, the banner + does not get sent until the timeout occurs. If the sending host + sent any input (before the banner), this causes a standard Exim + synchronization error (i.e. trying to pipeline before PIPELINING + was advertised). + - This is not advised, but is mentioned for completeness if you have + a specific internal configuration that you want this: If the Exim + server only has an internal IP address and no other machines in your + organization will connect to it to try to send email, you may + simply set the hostlist to "*", however, this will prevent local + mail programs from working because that would require mail from + localhost to use Proxy Protocol. Again, not advised! + +6. Example of a refused connection because the Proxy Protocol header was +not sent from a host configured to use Proxy Protocol. In the example, +the 3 second timeout occurred (when a Proxy Protocol banner should have +been sent), the banner was displayed to the user, but all commands are +rejected except for QUIT: + +# nc mail.example.net 25 +220-mail.example.net, ESMTP Exim 4.82+proxy, Mon, 04 Nov 2013 10:45:59 +220 -0800 RFC's enforced +EHLO localhost +503 Command refused, required Proxy negotiation failed +QUIT +221 mail.example.net closing connection + + + + +DANE +------------------------------------------------------------ +DNS-based Authentication of Named Entities, as applied +to SMTP over TLS, provides assurance to a client that +it is actually talking to the server it wants to rather +than some attacker operating a Man In The Middle (MITM) +operation. The latter can terminate the TLS connection +you make, and make another one to the server (so both +you and the server still think you have an encrypted +connection) and, if one of the "well known" set of +Certificate Authorities has been suborned - something +which *has* been seen already (2014), a verifiable +certificate (if you're using normal root CAs, eg. the +Mozilla set, as your trust anchors). + +What DANE does is replace the CAs with the DNS as the +trust anchor. The assurance is limited to a) the possibility +that the DNS has been suborned, b) mistakes made by the +admins of the target server. The attack surface presented +by (a) is thought to be smaller than that of the set +of root CAs. + +It also allows the server to declare (implicitly) that +connections to it should use TLS. An MITM could simply +fail to pass on a server's STARTTLS. + +DANE scales better than having to maintain (and +side-channel communicate) copies of server certificates +for every possible target server. It also scales +(slightly) better than having to maintain on an SMTP +client a copy of the standard CAs bundle. It also +means not having to pay a CA for certificates. + +DANE requires a server operator to do three things: +1) run DNSSEC. This provides assurance to clients +that DNS lookups they do for the server have not +been tampered with. The domain MX record applying +to this server, its A record, its TLSA record and +any associated CNAME records must all be covered by +DNSSEC. +2) add TLSA DNS records. These say what the server +certificate for a TLS connection should be. +3) offer a server certificate, or certificate chain, +in TLS connections which is traceable to the one +defined by (one of?) the TSLA records + +There are no changes to Exim specific to server-side +operation of DANE. + +The TLSA record for the server may have "certificate +usage" of DANE-TA(2) or DANE-EE(3). The latter specifies +the End Entity directly, i.e. the certificate involved +is that of the server (and should be the sole one transmitted +during the TLS handshake); this is appropriate for a +single system, using a self-signed certificate. + DANE-TA usage is effectively declaring a specific CA +to be used; this might be a private CA or a public, +well-known one. A private CA at simplest is just +a self-signed certificate which is used to sign +cerver certificates, but running one securely does +require careful arrangement. If a private CA is used +then either all clients must be primed with it, or +(probably simpler) the server TLS handshake must transmit +the entire certificate chain from CA to server-certificate. +If a public CA is used then all clients must be primed with it +(losing one advantage of DANE) - but the attack surface is +reduced from all public CAs to that single CA. +DANE-TA is commonly used for several services and/or +servers, each having a TLSA query-domain CNAME record, +all of which point to a single TLSA record. + +The TLSA record should have a Selector field of SPKI(1) +and a Matching Type field of SHA2-512(2). + +At the time of writing, https://www.huque.com/bin/gen_tlsa +is useful for quickly generating TLSA records; and commands like + + openssl x509 -in -pubkey -noout /dev/null \ + | openssl sha512 \ + | awk '{print $2}' + +are workable for 4th-field hashes. + +For use with the DANE-TA model, server certificates +must have a correct name (SubjectName or SubjectAltName). + +The use of OCSP-stapling should be considered, allowing +for fast revocation of certificates (which would otherwise +be limited by the DNS TTL on the TLSA records). However, +this is likely to only be usable with DANE-TA. NOTE: the +default of requesting OCSP for all hosts is modified iff +DANE is in use, to: + + hosts_request_ocsp = ${if or { {= {0}{$tls_out_tlsa_usage}} \ + {= {4}{$tls_out_tlsa_usage}} } \ + {*}{}} + +The (new) variable $tls_out_tlsa_usage is a bitfield with +numbered bits set for TLSA record usage codes. +The zero above means DANE was not in use, +the four means that only DANE-TA usage TLSA records were +found. If the definition of hosts_request_ocsp includes the +string "tls_out_tlsa_usage", they are re-expanded in time to +control the OCSP request. + +This modification of hosts_request_ocsp is only done if +it has the default value of "*". Admins who change it, and +those who use hosts_require_ocsp, should consider the interaction +with DANE in their OCSP settings. + + +For client-side DANE there are two new smtp transport options, +hosts_try_dane and hosts_require_dane. They do the obvious thing. +[ should they be domain-based rather than host-based? ] + +DANE will only be usable if the target host has DNSSEC-secured +MX, A and TLSA records. + +A TLSA lookup will be done if either of the above options match +and the host-lookup succeded using dnssec. +If the TLSA lookup succeeds, a TLS connection will be required +for the host. + +(TODO: specify when fallback happens vs. when the host is not used) + +If dane is in use the following transport options are ignored: + hosts_require_tls + tls_verify_hosts + tls_try_verify_hosts + tls_verify_certificates + tls_crl + tls_verify_cert_hostnames + +Currently dnssec_request_domains must be active (need to think about that) +and dnssec_require_domains is ignored. + +If verification was successful using DANE then the "CV" item +in the delivery log line will show as "CV=dane". + +There is a new variable $tls_out_dane which will have "yes" if +verification succeeded using DANE and "no" otherwise (only useful +in combination with EXPERIMENTAL_EVENT), and a new variable +$tls_out_tlsa_usage (detailed above). + + -------------------------------------------------------------- End of file --------------------------------------------------------------