Issue
-
How do I verify that my CloudBees Jenkins instance is listening for websocket connections?
-
When I attempt to connect my agent to a controller using websockets I see a Response code was not 101: 403, e.g.,
Feb 11, 2021 6:33:34 PM hudson.remoting.jnlp.Main$CuiListener error SEVERE: Handshake error. io.jenkins.remoting.shaded.javax.websocket.DeploymentException: Handshake error. at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:674) at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:712) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:866) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112) at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:511) at io.jenkins.remoting.shaded.org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:355) at hudson.remoting.Engine.runWebSocket(Engine.java:627) at hudson.remoting.Engine.run(Engine.java:469) Caused by: io.jenkins.remoting.shaded.org.glassfish.tyrus.core.HandshakeException: Response code was not 101: 403.
Environment
-
CloudBees CI (CloudBees Core) on modern cloud platforms - Managed controller
-
CloudBees CI (CloudBees Core) on modern cloud platforms - Operations Center
-
CloudBees CI (CloudBees Core) on traditional platforms - Client controller
-
CloudBees CI (CloudBees Core) on traditional platforms - Operations Center
Resolution
Agent to controller connections begin as TCP connections, before TLS is negotiated and messages are encrypted between agents and controllers. Afterwards, either a JNLP4-Connect procotol connection (on port 50000 by default) or Websocket protocol connection is attempted. In order to verify that Jenkins is listening for websocket connections you can use the following curl
command,
$ curl --http1.1 -i -N --header "Connection: Upgrade" --header "Upgrade: websocket" --header "Host: JENKINS_URL" --header "Origin: JENKINS_URL" --header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" --header "Sec-WebSocket-Version: 13" --header "Secret-Key:SECRET" --header "X-Remoting-Capability:rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAf4=" --header "Node-Name:my-agent" https://JENKINS_URL/wsagents/ HTTP/1.1 101 Switching Protocols Date: Fri, 12 Feb 2021 22:51:56 GMT Connection: upgrade X-Content-Type-Options: nosniff X-Remoting-Capability: rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAf4= X-Remoting-Minimum-Version: 3.14 Cookie: e834e14558b07b6a0099f06226f7862469b5c5eacd92bb65d5190988ba990548 Sec-WebSocket-Accept: qGEgH3En71di5rrssAZTmtRTyFk= Upgrade: WebSocket Strict-Transport-Security: max-age=15724800; includeSubDomains Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file. $
Note:
-
Secret-Key (secret generated by Jenkins)
-
X-Remoting-Capability
-
Node-Name (the name of the node created in Jenkins)