- 1. 概要
- 2. ダウンロード
- 3. 抽出スクリプト
- 4. 登録スクリプト
- 5. 参考サイト
1. 概要
前ページで、特定のアドレスをテーブルにいれて、まとめて、接続許可/拒否を設定するテキストとスクリプトを作成しましたが。
これを少し、発展させます。
もうね、メールサーバでリレーしようとしてくるような相手は、ほぼ国ごとに決まっているので、失礼ながらそこの国別ドメインをまるごと拒否しようと思います。
2. ダウンロード
国別ドメインを提供してくれているサイトがあります。
「ネットワークサービス - お役立ち・面白サイト」「国別 IP アドレス」のページで紹介しておりますので、そこから。
IP2LOCATION-LITE-DB1.CIDR.zip
というファイルをダウンロードします。
展開すると、中に。
IP2LOCATION-LITE-DB1.CIDR.CSV
というファイルがあります。
およそ。
"0.0.0.0/8","-","-"
"1.0.0.0/24","AU","Australia"
"1.0.1.0/24","CN","China"
"1.0.2.0/23","CN","China"
"1.0.4.0/22","AU","Australia"
"1.0.8.0/21","CN","China"
"1.0.16.0/20","JP","Japan"
"1.0.32.0/19","CN","China"
"1.0.64.0/18","JP","Japan"
"1.0.128.0/17","TH","Thailand"
てな感じで、「CIDR」形式で、444,086 行の国別ドメインが記述されています。
3. 抽出スクリプト
「python」で、国別の「IP」アドレスリストを抽出してファイルに出力するソースを作成します。
仮に、「ipfilter.py」というソース名として。
vi ipfilter.py
下記を記述します。
import csv
import os
import argparse
import sys
def parse_args():
parser = argparse.ArgumentParser(
description="指定した国コードのCIDRリストをipfw形式のシェルスクリプトとして抽出します"
)
# 半角2文字の必須引数として設定
parser.add_argument(
"country",
type=str,
help="対象の国コード(例: cn, ru, us)"
)
args = parser.parse_args()
# 簡易的なバリデーション(2文字チェック)
if len(args.country) != 2:
print(f"Error: 国コードは半角2文字で指定してください ({args.country})", file=sys.stderr)
sys.exit(1)
return args.country.lower()
def main():
country = parse_args()
# スクリプトの場所を基準にパスを設定
base_dir = os.path.dirname(os.path.abspath(__file__))
list_file = os.path.join(base_dir, 'IP2LOCATION-LITE-DB1.CIDR.CSV')
# 出力先ディレクトリ(update_tables.shの階層に合わせた ../../../ipfw/country/)
output_dir = os.path.abspath(os.path.join(base_dir, '../../../ipfw/country'))
output_file = os.path.join(output_dir, f'{country}.sh')
# 出力先ディレクトリが存在しない場合は作成
if not os.path.exists(output_dir):
os.makedirs(output_dir)
my_list = []
# CSVの読み込み
try:
with open(list_file, 'r', encoding='utf-8') as file:
reader = csv.reader(file, quotechar='"')
for row in reader:
# row[0]: CIDR, row[1]: Country Code
if len(row) >= 2 and row[1].lower() == country:
my_list.append(row[0])
except FileNotFoundError:
print(f"Error: 入力ファイルが見つかりません: {list_file}", file=sys.stderr)
sys.exit(1)
# シェルスクリプトの書き出し(改行コードはLF固定)
with open(output_file, 'w', newline='\n') as file:
file.write('#!/bin/sh\n')
for cidr in my_list:
# exists/addedの出力を抑止したい場合はここに >/dev/null 2>&1 を追記可能
line = f'ipfw table 12 add {cidr}\n'
file.write(line)
print(f"Successfully generated: {output_file} ({len(my_list)} records)")
if __name__ == "__main__":
main()
これで。
python ipfilter.py xx
と「xx」の箇所に国別ドメインの2文字をいれると。
ソースファイルの3階層上に、下記のファイルが作成されます。
ipfw/country/xx.sh
これを前ページのテーブル「12」にぶっこみます。
4. 登録スクリプト
前ページで作成した。
update_tables.sh
の最終行の前に、下記を追加します。
# countryディレクトリ配下のすべての.shファイルを実行する
if [ -d "${DIR}/country" ]; then
echo "Updating country tables from ${DIR}/country..."
for f in "${DIR}/country/"*.sh; do
# ファイルが存在することを確認(ファイルがない場合のワイルドカード展開対策)
if [ -f "$f" ]; then
echo " Executing $(basename "$f")..."
sh "$f" >/dev/null 2>&1 || true
fi
done
fi
これで、「update_tables.sh」のスクリプトを実行すると、前項で作成した国別ドメインの「IP」アドレスを拒否テーブルにいれるスクリプトを最後に実行することができます。
5. 参考サイト
本ページは、「Gemini」伍長を参考にさせていただきました。
|