skip to content

RMI Ports and Security

Why a first distributed run usually fails: RMI grabs dynamic ports a firewall blocks, and the channel is SSL by default, so every node needs the keystore or the disable switch.

on this pageshow

explore

questions

5

In JMeter 6, why does a distributed run refuse to start without rmi_keystore.jks?

level: juniorimportance: must knowfreq 55%

answer

  1. A fresh install has no keystore file
  2. The transport is encrypted before you configure it
  3. One property switches the requirement off
  4. Both ends must present a key
  5. A script in bin generates the file

basics

~20 s

Since JMeter 4.0 the RMI transport runs over SSL by default: server.rmi.ssl.disable is false. The keystore that server.rmi.ssl.keystore.file names, rmi_keystore.jks, is not in the download, so you generate it and copy it to every node.

solid answer

~40 s

In Apache JMeter 6.0.0 `server.rmi.ssl.disable` defaults to `false`, so both the controller and every `jmeter-server` build an SSL socket factory from the `server.rmi.ssl.*` properties. Those default to a keystore file called `rmi_keystore.jks`, type `JKS`, password `changeit`, alias `rmi`, and the truststore properties fall back to the same values. That file is deliberately absent from the binary distribution, so on a fresh install there is nothing to load and the socket cannot be created. Run `bin/create-rmi-keystore.sh` (or `create-rmi-keystore.bat`) from the `bin` directory and copy the resulting `rmi_keystore.jks` to every generator **and** to the controller — the server factory sets `setNeedClientAuth(true)`, so the controller must present a key too, not merely trust the engine.

code

shell · 6 lines
shell
cd $JMETER_HOME/bin
./create-rmi-keystore.sh

for host in gen1 gen2 gen3; do
  scp rmi_keystore.jks "$host:/opt/apache-jmeter/bin/rmi_keystore.jks"
done

go deeper

for a junior

Recall the default: server.rmi.ssl.disable is false, so RMI is encrypted out of the box and a keystore called rmi_keystore.jks must exist on each machine before a remote run works.

for a middle

Explain the whole property family, that the truststore settings default to the keystore ones, and that create-rmi-keystore.sh picks the alias and password those defaults already expect.

for a senior

Read the actual error and place the failure: a blank property fails at startup with a named message, a missing file fails when the socket is built, and mismatched keystores fail in the handshake.

for a principal

Decide how the keystore is produced, distributed and rotated across a generator fleet before anyone hits the error, so no team is ever tempted to disable SSL to unblock a run.

