Импортированные правила
Импортированные правила
Категория: Программы Теги: антивирус , вирус Опубликовано: 8 марта 2025

Скрипт для парсинга списков IP и ручного импорта в simplewall

Для обеспечения информационной безопасности необходимо блокировать взаимодействие с потенциально опасными IP-адресами, но антивирусы и межсетевые экраны обладают скудными списками, так как они включают туда только то, что сами проанализировали, а между тем, существует множество общедоступных списков потенциально опасных IP-адресов (подробнее про такие списки тут).

В данной статье расскажу как можно частично автоматизировать, а именно парсить списки, экспортировать текущие настройки свободного сетевого экрана simplewall и с сохранением текущих настроек импортировать новый набор правил, при этом предыдущие добавленные скриптом будут удалены, чтобы держать списки актуальными.

simplewall работает только под операционной системой Windows и подробнее про него можно прочитать по адресу континентсвободы.рф/simplewall-setevoj-ekran-dlya-windows/, а так же скачать.

Предварительно нужно открыть simplewall и в нем файл\экспорт. 

Экспортированный файл profile.xml необходимо поместить вместе с нашим скриптом, назовем его IP-XML.py.

Вот код нашего скрипта:

# -*- coding: utf-8 -*-
"""
Created on Sat Mar  8 18:31:48 2025

@author: Алексей Черемных https://alekseycheremnykh.ru/
"""

import requests
import ipaddress
from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement, tostring
from xml.dom import minidom
import time
import os

urls = [
    "https://feodotracker.abuse.ch/downloads/ipblocklist_recommended.txt",
    "https://sslbl.abuse.ch/blacklist/sslipblacklist.txt",
    "https://cinsarmy.com/list/ci-badguys.txt",
    "https://raw.githubusercontent.com/firehol/blocklist-ipsets/refs/heads/master/et_compromised.ipset"
]


def fetch_ips_from_url(url):
    """Загружает список IP-адресов и диапазонов из URL."""
    try:
        response = requests.get(url)
        response.raise_for_status()  # Raises HTTPError for bad responses (4XX, 5XX)
        return response.text.splitlines()
    except requests.exceptions.RequestException as e:
        print(f"Ошибка при загрузке {url}: {e}")
        return []

def clean_and_extract_ips(lines):
    """Очищает строки и извлекает IP-адреса и диапазоны."""
    ips = []
    for line in lines:
        line = line.strip()
        if not line or line.startswith("#") or "Spamhaus" in line or "Last-Modified" in line or "Expires" in line:
            continue

        # Разделяем строку по символу ';' и берем первую часть
        parts = line.split(";")
        ip_or_range = parts[0].strip()

        try:
            # Пробуем распарсить как IP-адрес или диапазон
            if "/" in ip_or_range:
                # Это CIDR диапазон
                network = ipaddress.ip_network(ip_or_range, strict=False)
                # Добавляем все IP-адреса из диапазона (кроме адреса сети и широковещательного адреса)
                ips.append(str(network))
                #for ip in network.hosts():
                #    ips.append(str(ip))
            else:
                # Это одиночный IP-адрес
                ipaddress.ip_address(ip_or_range)
                ips.append(ip_or_range)
        except ValueError:
            # Если не удалось распарсить, игнорируем строку
            print(f"Неверный формат IP: {line}")
            continue
    return ips

def create_simplewall_xml(url_ip_dict, existing_xml_root=None):
    """Создает XML-файл для Simplewall."""
    if existing_xml_root is None:
        root = Element("root")
        root.set("version", "5")
        root.set("type", "3")
        root.set("timestamp", str(int(time.time())))

        apps = SubElement(root, "apps")
        rules_custom = SubElement(root, "rules_custom")
        root.append(rules_custom)  # Добавляем rules_custom в root
        rules_config = SubElement(root, "rules_config")
    else:
        root = existing_xml_root
        rules_custom = root.find("rules_custom")
        if rules_custom is None:
            rules_custom = SubElement(root, "rules_custom")
            root.append(rules_custom)

    # Если есть существующий XML, удаляем правила с comment="IP from external list"
    if existing_xml_root is not None:
        for item in list(rules_custom): # Итерируемся по копии списка, чтобы можно было удалять элементы
            if item.get("comment") == "IP from external list":
                rules_custom.remove(item)  # Удаляем правило, если comment="IP from external list"

    # Добавляем правила для каждого URL, разбивая на части по 10 IP-адресов
    for url, ips in url_ip_dict.items():
        for i in range(0, len(ips), 10):
            ip_subset = ips[i:i + 10]
            ip_string = ";".join(ip_subset) + ";"  # Объединяем IP-адреса в строку, разделенную точкой с запятой
            item = SubElement(rules_custom, "item")
            item.set("name", f"Block IPs from {url} (part {i//10 + 1})")  # Имя правила
            item.set("rule", ip_string)  # IP-адреса из URL
            item.set("comment", "IP from external list")  # Комментарий
            item.set("dir", "2")
            item.set("is_block", "true") # Блокировать
            item.set("is_enabled", "true")

    # Преобразуем ElementTree в строку с форматированием
    xml_string = tostring(root, encoding='utf8', method='xml')
    dom = minidom.parseString(xml_string)
    pretty_xml = dom.toprettyxml(indent="  ")

    return pretty_xml

def main():
    """Основная функция."""
    # urls = [
    #     "https://rules.emergingthreats.net/blockrules/compromised-ips.txt",
    #     "https://www.spamhaus.org/drop/drop.txt",
    # ]

    url_ip_dict = {}  # Словарь для хранения IP-адресов для каждого URL
    for url in urls:
        lines = fetch_ips_from_url(url)
        if lines:
            url_ip_dict[url] = clean_and_extract_ips(lines)

    # Читаем существующий XML-файл (если он есть)
    existing_xml_root = None
    if os.path.exists("profile.xml"):
        try:
            tree = ElementTree.parse("profile.xml")
            existing_xml_root = tree.getroot()
        except Exception as e:
            print(f"Ошибка при чтении profile.xml: {e}")

    # Создаем XML
    xml_content = create_simplewall_xml(url_ip_dict, existing_xml_root)

    # Сохраняем в файл
    with open("simplewall_ips.xml", "w", encoding="utf-8") as f:
        f.write(xml_content)

    print("XML-файл simplewall_ips.xml успешно создан.")

if __name__ == "__main__":
    main()
    

Скрипт генерирует файл simplewall_ips.xml, который можно импортировать в simplewall при помощи файл\импорт.

Ве правила, которые были ранее добавлены при помощи данного скрипта будут удалены, а благодаря строке item.set("dir", "2") направление будет любое.

Импортированные правила в simplewall

В начале скрипта есть переменная urls, в которой содержаться списки. Просто добавьте туда их в формате urls = ["первый список", "второй список"]. 

Также списки можно поискать на iplists[.]firehol[.]org.

Сразу хочу предупредить, что данное решение я толком не тестировал и не могу гарантировать, что оно не будет сжирать ваши ресурсы.

Алексей Черемных
80