Smtp фильтры для postfix
Задача 1
На сервере с postfix нужно сделать так, что бы отправлять письма через него можно было только из определенных стран.
Решение
Использовать функционал postfix tcp_table, perl
и GeoIP
.
Нам понадобится пакет perl-Geo-IP
из repoforge
!
скрипт /etc/postfix/geo-reject.pl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #!/usr/bin/perl use strict; use warnings; use Sys::Syslog qw(:DEFAULT setlogsock); use Geo::IP; my $gi = Geo::IP->new(GEOIP_STANDARD); # maps country code to reject (this is just example) # add more country code you would like to reject my @geo_map = ( 'US' , 'CA' ); # # Initalize and open syslog. # openlog('postfix/geoIP-reject','pid','mail'); #openlog('postfix/geoIP-reject','pid','local1'); # # Autoflush standard output. # select STDOUT; $|++; while (<>) { chomp; if (/^get\s(.+)$/i) { my $client_ip = $1; my $country_code = $gi->country_code_by_name($client_ip); if (defined $country_code) { if ( !(grep /$country_code/, @geo_map) ) { print "200 REJECT you're from $country_code\n"; syslog("info","Rejecting: %s", $country_code); } else { print "200 DUNNO\n"; } } else { print "200 DUNNO\n"; } next; } print "200 DUNNO\n"; } |
Заставляем postfix запускать этот скрипт в фоне (master.cf
):
127.0.0.1:2528 inet n n n - 0 spawn user=nobody argv=/etc/postfix/geo-reject.pl
Подключаем, для этого, в main.cf
:
geoip = check_client_access tcp:[127.0.0.1]:2528
в master.cf
в сервисах submission и 465 добавляем в smtpd_client_restrictions примерно так:
465 inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=$geoip -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o syslog_name=postfix/smtps -o milter_macro_daemon_name=ORIGINATING submission inet n - n - - smtpd -o smtpd_etrn_restrictions=reject -o smtpd_sasl_auth_enable=no -o smtpd_tls_security_level=may -o smtpd_client_restrictions=$geoip -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o syslog_name=postfix/submission -o milter_macro_daemon_name=ORIGINATING
Проверяем:
# telnet localhost 2528 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. get 217.112.35.75 200 REJECT you're from GB
Задача 2
Если нужно сделать то же самое, но для только для нескольких почтовых акаунтов
Решение
Будем использовать функционал postfix Policy Delegation.
Скрипт /etc/postfix/postfix-geo-policy.pl
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #!/usr/bin/perl use strict; use warnings; use Switch; use Sys::Syslog qw(:DEFAULT setlogsock); use Geo::IP; my $DEBUG = 0; my $SENDERS_LIST='/etc/postfix/postfix-geo-policy-senders.txt'; # Add countries my @geo_map = ( 'US' , # 'RU' , ); my $gi = Geo::IP->new(GEOIP_STANDARD); my %attributes; # # Initalize and open syslog. # openlog('postfix/geoIP-reject','pid','mail'); #openlog('postfix/postfix-geo-policy','pid','local2'); # # Autoflush standard output. # select STDOUT; $|++; while (<>) { chomp; my $line = $_; $line =~ s/[\r\n]*$//; # this line remove \r\n from end of line if native perl chomp fails if ( $line eq '' ) { &policy; next; } (my $attr_name, my $attr_value) = split ( "=", $line ); $attributes{$attr_name} = $attr_value if $attr_value; } sub policy { my $result; # Add load senders list my @senders; open (IN, "<$SENDERS_LIST"); while (<IN>) { push @senders, $_; } close IN; # policy rules if ( $attributes{'sender'} && $attributes{'client_address'} ) { if ( grep /$attributes{'sender'}/, @senders ) { my $country_code = $gi->country_code_by_name($attributes{'client_address'}); if ( $country_code ) { if ( !(grep /$country_code/, @geo_map) ) { $result = "REJECT you're from $country_code"; syslog("info","REJECT! sender: $attributes{'sender'} IP: $attributes{'client_address'} country: $country_code"); } else { syslog("info","OK! sender: $attributes{'sender'} IP: $attributes{'client_address'} country: $country_code"); } } } else { syslog("info","OK! (sender is not in restriction list) addr: $attributes{'sender'} IP: $attributes{'client_address'}"); } } # cleanup %attributes foreach my $attr_name ( keys %attributes ) { syslog("info","$attr_name=$attributes{$attr_name}") if $DEBUG; delete($attributes{$attr_name}); } # output result if ( $result ) { print "action=$result\n\n"; syslog("info","Rejecting message with $result"); } else { syslog("info","OK!!") if $DEBUG; print "action=DUNNO\n\n"; } } |
Создаем файл со списком адресов отправителей, которые нужно проверять /etc/postfix/postfix-geo-policy-senders.txt
.
Заставляем postfix запускать этот скрипт в фоне (master.cf
):
127.0.0.1:9998 inet n n n - 0 spawn user=nobody argv=/etc/postfix/postfix-geo-policy.pl
Подключаем, для этого, в main.cf
:
geoip_policy = check_policy_service inet:127.0.0.1:9998
в master.cf
в сервисах submission и 465 добавляем в smtpd_client_restrictions примерно так:
465 inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=$geoip_policy -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o syslog_name=postfix/smtps -o milter_macro_daemon_name=ORIGINATING submission inet n - n - - smtpd -o smtpd_etrn_restrictions=reject -o smtpd_sasl_auth_enable=no -o smtpd_tls_security_level=may -o smtpd_client_restrictions=$geoip_policy -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o syslog_name=postfix/submission -o milter_macro_daemon_name=ORIGINATING
Проверяем:
# telnet localhost 9998 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. sender=mari**@***prop.com client_address=162.243.1.181 action=DUNNO
Список атрибутов, которые передаются в скрипт на этапе smtpd_client_restrictions:
protocol_state=RCPT request=smtpd_access_policy sasl_username=mari**@***prop.com recipient=srab_alk**@****.com sasl_method=LOGIN instance=7df1.57739b39.6bf8f.0 protocol_name=ESMTP encryption_keysize=256 helo_name=www.globalbotanical.com sender=mari***@***prop.com reverse_client_name=www.advanceqc.com client_name=unknown client_address=162.243.1.*** encryption_cipher=ECDHE-RSA-AES256-SHA encryption_protocol=TLSv1
Enjoy!