Postfix 用のアクセス制限スクリプトを Python で
中国からのアクセスで、Amazon を偽装するメール送信などがありました。そこで Python を用いた国別アクセス制限スクリプトを作成しました。
Postfix と Python の連携方法などについても解説していますのでご活用下さい。
Amazon などを偽装したメール
こういった偽装メールの多くは中国や香港から送られいます。
| Postfix SMTP server: errors from unknown[42.55.95.146] Transcript of session follows. Out: 220 magic-object.mydns.jp ESMTP Postfix In: EHLO amazon.co.jp Out: 250-XXXX.XXXXXX.mydns.jp Out: 250-PIPELINING Out: 250-SIZE 10240000 Out: 250-VRFY Out: 250-ETRN Out: 250-STARTTLS Out: 250-ENHANCEDSTATUSCODES Out: 250-8BITMIME Out: 250-DSN Out: 250-SMTPUTF8 Out: 250 CHUNKING In: MAIL FROM: <admin@amazon.co.jp> Out: 250 2.1.0 Ok In: RCPT TO: <xxxxxx@XXXXXXXXXXX.mydns.jp> Out: 450 4.7.25 Client host rejected: cannot find your hostname, [42.55.95.146] |
| $ whois 42.55.95.146 % Information related to ‘42.52.0.0/14AS4837’ route: 42.52.0.0/14 descr: China Unicom Liaoning Province Network country: CN origin: AS4837 mnt-by: MAINT-CNCGROUP-RR last-modified: 2011-03-02T05:24:02Z source: APNIC % This query was served by the APNIC Whois Service version 1.88.16 (WHOIS-JP1) |
Postfix 用のアクセス制限スクリプトの基本
データのやりとり
データのやりとりは基本的に標準入力と標準出力で行います。
形式:変数=値
参考:ポリシープロトコルの記述
標準入力
変数一覧(参考)
| client_address | client_helo | client_hostname | client_port | client_protocol |
| domain | extension | mailbox | nexthop | original_recipient |
| recipient | sasl_method | sasl_sender | sasl_username | sender |
| size | user |
標準出力
| 許可 | action=OK\n\n |
| 拒否 | action=REJECT Deny Country in List\n\n |
※ 送信する場合は必ず改行コードを2個追加してください。
※ 標準出力の「action」にはココで指定された文字列で返信してください。
コード
「/etc/postfix/geo-ip-countries.py」
#!/usr/bin/env python
##############################################
if __name__ == "__main__":
import configparser
import sys
import re
import pathlib
import datetime
import GeoIP
configFile = '/etc/postfix/geo-ip-countries.cf'
################ 初期設定 #################
# GeoIP の準備
gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
# 設定ファイルの準備
config = configparser.ConfigParser()
try:
config.read( configFile )
except:
denyCountries = []
if len( allowCountries ) < 1 and len( denyCountries ) < 1:
exit( 0 )
######### 読み込みループ作成 ##############
try:
for line in sys.stdin:
line = line.strip()
if len( line ) < 1:
continue
patrList = re.split( r'\s*=\s*', line )
if 'client_address' != patrList[0]:
continue
targetAddresStr = patrList[1].strip()
if targetAddresStr in accpectAddress:
print( "action=OK\n\n" )
break
targetCountry = gi.country_code_by_name( targetAddresStr )
if targetCountry in allowCountries:
print( "action=OK\n\n" )
break
elif targetCountry in denyCountries:
print( "action=REJECT Deny Country in List\n\n" )
break
else:
print( "action=OK\n\n" )
break
sys.stdout.flush()
#exit( 0 )
except:
exit( 1 )
################## 終了 ###################
exit( 0 )
※ IP アドレスから国のコードを取得する参考はコチラから。
| # ### SELinux の実行権限を付与 # chcon -t postfix_exec_t /etc/postfix/geo-ip-countries.py # # ## 実行権の付与 # chmod +x /etc/postfix/geo-ip-countries.py |
スクリプトの設定ファイル
「/etc/postfix/geo-ip-countries.cf」
[allow] countries = [deny] countries = CN, HK, KR [accpect address] ip_address =
Postfix の設定ファイル
「/etc/postfix/master.cf」
# ==================================================================== # GeoIP based Countries Blocking # ==================================================================== # =================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # =================================================================== geoip-policy unix y n n - 10 spawn user=nobody argv=/etc/postfix/geo-ip-countries.py
「/etc/postfix/main.cf」
smtpd_client_restrictions = permit_mynetworks,
permit_sasl_authenticated,
check_policy_service unix:private/geoip-policy,
check_client_access mysql:/etc/postfix/mysql-check_client_access.cf,
reject_unknown_client,
reject_rbl_client bl.spamcop.net,
reject_rbl_client zen.spamhaus.org,
permitpostfix の再起動
# systemctl restart postfix
