From 8fbe5e165b64db1c52a06ca36ca0348b4c5fdcbb Mon Sep 17 00:00:00 2001 From: sirmrak Date: Thu, 13 Aug 2026 20:40:09 +0300 Subject: [PATCH] Update get_vpn.py --- get_vpn.py | 123 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 28 deletions(-) diff --git a/get_vpn.py b/get_vpn.py index 83e0258..abf0cc8 100644 --- a/get_vpn.py +++ b/get_vpn.py @@ -3,62 +3,129 @@ import sys import requests -def fetch_clash_config(): - # Получаем ссылку-подписку из секретов Gitea/GitHub +def fetch_and_prepare_configs(): + # Забираем ссылку из секретов Gitea/GitHub sub_url = os.getenv("VPN_SUB_URL") if not sub_url: print("Ошибка: Переменная окружения VPN_SUB_URL не задана!") sys.exit(1) - # Имитируем заголовки оригинального клиента OpenClash / Mihomo + # Имитируем заголовки оригинального ядра Mihomo (Clash.Meta) для OpenClash headers = { - "User-Agent": "Clash.meta; mihomo; OpenClash", - "Accept": "*/*", + "User-Agent": "Mihomo/1.18.3 Clash.Meta OpenClash", + "Accept": "application/yaml, text/yaml, */*", + "Connection": "keep-alive", } - # На всякий случай проверяем, есть ли уже в ссылке флаг клиента. - # Если нет — панель может проигнорировать User-Agent, поэтому добавляем флаг принудительно. + # Принудительно заставляем панель выдать мета-конфиг if "flag=" not in sub_url: separator = "&" if "?" in sub_url else "?" - sub_url += f"{separator}flag=clash" + sub_url += f"{separator}flag=meta" try: - print("Отправка запроса к серверу VPN с заголовками Clash...") + print("Отправка запроса к серверу VPN...") response = requests.get(sub_url, headers=headers, timeout=20) if response.status_code != 200: print( - f"Ошибка сервера: Статус {response.status_code}. Проверьте ссылку." + f"Ошибка сервера: Статус {response.status_code}. Проверьте ссылку-подписку." ) sys.exit(1) - content = response.text.strip() + raw_content = response.text.strip() - # Проверяем, что сервер вернул именно YAML-подобную структуру, а не ошибку JSON - if "proxies:" in content or "proxy-groups:" in content: - print("Успешно получен готовый Clash-конфиг от сервера!") + # Проверяем, что в ответе реально есть сервера + if "proxies:" not in raw_content: + print( + "Ошибка: Сервер вернул YAML, но в нём отсутствует блок нод 'proxies:'." + ) + sys.exit(1) - # Сохраняем результат в файл - output_file = "clash.yaml" - with open(output_file, "w", encoding="utf-8") as f: - f.write(content) + # ФАЙЛ 1: Сохраняем оригинальный чистый конфиг от провайдера + with open("clash.yaml", "w", encoding="utf-8") as f: + f.write(raw_content) + print("Оригинальный конфиг успешно сохранен в clash.yaml") - print(f"Конфигурация сохранена в файл: {output_file}") + # ФАЙЛ 2: Создаем модифицированный конфиг для раздельного обхода + # Переводим режим работы в rule (по правилам) вместо global (весь трафик) + split_content = raw_content.replace("mode: global", "mode: rule") + + if "rules:" in split_content: + # Отрезаем старые правила провайдера (всё, что после 'rules:') + base_part = split_content.split("rules:")[0] + + # Формируем огромный расширенный список правил с разделением трафика + advanced_rules = """rules: + # 1. Локальные адреса и домашняя сеть (в обход VPN) + - DOMAIN-SUFFIX,local,DIRECT + - IP-CIDR,127.0.0.0/8,DIRECT + - IP-CIDR,172.16.0.0/12,DIRECT + - IP-CIDR,192.168.0.0/16,DIRECT + - IP-CIDR,10.0.0.0/8,DIRECT + - IP-CIDR,198.18.0.0/16,DIRECT + + # 2. Популярные заблокированные ресурсы и сервисы (через VPN) + - GEOSITE,onion,→ Remnawave + - GEOSITE,twitter,→ Remnawave + - GEOSITE,instagram,→ Remnawave + - GEOSITE,facebook,→ Remnawave + - GEOSITE,meta,→ Remnawave + - GEOSITE,youtube,→ Remnawave + - GEOSITE,netflix,→ Remnawave + - GEOSITE,openai,→ Remnawave + - GEOSITE,chatgpt,→ Remnawave + - GEOSITE,discord,→ Remnawave + - GEOSITE,protonmail,→ Remnawave + - GEOSITE,intel,→ Remnawave + - GEOSITE,amd,→ Remnawave + - GEOSITE,nvidia,→ Remnawave + - GEOSITE,spotify,→ Remnawave + - GEOSITE,linkedin,→ Remnawave + - GEOSITE,rutracker,→ Remnawave + - GEOSITE,notion,→ Remnawave + - GEOSITE,docker,→ Remnawave + - GEOSITE,medium,→ Remnawave + - GEOSITE,behance,→ Remnawave + - GEOSITE,pinterest,→ Remnawave + - GEOSITE,canva,→ Remnawave + - GEOSITE,epicgames,→ Remnawave + + # 3. Весь остальной зарубежный контент (по желанию, через VPN) + - GEOSITE,geolocation-!cn,→ Remnawave + + # 4. Российские государственные сайты, банки и крупные ресурсы (напрямую, без VPN) + - GEOSITE,win-russia,DIRECT + - GEOSITE,category-gov-ru,DIRECT + - GEOSITE,ru,DIRECT + - GEOSITE,yandex,DIRECT + - GEOSITE,vk,DIRECT + - GEOSITE,mailru,DIRECT + - GEOSITE,sberbank,DIRECT + - GEOSITE,tinkoff,DIRECT + - GEOSITE,kinopoisk,DIRECT + - GEOSITE,avito,DIRECT + - GEOIP,RU,DIRECT + + # 5. Финальное замыкающее правило: всё, что не подошло под списки выше, идет НАПРЯМУЮ + - MATCH,DIRECT +""" + # Склеиваем настройки и новые правила + full_split_yaml = base_part + advanced_rules + + with open("clash_split.yaml", "w", encoding="utf-8") as f: + f.write(full_split_yaml) + print("Раздельный конфиг успешно сохранен в clash_split.yaml") else: - print("Предупреждение: Сервер вернул ответ, но он не похож на Clash YAML.") - print("Первые 200 символов ответа для отладки:") - print(content[:200]) - - # Сохраняем как есть, чтобы вы могли посмотреть, что пришло - with open("response_debug.txt", "w", encoding="utf-8") as f: - f.write(content) + print( + "Ошибка: В исходном конфиге не найдена секция rules: для замены!" + ) sys.exit(1) except Exception as e: - print(f"Критическая ошибка при запросе: {e}") + print(f"Критическая ошибка во время выполнения: {e}") sys.exit(1) if __name__ == "__main__": - fetch_clash_config() + fetch_and_prepare_configs()