Connettiti alla porta del registry attraverso il tunnel, guarda l'handshake iniziare e poi guarda JConsole andare comunque in timeout. Succede perché la prima connessione TCP non è la connessione di gestione: è una ricerca. Il registry RMI risponde con un riferimento che indica un host e una seconda porta, e JConsole va poi dove le è stato detto. Se il tunnel raggiunge solo la prima porta del server, o se il riferimento indica un indirizzo che esiste solo sulla LAN del server stesso, il client si blocca dopo essere apparentemente riuscito.

Il mito: una porta aperta è una connessione

JMX remoto su RMI coinvolge almeno due endpoint, e sono scelti da parti diverse del sistema. La porta del registry è quella che digiti nel client, ed esiste per distribuire lo stub che descrive il connettore reale. Prendere il primo socket riuscito come prova che il percorso di gestione è aperto è ciò che trasforma una diagnosi di due minuti in un pomeriggio di ticket per il firewall.

Guarda l'errore del client stesso invece dell'elenco degli ascoltatori del server. Un errore dopo l'inizio dell'handshake ti dice che è la seconda connessione, non la prima, a non essersi completata.

Cosa restituisce il registry

Lo stub contiene un indirizzo e una porta, serializzati nel momento in cui è stato creato il connettore. Su un server con diverse interfacce, lo stack può aver scelto un indirizzo raggiungibile dalla rete locale e non dalla tua. Il client non conosce la differenza; compone semplicemente il valore che gli è stato dato, e il pacchetto segue la rotta che esiste per quell'indirizzo, che su un client VPN spesso non è nessuna. È il momento in cui viene tentata la seconda connessione.

È anche il motivo per cui l'errore è intermittente tra ambienti: lo stesso server può comportarsi diversamente per un utente sulla LAN e per un utente sul tunnel, senza alcuna modifica alla configurazione JMX.

Due porte e due proprietà che le fissano

La porta del registry viene da com.sun.management.jmxremote.port, e il connettore può essere fissato con com.sun.management.jmxremote.rmi.port invece di lasciarlo a ciò che assegna lo stack. Imposta entrambe esplicitamente quando tra client e server c'è un firewall o un security group, perché una seconda porta imprevedibile non può essere consentita in anticipo, e un intervallo ampio aperto per accoglierla è peggio che fissare un solo valore.

Poi conferma con ss -ltn o netstat -an sul server che entrambe le porte sono in ascolto e su quali indirizzi. Un listener legato al loopback è corretto per un deployment solo locale e inutile per questo.

Quando il nome annunciato è sbagliato

Il nome host che compare nel riferimento remoto è impostato da java.rmi.server.hostname. Influisce su ciò che lo stub annuncia; non è di per sé un'istruzione a legare ogni listener a una sola interfaccia, ed è per questo che impostarlo non produce sempre il comportamento a porta singola che ci si aspetta. Impostalo, riavvia il processo e poi verifica cosa contiene davvero lo stub. Scegli un nome o un indirizzo che il client possa risolvere e raggiungere attraverso il tunnel, e riavvia il processo in modo che lo stub venga ricostruito.

Le reti dei container peggiorano la situazione, perché l'indirizzo che il processo vede può essere interno e non instradabile da fuori del container. Pubblica esplicitamente il nome host previsto invece di lasciare che la piattaforma scelga.

Se usi un tunnel SSH invece di una VPN, lo stesso problema appare in un altro travestimento: inoltrare solo la porta del registry lascia il secondo endpoint puntato a un indirizzo che il tuo client non può raggiungere. Inoltra entrambe le porte e fai in modo che il nome annunciato risolva in qualcosa che il client può raggiungere localmente.

Non disattivare la sicurezza di gestione per semplificare

Gli snippet che disattivano autenticazione e TLS sono facili da trovare e fanno funzionare la connessione in un modo che dovrai annullare più tardi. JMX remoto è un'interfaccia di gestione con gli stessi privilegi del processo che ispeziona; mantieni i suoi controlli di accesso, e se il client non può presentare credenziali, risolvi quello invece.

Quando gli endpoint sono corretti, conserva il prossimo errore che vedi. Un rifiuto del truststore o dell'account è una fase successiva a un connettore irraggiungibile e significa che il lavoro di rete è finito.

Articoli correlati