Бедолаги, наколякал такое добро для тех, кто устал покупать "секретный скрипт"
у очередного маркетного шамана. Оно запускается с вашего ПК, ходит в Yandex
Cloud API, крутит публичные IPv4 и останавливается, когда выпал адрес из ваших
target_ips или target_cidrs.
Форкайте, ломайте, чините, присылайте PR. Может, иногда буду обновлять. Может, буду просто смотреть, как сообщество снова воюет с JSON без запятых.
- Резервирует случайные статические IPv4 в Yandex Cloud.
- Проверяет адрес по списку нужных IP/CIDR.
- Неподходящие адреса удаляет.
- При лимитах умеет менять folder/cloud, если это включено.
- При успехе оставляет найденный адрес зарезервированным.
- Пишет логи в
run.log, состояние вstate.json. - Может отправить Telegram-уведомление.
- Может открыть сюрприз-видос, потому что страдать надо красиво.
Эти файлы должны жить только локально:
config.jsonsa-key.jsonstate.jsonrun.logrunner.*.log.env- любые
*.key,*.pem
Они уже в .gitignore. Если вы все равно запушили ключ в публичный репозиторий,
поздравляю: вы прошли обучение кибербезопасности методом лица об асфальт.
Удалите ключ в Yandex Cloud и создайте новый.
Нужен Python 3.9+.
python -m pip install PyJWT cryptographyСкопируйте пример конфига:
Copy-Item .\config.example.json .\config.jsonКлюч сервисного аккаунта положите рядом:
yc_ip_hunter/
yc_ip_hunter.py
config.json
sa-key.json
Открываем console.yandex.cloud. Дальше без магии, просто тыкаем нужные меню.
Это ID организации, в которой создаются cloud.
Как найти:
- В левом верхнем углу консоли нажмите на название организации.
- Откройте Cloud Center или страницу организации.
- Найдите строку Идентификатор.
- Скопируйте значение в
organization_id.
Выглядит примерно так:
"organization_id": "REPLACE_WITH_ORGANIZATION_ID"Если вы не видите организацию, значит вы либо не там, либо Яндекс снова решил сыграть в UX-квест. Ищите в верхней панели переключатель организации/облака.
Нужен, чтобы новые cloud можно было привязать к биллингу.
Как найти:
- В левом меню нажмите Биллинг.
- Откройте нужный платежный аккаунт.
- Найдите ID платежного аккаунта.
- Скопируйте его в
billing_account_id.
"billing_account_id": "REPLACE_WITH_BILLING_ACCOUNT_ID"Если биллинг не привязан, новые cloud могут создаваться, но ресурсы внутри будут падать с ошибками. Да, это тот самый момент, где полчаса жизни улетают в окно.
Это cloud, который нельзя удалять. В нем живет сервисный аккаунт, через который скрипт управляет остальными cloud.
Как найти:
- В списке облаков выберите ваше служебное облако.
- Под названием облака найдите ID.
- Скопируйте его в
service_cloud_id.
"service_cloud_id": "REPLACE_WITH_SERVICE_CLOUD_ID"Важно: это облако должно жить всегда. Удалите его - и скрипт останется без рук.
Создаем аккаунт, который будет делать всю грязную работу.
Как создать:
- Выберите служебное облако.
- Выберите каталог, обычно
default. - В левом меню откройте Identity and Access Management.
- Откройте Сервисные аккаунты.
- Нажмите Создать сервисный аккаунт.
- Назовите его, например
huntersa.
Минимально для folder mode:
adminна target cloud.
Для cloud/hybrid mode:
- права на организацию для создания cloud;
- права на billing account для привязки billing;
adminна создаваемые cloud/folder.
Самый простой путь для тех, кто не хочет читать IAM-доки:
- Откройте нужный ресурс: cloud или organization.
- Перейдите в Права доступа.
- Нажмите Добавить пользователя или Назначить роли.
- Выберите сервисный аккаунт
huntersa. - Добавьте роль
admin. - Сохраните.
Да, admin жирно. Да, можно тоньше. Нет, в гайде для бедолаг мы не будем
собирать IAM-мозаику из 14 ролей и трех молитв.
Это файл, через который скрипт авторизуется.
Как скачать:
- Откройте Identity and Access Management.
- Перейдите в Сервисные аккаунты.
- Откройте
huntersa. - Справа сверху нажмите Создать новый ключ.
- Выберите Создать авторизованный ключ.
- Скачайте JSON.
- Переименуйте файл в
sa-key.json. - Положите его рядом со скриптом.
В config.json должно быть:
"auth": {
"service_account_key_file": "sa-key.json",
"iam_token_env": "YC_IAM_TOKEN"
}Нужен только для rotation_mode: "folder".
Как найти:
- Откройте cloud, внутри которого хотите создавать временные folder.
- Под названием cloud скопируйте ID.
- Вставьте в
target_cloud_id.
"target_cloud_id": "REPLACE_WITH_TARGET_CLOUD_ID_FOR_FOLDER_MODE"Если используете hybrid или cloud, поле можно оставить плейсхолдером/пустым,
а рабочими будут organization_id, billing_account_id, service_cloud_id.
Базовый живой вариант для hybrid:
{
"dry_run": false,
"rotation_mode": "hybrid",
"organization_id": "ВАШ_ORGANIZATION_ID",
"billing_account_id": "ВАШ_BILLING_ACCOUNT_ID",
"service_cloud_id": "ВАШ_SERVICE_CLOUD_ID",
"auth": {
"service_account_key_file": "sa-key.json",
"iam_token_env": "YC_IAM_TOKEN"
},
"zone": "ru-central1-a",
"zones": ["ru-central1-a"],
"target_ips": [],
"target_cidrs": [
"84.201.188.0/23",
"84.201.184.0/22",
"84.201.128.0/18",
"158.160.0.0/16"
],
"max_iterations": 0,
"max_addresses_per_cloud": 9,
"max_parallel_clouds": 3,
"allow_delete_cloud": true,
"immediate_delete_cloud": true
}target_cidrs - это ваши нужные подсети. Хотите другие - меняйте. Скрипт
остановится только на том, что вы сами туда положили.
Создает новый folder внутри одного существующего cloud. Самый спокойный режим, но если лимиты душат на уровне cloud, будет грустно.
Создает новый cloud, привязывает billing, крутит IP, удаляет cloud при промахе. Жестче, но можно упереться в лимит cloud в организации.
Основной режим. Крутит адреса, при лимитах переходит к следующему cloud. Для текущего хаоса это самый рабочий вариант.
В config.json:
"notifications": {
"enabled": true,
"telegram": {
"enabled": true,
"bot_token_env": "TELEGRAM_BOT_TOKEN",
"chat_id": "ВАШ_CHAT_ID"
}
}Токен лучше хранить в переменной окружения:
$env:TELEGRAM_BOT_TOKEN="123456:ABCDEF..."Проверить:
python .\yc_ip_hunter.py --config .\config.json --test-telegramЕсли бот молчит, проверьте:
- токен бота;
chat_id;- что вы написали боту хотя бы одно сообщение;
run.log.
Сначала dry-run:
python .\yc_ip_hunter.py --config .\config.json --dry-runБоевой запуск:
python .\yc_ip_hunter.py --config .\config.json --run --yes-delete-cloudЕсли allow_delete_cloud: true, но вы забыли --yes-delete-cloud, скрипт
откажется удалять cloud. Это не баг, это защита от пользователей с быстрыми
пальцами и медленным осознанием.
В терминале и run.log появится:
TARGET MATCH: allocated IP ... is in configured target ranges.
После этого скрипт:
- сохраняет результат в
state.json; - не удаляет найденный address;
- отправляет Telegram, если включен;
- открывает сюрприз-видос;
- завершает работу с кодом
0.
Сервисному аккаунту не хватает прав на organization. Идите в организацию, Права доступа, добавляйте роль.
Не хватает прав на cloud/folder/VPC. Дайте сервисному аккаунту admin на cloud
или folder, где идет охота.
В организации забита квота cloud. Старые cloud могут висеть в удалении долго. Скрипт делает deep cleanup перед удалением, но внутреннюю очередь Яндекса за вас не победит.
Запустите:
python .\yc_ip_hunter.py --config .\config.json --test-telegramПотом смотрите run.log.
python -m unittest .\test_yc_ip_hunter.pyЭто утилита для управления собственными облачными ресурсами и проверки выделенных вам адресов. За лимиты, квоты, биллинг, удаленные cloud, внезапные расходы и прочие радости взрослой жизни отвечает тот, кто нажал Enter.