Проверка диапазонов
Проверка диапазонов — полезный скрипт для проверки наличия адресов определённых стран в IP-диапазонах.
Описание[править]
В одно время на некоторые сайты произошла атака очень яростного и агрессивного что ли дятла, который в связи с ограничениями прав и каптчей не мог нанести серьёзный вред, но при этом вполне мог отвлекать от работы. Было решено произвести сжигание гнёзд в виде IP.
Однако возникла проблема — часто в диапазоне /16 встречаются как диапазоны прокси, датацентров, так и вполне нормальные пользователи. Соответственно потребовалось перед баном проверять диапазоны, чтобы не заблокировать кого лишнего.
Для этого был сделан скрипт на Python, который проверяет список с использованием GeoLite2-Country.mmdb.
Вначале скрипт был написан на Perl, но оказалось что перл не особенно качественно работает с MMDB и происходит проверка крайне медленно. Так что было решено провести трансфер в питона, который немедленно встал и начал что ли шипеть, причём громко.
Применяется скрипт спокойно из Power Shell или даже обычного cmd. Программист даже восрал полноценный прогресс-бар!
Исходный код[править]
#!/usr/bin/env python3
import sys
import maxminddb
if len(sys.argv) < 3:
print("Usage: python filter_clean.py input_ranges.txt GeoLite2-Country.mmdb > clean_ranges.txt", file=sys.stderr)
sys.exit(1)
input_file = sys.argv[1]
mmdb_file = sys.argv[2]
forbidden_countries = {'RU', 'BY', 'UA'}
print("Loading GeoIP database...", file=sys.stderr)
reader = maxminddb.open_database(mmdb_file)
# ====================== Count total ranges ======================
print("Counting valid /16 ranges...", file=sys.stderr)
total = 0
with open(input_file, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line and line.endswith('/16'):
base = line.split('/')[0]
if base.count('.') == 3 and base.endswith('.0.0'):
total += 1
print(f"Found {total} valid /16 ranges to process.\n", file=sys.stderr)
if total == 0:
print("No valid ranges found.", file=sys.stderr)
sys.exit(0)
# ====================== Process with live progress ======================
clean_count = 0
processed = 0
with open(input_file, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if not line or not line.endswith('/16'):
continue
base = line.split('/')[0]
if not (base.count('.') == 3 and base.endswith('.0.0')):
continue
try:
o1, o2, _, _ = map(int, base.split('.'))
except:
continue
processed += 1
has_forbidden = False
for third_octet in range(256):
test_ip = f"{o1}.{o2}.{third_octet}.1"
try:
data = reader.get(test_ip)
if data and isinstance(data, dict):
iso_code = data.get('country', {}).get('iso_code')
if iso_code in forbidden_countries:
has_forbidden = True
break
except:
pass # rare lookup error, treat as safe
# Output only clean ranges
# if not has_forbidden:
if not has_forbidden:
print(line)
clean_count += 1
# Live progress bar (updates on same line)
percent = int(100 * processed / total)
bar_width = 50
filled = int(bar_width * processed / total)
bar = '#' * filled + '-' * (bar_width - filled)
print(f"\rProgress: [{bar}] {percent:3d}% ({processed}/{total}) | Clean: {clean_count}",
end='', file=sys.stderr, flush=True)
reader.close()
print("\n\nDone!", file=sys.stderr)
print(f"Processed {processed}/{total} ranges", file=sys.stderr)
print(f"Found {clean_count} clean /16 ranges (no IPs from RU/BY/UA/KZ/UZ)", file=sys.stderr)