Message d’erreur
javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
Également affiché sous la forme
- Remote host terminated the handshake
Les JDK 21 et 25 affichent « Remote host terminated the handshake ». Dans les journaux de Java 8, la même situation apparaît couramment sous la forme « Remote host closed connection during handshake », causée par « SSL peer shut down incorrectly ».
Java (JSSE) — the TCP connection closed during the handshake without a TLS alert
Ce que cela signifie
L’autre extrémité (ou un équipement intermédiaire) a fermé la connexion TCP pendant que la JVM était dans le handshake TLS, sans envoyer d’alerte TLS. Java ne peut pas en connaître la raison : il voit seulement la connexion se terminer. En général, un pare-feu, un proxy ou un répartiteur de charge interrompt le handshake, ou bien le serveur rejette silencieusement le ClientHello.
Pourquoi cela se produit
Un proxy ou un pare-feu sur le chemin
fréquenteLes réseaux qui imposent un proxy HTTPS, les pare-feu à inspection approfondie des paquets qui bloquent selon le SNI ou l’empreinte JA3/JA4, et les VPN mettent souvent fin silencieusement aux connexions bloquées.
Le serveur coupe les handshakes qu’il refuse
fréquenteCertains serveurs et répartiteurs de charge ferment la connexion au lieu de répondre par une alerte lorsque la version du protocole, la liste des suites de chiffrement ou le SNI est inacceptable.
SNI absent
occasionnelleUne connexion par adresse IP, ou avec jsse.enableSNIExtension=false, n’envoie aucun nom de serveur ; les nœuds de périphérie des CDN abandonnent couramment ces handshakes.
Limites de connexions et limitation de débit
occasionnelleLes serveurs qui ont atteint leur limite de connexions, ou les limiteurs de débit face à des pics de trafic, réinitialisent les nouvelles connexions ; l’erreur apparaît alors de façon intermittente.
Comment corriger l’erreur
- 1.
Tracer le handshake et comparer avec openssl
javax.net.debug montre jusqu’où le handshake est allé ; si openssl s_client lancé depuis le même hôte est lui aussi coupé, la cause se trouve dans le réseau ou le serveur, pas dans la JVM.
bash java -Djavax.net.debug=ssl:handshake -jar app.jar 2>&1 | grep -E 'ClientHello|server_name|EOF|terminated' # Same handshake without Java: is it the network or the JVM? openssl s_client -connect api.example.com:443 -servername api.example.com -brief </dev/null - 2.
Utiliser le proxy du réseau
Par défaut, Java n’utilise pas les paramètres de proxy du système d’exploitation ni ceux du navigateur ; définissez https.proxyHost/https.proxyPort (ou -Djava.net.useSystemProxies=true) et excluez les hôtes internes avec http.nonProxyHosts.
bash # Corporate networks: route HTTPS through the proxy the browser uses java -Dhttps.proxyHost=proxy.example.net -Dhttps.proxyPort=3128 \ -Dhttp.nonProxyHosts="localhost|*.internal.example.com" -jar app.jar - 3.
Envoyer le SNI
Utilisez le nom d’hôte dans l’URL et laissez l’extension SNI activée.
text Connect with the host name (not an IP address) so JSSE sends SNI, and do not set -Djsse.enableSNIExtension=false: front ends that need SNI close such connections.