RMI 注册表是什么
Java RMI(Remote Method Invocation)允许一个 JVM 调用另一个 JVM 上的对象方法,rmiregistry 就是这套机制的电话簿:服务端把远程对象按名字绑定进去,客户端先查名字换回桩(stub),再由桩发起真正的调用。1099 是 rmiregistry 的默认端口。从 Java 5 起平台 MBean Server 又提供了基于 RMI 的 JMX 连接器,运维图省事常把它挂到同一个 1099 上,管理面与业务面就此重合。
基本信息
| 服务 | rmiregistry / JMX RMI 连接器 |
|---|---|
| 协议 | TCP(RMI 调用本身还要再开一个导出端口) |
| 默认端口 | 1099(注册表) |
| 适用环境 | Oracle JDK / OpenJDK 等 JVM 应用 |
| 安全等级 | 仅管理网段,禁止公网暴露 |
典型使用场景
- Java 传统分布式应用先启动 rmiregistry,服务端 rebind 远程对象供其他进程查找
- JMX 远程监控:jconsole、VisualVM、Zabbix JMX 网关连到应用的 1099 读取 MBean
- 老版本中间件、调度框架用 RMI 做节点间调用与任务分发
- 安全评估:扫描器把 1099 列为 Java 反序列化利用面的高价值入口
- 排障:应用报 ConnectException 或 NotBoundException 时,先确认注册表在监听且名字已绑定
监听与调用自检
监听与调用自检
ss -lntp | grep 1099 # 谁在监听注册表
nc -vz -w2 127.0.0.1 1099 # 端口是否可达
jcmd <pid> VM.system_properties | grep -iE 'jmxremote|rmi.server' # 查看启动参数
# 应用侧:确认绑定名与查找名一致
# Naming.lookup("rmi://host:1099/HelloService")RMI 用到的两个端口
| 端口 | 作用 | 固定方式 |
|---|---|---|
| 1099/tcp | 注册表:按名字查远程对象 | rmiregistry 1099 或 jmxremote.port |
| 导出端口(随机) | 服务端对象真正接受调用 | -Dcom.sun.management.jmxremote.rmi.port |
| 防火墙视角 | 只放 1099 往往连不上 | 两个端口都要规划并放行 |
JMX 认证一旦关闭,任何能连到 1099 的人都能读 MBean 甚至触发操作;再叠加反序列化链即可在目标 JVM 上执行代码,公网暴露通常在数天内被入侵。
JMX 只监听本机
JMX 只监听本机
java -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=1099 \
-Dcom.sun.management.jmxremote.rmi.port=1099 \
-Dcom.sun.management.jmxremote.local.only=true \
-Dcom.sun.management.jmxremote.authenticate=true \
-jar app.jar
# 远端访问优先用 SSH 隧道,而不是把 1099 放到公网:
# ssh -L 1099:127.0.0.1:1099 ops@server本地连不上 1099 时先看应用是否绑定了 127.0.0.1 或开启了 local.only;远端场景别急着改绑定地址,SSH 隧道既省掉开放端口,也不用把管理面写进防火墙放行清单。