Remoting and JNLP4

The Remoting Protocol and JNLP4

Remoting (github.com/jenkinsci/remoting (https://github.com/jenkinsci/remoting 262 )) turns the controller and an agent into one distributed Java program. Over one bidirectional channel, the controller sends serialized Callable objects to run in the agent's JVM, ships the classes they need on demand (cached in the agent's jarCache), and streams files, process output and exit codes back. Every sh step and file copy is a Remoting call.

An inbound agent first asks an HTTP endpoint for the TCP port, the protocols on offer and the controller's public key, the instance identity each controller generates on first start:

The inbound-agent endpoint, and the fingerprint of the controller's identityShell
curl -sI http://localhost:32080/tcpSlaveAgentListener/ | tr -d '\r' | grep -E '^X-(J|Rem)'
curl -sI http://localhost:32080/tcpSlaveAgentListener/ | tr -d '\r' \
  | sed -n 's/^X-Instance-Identity: //p' | base64 -d | md5sum | cut -c1-32 | sed 's/../&:/g; s/:$//'
docker logs l2-agent-1 2>&1 | grep -E 'Trying|confirmed'
Output
X-Jenkins-JNLP-Port: 50000
X-Jenkins-Agent-Protocols: JNLP4-connect, Ping
X-Remoting-Minimum-Version: 3176.v207ec082a_8c0
ff:1f:05:dd:6e:18:1d:6b:18:43:50:8c:5b:1c:f2:b1
INFO: Trying protocol: JNLP4-connect
INFO: Remote identity confirmed: ff:1f:05:dd:6e:18:1d:6b:18:43:50:8c:5b:1c:f2:b1

JNLP4-connect, the only TCP protocol left, wraps the channel in TLS keyed to that identity, and the agent's log confirms the same fingerprint before it proves itself with its secret. JNLP4 arrived in Jenkins 2.27 8,793 (October 2016); the unencrypted or weakly encrypted JNLP1 to JNLP3 were removed in 2.214. Since early 2020 -webSocket agents can use the web port instead, which suits a reverse proxy; SSH agents (SSH Agents) are started by the controller.

Older agents than X-Remoting-Minimum-Version are refused (agent-1 runs Remoting 3391.va_37fa_a_305d6d), so upgrade the jenkins/inbound-agent image with the controller.