Sign In
Email Marketing

How to filter spamming explained

How to Filter Spam Using Postfix Header Checks

Spam is a persistent problem for anyone managing an email server. While solutions like SpamAssassin and greylisting are effective, sometimes you need a more direct approach. Postfix header checks offer a powerful way to filter spam based on patterns found in email headers. This article will guide you through implementing header checks in Postfix to identify and reject spam, focusing on practical examples and configuration steps.

Table of Contents

Understanding Postfix Header Checks

Postfix header checks analyze the headers of incoming emails and compare them against a set of regular expressions. When a match is found, you can take various actions, such as rejecting the email, adding a header, or simply discarding it. This method is particularly useful for blocking spam that consistently uses certain header patterns or originates from known spam sources. Header checks are configured through the header_checks parameter in Postfix’s main.cf file.

Unlike content filtering, which examines the body of the email, header checks focus solely on the headers. This makes them faster and less resource-intensive. However, they are also less flexible, as spammers can often modify or obfuscate their header information. Combining header checks with other spam filtering methods provides a robust defense against unwanted emails.

How Postfix Header Checks Work The process is relatively straightforward:

  • Postfix receives an email.
  • It examines the headers of the email.
  • It compares the headers against the patterns defined in your header check file.
  • If a match is found, the specified action is taken (e.g., reject, discard, add header).
  • If no match is found, the email is processed normally.
Header checks are processed in the order they appear in the configuration file. Once a match is found and an action is taken, further checks are usually skipped (unless you configure specific exceptions).

Example Scenarios for Header Checks Header checks excel in several scenarios:

  • Blocking emails with forged sender addresses: Many spam emails use forged sender addresses in the “From” header. You can create rules to detect and reject emails where the “From” header doesn’t match the sending domain’s SPF record or other authentication mechanisms.
  • Identifying spam campaigns based on subject line patterns: Spammers often use specific keywords or phrases in the subject line of their emails. Header checks can be used to identify and reject emails with these patterns.
  • Blocking emails originating from known spam sources: If you have a list of known spam domains or IP addresses, you can create header checks to reject emails originating from these sources.
  • Adding headers for further processing: You can add custom headers to emails that match certain criteria. These headers can then be used by other spam filtering tools, such as SpamAssassin, to further analyze the email.
Example 1: Blocking Emails with Suspicious Subject Lines

Many spam emails use the same subject line repeatedly. Let’s say you want to block emails with the subject line “URGENT: Account Verification Required”. You can add the following rule to your header check file (e.g., /etc/postfix/header_checks):

/^Subject:.*URGENT: Account Verification Required/ REJECT Suspicious Subject Line
This rule uses a regular expression to match any subject line that contains “URGENT: Account Verification Required”. The REJECT action tells Postfix to reject the email with the message “Suspicious Subject Line”.

After adding the rule, you need to tell Postfix to use the header_checks file. Add the following line to your /etc/postfix/main.cf file:

header_checks = regexp:/etc/postfix/header_checks
Finally, reload Postfix to apply the changes:

sudo systemctl reload postfix
Example 2: Blocking Emails with Missing Message-ID Headers

Legitimate emails almost always have a Message-ID header. Spam emails sometimes omit this header to avoid detection. You can block emails that are missing the Message-ID header with the following rule in your /etc/postfix/header_checks file:

/^Message-ID:/ IGNORE
/^$/ REJECT Missing Message-ID Header
This rule first uses IGNORE to skip any line that *does* contain “Message-ID:”. The second line then matches an empty line /^$/ (signifying the end of the headers and the absence of a Message-ID) and rejects the email with the message “Missing Message-ID Header”. Remember to reload Postfix after making these changes.

Expert Tip: Keep your header check rules specific and targeted. Overly broad rules can lead to false positives, blocking legitimate emails.

Setting Up a Basic Header Check Rule

The foundation of Postfix header checks lies in creating and configuring rules within a text file, typically named header_checks and located in the /etc/postfix directory. These rules are regular expressions that define the patterns to match in email headers. Once a matching pattern is found, Postfix can perform a defined action. This section will guide you through setting up a basic rule to reject spam emails based on a specific header pattern.

Creating the Header Check File First, ensure the header_checks file exists and is properly configured. You can create it using the following command:

sudo touch /etc/postfix/header_checks
Then, set the appropriate permissions:

sudo chown root:root /etc/postfix/header_checks
sudo chmod 644 /etc/postfix/header_checks
These commands create the file, set the owner to root, and set the permissions to allow the owner to read and write, and everyone else to read. This is a standard security practice.

Configuring Postfix to Use Header Checks Next, you need to tell Postfix to use this file. Edit the /etc/postfix/main.cf file and add the following line:

