Truy vấn vị trí địa lý của địa chỉ IP bằng Python

1. Tổng quan

Bài viết hướng dẫn cách sử dụng Python để phân tích cơ sở dữ liệu IP và nhanh chóng truy vấn vị trí địa lý của một địa chỉ IP cụ thể.

2. Thư viện mã nguồn mở

Các thư viện hỗ trợ cho nhiều ngôn ngữ lập trình:

  • JAVA: github.com/tagphi/czdb-search-java
  • PHP: github.com/tagphi/czdb_searcher_php
  • C: github.com/tagphi/czdb-search-c

3. Cách lấy cơ sở dữ liệu IP

Để có được cơ sở dữ liệu IP, cần tải xuống và cài đặt ứng dụng chính thức, sau đó giải nén để lấy tệp cơ sở dữ liệu ở định dạng văn bản (txt).

4. Xử lý cơ sở dữ liệu IP bằng Python

4.1. Phương pháp tiếp cận

Đọc từng dòng từ tệp IP, tách dữ liệu và lưu trữ vào cấu trúc cây khoảng (interval tree) để tối ưu hóa tốc độ truy vấn.

4.2. Tải dữ liệu IP vào bộ nhớ

Quá trình tải dữ liệu có thể mất thời gian do chi phí tạo các nút trong cây khoảng.

def load_ip_database(self, file_path):
    """
    Tải phạm vi địa chỉ IP và địa chỉ vị trí thực tế
    :param file_path: Đường dẫn đến tệp chứa dữ liệu phạm vi IP
    :return: Từ điển ánh xạ phạm vi IP đến vị trí thực tế
    """
    ip_mapping = {}
    with open(file_path, 'r') as file:
        for line in file:
            parts = line.strip().split()
            if len(parts) >= 3:
                start_ip = int(parts[0])
                end_ip = int(parts[1])
                location = ' '.join(parts[2:])
                if start_ip != end_ip:
                    self.interval_tree.add(Interval(start_ip, end_ip, location))
                    self.single_ips[start_ip] = location
                else:
                    self.single_ips[start_ip] = location
    return ip_mapping

4.3. Truy vấn vị trí địa lý từ địa chỉ IP

def lookup_ip_location(self, ip):
    """
    Tìm địa chỉ thực tế dựa trên địa chỉ IP đầu vào
    :param ip: Địa chỉ IP cần tra cứu
    :return: Vị trí địa lý tương ứng, hoặc chuỗi rỗng nếu không tìm thấy
    """
    ip_int = int.from_bytes(socket.inet_aton(ip), byteorder='big')
    matching_ranges = self.interval_tree[ip_int]
    result = ''
    if matching_ranges:
        for range_item in matching_ranges:
            result = range_item.data
    else:
        result = self.single_ips.get(ip_int, '')
        if not result:
            print(f"Không tìm thấy IP {ip} trong bất kỳ phạm vi nào.")
    return result

4.4. Xử lý các trường hợp IP đơn lẻ

Đối với các phạm vi IP chỉ chứa một địa chỉ duy nhất, lưu trữ bằng từ điển với khóa là IP bắt đầu.

if start_ip != end_ip:
    self.interval_tree.add(Interval(start_ip, end_ip, location))
    self.single_ips[start_ip] = location
else:
    self.single_ips[start_ip] = location

4.5. Mã nguồn hoàn chỉnh

import socket
from intervaltree import Interval, IntervalTree

class IPLocationFinder:
    def __init__(self, database_file):
        """
        Khởi tạo bộ tìm kiếm vị trí địa lý IP
        :param database_file: Đường dẫn đến tệp chứa dữ liệu phạm vi IP
        """
        self.interval_tree = IntervalTree()
        self.single_ips = {}
        self.load_ip_database(database_file)

    def load_ip_database(self, file_path):
        """
        Tải phạm vi địa chỉ IP và địa chỉ vị trí thực tế
        :param file_path: Đường dẫn đến tệp chứa dữ liệu phạm vi IP
        :return: Từ điển ánh xạ phạm vi IP đến vị trí thực tế
        """
        ip_mapping = {}
        with open(file_path, 'r') as file:
            for line in file:
                parts = line.strip().split()
                if len(parts) >= 3:
                    start_ip = int(parts[0])
                    end_ip = int(parts[1])
                    location = ' '.join(parts[2:])
                    if start_ip != end_ip:
                        self.interval_tree.add(Interval(start_ip, end_ip, location))
                        self.single_ips[start_ip] = location
                    else:
                        self.single_ips[start_ip] = location
        return ip_mapping

    def lookup_ip_location(self, ip):
        """
        Tìm địa chỉ thực tế dựa trên địa chỉ IP đầu vào
        :param ip: Địa chỉ IP cần tra cứu
        :return: Vị trí địa lý tương ứng, hoặc chuỗi rỗng nếu không tìm thấy
        """
        ip_int = int.from_bytes(socket.inet_aton(ip), byteorder='big')
        matching_ranges = self.interval_tree[ip_int]
        result = ''
        if matching_ranges:
            for range_item in matching_ranges:
                result = range_item.data
        else:
            result = self.single_ips.get(ip_int, '')
            if not result:
                print(f"Không tìm thấy IP {ip} trong bất kỳ phạm vi nào.")
        return result

# Ví dụ sử dụng
if __name__ == "__main__":
    finder = IPLocationFinder("ip_data.txt")
    test_ip = "127.0.0.1"
    location = finder.lookup_ip_location(test_ip)
    print(f"Địa chỉ IP {test_ip} thuộc vị trí: {location}")

5. Ứng dụng thực tế

Phương pháp truy vấn vị trí IP này đặc biệt hữu ích trong công tác vận hành an ninh và điều tra sự cố. Khi phân tích log từ các máy chủ web như access.log hoặc IIS logs, việc xác định vị trí địa lý của các địa chỉ IP giúp phát hiện các hoạt động bất thường một cách hiệu quả.

Thẻ: python IP geolocation interval tree Network Security log analysis

Đăng vào ngày 26 tháng 10 lúc 15:34