Поднять или починить браузер на машине пользователя через обратный туннель - когда нужен домашний IP или логин пользователя. Не обычная работа с браузером - `rules/agent-browser.md`.
Installs into .claude/skills of the current project.
Are you the author of Agent Browser?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/dewil-agent-browser)
---
name: agent-browser
description: Поднять или починить браузер на машине пользователя через обратный туннель - когда нужен домашний IP или логин пользователя. Не обычная работа с браузером - `rules/agent-browser.md`.
---
# agent-browser: браузер по требованию на машине пользователя
Скилл развертывания и починки. Повседневные правила работы с браузером (какую площадку выбрать, гигиена, гонка общего окна, диагностика симптомов) - `rules/agent-browser.md`; сюда ходят, когда схемы на устройстве еще нет или она сломалась.
## Зачем схема
Два ресурса, которых нет у серверного headless Chrome:
- **домашний IP** - когда сайт режет трафик дата-центров по адресу. Прежде чем разворачивать схему ради этого, проверить, что фильтр действительно по адресу, а не по заголовку клиента: порядок проверки - в `rules/agent-browser.md`, раздел "Сайт не отдает контент";
- **живые сессии пользователя** - сайты, привязывающие логин к устройству и IP (LinkedIn), при переносе кук на сервер дают checkpoint или тихий разлогин.
Банк, госуслуги и почта восстановления запрещены в агентском профиле: это работа человека в обычном браузере. См. [ограничение в rules/agent-browser.md](../../rules/agent-browser.md), раздел "Что этот канал не защищает".
## Из чего состоит
На машине пользователя постоянно живет только `autossh` с обратным туннелем на сервер; браузер поднимается по требованию и гасится после работы:
```
[машина пользователя] [Сервер]
autossh (постоянно) ──── SSH ───────────────▶ слушает 127.0.0.1:9222 (CDP)
-R 9222 -R 2222 слушает 127.0.0.1:2222 (управление)
│
chrome-ctl ◀──── forced command по ключу ◀──────────────┘
└─▶ Chrome (headless, отдельный профиль) - живет только на время задачи
```
Ключ управления ограничен forced command: по нему исполняется только `chrome-ctl start|start-gui|stop|status`, произвольные команды на машине пользователя по этому каналу невозможны.
**Чего эта граница не закрывает - понимать до развертывания.** Ограничен только SSH-канал; проброшенный порт CDP аутентификации не имеет вовсе - разбор в `rules/agent-browser.md`, раздел "Что этот канал не защищает".
Что из этого следует для развертывания: профиль агента - отдельный от личного (в схеме так и есть); порт CDP слушать строго на loopback (проверка `GatewayPorts` в ранбуке идет до поднятия туннеля) и дальше не пробрасывать; ключ туннеля - выделенный, с forced command (Шаг 5а ранбука).
## Установка
- **macOS** - пошаговый ранбук: `runbook-mac.md` (Remote Login, autossh через LaunchAgent, chrome-ctl, forced command, сторож простоя, проверка с обеих сторон).
- **Linux** - пошаговый ранбук: `runbook-linux.md` (проверено на Ubuntu 24.04): systemd-юнит вместо LaunchAgent, Chrome из репозитория Google, `DISPLAY`/`XAUTHORITY` для режима с окном, сторож простоя на systemd timer. Разбор решений не дублируется - ранбук ссылается на macOS-версию.
- **Windows** - готового ранбука нет; разворачивать по аналогии, после отладки оформить ранбук и поднять в канон.
**Выход через домашний прокси - отдельная задача от развертывания браузера.** Если нужен не компьютер пользователя, а только его адрес, браузер остается серверным, а на домашней машине поднимается прокси-клиент, чей порт пробрасывается тем же обратным туннелем (`-R 127.0.0.1:<PROXY_PORT>:127.0.0.1:<локальный порт прокси>` - адрес в левой части обязателен по той же причине, что и у портов CDP и управления: без него при серверном `GatewayPorts clientspecified` порт уйдет слушать наружу). После подъема сверить `ss -tlnp` на `<PROXY_PORT>` - адрес обязан быть `127.0.0.1`. Два места, где это легко забыть: порт надо разрешить в ключе туннеля (`permitlisten="127.0.0.1:<PROXY_PORT>"` - иначе `ExitOnForwardFailure=yes` уронит **весь** туннель вместе с CDP и управляющим каналом, поэтому сперва правится ключ на сервере и только потом добавляется `-R`), и на сервере этот порт должен быть свободен - там может уже работать свой прокси-клиент. Правка `authorized_keys` - изменение доступа: готовь точную команду и показывай ее пользователю, а не рассчитывай провести схему целиком сам. На части конфигураций она агенту вообще не дана, и тогда схема, где новый порт нужен "прямо сейчас", упрется в человека - это надо учитывать в плане, а не обнаруживать на середине. Дальше браузер стартует с `--proxy-server=http://127.0.0.1:<PROXY_PORT>`; выбор маршрута и обязательная проверка выхода - в `rules/agent-browser.md`.
**Несколько машин на одном сервере.** Порты `9222`/`2222` занимает та машина, которую развернули первой, и это не про Linux - вторая macOS упрется точно так же. Перед развертыванием проверить занятость на сервере (`ss -tln | grep -E ":(9222|2222)\b"`) и при необходимости взять следующую свободную пару, подставив ее везде: в `chrome-ctl`, в `-R` автозапуска, в `permitlisten` ключа туннеля, в проверках. Ключи и forced command у каждой машины свои, поэтому схемы сосуществуют без конфликтов.
## Бэкап сессий
Жесткое завершение браузера теряет куки текущего сеанса - для сайтов с ротацией токена это потеря логина и ручной заход владельца. Канонический `scripts/chrome-cookies.py` (stdlib, CDP по голым сокетам) снимает куки живой сессии и заливает их обратно без GUI:
```bash
python3 scripts/chrome-cookies.py dump --port <CDP_PORT> --domain linkedin.com --require-cookie li_at
python3 scripts/chrome-cookies.py list
python3 scripts/chrome-cookies.py restore --port <CDP_PORT> --in ~/.config/browser-sessions/linkedin.com.json
```
**`--port` указывать явно, когда машин больше одной.** Дефолт скрипта - `9222`, и он достается той машине, которую развернули первой. Забытый флаг подключит `dump` к чужому браузеру. Если существующий бэкап содержит метку другого профиля, скрипт откажет в перезаписи (без `--force`). Для первого дампа и бэкапа без метки источника сравнивать профили не с чем, поэтому порт нужно проверять явно.
Проверка `--require-cookie` и сохранение дампа - по [rules/agent-browser.md](../../rules/agent-browser.md).
**Дамп кук - секрет, эквивалент пароля** (`rules/secrets-handling.md`): хранилище `~/.config/browser-sessions/` живет вне репозитория и вне синкаемых папок, права 600 выставляет сам скрипт, содержимое в чат и артефакты не выводится. Порядок: сразу после первичного GUI-логина владельца - `dump`; при слете сессии - `restore`, и только если сайт инвалидировал токен на своей стороне - снова звать владельца.
## Границы
- Машина пользователя выключена или спит - браузера нет; это осознанная плата за домашний IP.
- Скилл не занимается выбором площадки на конкретную задачу и не учит пользоваться браузером - это правило `rules/agent-browser.md`.