header_checks = regexp:/etc/postfix/header_checks
This line tells Postfix to use the header_checks file for header filtering. The regexp: prefix indicates that the file contains regular expressions. You can use other types of lookup tables as well (e.g., hash:, pcre:), but regexp: is the most common and flexible for header checks.

After editing main.cf, you must reload Postfix for the changes to take effect:

sudo systemctl reload postfix
Writing a Simple Header Check Rule Let’s create a simple rule to reject emails with a specific “X-Spam-Flag” header. Some spam filters add this header to mark emails as spam. If you want to reject all emails that have this header set to “YES”, you can add the following rule to your /etc/postfix/header_checks file:

/^X-Spam-Flag: YES/ REJECT Marked as Spam
This rule looks for any line that starts with “X-Spam-Flag: YES”. The ^ character matches the beginning of the line. The REJECT action tells Postfix to reject the email with the message “Marked as Spam”. This message will be sent back to the sender in a bounce message.

Example 1: Blocking Emails Based on the “Received” Header

Spammers sometimes use fake or manipulated “Received” headers to hide the origin of their emails. You can create rules to detect and reject emails with suspicious “Received” headers. For example, if you want to block emails where the “Received” header contains the string “bad.example.com”, you can add the following rule to your /etc/postfix/header_checks file:

/^Received:.*bad\.example\.com/ REJECT Suspicious Received Header
Note the escaped dot (\.) in the regular expression. This is necessary to match a literal dot character, as a dot has a special meaning in regular expressions (matching any character).

Example 2: Using the WARN Action for Testing

Before rejecting emails outright, it’s often a good idea to test your header check rules using the WARN action. This action will log a warning message to the Postfix log file (typically /var/log/mail.log or /var/log/maillog) when a match is found, but it will not reject the email. This allows you to see which emails are being matched by your rules without disrupting mail flow.

For example, to test the previous rule about suspicious “Received” headers, you can replace REJECT with WARN:

/^Received:.*bad\.example\.com/ WARN Suspicious Received Header
After reloading Postfix, check the log file to see if the rule is being triggered:

tail -f /var/log/mail.log
You should see log entries similar to this if the rule is triggered:

postfix/cleanup[12345]: warning: header Received: from mail.example.com (unknown [192.168.1.100]); by your.server.com (Postfix) with ESMTP id ABC123456789 for <user@example.com>; Tue, 20 Jul 2024 10:00:00 +0000: Suspicious Received Header
Once you are confident that the rule is working correctly, you can change the action from WARN to REJECT.

Quote: “Regular expressions are a powerful tool for pattern matching, but they can also be complex and difficult to debug. Start with simple rules and gradually add complexity as needed.” – Expert Email Administrator

Advanced Header Check Techniques

Beyond simple pattern matching, Postfix header checks allow for sophisticated filtering using regular expressions. This section explores advanced techniques such as character classes, quantifiers, and anchors to create more precise and effective spam filters. We’ll also cover how to combine multiple checks for greater accuracy.

Using Character Classes Character classes allow you to match a set of characters within a regular expression. For example, [0-9] matches any digit, [a-z] matches any lowercase letter, and [A-Za-z] matches any letter (uppercase or lowercase).

Example: Blocking Emails with Non-ASCII Characters in the Subject

Spammers often use non-ASCII characters in the subject line to bypass spam filters. You can block emails with non-ASCII characters in the subject using the following rule:

/^Subject:.*[^\x00-\x7F]/ REJECT Non-ASCII Characters in Subject
This rule uses the character class [^\x00-\x7F] to match any character that is not in the ASCII range (0x00 to 0x7F). The ^ inside the square brackets negates the character class, so it matches any character *not* in the specified range.

Using Quantifiers Quantifiers specify how many times a character or group should be repeated. Common quantifiers include:

  • *: Zero or more times
  • +: One or more times
  • ?: Zero or one time
  • {n}: Exactly n times
  • {n,}: n or more times
  • {n,m}: Between n and m times
Example: Blocking Emails with Excessive Spaces in the Subject

Spammers sometimes use excessive spaces in the subject line to make their emails look less suspicious. You can block emails with more than 5 consecutive spaces in the subject using the following rule:

/^Subject:.* {5,}/ REJECT Excessive Spaces in Subject
This rule uses the quantifier {5,} to match 5 or more consecutive spaces.

Using Anchors Anchors specify the position of the match within the string. The most common anchors are:

  • ^: Matches the beginning of the string
  • $: Matches the end of the string
  • \b: Matches a word boundary
Example: Blocking Emails Where the Subject Starts with “SPAM”

While unlikely, some poorly configured systems might prepend “SPAM” to the subject line. To block these, use:

/^Subject:^SPAM/ REJECT Subject Starts with SPAM
Example 1: Combining Multiple Checks Using Logical OR

