Browse

Tag: tech

Halon 5.2 with ultra-flexible queuing

Photo by Karen Roe

We’re very proud to announce the upcoming 5.2 release “polly” which introduces a powerful queue policy engine. First and foremost, the queue and SMTP client’s network layer is now asynchronous. This allows an instance to handle tens of thousands of parallel connections. In combination with the reworked connection concurrency limits, this allows dynamic creation of a virtually unlimited number of independent sub-queues. This is useful for senders that need to separate email streams so that those that move slowly or get stuck don’t block others.

As usual, we made it flexible enough to fit any email service provider’s needs. Rather than having a fixed set of parameters and rollup/grouping options for establishing the sub-queues (with their respective thresholds), we allow you to define what constitutes a unique entry. You can choose any combination of fields, and group/rollup entries using regular expressions or wildcard. In the example below, we limit the concurrent per source IP and remote MX, and also rollup all Google’s MX entries into the same entry. The default concurrency is 5, except Google that gets 10.

- fields:
  - localip
  - remotemx:
      gsuite:
        - '*.google.com'
        - '*.googlemail.com'
        - '*.smtp.goog'
  conditions:
  - if:
      remotemx: '#gsuite'
    then:
      concurrency: 10
      rate: 50
  default:
    concurrency: 5
    rate: 10


Sometimes rollup per MX doesn’t cut it. There are several Microsoft Office365 locations (clusters), but the customer MX doesn’t reveal which they are on. To set a certain threshold for Office365 locations, we can rollup and match per MX, but limit per IP, as per the example below. Note that there’s no default threshold; it only affects Office365.

- fields:
  - localip
  - remotemx:
      o365:
       - '*.protection.outlook.com'
  - remoteip
  conditions:
  - if:
      remotemx: '#o365'
    then:
      concurrency: 10
      rate: 30

API, CLI, web administration or the MTA itself can, through this Halon script, add suspensions, and threshold can be adjusted dynamically:

// If we have more than 10 failures per minute, lower rate for 5 minutes
$mx = $arguments["attempt"]["connection"]["remotemx"];
$code = $arguments["attempt"]["result"]["code"];
if ($mx and $code >= 400 and !rate("mx-fail", $mx, 10, 60, ["sync" => false]))
    cache ["ttl" => 300]
        PickupPolicy(
            ["localip", "remotemx"],
            ["remotemx" => $mx],
            ["rate" => [10, 60]], 300);

The reworked queue naturally comes with many new tools and APIs for interacting with the new functionality. This includes more subtle improvements, like the ability to view the queue’s shape by message age. By pressing an interval, you can dig into the specific messages, which are grouped by fields of your choice.

The new shared memory script functions and API opens up several possibilities. You can script statistic counters, which can then be read periodically over the API. Another use case is pre-loading data into the MTA over the API, rather than fetching and caching from within the script.

Finally, we now offer the ability to call methods in external shared libraries using our foreign function interface (FFI) class.

Check out the full changelog on GitHub for more information, and familiarise yourself with the important changes outlined in the release notes document before upgrading.

Implementing SMTP LANG with proxy script

The upcoming Halon 5.1 release introduces a new SMTP server proxy script. It’s configured to be executed before specific (or all) SMTP commands, even command which isn’t recognised by the SMTP server. In this blog we’ll describe how to implement our proposed SMTP LANG extension using this new script hook. First of all, we announce the LANG extension and the languages supported in the HELO script:

$announce =  [...$arguments["extensions"], "LANG SE"];
Accept(["extensions" => $announce]);

Next, we configure to proxy script to hook onto the new “BREV”, “INNEHÅLL” and “HEJDÅ” commands:

Finally, we setup the proxy script to translate the international (Swedish, in this case) commands with their standard SMTP respective:

$cmd = str_upper($arguments["command"]);
if ($cmd[0:11] == "BREV FRÅN:") { // MAIL FROM
    $realcmd = "MAIL FROM:" + $arguments["command"][11:];
    Pass(["command" => $realcmd]);
}
if ($cmd == "HEJDÅ") { // QUIT
    $codes = ["code" => 221, "enhanced" => [2, 0, 0]];
    Reply("Ha det bra", ["reply_codes" => $codes, "disconnect" => true]);
}
// etc...

The proxy script and the corresponding xtext functions can be used for many other things, like custom XCLIENT implementations. More information on the 5.1 will be released later this month.

