Robin Proxy Bridge
WordPress-мост: разворачивает исходящие запросы Robin Image Optimizer на собственный обратный прокси через pre_http_request, не изменяя код плагина
by boris0024 · github.com/boris0024/robin-proxy-bridge · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/boris0024/robin-proxy-bridge/archive/refs/heads/main.zipПлагин WordPress, который разворачивает исходящие запросы Robin Image Optimizer на ваш собственный обратный прокси.
Нужен в одной ситуации: плагин установлен, настроен и работает, но его API (dashboard.robinoptimizer.com) недоступно с вашего сервера. Картинки не жмутся, WebP не создаётся, а в логах плагина висят неудачные запросы.
Обычные пути решения плохие: форкать чужой плагин больно на каждом обновлении, менять оптимизатор дорого, если библиотека уже обработана наполовину. Этот мост не трогает код Robin вообще.
Как это работает
WordPress пропускает все исходящие HTTP-запросы через свой HTTP API, а тот даёт фильтр pre_http_request, который срабатывает до отправки. Плагин ловит запрос, подменяет адрес и выполняет его сам.
Три точки перехвата:
pre_http_request- запрос к API оптимизатора разворачивается на прокси.http_response- в теле ответа переписываются ссылки на скачивание результата. Бесплатный тариф Robin отдаёт JSON со ссылкой на готовый файл, и без подмены плагин пошёл бы за ним напрямую, снова в недоступный хост.http_api_curl- точечно отключает проверку сертификата, если прокси работает на самоподписанном (по умолчанию проверка включена).
Приём универсальный. Замените хост через фильтр rpb_target_host, и тот же мост будет работать для любого плагина, который ходит в недоступный сервис через WP HTTP API:
add_filter( 'rpb_target_host', function () {
return 'api.example-service.com';
} );
Почему не WP_PROXY_HOST
В WordPress есть встроенная поддержка прокси через константы в wp-config.php. Она не подходит по трём причинам:
- через прокси пойдут все запросы WordPress: обновления ядра, тем, других плагинов, а
WP_PROXY_BYPASS_HOSTSэто список исключений, а не белый список; - нужен полноценный прямой прокси (squid, 3proxy), то есть отдельный демон, который придётся закрывать от посторонних;
- здесь используется обратный прокси на nginx, который умеет ходить ровно к одному хосту и прячется за секретным путём.
Установка
1. Прокси на сервере, с которого API доступно
Возьмите nginx/robin-proxy.conf, замените плейсхолдеры и подключите:
cp nginx/robin-proxy.conf /etc/nginx/sites-available/robin-proxy
# сгенерируйте свой секретный путь:
echo "rp_$(openssl rand -hex 16)"
# впишите его, IP вашего сайта в allow и пути к сертификатам
ln -s /etc/nginx/sites-available/robin-proxy /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Строку limit_req_zone нужно положить в nginx.conf, в блок http:
limit_req_zone $binary_remote_addr zone=robin_proxy_limit:1m rate=10r/s;
2. Плагин на сайте
Скопируйте папку в wp-content/plugins/robin-proxy-bridge, активируйте, откройте Настройки → Robin Proxy Bridge:
- включите прокси;
- впишите полный адрес вместе с секретным путём:
https://proxy.example.com:8443/rp_ваш_секрет; - оставьте проверку сертификата включённой, если у прокси нормальный сертификат;
- нажмите «Проверить прокси».
Ответ с любым кодом кроме 404 означает, что туннель работает. Код 404 обычно значит, что секретный путь в настройках не совпадает с location в nginx.
Обновление с версии 1.0.0
В 1.0.0 проверка TLS-сертификата была отключена жёстко, в 1.1.0 она стала настройкой и включена по умолчанию.
Если ваш прокси работает на самоподписанном сертификате, сразу после обновления запросы начнут падать:
cURL error 60: SSL certificate problem: self-signed certificate
Лечится одним из двух способов:
- выпустить нормальный сертификат Let's Encrypt на домен прокси (правильный путь);
- снять галку «Проверять сертификат» в настройках плагина.
Безопасность
Прочитайте, прежде чем поднимать это в продакшене.
- Закрывайте прокси по IP.
allow <IP сайта>; deny all;в конфиге это главный рубеж. Открытый порт находят сканеры: на боевом сервере за сутки набегает больше сотни посторонних запросов. - Секретный путь это секрет. Он попадает в настройки WordPress, в бэкапы базы и, что неприятнее, в логи самого Robin Image Optimizer открытым текстом, потому что тот пишет полный URL скачивания. Кто получил доступ к логам сайта, получил доступ к прокси.
- Не выключайте проверку сертификата без нужды. Через прокси идут файлы, а на платном тарифе ещё и ключ лицензии в заголовке
Authorization. Лучше выпустить Let's Encrypt на домен, чем жить с самоподписанным сертификатом. - Ротируйте секретный путь, если он мог утечь: поменяйте
locationв nginx и адрес в настройках плагина.
Проверено на
| Компонент | Версия |
|---|---|
| WordPress | 6.7.5 |
| Robin Image Optimizer | 2.0.5 |
| PHP | 8.3.31 |
| nginx | 1.22.1 и 1.31.1 |
Версия 1.1.0 проверена на боевой связке с реальным прокси: перехват запроса к API отдаёт HTTP 200 через прокси, ссылка на скачивание в ответе переписывается корректно, запросы к посторонним хостам (api.wordpress.org) остаются нетронутыми, а с включённой проверкой самоподписанного сертификата запрос ожидаемо падает с cURL error 60.
Результат на двух боевых сайтах: 7 684 изображения сконвертированы в WebP, 1 309.7 МБ оригиналов против 443.2 МБ WebP, то есть минус 66% веса картинок.
Что этот плагин не делает
Он не отдаёт WebP посетителям. Отдачей занимается сам Robin Image Optimizer: по умолчанию он подставляет теги <picture> в HTML через выходной буфер PHP. Режим отдачи средствами сервера у Robin реализован только для Apache через .htaccess, на nginx он в настройках недоступен. Этот мост решает другую задачу: доставить запрос до API, чтобы WebP вообще создался.
Лицензия
GPL-2.0-or-later, как и сам WordPress. См. LICENSE.
Проект не связан с разработчиками Robin Image Optimizer и не аффилирован с ними. Robin Image Optimizer распространяется по своей лицензии, его код в этот репозиторий не входит.