Иногда нужно дёрнуть команду на сервере по HTTP: из системы автоматизации, из скрипта на другой машине, из пайплайна. Поднимать ради этого Python-сервис с фреймворком — избыточно. Так появился http2shell — HTTP API-сервер, написанный целиком на Bash.

Зачем

Я автоматизировал процессы bug bounty в n8n и упёрся в ограничение: n8n не сохраняет вывод shell-команд больше 1 МБ. Для инструментов разведки, которые выдают мегабайты поддоменов и URL, это критично. Решение — вынести выполнение команд в отдельный HTTP-сервис и забирать результат обычным HTTP-запросом.

Идея вдохновлена статьёй на Хабре о HTTP-сервере на Bash; я развил её в инструмент с аутентификацией, своими эндпоинтами и таймаутами.

Возможности

  • чистый Bash, без фреймворков;
  • HTTP Basic Authentication;
  • встроенные эндпоинты с информацией о системе;
  • выполнение произвольных команд (можно отключить);
  • свои эндпоинты: URI → команда;
  • системный shell по умолчанию или любой указанный;
  • таймауты на выполнение команды и на чтение тела запроса;
  • цветные логи (отключаются).

Зависимости минимальные: bash, socat, jq, timeout, dd, sha256sum и стандартные утилиты.

Установка и запуск

apt install socat jq          # Debian/Ubuntu
git clone https://github.com/solo10010/http2shell.git
cd http2shell
chmod +x http2shell.sh
./http2shell.sh

По умолчанию сервер слушает 127.0.0.1:8007, Basic Auth rest:api (поменяйте!), эндпоинт /exec включён.

Параметры

-ip, --ip <ip>                  адрес (по умолчанию 127.0.0.1)
-port, --port <port>            порт (по умолчанию 8007)
-u, --user / -p, --pass         логин и пароль Basic Auth
-s, --shell <path>              shell для выполнения команд
--no-exec                       отключить /exec и /execf
-e, --endpoint <uri> <command>  добавить свой POST-эндпоинт
--cmd-timeout <sec>             таймаут выполнения (по умолчанию 20)
--body-timeout <sec>            таймаут чтения тела запроса (по умолчанию 10)
--no-color                      без цветных логов

Примеры

Системная информация:

curl -u user:pass http://127.0.0.1:8007/api/uptime
curl -u user:pass http://127.0.0.1:8007/api/disk

Выполнение команды:

curl -u user:pass -X POST http://127.0.0.1:8007/exec -d "id"

Свой эндпоинт вместо произвольного выполнения — предпочтительный вариант:

./http2shell.sh --no-exec --endpoint /api/procs "ps aux"
curl -u user:pass -X POST http://127.0.0.1:8007/api/procs

Использование в n8n

В n8n это обычная нода HTTP Request:

  • метод POST;
  • URL — адрес http2shell и эндпоинт (/exec или свой);
  • аутентификация — Basic Auth;
  • тело — команда в виде текста.

Ответ приходит как обычный HTTP-ответ, без ограничения на 1 МБ, и дальше обрабатывается в workflow.

Безопасность — важнее всего

Сервис, выполняющий команды по HTTP, — это по определению удалённое выполнение кода. Поэтому:

  • никогда не выставляйте http2shell в интернет. Только 127.0.0.1 или внутренняя сеть / VPN;
  • смените логин и пароль по умолчанию;
  • отключите /exec (--no-exec) и используйте только заранее заданные эндпоинты с фиксированными командами;
  • запускайте от непривилегированного пользователя, не от root;
  • Basic Auth передаёт пароль открытым текстом — если трафик идёт не по localhost, ставьте перед сервисом обратный прокси с TLS;
  • ограничьте доступ файрволом.

Инструмент создавался для внутренней автоматизации, DevOps-задач, учебных лабораторий и CTF — именно в таких сценариях он и уместен.

Итоги

http2shell показывает, что для простых задач не обязательно тянуть фреймворк: Bash и socat позволяют за несколько сотен строк сделать работающий HTTP API. А главный урок — любой «удобный способ выполнить команду удалённо» должен проектироваться сразу с ограничениями доступа, иначе он станет чужим бэкдором.