Halon 5.0 “tidy” with new REST API

Photo by Steve Hodgson

We celebrate the new year with news on the upcoming release, which bundles many exciting features.

First and foremost, the new RESTful API with an OpenAPI specification makes integration into various development and deployment toolchains much more enjoyable. Since most of our customers already integrate Halon into their directories and control panels by making REST queries from Halon, it makes perfect sense that Halon can be provisioned in the same way.

$ curl https://halon1/api/1.0.0/email/queue
   -X PATCH
   -d '{"filter": "ip=192.0.2.1", "fields": {"transport": "srv2"}}'
   -u username:password
{
    "affected": 10
}

Secondly, we’re introducing a new end-of-DATA script that’s executed once per message, as opposed to the per-recipient DATA script. Whereas the per-recipient version is convenient when you want to treat each recipient individually and let the Halon software take care of queueing and consolidating the respective actions into an SMTP response, the per-message version gives you maximum flexibility and control over execution. The $transaction variable is populated gradually during the SMTP conversation with sender information, and an array with recipients accepted by each RCPT TO command. To then relay a message to its recipients, you call Queue() for each $transaction["recipients"] and then Accept(). Making per-recipient message modifications using the MIME() class is now easier thanks to the new snapshot() and restore() methods.

The code editor’s built-in CSV editor now supports custom form controls, defined like a “schema” on a per-file basis using a JSON format. You can use checkboxes for booleans, select controllers for enumerated types, and input fields with validation for things like dates, email addresses or any regular expression you like. It makes it much more convenient and safe to create and edit lists and settings that you want to have in your Halon configuration file.

There’s a new LDAP() class that replaces the previous ldap_ functions and LDAP settings in the configuration. It provides greater flexibility, and an improved usage pattern using an iterable LDAP result object.

Finally, there are massive under-the-hood improvements. There’s a new on-disk YAML configurations with JSON schemas and Protobuf control sockets, which is used by the componentised Linux package’s new Visual Studio Code plugin and command line tools. The integrated package is built on FreeBSD 12, which ships with OpenSSL 1.1 and thus TLS 1.3 support. It was published as a standard by IETF in August last year, and is much anticipated as it contains many security improvements over previous TLS versions. The queue database is now using the latest and greatest PostgreSQL version 11.1, and the queue is automatically migrated on boot as usual.

We have that you’ll like this new release as much as we do! Check out the full changelog on GitHub for more information, and familiarise yourself with the important changes outlined in the release notes document before upgrading.

Halon 4.7 “ahoy” and 4.8 “truly” with live debugging and HELO script

Halon 4.0 introduced a feature we call “live staging” where you can deploy multiple running configurations at the same time, with per-connection conditions. It allows you to reliably rollout changes or new features to a production system for only a few testing IPs, or a select percentage of the traffic. With Halon 4.7, we proudly present “live debugging” using which you can add logpoints to your scripts. It enables you to inspect the full context of SMTP transactions in real-time, using the live staging conditions as connection selector.

Those points are added directly to the Monaco-based IDE, and results are inspected on a per-connection basis. You can create multiple points, triggered by multiple messages, and jump back and forth between them.

We’ve also added a HELO/EHLO phase script, support for ARC in DKIMSign() and a full implementation of draft 18 on Github, EdDSA (ed25519) and a native boolean type with corresponding strict comparison operator. The standard library have many new functions such as rsa_sign() and verify, idna_encode() and decode, aes_encrypt() and decrypt.

We hope that the live debugging will come handy! Please see the changelog on Github for a full list of improvements and changes, or get in touch with us if you want more detailed information.

Using ARC to work around DMARC’s forwarder issues

Authenticated Received Chain (ARC) is a proposed standard that have been developed to help address issues with DMARC and certain forwarders, such as mailing lists. It defines a standard for how to pass authentication results from one intermediary to another, making this information available to the recipient system. It works even in the case of multiple intermediaries, a.k.a. a chain

DMARC verifies the sender authenticity, as specified by the RFC5322.From header domain name, using SPF and DKIM. Certain indirect email flows such as mailing lists break this by altering the message, while maintaining the original From header. It causes issues for both senders that publish a DMARC policy, and receivers that verify DMARC. The two large mailbox providers AOL and Yahoo published a p=reject DMARC policy for their domains in 2014, causing some disruption for senders on those domains. It occurred when emailing recipients on mailbox services that verifies DMARC via for example mailing lists. This was, and still is, remedied by ad-hoc solutions.

