Серверная (www.it-simple.ru)

Перехват исходящих писем с помощью proxsmtp: SMTP-снифер


proxsmtp - средство для обработки «на лету» исходящих почтовых сообщений. Работает в виде демона, слушает по умолчанию 10025 порт и представляет собой, как не трудно догадаться, прокси для SMTP.

Постановка задачи и умолчания

Есть внешний почтовый сервер, находится по адресу 1.2.3.4. Пользователи локальной сети отправляют с него почту, подключаясь на 25 порт (стандартный smtp без шифрования).

В локальной сети 192.168.0.0/24 есть шлюз на Linux, находящийся по адресу 192.168.0.1. На шлюзе есть iptables, никакие дополнительные пакеты ставить нельзя. То есть, proxsmtp на нём стоять не может.

В этой же локалке есть сервер 192.168.0.22, на котором есть возможность поставить proxsmtp и достаточное количество свободного места для хранения собранных исходящих сообщений.

Для пользователей всё должно быть прозрачно, они не должны почувствовать никаких изменений.

Решение

При отправке письма происходит соединение компьютера пользователя с почтовым сервером. Причём подключение идёт с произвольного порта локальной машины на 25 порт почтового сервера.

Для простоты рассмотрим пока единственного пользователя локальной сети, с адресом 192.168.0.333

Схема движения сетевых пакетов

В нашей схеме пакеты должны будут двигаться так:

Настройка iptables на шлюзе

eth0 - внутренний сетевой интерфейс, локальная сеть.
eth1 - внешний сетевой интерфейс, провайдер интернета.

1. Проверяем, осуществляется ли подключение к почтовому серверу. Если да, то загибаем такой пакет на локальный сборщик почты 192.168.0.22. В зависимости от того, пропустим мы пакет или загнём, он уйдёт в интернет или останется в локальной сети, поэтому это действие должно выполняться перед решением о маршрутизации. То есть, должно находиться в цепочке PREROUTING таблицы nat.

iptables -t nat -A PREROUTING -i eth0 -s 192.168.0.333 -d 1.2.3.4 -p tcp --dport 25 -j DNAT --to-destination 192.168.0.22:10025

2. Если пакет был загнут и остался в локальной сети, то получится, что он пришёл с интерфейса eth0 и уходит обратно туда же. На многих шлюзах такие пакеты считаются некорректными и дропаются цепочкой FORWARD таблицы filter. Надо убедиться, чтобы это было не так.

iptables -t filter -I FORWARD N -i eth0 -o eth0 -j ACCEPT

Здесь N - корректный номер правила для цепочки FORWARD.

3. Решение о маршрутизации принято, пакет успешно загнут и прошёл фильтры. Вот только proxsmtp попытается вернуть ответ по обратному адресу, то есть станции 192.168.0.333. Минуя шлюз. Станция этого не поймёт, потому что ожидает ответ именно от шлюза. Чтобы этого не произошло, добавляем ещё одно правило.

iptables -t nat -A POSTROUTING -d 192.168.0.22 -p tcp --dport 10025 -j SNAT --to-source 192.168.0.1

Настройка proxsmtp

proxsmtp - мощный инструмент, но нам много от него не надо. Требуется только, чтобы он все проходящие письма сохранял на жёсткий винт.

Проходящие письма обрабатываются самописным скриптом (в прямом смысле, мы его должны сами написать), путь к этому скрипту указывается настройкой в конфигурационном файле proxsmtp. Там же указывается как скрипт будет оперировать с данными: править файл или брать из стандартного ввода и отправлять на стандартный вывод. Я выбрал второй вариант: меньше операций с диском, поэтому работает быстрее.

Но - обо всём по порядку.

Конфигурационный файл proxsmtp изначально не существует. В убунте демон стартует в стольких экземплярах, сколько существует файлов *.conf в каталоге /etc/proxsmtp. Это очень удобно: можно обрабатывать письма для нескольких почтовых серверов. У нас - один.

Создаём файл /etc/proxsmtp/1-2-3-4.conf и наполняем его таким содержимым:

Listen: 192.168.100.22:10025
MaxConnections: 256
OutAddress: 1.2.3.4
TransparentProxy: off
User: имя_пользователя
FilterCommand: /etc/proxsmtp/tee.sh
FilterType: pipe

Listen: ловим пакеты, предназначенные порту 10025 адреса 192.168.0.22 (их нам любезно предоставляет iptables шлюза)
MaxConnections: разрешаем 256 одновременных соединений, для обычной сети больше и не надо
OutAddress: указываем, что письма, прошедшие через наш скрипт (см. ниже) будут отправлены на сервер 1.2.3.4, для дальнейшего движения
TransparentProxy: демон работает не в режиме прозрачного прокси.

