Email authentication #1 : DNS and IPREV

Email authentication protocols play crucial roles in securing email communication by verifying the authenticity of the sender and preventing email spoofing and phishing attacks. During this journey through the landscape of email authentication protocols, we will overfly protocols like IPREV or SPF but also DKIM, ARC and DMARC and the way to operate them using vSMTP.

Let’s take off.

Domain Name System : the common base

The first stage brings us in the 80s when the IETF (Internet Engineering Task Force) released the RFC 1034 (Request For Comment) : “DOMAIN NAMES – CONCEPTS AND FACILITIES”. This RFC aims to:

[…]standardize the domain style names, their use for Internet mail and host address support, and the protocols and servers used to implement domain name facilities[…]

Whatever the email authentication mechanism, it relies on the DNS (Domain Name System). If you have any doubts about how DNS works, there is an excellent article on the CloudFlare website.

IPREV : back to the 90s

In the 1990s, hackers quickly noticed the lack of SMTP sending server authentication, allowing them to send emails using a spoofed Internet domain name.

The first countermeasure deployed against Domain Name Spoofing was the Reverse DNS Lookup or PTR (Pointer) Record method. It was a simple but effective email authentication method.

By associating an IP address with a domain name by creating a reverse DNS record, when an email server receives an email, the server can perform a reverse DNS lookup to check if the sending IP address matches the domain’s DNS records.

Mail servers use reverse DNS to perform simple anti-spoofing checks but this method can be refined. The method is called “Forward-confirmed reverse DNS” or IPREV. This forward DNS lookup check that the reverse lookup matches the FQDN of the email header (aka seeing if it resolved back to the original IP number).

This mechanism has some limits. In some scenario i.e. when many MTAs are masked behind a unique IP address, reverse DNS query may return in a round-robin manner one of the server hostname.

vSMTP implementation

As always, we tried to make the work of administrators easier by adding functions that can be used directly in the configuration scripts of vSMTP.

The vSMTP dns and the iprev classes describe all the required functions to handle IPREV and DNS queries. To query a DNS server we have to build a DNS resolver. Let’s create a resolver that connects to Google DNS servers.

const google_dns = dns::resolver(#{
    config: "google_tls",
});Code language: PHP (php)

And the reverse lookup :

fn on_mail_from(ctx) {
  let result = dns::rlookup(#{
     dns_resolver: global::google_dns,
     ip: ctx.client_ip
  }); 

  // rlookup function returns an array of FQDN
  if result.is_empty() {
    return status::deny("550 5.7.25 Reverse DNS validation failed.");
  }

  // The first record must match the MAIL FROM domain
  if result[0] != ctx.sender.domain {
    return status::deny("550 5.7.25 Reverse DNS validation failed."); 
  }
 
  return status::next();
}
Code language: JavaScript (javascript)

This simple implementation should block most basic SPAM.

You should also use the iprev::check fonction to perform a forward-confirmed reverse DNS and, in case of failure, log the IP and close the connection.

fn on_connect(ctx) {
  let iprev_res = iprev::check(#{
     ip: ctx.client_ip,
     dns_resolver: global::google_dns
  });

  if iprev_res.value != "pass" {
    // Send a custom message to the log dispatcher using RFC 5424 "SD" style.
    log("info", `[netsec@vsmtp mechanism="iprev" ip="${ctx.client_ip}" domain="${ctx.sender.domain}"]`); 

    // Send an error code and close the connection
    return status::deny("550 5.7.25 Reverse DNS validation failed.");
  }

  return status::next();
}Code language: PHP (php)

Perhaps you may want to refine this implementation by fetching the log and updating a firewall rule to block this IP address or you may wish to add this pair (IP, domain) to an ephemeral cache to avoid saturating your DNS servers with requests… we will explain how to use the log dispatcher service and the native vSMTP plugins in upcoming posts.

Otherwise you can only store the iprev result in the context, so it can be used later to generate the “Authentication-Results” header field and continue processing.

fn on_connect(ctx) {
  let iprev_res = iprev::check(#{
     ip: ctx.client_ip,
     dns_resolver: global::google_dns
  });

  ctx.store(iprev_res);
  return status::next();
}Code language: PHP (php)

Imagination is the only limit to the power of vSMTP scripting.

What’s next ?

IPREV and reverse DNS lookup were great SPAM killers but the rise of the Internet in the 2000s saw the emergence of increasingly complex email architectures. A new protocol became popular through an experimental RFC : the Send Policy Framework (SPF)

In 2014 the adoption of the RFC 7208 definitely anchors SPF as a standard.

This will be the second stage of your journey.

Stay tuned.