我们有一些应用程序有时会陷入糟糕的状态,但仅限于生产(当然!)。虽然进行堆转储可以帮助收集状态信息,但使用远程调试器通常更容易。设置它很容易 - 只需将其添加到他的命令行:
-Xdebug -Xrunjdwp:transport = dt_socket,server = y,suspend = n,address = PORT
似乎没有可用的安全机制,因此在生产中启用调试将有效地允许任意代码执行(通过hotswap)。
我们在Solaris 9和Linux(Redhat Enterprise 4)上运行1.4.2和1.5个Sun JVM。我们如何启用安全调试?有没有其他方法来实现我们的生产服务器检查目标?
更新:对于JDK 1.5+ JVM,可以指定调试器应绑定的接口和端口。因此,如果在服务器上正确设置了SSH,KarlP建议绑定到环回并仅使用SSH隧道连接到本地开发人员框。
但是,似乎JDK1.4x不允许为调试端口指定接口。那么,我们可以阻止访问网络中某个地方的调试端口,或者在操作系统本身中进行一些特定于系统的阻塞(如Hared建议的那样,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正好处理了垃圾值。
我们计划制作一个小型servlet,在适当的安全性之后,可以允许我们打开调试器。当然,之后无法将其关闭,调试器一旦打开就仍然会混杂地监听。但是,这些是我们愿意接受的限制,因为生产系统的调试总是会导致重新启动。
更新#3:我最后编写了三个类:(1)TurnOnDebuggerException,一个简单的'ol Java异常,(2)DebuggerPoller,一个后台线程检查是否存在指定文件在文件系统上,和(3)DebuggerMainWrapper,一个启动轮询线程然后反射调用另一个指定类的main方法的类。
这是它的用法:
现在,当您启动JVM时,除了启动后台轮询器线程之外,所有内容都是相同的。假设文件(我们的名为TurnOnDebugger)最初不存在,轮询器每隔N秒检查一次。当轮询器首次注意到它时,它会抛出并立即捕获TurnOnDebuggerException。然后,代理人开始了。
您无法将其关闭,并且机器在打开时不是非常安全。从好的方面来说,我不认为调试器允许多个同时连接,因此保持调试连接是最好的防御。我们选择了文件通知方法,因为它允许我们通过在只有正确使用权限的目录中指定触发器文件来捎带我们现有的Unix authen / author。您可以轻松地构建一个通过套接字连接实现相同目的的war文件。当然,由于我们无法关闭调试器,因此我们只会在杀死病毒应用程序之前使用它来收集数据。如果有人想要这个代码,请告诉我。但是,你自己只需几分钟就可以把它扔在一起。
答案 0 :(得分:8)
如果使用SSH,则可以允许隧道连接并将端口隧道连接到本地主机。无需开发,全部使用sshd,ssh和/或putty完成。
可以在本地接口127.0.0.1上设置java服务器上的调试套接字。
答案 1 :(得分:2)
你说得对:Java Debugging API本质上是不安全的。但是,您可以将其限制为UNIX域套接字,并使用SSL / SSH编写代理,以便您具有经过身份验证和加密的外部连接,然后将这些外部连接代理到UNIX域套接字中。这至少可以减少您对可以进入服务器的人或可能破解SSL的人的暴露。
答案 2 :(得分:0)
将信息/服务导出到JMX,然后使用RMI + SSL远程访问它。您的情况就是JMX的设计目标(M代表管理层)。
答案 3 :(得分:0)
好问题。
我不知道有任何加密连接到调试端口的内置功能。</ p>
可能有更好/更容易的解决方案,但我会做以下事情: