Java RMI + Zabbix

Черновая запись по поиску проблем коннекта двух сервисов на java с сертификатами созданными через keytool.

На эту заметку я ориентировался, когда разбирал проблему по работе java+ssl+https, поэтому решил её опубликовать. Мало ли для кого-то будут какие-то зацепки.

Официальный мануал от Оракл по keytool — https://docs.oracle.com/javase/1.5.0/docs/tooldocs/solaris/keytool.html

Описание параметров для запуска ява приложения с ключами — https://docs.oracle.com/javase/1.5.0/docs/guide/management/agent.html#client_ssl

https://mirrors.huaweicloud.com/java/jdk/8u191-b12/

https://docs.datastax.com/en/jdk-install/doc/jdk-install/installOracleJdkDeb.html — установка oracle java из пакетов

Как работает SSL, полезно знать перед тем как что-то делать с сертификатами — http://java-online.ru/ssl-about.xhtml

Добавление рутовых сертификатов в доверенные — http://wiki.cacert.org/FAQ/ImportRootCert#Java

Проверка сертификатов:

openssl s_client -connect service.serviceprovider.com:5368 -showcerts
openssl s_client -debug -connect 94.23.162.32:10053

The error trustAnchors parameter must be non-empty means the Java cannot find or read the client Truststore

После создания CA сертификата и подписи обычного сертификата на стороне клиента получил:

*** ServerHelloDone
RMI TCP Connection(8)-11.22.33.44, WRITE: TLSv1.2 Handshake, length = 958
RMI TCP Connection(8)-11.22.33.44, READ: TLSv1.2 Handshake, length = 262
RSA premaster secret decryption error:
java.security.NoSuchAlgorithmException: Cannot find any provider supporting RSA/ECB/PKCS1Padding
at javax.crypto.Cipher.getInstance(Cipher.java:540)
at sun.security.ssl.JsseJce.getCipher(JsseJce.java:208)
at sun.security.ssl.RSAClientKeyExchange.<init>(RSAClientKeyExchange.java:143)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:249)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readInt(DataInputStream.java:387)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:722)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
RMI TCP Connection(8)-11.22.33.44, handling exception: java.lang.RuntimeException: Could not generate dummy secret
%% Invalidated: [Session-7, TLS_RSA_WITH_AES_128_CBC_SHA256]
RMI TCP Connection(8)-11.22.33.44, SEND TLSv1.2 ALERT: fatal, description = internal_error

Из всей этой кучи лога я взял «java.security.NoSuchAlgorithmException» и вот что оно обозначает:

Это исключение выдается, когда запрашивается конкретный криптографический алгоритм, но он недоступен в среде.

Это было не очевидно (для меня), но не хватало библиотеки sunjce_provider.jar. Её надо было указывать через скрипт запуска вот так (тут указан каталог depends, может быть любой другой, он делается вручную и туда можно положить все нужные библиотеки):

-Djava.ext.dirs=../depends:. \

После добавление библиотеки чуда не случилось, но ошибка поменялась. Значит путь верный.

*** ServerHelloDone
RMI TCP Connection(9)-78.47.90.190, WRITE: TLSv1.2 Handshake, length = 958
RMI TCP Connection(9)-78.47.90.190, READ: TLSv1.2 Handshake, length = 262
RSA premaster secret decryption error:
java.security.InvalidAlgorithmParameterException: Parameters not supported
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineInit(DashoA13*..)
at javax.crypto.Cipher.implInit(Cipher.java:806)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at sun.security.ssl.RSAClientKeyExchange.<init>(RSAClientKeyExchange.java:146)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:249)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readInt(DataInputStream.java:387)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:722)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
RMI TCP Connection(9)-78.47.90.190, handling exception: java.lang.RuntimeException: Could not generate dummy secret
%% Invalidated: [Session-8, TLS_RSA_WITH_AES_128_CBC_SHA256]
RMI TCP Connection(9)-78.47.90.190, SEND TLSv1.2 ALERT: fatal, description = internal_error

Пробую скачать и поставить более новую библиотеку.