ARC in itself isn’t a reputation system. The specification doesn’t define how the reputation of intermediates should be tracked, nor how public lists should be operated. In other words, as a recipient mailbox provider you still have to operate such systems in order to make use of the information that ARC provides. DMARC.org announced ARC at a M3AAWG meeting in Atlanta, 2015, where it’s been a frequent topic ever since.

include "authentication.header";
include "authentication.arc";

$chain = ARC::chainValidate();
if ($chain["status"] == "pass" or $chain["status"] == "none")
{
	ARC::seal(
			"201805", "example.com", "pki:arc",
			$chain,
			AuthenticationResults()
				->SPF(["smtp.client-ip" => $senderip])
				->DKIM()
				->DMARC()
				->addMethod("arc", $chain["status"], ["header.oldest-pass" => $chain["oldestpass"] ?? "0"])
				->toString()
		);
}

 

We have just released an implementation for ARC (draft 14) on Github, which supports both verification and (re)sealing. It’s written in Halon script, and we’re using it on our own domain to start with. If you’re interested in taking it for a spin, just let us know.

Let’s meet at M3AAWG #43 in Munich

M3AAWG meetings are an exceptional opportunity to discuss the latest in messaging security with other professionals in a focused environment of working sessions and educational panels. This time we meet in Munich, Germany. Leading industry experts, researchers and public policy officials address such diverse topics as bot mitigation practices, social networking abuse, mobile abuse and pending legislation.

As an official supporter member, we will of course participate in the Munich meeting on June 4th-7th. If you want to meet up, just get in touch!

Halon 4.6 “curry” with outbound anti-spam

You probably know from before that Halon’s scriptable SMTP server enable email providers to avoid blacklisting and increase deliverability. The 4.6 release, “curry”, contains Cyren’s outbound anti-spam (OAS). In combination with our cluster-synchronised rate limit function, it provides incredibly effective and accurate abuse prevention. Just like their Cyren’s inbound anti-spam, OAS uses a hash-sharing technology called recurrent pattern detection (RPD) that identifies outbreak patterns. It’s designed to detect spam from internal sources rather than external, and doesn’t report/contribute any signatures since it could blacklist your own infrastructure.

With the flexibility of scripting you can determine customer/sender identities accurately even in mixed traffic. This is used as identifier for rate limits based on classifiers such as Cyren’s OAS, delivery failure rate, queue size, etc. By using IP source hashing and alternative IPs for suspicious traffic, deferring obvious abuse and controlling connection concurrency, you can achieve high deliverability with minimal administration.

The 4.6 release comes with many additional features and improvements. It adds SNI support to the TLS functions. The Monaco-based code editor now have additional code completion, built-in documentation, tabs, and a mini-map.

For more information on the release, see the full changelog on GitHub. If you want to try Cyren’s outbound anti-spam, contact our sales team.

Halon 4.6 “funny” supporting our SMTP LANG extension

In the beginning, everything was ASCII and English. Since then, we’ve seen Unicode (international character sets) and IDN (international domains names) become widely adopted. Last year we implemented SMTPUTF8 that enables international mailboxes.

So why not support other languages in text-based protocols? We give to you “The SMTP Service Extension for Protocol Internationalization” RFC draft, introducing the EHLO keyword LANG. It will be the first SMTP software to support our to-be submitted RFC draft. Initially it will support Swedish, Spanish and Australian, and will default to Swedish when talking to supported systems.

EHLO example.com
250-LANG SE ES AU
LANG SE
250 Ok
BREV FRÅN:<>
250 Tack
BREV TILL:<hå[email protected]än.se>
250 Tack
INNEHÅLL
Subject: asdf

Hej!
.
250 Togs emot
HEJDÅ
250 Vi ses!

If you made it this far, April fool! We will publish information on the upcoming 4.6 release some time after the 1st of April.

Happy easter!

The birth of Halon’s scripting language

April 28th marks the date for Halon’s 10th anniversary and I would like to share with you the story about Halon’s scripting language, HSL. In order to understand why we created our own scripting language you have to look back at what it was intended to do, and the landscape of embeddable languages in 2007.