You can achieve a logical OR effect by using multiple rules. For example, to reject emails that have either “Free Viagra” or “Cheap Medications” in the subject line, you can use the following rules:

/^Subject:.*Free Viagra/ REJECT Spam Subject
/^Subject:.*Cheap Medications/ REJECT Spam Subject
This is equivalent to a logical OR condition: (Subject contains “Free Viagra”) OR (Subject contains “Cheap Medications”).

Example 2: Checking the “From” Header for Numeric IPs

Sometimes spammers will put the sender IP address directly in the “From” header. This is almost always a sign of spam. Use this rule:

/^From:.*@[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ REJECT Numeric IP in From Header
This looks for an “@” followed by a pattern that looks like an IP address (four groups of digits separated by dots). This rule might have some false positives (legitimate emails where the domain name resolves to an IP address that happens to be in the same format), so use it with caution.

Expert Tip: Test your regular expressions thoroughly before deploying them in a production environment. Use online regex testers to ensure they match the intended patterns and avoid unintended consequences. A good website to test regular expressions is regex101.com.

Testing and Troubleshooting Header Checks

Proper testing and troubleshooting are crucial when implementing Postfix header checks. Incorrectly configured rules can lead to false positives, blocking legitimate emails. This section provides practical guidance on testing your rules, interpreting Postfix logs, and addressing common issues.

Testing Header Check Rules The most reliable way to test header check rules is to send test emails that match and do not match the rules you have configured.

  • Send test emails: Create emails with headers that specifically trigger your rules and emails that should not be affected.
  • Check the logs: Examine the Postfix log file (usually /var/log/mail.log or /var/log/maillog) to see if the rules are being triggered as expected.
  • Use the WARN action: As mentioned earlier, the WARN action is invaluable for testing. It allows you to see which emails are being matched without actually rejecting them.
Example: Testing a Rule with a Test Email

Let’s say you have the following rule in your /etc/postfix/header_checks file:

/^Subject:.*Test Spam Subject/ REJECT Test Rule Triggered
To test this rule, send an email with the subject “This is a Test Spam Subject”. Then, check the Postfix log file. If the rule is working correctly, you should see a log entry similar to this:

postfix/cleanup[12345]: message-id= <your-message-id>: header check REJECT from mail.example.com[192.168.1.100]; from=<test@example.com> to=<you@yourdomain.com> proto=ESMTP helo=<mail.example.com>: Test Rule Triggered
If you don’t see this log entry, then the rule is not being triggered correctly.

Interpreting Postfix Logs Postfix logs provide valuable information about how header checks are being processed. Here are some key things to look for:

  • “header check REJECT”: This indicates that a header check rule has triggered the REJECT action. The log entry will usually include the rule that was matched and the reason for the rejection.
  • “header check WARN”: This indicates that a header check rule has triggered the WARN action. The log entry will include the rule that was matched and the warning message.
  • “header_checks, defer”: This indicates that there was a problem accessing the header_checks file (e.g., incorrect permissions, file not found).
Example: Troubleshooting a “defer” Error

If you see a log entry like this:

postfix/smtpd[12345]: warning: header_checks, defer: open /etc/postfix/header_checks: permission denied
This indicates that Postfix does not have permission to read the /etc/postfix/header_checks file. To fix this, make sure the file has the correct permissions (as shown in the previous section):

sudo chown root:root /etc/postfix/header_checks
sudo chmod 644 /etc/postfix/header_checks
Common Issues and Solutions
IssuePossible CauseSolution
Rules are not being triggeredIncorrect regular expressionsUse a regex tester to verify your expressions
False positives (legitimate emails are being blocked)Overly broad rulesMake your rules more specific and targeted
Postfix is not using the header_checks fileIncorrect configuration in main.cfEnsure the header_checks parameter is correctly set and Postfix is reloaded
“defer” errors in the logIncorrect file permissionsVerify that Postfix has permission to read the header_checks file
Example 1: Debugging Regular Expression Issues

If your rules are not being triggered, the most likely cause is an error in your regular expression. Use a tool like regex101.com to test your regular expressions against sample email headers. Pay close attention to escaping special characters (like dots and parentheses) and ensure that your anchors (^ and $) are used correctly.

Example 2: Handling False Positives

If you are experiencing false positives, review your rules and try to make them more specific. For example, if you are blocking emails based on a specific keyword in the subject line, try adding additional criteria to the rule to reduce the chance of matching legitimate emails. You can also use the WARN action to identify which emails are being incorrectly matched and then adjust your rules accordingly.

By following these testing and troubleshooting steps, you can effectively implement Postfix header checks to filter spam and protect your email server. Remember to monitor your logs regularly and adjust your rules as needed to adapt to evolving spam techniques.

Share this article