В итоге ошибка ушла, я пробовал ещё другие библиотеки, например вот — https://ru.wikipedia.org/wiki/Bouncy_Castle. Но по итогу пришёл, откуда начинал. Игра с библиотеками не принесла успеха.

Поменял список провайдеров nano /usr/lib/jvm/jre1.8.0_45/lib/security/java.security

security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI

Ошибки:

С ключами DSA:

RSA master secret generation error:
java.security.NoSuchAlgorithmException: SunTls12MasterSecret KeyGenerator not available
at javax.crypto.KeyGenerator.<init>(KeyGenerator.java:169)
at javax.crypto.KeyGenerator.getInstance(KeyGenerator.java:223)
at sun.security.ssl.JsseJce.getKeyGenerator(JsseJce.java:251)
at sun.security.ssl.Handshaker.calculateMasterSecret(Handshaker.java:1209)
at sun.security.ssl.Handshaker.calculateKeys(Handshaker.java:1157)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:292)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readInt(DataInputStream.java:387)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:722)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
RMI TCP Connection(8)-78.47.90.190, handling exception: java.security.ProviderException: java.security.NoSuchAlgorithmException: SunTls12MasterSecret KeyGenerator not available
%% Invalidated: [Session-7, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256]
RMI TCP Connection(8)-78.47.90.190, SEND TLSv1.2 ALERT: fatal, description = internal_error

С ключами RSA:

RSA premaster secret decryption error:
java.lang.IllegalArgumentException: unknown parameter type.
at org.bouncycastle.jce.provider.JCERSACipher.engineInit(Unknown Source)
at javax.crypto.Cipher.implInit(Cipher.java:806)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at sun.security.ssl.RSAClientKeyExchange.<init>(RSAClientKeyExchange.java:146)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:249)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readInt(DataInputStream.java:387)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:722)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
RMI TCP Connection(9)-78.47.90.190, handling exception: java.lang.RuntimeException: Could not generate dummy secret
%% Invalidated: [Session-8, TLS_RSA_WITH_AES_128_CBC_SHA256]

Библиотеки для криптографии:

./jre/lib/security/policy/limited/US_export_policy.jar
./jre/lib/security/policy/limited/local_policy.jar
./jre/lib/security/policy/unlimited/US_export_policy.jar
./jre/lib/security/policy/unlimited/local_policy.jar

jce.jar

sunec.jar

sunpkcs11.jar

sunjce_provider.jar

bcprov-jdk16-145.jar

localedata.jar,sunpkcs11.jar,sunmscapi.jar,sunjce_provider.jar,dnsns.jar

после выравнивая этих библиотек:

./java-7-openjdk-amd64/jre/lib/ext/sunjce_provider.jar
./java-7-openjdk-amd64/jre/lib/ext/sunec.jar
./java-7-openjdk-amd64/jre/lib/ext/sunpkcs11.jar

ошибка

*** ServerHelloDone
RMI TCP Connection(13)-147.22.239.190, WRITE: TLSv1.2 Handshake, length = 745
RMI TCP Connection(13)-147.22.239.190, READ: TLSv1.2 Handshake, length = 134
RSA premaster secret decryption error:
java.security.NoSuchAlgorithmException: Cannot find any provider supporting RSA/ECB/PKCS1Padding
at javax.crypto.Cipher.getInstance(Cipher.java:540)
at sun.security.ssl.JsseJce.getCipher(JsseJce.java:208)
at sun.security.ssl.RSAClientKeyExchange.<init>(RSAClientKeyExchange.java:143)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:249)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readInt(DataInputStream.java:387)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:722)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
RMI TCP Connection(13)-147.22.239.190, handling exception: java.lang.RuntimeException: Could not generate dummy secret
%% Invalidated: [Session-11, TLS_RSA_WITH_AES_128_CBC_SHA256]

./java-7-openjdk-amd64/jre/lib/security/US_export_policy.jar
./java-7-openjdk-amd64/jre/lib/security/local_policy.jar
./java-7-openjdk-amd64/jre/lib/security/policy/limited/US_export_policy.jar
./java-7-openjdk-amd64/jre/lib/security/policy/limited/local_policy.jar
./java-7-openjdk-amd64/jre/lib/security/policy/unlimited/US_export_policy.jar
./java-7-openjdk-amd64/jre/lib/security/policy/unlimited/local_policy.jar

Начал работу вот с такой строкой:

security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg

она есть на стороне заббикс сервера, но её нет на стороне клиента.

Добавил вот такие строки с обоих сторон:

security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg
security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider

Ошибка:

*** ECDH ServerKeyExchange
Signature Algorithm SHA512withRSA
Server key: EC Public Key
X: a3cf51576882c92e9d670dece67610017faa6c71fa3890d024be44e56d300e7b
Y: ff79771b189a9b8fac5ab6bc05d1f5e43aa756f92914c82cd6d36681b2ce7a89

*** ServerHelloDone
RMI TCP Connection(15)-147.22.239.190, WRITE: TLSv1.2 Handshake, length = 950
RMI TCP Connection(15)-147.22.239.190, READ: TLSv1.2 Handshake, length = 70
*** ECDHClientKeyExchange
ECDH Public value: { 4, 62, 84, 205, 6, 252, 135, 128, 0, 131, 152, 188, 112, 125, 169, 50, 245, 120, 186, 140, 173, 83, 89, 102, 144, 111, 3, 26, 177, 35, 215, 133, 126, 198, 253, 129, 2, 88, 18, 130, 222, 88, 144, 49, 187, 4, 34, 155, 95, 185, 98, 56, 93, 25, 112, 81, 151, 71, 245, 221, 245, 94, 73, 56, 109 }
RMI TCP Connection(15)-147.22.239.190, handling exception: javax.net.ssl.SSLHandshakeException: Could not generate secret
%% Invalidated: [Session-12, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256]
RMI TCP Connection(15)-147.22.239.190, SEND TLSv1.2 ALERT: fatal, description = handshake_failure
RMI TCP Connection(15)-147.22.239.190, WRITE: TLSv1.2 Alert, length = 2
RMI TCP Connection(15)-147.22.239.190, called closeSocket()
RMI TCP Connection(15)-147.22.239.190, called close()
RMI TCP Connection(15)-147.22.239.190, called closeInternal(true)

Перешёл на java 8 oracle 252

Если в настройках есть такая строка — security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider, то ошибка:

Exception in thread "RMI TCP Connection(idle)" java.lang.NoSuchMethodError: sun.security.util.ECUtil.equals(Ljava/security/spec/ECParameterSpec;Ljava/security/spec/ECParameterSpec;)Z
at sun.security.ec.CurveDB.lookup(CurveDB.java:109)
at sun.security.ec.ECParameters.engineInit(ECParameters.java:119)
at java.security.AlgorithmParameters.init(AlgorithmParameters.java:275)
at sun.security.util.ECUtil.getCurveName(ECUtil.java:176)
at sun.security.ssl.JsseJce.getNamedCurveOid(JsseJce.java:377)
at sun.security.ssl.SupportedEllipticCurvesExtension.getCurveIndex(SupportedEllipticCurvesExtension.java:365)
at sun.security.ssl.HandshakeMessage$ECDH_ServerKeyExchange.<init>(HandshakeMessage.java:1013)
at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:901)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:224)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:928)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readInt(DataInputStream.java:387)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:722)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)

Убрал security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider.

На стороне сервера:

DEBUG c.z.gateway.BinaryProtocolSpeaker - sending the following data in response: {"response":"failed","error":"Received close_notify during handshake: service:jmx

На стороне клиента:

Exception in thread "RMI TCP Connection(idle)" java.lang.NoSuchMethodError: sun.security.internal.spec.TlsMasterSecretParameterSpec.getExtendedMasterSecretSessionHash()[B
at com.sun.crypto.provider.TlsMasterSecretGenerator.engineGenerateKey(TlsMasterSecretGenerator.java:107)
at javax.crypto.KeyGenerator.generateKey(KeyGenerator.java:546)
at sun.security.ssl.Handshaker.calculateMasterSecret(Handshaker.java:1211)
at sun.security.ssl.Handshaker.calculateKeys(Handshaker.java:1157)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:292)

 

Добавить комментарий