Здесь надо остановиться подробнее.
Режим прозрачного прокси удобен в том случае, если proxsmtp установлен непосредственно на шлюзе. В этом случае не надо было бы указывать сервер в OutAddress и для ловли пакетов потребовалось бы только одно правило в iptables.
Но результат был бы тем же: пользователь ничего не знает о том, что его отправленные письма сохраняются.

User: указанное здесь имя_пользователя используется для запуска демона, от этого же имени демон производит операции над данными. Для этих целей рекомендуется создавать отдельного пользователя.
FilterType: тип фильтрации. Как будем обрабатывать данные. pipe означает, что данные будем передавать скрипту в стандартный ввод, а результат брать из стандартного вывода.
FilterCommand: полный путь к фильтрующему скрипту. Может лежать где угодно, я расположил в /etc/proxsmtp/tee.sh

В моём случае скрипт такой:

#!/bin/bash
tee "/mnt/proxsmtp/`date +\%Y\%m\%d-\%H\%M\%S-\%N`.eml"

Здесь:
Команда tee дублирует информацию из стандартного ввода в файл и в стандартный вывод
/mnt/proxsmtp/ - хранилище проходящей почты
`date +\%Y\%m\%d-\%H\%M\%S-\%N` - формирует имя для каждого сохранённого письма. Так они будут храниться аккуратно, по датам отправки. Микросекунды в конце исключают потерю разных писем, отправленных в одно и то же время, в противном случае одно может затереться другим.

Всё.

Теперь при отправке письма пользователем, оно упадёт в каталог /mnt/proxsmtp и в неизменном виде будет отправлено адресату.
В случае ошибок смотрим лог /var/log/mail.log, демон пишет сообщения туда.


Напоминаю: настройка выше производилась для перехвата исходящей почты с единственного компьютера в сети. Теперь рассмотрим варианты.

Перехват почты со всех компьютеров локальной сети

Потребуется изменить только первое правило в iptables. Теперь оно будет выглядеть так:

iptables -t nat -A PREROUTING -i eth0 -s !192.168.0.22 -d 1.2.3.4 -p tcp --dport 25 -j DNAT --to-destination 192.168.100.22:10025

Обращаю отдельное внимание: перенаправляются пакеты со всех адресов локальной сети кроме самого сервера proxsmtp! Если его не исключить - возникнет страшная рекурсия.

Правда, программу тоже не дураки писали, поэтому всё закончится на второй итерации, выводом в /var/log/mail.log ошибки.

Перехват почты с диапазона адресов локальной сети

Опять же, изменяем только первое правило. Например, для диапазона 192.168.0.144-159:

iptables -t nat -A PREROUTING -i eth0 -s 192.168.100.144/28 -d 1.2.3.4 -p tcp --dport 25 -j DNAT --to-destination 192.168.0.22:10025

Очень удобный вариант. Если надо сохранять исходящую почту не от всех пользователей, а от избранных (например, есть подозрение, что хамят клиентам ;), то поступаем следующим образом:

1. Настраиваем систему на сбор почты с диапазона адресов.
2. Вносим в этот диапазон нужных людей.

После чего процедуры «поставить на наблюдение» и «снять с наблюдения» сводятся к изменению ip-адреса рабочей станции. Вдвойне удобнее, если в локальной сети работает DHCP.

Многие не могут понять, почему диапазон адресов 192.168.0.144-159 можно задать в iptables как 192.168.100.144/28 (кстати, по-другому там ряд адресов и не задашь). Даю подсказку:

144: 10010000
159: 10011111

Перехват почты для нескольких почтовых серверов

Например, 5.6.7.8 - второй почтовый сервер, письма на который надо перехватывать.

Добавляем в iptables:

iptables -t nat -A PREROUTING -i eth0 -s 192.168.0.333 -d 5.6.7.8 -p tcp --dport 25 -j DNAT --to-destination 192.168.0.22:10026
iptables -t nat -A POSTROUTING -d 192.168.0.22 -p tcp --dport 10026 -j SNAT --to-source 192.168.0.1

Обращаю внимание: изменился порт, на который перенаправляем пакеты. Это другой почтовик и его будет слушать другой демон.

На сервере proxsmtp добавляем второй конфиг для демона: /etc/proxsmtp/5-6-7-8.conf. Например, такого содержания:

Listen: 192.168.100.22:10026
MaxConnections: 256
OutAddress: 5.6.7.8
TransparentProxy: off
User: имя_пользователя
FilterCommand: /etc/proxsmtp/tee2.sh
FilterType: pipe

Можно использовать и одинаковые скрипты (tee.sh), но есть смысл отделять почту, отправляемую с разных серверов, по разным папкам. Пример tee2.sh:

#!/bin/bash
tee "/mnt/proxsmtp5678/`date +\%Y\%m\%d-\%H\%M\%S-\%N`.eml"

Надеюсь, система понятна.


http://thewalter.net/stef/software/proxsmtp/transparent.html (http://thewalter.net/stef/software/proxsmtp/transparent.html)