Безопасная отладка для производственных JVM
У нас есть некоторые приложения, которые иногда попадают в плохое состояние, но только в производстве (конечно!). Хотя получение дампа кучи может помочь собрать информацию о состоянии, часто проще использовать удаленный отладчик. Настроить это легко - нужно только добавить это в его командную строку:
-Xdebug -Xrunjdwp: transport = dt_socket, server = y, suspend = n, address = PORT
Похоже, что нет никакого доступного механизма безопасности, поэтому включение отладки в производство эффективно разрешит выполнение произвольного кода (через горячую замену).
У нас есть смесь 1.4.2 и 1.5 Sun JVM, работающих на Solaris 9 и Linux (Redhat Enterprise 4). Как мы можем включить безопасную отладку? Есть ли другие способы достичь нашей цели проверки производственных серверов?
Обновление: для JVK JDK 1.5+ можно указать интерфейс и порт, к которому должен быть привязан отладчик. Таким образом, предложение KarlP о привязке к loopback и просто использовании SSH-туннеля к локальному блоку разработчика должно работать, если SSH правильно настроен на серверах.
Однако кажется, что JDK1.4x не позволяет указывать интерфейс для порта отладки. Итак, мы можем либо заблокировать доступ к порту отладки где-нибудь в сети, либо сделать какую-то системную блокировку в самой ОС (IPChains, как предложил Джаред, и т. Д.)?
Обновление № 2: это хак, который позволит нам ограничить наш риск, даже на 1.4.2 JVM:
Параметры командной строки:
-Xdebug
-Xrunjdwp:
transport=dt_socket,
server=y,
suspend=n,
address=9001,
onthrow=com.whatever.TurnOnDebuggerException,
launch=nothing
Java-код для включения отладчика:
try {
throw new TurnOnDebuggerException();
} catch (TurnOnDebugger td) {
//Nothing
}
TurnOnDebuggerException может быть любым исключением, которое гарантированно не будет выброшено где-либо еще.
Я проверил это на Windows-боксе, чтобы доказать, что (1) порт отладчика не получает соединения изначально, и (2) выдает исключение TurnOnDebugger, как показано выше, вызывает оживление отладчика. Параметр запуска был обязательным (по крайней мере, в JDK1.4.2), но JVM изящно обрабатывал значение мусора.
Мы планируем создать небольшой сервлет, который при соответствующей безопасности может позволить нам включить отладчик. Конечно, потом его нельзя отключить, и отладчик все равно беспорядочно прислушивается. Но это ограничения, которые мы готовы принять, поскольку отладка производственной системы всегда приводит к перезапуску.
Обновление № 3: я закончил писать три класса: (1) TurnOnDebuggerException, обычное исключение Java, (2) DebuggerPoller, фоновый поток проверяет наличие указанного файла в файловой системе и (3) DebuggerMainWrapper, класс, который запускает поток опроса и затем рефлексивно вызывает метод main другого указанного класса.
Вот как это используется:
- Замените свой "основной" класс на DebuggerMainWrapper в ваших сценариях запуска
- Добавьте два системных (-D) параметра, один из которых задает реальный основной класс, а другой - файл в файловой системе.
- Настройте отладчик в командной строке, добавив часть onthrow=com.whwhat.TurnOnDebuggerException
- Добавьте банку с тремя упомянутыми выше классами в путь к классам.
Теперь, когда вы запускаете свою JVM, все то же самое, за исключением того, что запускается фоновый поток. Предполагая, что файл (наш называется TurnOnDebugger) изначально не существует, он проверяет его каждые N секунд. Когда поллер впервые замечает это, он выдает и сразу же ловит исключение TurnOnDebuggerException. Затем агент стартует.
Вы не можете выключить его, и машина не очень защищена, когда включена. С другой стороны, я не думаю, что отладчик допускает несколько одновременных соединений, поэтому поддержание отладочного соединения - ваша лучшая защита. Мы выбрали метод уведомления о файлах, потому что он позволил нам воспользоваться нашим существующим Unix-автором / автором, указав файл триггера в каталоге, где права имеют только правильные пользователи. Вы можете легко создать небольшой файл войны, который достиг той же цели через соединение через сокет. Конечно, поскольку мы не можем отключить отладчик, мы будем использовать его только для сбора данных перед тем, как завершить работу некорректного приложения. Если кто-то хочет этот код, пожалуйста, дайте мне знать. Однако вам понадобится всего несколько минут, чтобы собрать все вместе.
4 ответа
Если вы используете SSH, вы можете разрешить туннелирование и туннелирование порта на ваш локальный хост. Никакой разработки не требуется, все сделано с использованием sshd, ssh и / или putty.
Сокет отладки на вашем Java-сервере может быть настроен на локальном интерфейсе 127.0.0.1.
Вы абсолютно правы: API отладки Java по своей природе небезопасен. Однако вы можете ограничить его сокетами домена UNIX и написать прокси-сервер с SSL/SSH, чтобы позволить вам проверять подлинность и шифровать внешние соединения, которые затем перенаправляются в сокет домена UNIX. Это по крайней мере уменьшает вашу подверженность тому, кто может получить процесс на сервере, или тому, кто может взломать ваш SSL.
Экспортируйте информацию / сервисы в JMX, а затем используйте RMI+SSL для удаленного доступа к нему. Ваша ситуация - это то, для чего предназначен JMX (M обозначает Управление).
Хороший вопрос.
Я не знаю какой-либо встроенной возможности для шифрования соединений с портом отладки.
Там может быть гораздо лучшее / простое решение, но я бы сделал следующее:
- Поместите производственную машину за брандмауэр, который блокирует доступ к портам отладки.
- Запустите прокси-процесс на самом хосте, который подключается к порту и шифрует ввод и вывод из сокета.
- Запустите прокси-клиент на рабочей станции отладки, которая также шифрует / дешифрует ввод. Имейте это, соединяются с прокси сервера. Связь между ними будет зашифрована.
- Подключите ваш отладчик к прокси-клиенту.