LoginSignup
2
3

【Python】WAF/Firewallで検知したIPアドレスが危険かどうかをAbuseIPDBでまとめてチェックする

Last updated at Posted at 2023-05-29

概要

WAFやFirewallで日々検知されるログを確認している際に、「このIPアドレスはどこのIPだろう?怪しいIP?」と思うことが多々あると思います。
危険なIPアドレスかどうかを調べる際によくAbuseIPDBを使用しているのですが、Web上だと1つずつしか確認ができないため、複数のIPアドレスをまとめてチェックしたい時には手間がかかります。
そのため、APIを使用してまとめてチェックするプログラムをPythonで作成しました。

前提条件

  • AbuseIPDBのアカウントを持っていること
  • AbuseIPDBのAPIキーを取得していること
    取得方法は公式ページを参照してください
  • 検知したIPアドレス一覧を「ipaddress-list.csv」に保存すること

制限事項

  • 無料版だと1日あたり1000IP分までしか検索ができません。

プログラム

abuseIp.py
import requests
import json
import csv
import ipaddress

api_key = 'API Key'
max_age_in_days = '90'


def main():
    ip_address_list_file = 'ipaddress-list.csv'
    check_ip_list = read_ip_address_list_file(ip_address_list_file)

    # IPの個数分ドメイン情報を取得する
    # get domain info of ip addresses
    for ip_address in check_ip_list:
        if is_valid_ip(ip_address[0]):
            domain_info = get_domain_info(ip_address[0])
            domain, isp, score, countryCode, is_public = domain_info
            if is_public == True:
                print(f"{ip_address[0]},{domain},{isp},{countryCode},{score}")

            else:
                print(f"{ip_address[0]},Private IP,Private IP,0")
        else:
            print(f"Invalid IP address: {ip_address[0]}")


def get_domain_info(ip_address):
    # This function receives a ip address and check its domain info by using abuseip api.
    # Then return a list of its domain name, isp info, countryCode, abuse score, and IPAddress info(Public or Private)

    # Defining the api-endpoint
    url = 'https://api.abuseipdb.com/api/v2/check'

    # Curlを投げてドメイン情報を取得
    # get domain info with curl command
    querystring = {
        'ipAddress': ip_address,
        'maxAgeInDays': max_age_in_days
    }

    headers = {
        'Accept': 'application/json',
        'Key': api_key
    }

    response = requests.request(
        method='GET', url=url, headers=headers, params=querystring)

    try:
        # JSONデータを辞書型に変換
        data_dict = response.json()

        # 必要なデータを取得
        domain = data_dict['data']['domain']
        isp = data_dict['data']['isp']
        countryCode = data_dict['data']['countryCode']
        score = data_dict['data']['abuseConfidenceScore']
        is_public = data_dict['data']['isPublic']

        return domain, isp, score, countryCode, is_public

    except KeyError as e:
        print(f"KeyError: {e} in response: {response.text}")
        return None, None, None, None, None


def read_ip_address_list_file(ip_address_list_file):
    # This function reads csv file and return a list of ip addresses

    # 検索したいIPリストを記載したCSVファイルを読み込む
    # read csv file which has ip addresses you want to search domain info
    with open(ip_address_list_file, encoding='utf-8-sig') as f:
        reader = csv.reader(f)
        search_ipaddress = []

        for row in reader:
            # 確認したいIPアドレスをリスト化
            # create a list of ip addresses
            # [['IPアドレス','検知数']・・・]の情報が入る
            # list will be [['IP Address', 'count of ip address']・・・]
            search_ipaddress.append(row)

    return search_ipaddress


def is_valid_ip(ip_addr):
    try:
        ipaddress.ip_address(ip_addr)
        return True
    except ValueError:
        return False


if __name__ == "__main__":
    main()


「ipaddress-list.csv」は以下のように準備してください。

ipaddress-list.csv
192.168.0.1
192.168.0.2
192.168.0.3
・・・

結果は以下のようなイメージになります。

出力イメージ.txt
['XX.XX.XX.XX'],paloaltonetworks.com,Palo Alto Networks Inc,US,100

2024/1/31追記

IPアドレスのバリデーションや、エラーハンドリングを追加しました。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3