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:
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'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.