A first distributed JMeter run usually fails twice before it ever sends a request: once on ports, and once on this. The second failure is the one that reads like a configuration mistake but is actually the shipped default doing its job. ## The default `RmiUtils` reads `server.rmi.ssl.disable` with a default of `false`. Both `createClientSocketFactory()` and `createServerSocketFactory()` return `null` — meaning plain RMI sockets — only when that property is `true`. Otherwise they construct an `SSLRMIClientSocketFactory` / `SSLRMIServerSocketFactory` and configure it from the rest of the family: | Property | Default | |---|---| | `server.rmi.ssl.keystore.file` | `rmi_keystore.jks` | | `server.rmi.ssl.keystore.type` | `JKS` | | `server.rmi.ssl.keystore.password` | `changeit` | | `server.rmi.ssl.keystore.alias` | `rmi` | | `server.rmi.ssl.truststore.file` | the keystore file | | `server.rmi.ssl.truststore.password` | the keystore password | | `server.rmi.ssl.disable` | `false` | The truststore properties falling back to the keystore values is what makes a **single shared file** workable: one `rmi_keystore.jks` is simultaneously the node's identity and the set of identities it accepts. ## Why one file has to reach every node `RmiUtils.createServerSocketFactory()` calls `factory.setNeedClientAuth(true)`. Both ends therefore have to present a key, not just validate one, so the controller needs the same file the generators have. Copy it to `bin` on each machine, or point `server.rmi.ssl.keystore.file` at an absolute path — the default is relative, which is why the manual tells you to run the generator script from inside `bin`. ## Generating it The distribution ships the script, not the keystore. `bin/create-rmi-keystore.sh` is a single `keytool` line: ``` keytool -genkey -keyalg RSA -alias rmi -keystore rmi_keystore.jks \ -storepass changeit -validity 7 -keysize 2048 "$@" ``` The `-alias rmi` and `-storepass changeit` match the property defaults exactly, which is why an untouched `jmeter.properties` works with an untouched script. ## Why the download has no keystore The source tree does contain a `bin/rmi_keystore.jks` for the project's own tests, but the release build excludes it from the binary layout. That is deliberate: a shipped keystore would be a published private key, and every reachable engine on earth would then accept a test plan from anyone who downloaded JMeter. Keeping it out is what turns "SSL on by default" into a real control instead of a formality. ## What the failure actually looks like - If the property is left blank, `RmiUtils` throws immediately with `No keystore for RMI over SSL specified.` and tells you to set `server.rmi.ssl.disable` to `true` if that was intentional. - If the property names a file that does not exist, the store is only opened when a socket is created. The generator fails while exporting its engine object, so `jmeter-server` dies at startup; the controller, whose client factory loads the store inside `createSocket`, fails later, at the registry lookup. - If one node has the file and another does not, or two nodes hold keystores generated separately, the connection fails during the handshake rather than at startup. ## The opt-out `server.rmi.ssl.disable=true` removes the requirement, and it has to be set on **every** node — a mixed fleet cannot negotiate anything. Treat that as a decision about network exposure, not a shortcut, because it also removes the mutual client authentication that keeps an unknown controller from driving your engine. How certificates, key pairs and trust chains work underneath is TLS material and is covered by the dedicated TLS topics; what belongs here is the JMeter property names, the script, and the fact that the file has to exist on every participant before a run can start.

  • Does the JMeter controller need the keystore, or only the generators?
    Both. `RmiUtils.createServerSocketFactory()` sets `setNeedClientAuth(true)`, so the engine demands a key from whatever connects to it, and the controller's own client socket factory loads the same `server.rmi.ssl.keystore.file`. A controller without the file fails at the registry lookup.
  • What happens if you set server.rmi.ssl.disable=true on the generators but not on the controller?
    Nothing connects. One side offers plain RMI sockets and the other insists on SSL, so the link fails before any JMeter-level message is exchanged. The property has to carry the same value on every node in the run.

saying these in an interview costs you the question

  • Says JMeter's RMI transport is plaintext by default
  • Expects rmi_keystore.jks to be in the download
  • Copies the keystore to the generators only
  • Thinks only the engine needs a key
  • Reaches for server.rmi.ssl.disable before reading the error
open as a page

Which JMeter properties fix the RMI ports of a distributed run so a firewall can allow them?

level: middleimportance: must knowfreq 62%

basics

~10 s

Three ports, three properties. server.rmi.port pins the engine's RMI registry, default 1099. server.rmi.localport pins the engine object itself, dynamic by default. client.rmi.localport pins the controller's two result-callback ports, also dynamic by default.

open as a page

A JMeter remote run starts behind a corporate firewall but no samples arrive. Which RMI leg is blocked?

level: seniorimportance: should knowfreq 44%

basics

~20 s

The return leg. The registry and engine ports are open, since the plan is running, but the engine cannot connect back to the controller's callback ports. Pin them with client.rmi.localport and allow them inbound on the controller.

open as a page

How would you decide whether a JMeter generator fleet keeps RMI SSL or sets server.rmi.ssl.disable=true?

level: principalimportance: should knowfreq 30%

basics

~20 s

Decide what reaching an engine's RMI port should be worth. The default buys mutual authentication and costs a shared keystore on every node. Disabling it removes the file and leaves an engine that runs any plan it is handed.

open as a page

Why does a JMeter distributed setup that ran last week suddenly fail its RMI connection?

level: seniorimportance: nice to knowfreq 20%

basics

~10 s

The stock keystore expires. JMeter's bin/create-rmi-keystore.sh and .bat call keytool with -validity 7, so the rmi_keystore.jks they produce is good for seven days. Nothing on either node changed; the key pair simply aged out.

open as a page