The Halon scripting language started out as an idea of having a dynamic configuration. We wanted people to easily be able to weight the results of different anti-spam engines (Cyren’s RPD and SpamAssassin). Hence, we came up with the idea of having a simple language with functions, ScanRPD returning the spam score from the Cyren engine, and ScanSA returning the result of SpamAssassin. The configuration could look like:

if (ScanSA() > 5 and ScanRPD() > 0) Reject();
if (ScanSA() > 3 and ScanRPD() >= 50) Reject();

In order to facilitate this, we needed a simple scripting language. At the time, the intent was not to allow any general purpose programming features. We didn’t even want loops, in order to prevent runaway programs.

Creating a domain-specific scripting language

If you’re not into programming languages, I should explain that creating a simple domain-specific scripting language is easy. There are tons of guides and it doesn’t take more than a few lines until you get simple arithmetic to work (5 + 6). The hardest and most important part of creating a language is the design, also called the syntax. You want to make it as easy as possible to read and write.

Domain-specific languages are no a new phenomena, as they have existed in a lot of different applications. I believe that custom application scripting DSLs are getting less common today, as a few selected embeddable scripting language engines are getting more traction. A few years ago you would probably pick Lua to be the embedded language of choice, while nowadays JavaScript (v8) is the language everyone knows.

Why not choose an established scripting language?

Over the years, people have asked me why we developed our own language and not used e.g. Sieve, Lua or JavaScript. Here’ why:

  • Sieve (rfc3028), could technically have been an alternative, but in 2007 we hadn’t heard about Sieve. It crossed our paths a few years later. Speaking against it; Sieve was created by Mirapoint, an email gateway competitor at the time. Looking back, it was probably good that we didn’t end up using Sieve. Having our own language made our own platform evolve way beyond Sieve, and what you would expect of a traditional email gateway.
  • Lua, it just didn’t happen and I suspect that if we would have considered Lua it would had been too large and unfamiliar as a language for our initial goal. Despite the fact that arrays starts at one 😃.
  • JavaScript wasn’t just that common as an embeddable language and v8 wasn’t released at the time. And to be honest, in 2007 no one expected JavaScript to be where it is today.
Easy to learn and easy to build upon

Today we try to make HSL as familiar and easy to learn as possible, which is really important when you have a custom language. Everything we add or change is by the principle of least surprise. The language has copied a lot of syntax and good ideas from different languages. It may look a lot like PHP, it may even be mistaken for PHP, while other major concepts are from JavaScript and Python. Development of new language features are in many cases intentionally slow, as they needs to be well thought through. From a language designer perspective I would say that there isn’t much syntax in HSL that I don’t like. However we continuously add modern features. In the recent year or two, a lot of time has been put in to the language and it has gained features such as closures, classes and modules. They allow our language to be easily extendable so that you can build reusable modules on top of it. Our entire examples collection on GitHub can be imported as modules and a lot of them are written as classes.

One of the most innovating features of HSL is the cache statement as it allows you to cache the result of any function call based on the input arguments. Sure, the same functionality can be built in other ways, but having such a powerful tool so easy at hand in HSL makes it stand out. It gets really neat when you do network lookup queries, such as API lookups using http() or ldap_search().

cache [] http("http://api.example.com/v1/?param=$1", [], ["foo"]);

I personally really like the concept of custom languages, I think it’s important to try to evolve and challenge the concept of established languages, and by doing so we progress and learn from each other. I think every new language brings something new to the table; it can be a specific feature or the entire concept of why it was created in the first place.

Halon to sponsor M3AAWG 42nd General Meeting in San Francisco

M3AAWG is the Messaging, Malware and Mobile Anti-Abuse Working Group, a trusted global forum that focuses on operational issues of internet abuse, including technology, industry collaboration and public policy. They host three general meetings per year, two in the US and one in Europe, and Halon will be one of the sponsors at this years first General Meeting in San Francisco in late February.

With over 200 members worldwide, including giants such as Apple, Google and Microsoft as well as many smaller companies, M3AAWG  is the largest global association of the industry. Companies can apply for different levels of membership, Sponsor, Full Member and Supporter. Halon became a supporter one year ago today and is represented by CTO Erik Lax and CPO Anders Berggren:

I’m very proud that we got accepted into M3AAWG. Halon is committed to help driving email transport encryption adoption, and we participate in the Special Interest Group for pervasive monitoring.