2009-05-28 6 views
16

Mamy pewne aplikacje, które czasami popadają w zły stan, ale tylko w produkcji (oczywiście!). Podczas wykonywania zrzutu sterty może pomóc w zbieraniu informacji o stanie, często łatwiej jest użyć zdalnego debuggera. Ustawienie to jest prosta - Wystarczy tylko dodać to do jego linii poleceń:Bezpieczne debugowanie dla maszyn produkcyjnych JVM

-Xdebug -Xrunjdwp: transport = dt_socket, server = y, zawiesić = n, address = PORT

Wydaje się, że nie dostępny mechanizm bezpieczeństwa, więc włączenie debugowania w produkcji skutecznie umożliwiłoby wykonanie dowolnego kodu (poprzez hotswap).

Mamy zestaw JVM 1.4.2 i 1.5 Sun działających na Solaris 9 i Linux (Redhat Enterprise 4). Jak możemy włączyć bezpieczne debugowanie? Jakieś inne sposoby osiągnięcia naszego celu związanego z inspekcją serwera produkcyjnego?

Aktualizacja: Dla JVD JDK 1.5+ można określić interfejs i port, z którym debugger powinien się połączyć. Tak więc propozycja KarlP wiązania do pętli zwrotnej i po prostu użycie tunelu SSH do lokalnego pudełka deweloperskiego powinna działać pod warunkiem, że SSH jest poprawnie skonfigurowany na serwerach.

Jednak wydaje się, że JDK1.4x nie zezwala na podanie interfejsu dla portu debugowania. Możemy zablokować dostęp do portu debugowania w sieci lub wykonać blokowanie specyficzne dla systemu w samym systemie operacyjnym (IPChains, jak zasugerował Jared itp.)?

Aktualizacja # 2: To jest hack, który pozwoli nam ograniczyć nasze ryzyko, nawet na 1.4.2 JVMs:

poleceń params linia:

-Xdebug 
-Xrunjdwp: 
    transport=dt_socket, 
    server=y, 
    suspend=n, 
    address=9001, 
    onthrow=com.whatever.TurnOnDebuggerException, 
    launch=nothing 

kodu Java, aby włączyć debuggera:

try { 
    throw new TurnOnDebuggerException(); 
} catch (TurnOnDebugger td) { 
    //Nothing 
} 

Wyjątkiem TurnOnDebuggerException może być każdy wyjątek gwarantowany, którego nie można nigdzie rzucać.

Przetestowałem to na skrzynce systemu Windows, aby udowodnić, że (1) port debuggera nie odbiera początkowo połączeń, oraz (2) wyrzucenie wyjątku TurnOnDebugger, jak pokazano powyżej, powoduje, że debugger ożyje. Parametr uruchamiania był wymagany (przynajmniej w JDK1.4.2), ale wartość Javy była obsługiwana z wdzięcznością przez maszynę JVM.

Planujemy zrobić mały aplet, który za odpowiednimi zabezpieczeniami pozwoli nam włączyć debugger. Oczywiście później nie można go wyłączyć, a debugger nadal słucha rozwiązłowo po jego uruchomieniu. Ale są to ograniczenia, które możemy zaakceptować, ponieważ debugowanie systemu produkcyjnego zawsze spowoduje ponowne uruchomienie.

Aktualizacja # 3: skończyło się na piśmie trzy klasy: (1) TurnOnDebuggerException, zwykły „ol wyjątek Java (2) DebuggerPoller, tło przewlec sprawdza istnienie określonego pliku w systemie plików, oraz (3) DebuggerMainWrapper, klasa, która uruchamia wątek odpytywania, a następnie odbija refleksyjnie główną metodę innej określonej klasy.

ten sposób jego zastosowanie:

  1. Wymień „main” klasę z DebuggerMainWrapper w skryptach startowych
  2. dodać dwa systemu (-D) params, jednego określenia prawdziwego główną klasę i drugi określa plik w systemie plików.
  3. Skonfiguruj debugger w wierszu poleceń z dodaną częścią onthrow = com.whatever.TurnOnDebuggerException
  4. Dodaj słoik z wymienionymi powyżej trzema klasami do ścieżki klasy.

Teraz, po uruchomieniu JVM wszystko jest takie samo, z wyjątkiem uruchomienia wątku polleru tła. Zakładając, że plik (nasz nazywa się TurnOnDebugger) początkowo nie istnieje, poller sprawdza to co N sekund. Kiedy poller najpierw zauważy to, rzuca i natychmiast łapie wyjątek TurnOnDebuggerException. Następnie agent zostaje wyrzucony.

Nie można wyłączyć urządzenia, a urządzenie nie jest bardzo bezpieczne, gdy jest włączone. Z drugiej strony nie sądzę, że debugger pozwala na wiele jednoczesnych połączeń, więc utrzymanie połączenia debugowania jest najlepszą obroną. Wybraliśmy metodę powiadamiania o plikach, ponieważ pozwalała nam na podciąganie się z istniejącego authenta/autora Uniksa, określając plik wyzwalacza w katalogu, w którym tylko właściwe zastosowania mają prawa. Możesz łatwo zbudować mały plik wojenny, który osiągnął ten sam cel poprzez połączenie z gniazdem. Oczywiście, ponieważ nie możemy wyłączyć debuggera, użyjemy go tylko do zebrania danych przed zabiciem chorego wniosku. Jeśli ktoś chce tego kodu, proszę dać mi znać. Jednak samo samodzielne wrzucenie go zajmie Ci tylko kilka minut.

