セキュリティ対策 - ファイアウォール IP Firewall - メールサーバ設定


 クラウディア


1. 概要
2. 考察
3. 接続許可
4. 受信接続拒否
5. 送信接続許可
6. プログラム
7. 効果

1. 概要

 「FreeBSD」のマシンをメールサーバとして使用する際。  「smtp」で接続してくる相手は、変な国からの接続は拒否したいし。  「pop/imap」で接続を許可するのは、ユーザとして接続してくる可能性のあるもののみ許可したい。

2. 考察

 そのあたり、メールサーバの設定で、もちろんできるのではありますが。  メールサーバのログに、わらわらと残る可能性があります。  かといって、設定すべきネットワークの量が多すぎて、ルータのファイアウォールに設定するには、面倒くさい。  そこで、「IP Firewall」を使うのはどうかな?と思った次第です。

3. 接続許可

 まず、「LAN」、自ドメイン内等の許可すべきアドレスからの接続は、すべて許可します。  下記のような定義ですな。

add 10002 allow tcp from 192.168.0.0/16 to me any

4. 受信接続拒否

 前項以外の「ip」は、受信接続を拒否します。

add 20001 deny tcp from any to me pop3,imap

5. 送信接続許可

 当初、日本以外の「ip」アドレスを列挙して、送信接続を拒否しようかと思ったのですが、ネットワークの数が多すぎて、設定ファイルに書くには、長すぎるし、「ipfw」自体が重くなりすぎそうです。  なので、日本国内の「ip」アドレスを送信接続許可したのちに、それ以外のアドレスを、送信接続拒否するように定義します。  日本国内の「ip」アドレスは、「無料の IP ジオロケーションデータベース」から、「.csv」ファイルをいただいて、国名の箇所が「JP」になっているものを抜き出します。

add 30001 allow tcp from 1.0.16.0/20 to me smtp
add 30002 allow tcp from 1.0.64.0/18 to me smtp
add 30003 allow tcp from 1.1.64.0/18 to me smtp

・・・	略	・・・

add 39054 allow tcp from 223.223.224.0/19 to me smtp
add 39055 allow tcp from 223.252.64.0/19 to me smtp
add 39056 allow tcp from 223.252.112.0/20 to me smtp
add 39057 deny log tcp from any to me smtp
 てな感じになります。

6. プログラム

 以上のものを、「python」でプログラム化してみました。  下記のソースになります。

import csv
import ipaddress
import os

allow = [ 'JP' ]
deny  = [ 'AL', 'AM', 'AT', 'AU', 'AZ', 'BA', 'BD', 'BG', 'BR', 'BS', 'BY', 'CA', 'CN', 'CO', 'CS', 'CZ',
          'DE', 'DK', 'DO', 'ES', 'EU', 'FO', 'FR', 'GB', 'GR', 'HK', 'HR', 'HU', 'ID', 'IE', 'IN', 'IQ',
          'IR', 'JO', 'KG', 'KH', 'KR', 'KW', 'KZ', 'LA', 'LB', 'MA', 'MD', 'ME', 'MH', 'MN', 'MO', 'MT',
          'MU', 'MY', 'NL', 'NP', 'NZ', 'PF', 'PG', 'PH', 'PK', 'PL', 'PR', 'RO', 'RS', 'RU', 'SA', 'SC',
          'SE', 'SG', 'SK', 'TH', 'TM', 'TR', 'UA', 'UY', 'VN', 'ZZ' ]

os.chdir(os.path.dirname(__file__))
allowFile = 'allow_ipfw.txt'
denyFile  = 'deny_ipfw.txt'
listFile   = 'IP2LOCATION-LITE-DB1.CSV'
outputFile = 'ipfw-all.txt'

myList = []

with open(listFile) as file:
  reader = csv.reader(file, quotechar='"')

  for row in reader:
    if row[2] == '-':
      continue

    start = str(ipaddress.IPv4Address(int(row[0])))
    end   = str(ipaddress.IPv4Address(int(row[1])))

    try:
      start_ip = ipaddress.ip_address(start)
      end_ip = ipaddress.ip_address(end)

      networks = list(ipaddress.summarize_address_range(start_ip, end_ip))

      if len(networks) <= 0:
        print("The specified IP address range is invalid")
        continue

    except ValueError as e:
      print(f"An invalid IP address was specified - {e}")
      continue

    for network in networks:
      dic = { 'country': row[2], 'start': start, 'end': end, 'range': network  }
      myList.append(dic)


# ここから出力にはいる
with open(outputFile, 'w') as file:

  # LAN ドメインネットワークの接続はすべて許可する
  filter_number = 10001

  with open(allowFile, 'r') as rfile:
    readall = rfile.read()

    lines = readall.split('\n')

    for line in lines:
      file.write('add '+ str(filter_number) +' allow tcp from '+ line +' to me any\n')
      filter_number += 1

  # ここまでの アドレス以外は pop/imap を拒否という定義を作成
  filter_number = 20001

  file.write('add '+ str(filter_number) +' deny log tcp from any to me pop3,imap\n')

  # smtp で 拒否するアドレスを定義
  filter_number = 30001

  for one in myList:
    if one['country'] in allow:
      file.write('add '+ str(filter_number) +' allow tcp from '+ str(one['range']) +' to me smtp\n')
      filter_number += 1

  file.write('add '+ str(filter_number) +' deny log tcp from any to me smtp\n')
 主な個所を説明しておきます。  16行目まで、許可する国の識別コード、拒否したい国の識別コード(これは、現在のところ使用していません)。  「allowFile」で定義しているファイル内に、「LAN」アドレス、ドメインのネットワーク等、ほぼ無条件で許可する「IP」アドレスを定義しています。  「denyFile」は、現在使用していませんが、悪質なアドレスを列挙して、何も接続させないようにしようと考えています。  「listFile」は、国別の「IP」アドレスを定義した、「.csv」ファイルです。  「outputFile」が、最終的に許可・拒否の定義を出力するファイルになります。  20~46行で、国別「IP」アドレスの「.csv」ファイルを「国識別コード」「開始アドレス」「終了アドレス」「203.0.113.0/24 形式のネットワークアドレス」の辞書型へ変換しています。  50~77行で、許可・拒否の定義を出力しています。  55~58行で、許可アドレスを、下記の形式で許可定義しています。

add 10001 allow tcp from 127.0.0.1 to me any
 65~67行で、下記の形式で、前項で許可した「IP」アドレス以外からの「pop3」「imap」への接続を拒否しています。

add 20001 deny log tcp from any to me pop3,imap
 72~75行で、国識別コード「JP」のアドレスからの「smtp」への接続を許可しています。

add 30001 allow tcp from 1.0.16.0/20 to me smtp
 77行で、上のアドレス以外からの「smtp」への接続を拒否しています。  (ここのルール番号は、上記の連番になります)

add 39057 deny log tcp from any to me smtp

7. 効果

 さて、この設定の効果なのですが。  実は、抜群。  毎日、恐ろしいほど届いていた、スパムメールが激減しました。

/var/log/security
 と見てみると、毎分、「smtp」への接続を試みるものを拒否しているのが出力されています。  ログを出力するのは、やめておこうかと思えるほどです。  あれこれやってみた結果、メールサーバに対しては、これが一番効果がありました。

AbemaTV 無料体験
EMEET 1