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, permit
postfix の再起動
# systemctl restart postfix