Odpowiedz

8

Jeśli używasz protokołu SSH, możesz zezwolić na tunelowanie i tunelowanie portu do lokalnego hosta. Bez konieczności programowania, wszystko za pomocą sshd, ssh i/lub putty.

Gniazdo debugowania na serwerze Java można skonfigurować w lokalnym interfejsie 127.0.0.1.

+0

Jeśli to działa (testowanie teraz), wydaje się najlepszą opcją dla nas. To nie jest tak, że regularnie debugujemy, ale chcemy, aby złapać JVM w niewłaściwym stanie. – ShabbyDoo

+1

Myślę, że to zadziała tylko na JDK 1.5+: http://java.sun.com/j2se/1.5.0/docs/guide/jpda/enhancements.html Zobacz "transport dt_socket został zmieniony na wziąć lokalny adres, gdy działasz w trybie serwera "w powyższym linku. – ShabbyDoo

+0

@Shabby - yep - wygląda na to, że działa 1.5+ i jest świetnym rozwiązaniem. Alternatywą jest zablokowanie portów debugowania za pomocą zapory ogniowej (oprogramowania lub sprzętu). Może wypytać ipchains dla hostów Linuxa? (http://tldp.org/HOWTO/IPCHAINS-HOWTO.html) – Jared

0

Wyeksportuj informacje/usługi do JMX, a następnie użyj RMI + SSL, aby uzyskać do niego zdalny dostęp. Twoja sytuacja jest przeznaczona dla JMX (M oznacza zarządzanie).

+0

Zgadzam się, że wspólne wskaźniki powinny być udostępniane za pośrednictwem JMX. W rzeczywistości używamy lekkiego profilera produkcyjnego (Wily), ale nie jest on zbyt dobry w przechwytywaniu informacji o stanie i może być skuteczny tylko wtedy, gdy jest ograniczony do gruboziarnistych śladów. Drugą kwestią jest to, że niektóre z tych aplikacji są (częściowo) niezależne, więc w najlepszym przypadku będziemy debugować przy użyciu skompilowanego źródła. – ShabbyDoo

+1

Nadal utrzymuję, że podłączenie twojego debuggera do aplikacji produkcyjnej to zły pomysł. Użytkownicy nie będą mieli pojęcia, co się dzieje po dotarciu do punktu przerwania i spędzają kilka chwil przeglądając pamięć. Chciałbym znaleźć miejsca w kodzie, które mają problemy i ujawnić bieżący stan za pośrednictwem JMX i zachować szczegółowe dzienniki kontroli, co się dzieje. – Kevin

+1

Przed debugowaniem faktycznie wybraliśmy źle działającą instancję z naszego zbalansowanego klastra. Zgadzam się, że debugowanie aplikacji z aktywnymi użytkownikami byłoby naprawdę złym pomysłem. – ShabbyDoo

2

Masz całkowitą rację: Java Debugging API jest z natury niepewny. Możesz jednak ograniczyć go do gniazd domenowych systemu UNIX i napisać serwer proxy z SSL/SSH, aby umożliwić uwierzytelnianie i szyfrowanie połączeń zewnętrznych, które są następnie kierowane do gniazda domeny UNIX. To przynajmniej zmniejsza twoją ekspozycję na kogoś, kto może dostać proces na serwer lub kogoś, kto może złamać twój SSL.

+0

Czy można odwzorować port w domyślnym interfejsie na gniazdo domeny? Problem, który mam (który dowiedziałem się po moim pierwszym wpisie) jest taki, że maszyna JVM 1.4.x Sun może jedynie powiązać domyślny (?) Interfejs. Dlatego wymagane byłoby pewne magiczne mapowanie, aby ten port nie był odsłonięty poza maszyną wirtualną. – ShabbyDoo

0

Dobre pytanie.

Nie jestem świadomy żadnej wbudowanej możliwości szyfrowania połączeń z portem debugowania.

Nie może być dużo lepiej/łatwiejsze rozwiązanie, ale chciałbym wykonaj następujące czynności:

  1. Put maszyny produkcyjnej za zaporą ogniową, która blokuje dostęp do portu (ów) debugowania.
  2. Przeprowadź proces proxy na hoście, który łączy się z portem, i szyfruje dane wejściowe i wyjściowe z gniazda.
  3. Uruchom klienta proxy na stacji roboczej debugowania, która również szyfruje/odszyfrowuje dane wejściowe. Połącz to z serwerem proxy. Komunikacja między nimi byłaby szyfrowana.
  4. Podłącz swój debugger do klienta proxy.
+0

Na marginesie: nasze serwery produkcyjne znajdują się za zaporą ogniową, ale są narażone na niektóre wewnętrzne segmenty sieci. – ShabbyDoo

Powiązane problemy