Tracking Authenticated SMTP Users in Postfix with MySQL Virtual Mailboxes


2 views

When dealing with Postfix SMTP authentication through virtual mailboxes (MySQL backend), you might encounter situations where you need to trace which authenticated user account was used to relay a specific email. The standard mail headers often don't reveal this crucial information directly.

First, ensure your Postfix logging includes SASL authentication details. Add this to your main.cf:

# Enable detailed SASL logging
debug_peer_list = 0.0.0.0/0
debug_peer_level = 2

Assuming your virtual mailbox setup looks like this in main.cf:

virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Check these log files for authentication traces:

  • /var/log/mail.log
  • /var/log/auth.log
  • /var/log/syslog

Look for entries containing 'sasl_method=LOGIN' or similar. Example log entry:

Jul  3 05:42:59 ourserver postfix/smtpd[12345]: ABC123456: client=c-76-109-241-139.hsd1.fl.comcast.net[xx.109.xxx.139], sasl_method=LOGIN, sasl_username=realuser@domain.com

If logs don't show the username, query your mailbox database:

SELECT username FROM mailbox WHERE username IN 
(SELECT name FROM aliases WHERE destination LIKE '%realuser@domain.com%')
UNION
SELECT username FROM mailbox WHERE username = 'realuser@domain.com';

Create a shell script to parse logs for specific message IDs:

#!/bin/bash
MSGID="7BA184B4AD4"
grep "$MSGID" /var/log/mail.log | grep sasl_username

For future messages, add this to main.cf to include auth info in headers:

smtpd_sasl_authenticated_header = yes

If logs are missing authentication info:

  1. Verify logrotate isn't compressing logs too aggressively
  2. Check syslog filters aren't dropping auth messages
  3. Ensure proper SELinux permissions for Postfix logging

When troubleshooting email delivery issues or investigating potential abuse cases, determining which authenticated user account was used to send a message through Postfix is critical. With a MySQL-based virtual mailbox setup, we need to examine multiple system components:

# Key components to investigate:
1. Postfix SMTP authentication logs
2. MySQL virtual_users table
3. SASL authentication mechanisms
4. Header analysis techniques

First, verify your Postfix and SASL logging configuration. Add these to /etc/postfix/main.cf:

# Enhanced logging for SMTP authentication
debug_peer_list = xx.109.xxx.139
debug_peer_level = 2
smtpd_sasl_authenticated_header = yes

Search your mail logs (typically /var/log/mail.log) for the message ID 7BA184B4AD4:

grep '7BA184B4AD4' /var/log/mail.log | grep -i 'sasl_username'

This should reveal lines like:

postfix/smtpd[1234]: 7BA184B4AD4: client=c-76-109-241-139.hsd1.fl.comcast.net[xx.109.xxx.139], sasl_method=LOGIN, sasl_username=actualuser@domain.com

If logs don't show the SASL username, query your MySQL virtual users table directly. First identify the connecting IP's timestamp:

SELECT * FROM postfix_log 
WHERE client_ip = 'xx.109.xxx.139' 
AND timestamp BETWEEN '2012-07-03 05:42:00' AND '2012-07-03 05:43:00';

Then cross-reference with your virtual_users table:

SELECT * FROM virtual_users 
WHERE id = (SELECT user_id FROM postfix_log WHERE message_id = '7BA184B4AD4');

The ESMTPA in your Received header confirms authentication occurred. While the header shows "User", the actual authenticated username would be in logs. You can add header checks to /etc/postfix/main.cf:

smtpd_sasl_authenticated_header = yes
header_checks = regexp:/etc/postfix/header_checks

Create /etc/postfix/header_checks with:

/^Received:.*with ESMTPA/ PREPEND X-Authenticated-User: $sasl_username

Implement these changes to better track authenticated senders:

# In main.cf:
always_add_missing_headers = yes
smtpd_sasl_exceptions_networks = 
smtpd_sasl_security_options = noanonymous

And create a log processor script (log_analyzer.php):

<?php
$log = file_get_contents('/var/log/mail.log');
preg_match_all('/message-id=([A-Z0-9]+).*sasl_username=([^\s]+)/', $log, $matches);
$messageMap = array_combine($matches[1], $matches[2]);
file_put_contents('/var/lib/postfix/message_user_map.json', json_encode($messageMap));
?>