Многие знают, а многие возможно и не знают, что передача различной чувствительной информации в финансовой и банковской сфере, по требованиям ФСТЭК, должна защищаться отечественными алгоритмами шифрования и продуктами прошедшими сертификацию в ФСБ. Но как тестировать создаваемые продукты на отечественной криптографии, если большинство утилит тестирования ориентируется на западную криптографию ? Для Jmeter есть достаточно простой способ подключить отечественную криптографию.
О чём пойдёт речь в статье ?
Множество QA специалистов, а также специалисты по нагрузочному тестированию, используют jmeter в своей работе из-за его достаточно большой гибкости. Пакет всем хорош, но в своей базовой поставке он ничего не знает про российские алгоритмы шифрования. На самом деле тема с попыткой подключения российской криптографии к jmeter возникла после того, как мои коллеги попытались нагрузить и протестировать связку нового API, закрытого ГОСТовым mTLS, использующим пучок сертификатов выданных различными УЦ. Коллеги начали пилить свои приложения на Java, придумывать варианты с использованием stunnel с поддержкой российской криптографии, что в принципе имело определённый результат, но не имело гибкости в настройках. Поэтому были решено произвести исследования о возможности нативно использовать криптографию КриптоПро в jmeter.
Ремарка: для настройки и запуска jmeter используется Java17, операционная система Ubuntu 20.04
С чего всё началось ?
Так как текущим стандартом для разработки приложений на Java, с поддержкой отечественной криптографии, является использование библиотек от КриптоПро, было решено поисследовать форум компании на предмет подключения внешних библиотек JCP/JCSP к существующим проектам. Тема оказалась не очень популярной и каких-либо конкретных данных особо не нашлось. Правда нашлась информация о том, что практически "из коробки" можно подключить загрузку сертификатов в любое приложение на Java, использующее штатную Java криптографию. Далее началась череда длительных экспериментов подборки различных конфигураций.
Подключение библиотек
Для подключения библиотек КриптоПро, в исполняемый код, достаточно определить для java vm параметр classpath(-cp, --classpath) с указанием директории или списка jar файлов из которых необходимо загрузить дополнительные классы. Стоит сразу сделать несколько оговорок, о которых возможно кто-то не знает:
Для Linux и Windows используются различные разделители в списке загружаемых библиотек. В Linux это ":"(двоеточние), в Windows ";"(точка с запятой)
-cp "JCP.jar:JCryptoP.jar:JCPRevCheck.jar:JCPRevTools.jar"Загрузка библиотек указанных в classpath не работает для fat jar файлов в режиме запуска java -jar myjarfile.jar
Загрузка внешних библиотек не гарантирует корректную инициализацию всех механизмов защиты
Корректность инициализации и работы криптопровайдера может зависеть от настроек в java.security
Подключение библиотек для работы с ключами не делает автоматически доступной работу с TLS
Решением первой и второй проблемы является использование параметра user.classpath в файле user.properties. Jmeter загружает все указанные в параметре библиотеки при старте основного процесса. Например:
user.classpath=/opt/jcp-2.0.41940-A/*.jar
Решением третьей и четвёртой проблемы является использование отдельной копии java.security с переопределением пути к нему через параметры java vm.
-Djava.security.properties=./java.security
Для корректной инициализации криптопровайдера и библиотек необходимо добавить в файл java.security дополнительные строки:
#
# List of providers and their preference orders (see above):
#
security.provider.1=SUN
security.provider.2=SunRsaSign
security.provider.3=SunEC
security.provider.4=SunJSSE
security.provider.5=SunJCE
security.provider.6=SunJGSS
security.provider.7=SunSASL
security.provider.8=XMLDSig
security.provider.9=SunPCSC
security.provider.10=JdkLDAP
security.provider.11=JdkSASL
security.provider.12=SunPKCS11
security.provider.13=JCP
security.provider.14=RevCheck
security.provider.15=Crypto
либо
security.provider.13=ru.CryptoPro.JCP.JCP
security.provider.14=ru.CryptoPro.reprov.RevCheck
security.provider.15=ru.CryptoPro.Crypto.CryptoProvider
Это позволит механизмам криптографии определить последовательность "обхода/инициализации" провайдеров в работе.
Для решения пятой проблемы необходимо обеспечить вызов конструкторов по загрузке провайдера в приложение. Об этом мы поговорим чуть позже.
Загрузка ключей КриптоПро при старте приложения
Для загрузки внешних ключей при старте, в Jmeter был добавлен специализированный механизм SSL Manager и JSSESSLManager. SSL Manager имеет два варианта использования:
Загрузка ключей из командной строки
Загрузка ключей из интерфейса
JSSESSLManager используется для инициализации SSL контекста в jmeter опираясь на параметры SSLManager. Любые действия с ключами и внешними вызовами с SSL/TLS идут через инициализацию JsseSSLManager.
Если внимательно посмотреть в файл system.properties, то там будут присутствовать следующие строки:
#
#
# SSL properties (moved from jmeter.properties)
#
# See http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#Customization
# for information on the javax.ssl system properties
# Truststore properties (trusted certificates)
#javax.net.ssl.trustStore=/path/to/[jsse]cacerts
#javax.net.ssl.trustStorePassword
#javax.net.ssl.trustStoreProvider
#javax.net.ssl.trustStoreType [default = KeyStore.getDefaultType()]
# Keystore properties (client certificates)
# Location
#javax.net.ssl.keyStore=.keystore
#
#The password to your keystore
#javax.net.ssl.keyStorePassword=changeit
#
#javax.net.ssl.keyStoreProvider
#javax.net.ssl.keyStoreType [default = KeyStore.getDefaultType()]
Строки относящиеся к keyStore и trustStore позволяют указать параметры контейнеров содержащих ключи шифрования и доверенные сертификаты. Особенность ключевых контейнеров КриптоПро в том, что они не совместимы со штатными JKS контейнерами. Поэтому для их чтения необходима определенная последовательность действий.
Для использования ключей необходимо их скопировать из существующих установок КриптоПро или сгенерировать в поддерживающем ГОСТ 2012 УЦ. Способов тут два:
ручной
в ручном режиме создаётся дерево каталогов для хранения ключей пользователя и существующие ключи копируются в это деревоmkdir -p /var/opt/cprocsp/keys/<имя пользователя>
mkdir -p /var/opt/cprocsp/tmp && chmod 1777 /var/opt/cprocsp/tmp
cp -r CONTNR.000 /var/opt/cprocsp/keys/<имя пользователя>/
chown -R <имя пользователя>:<имя пользователя> /var/opt/cprocsp/keys/<имя пользователя>/через браузер
необходим браузер поддерживающий ГОСТ (chromium-gost, yandex browser) с установленным CADES плагином от КриптоПро и установленным КриптоПро CSP на машине.
При получении нового сертификата, плагин автоматически создаст структуру ключей в/var/opt/cprocsp/keys/
Так как ключевой контейнер является нестандартным, описание параметров для доступа к нему тоже нестандартное.-Dkeytool.compat=true -Duse.cert.stub=true -Djavax.net.ssl.keyStore=NONE -Djavax.net.ssl.keyStoreType=HDImageStore -Djavax.net.ssl.keyStorePassword=password
Особенностью загрузки ключей является то, что в параметр keyStore передаётся значение None, а в keyStoreType передаётся значение HDImageStore, JCP сам производит опрос имеющихся ключей и их загрузку. По сути для загрузки конкретного ключа можно в keyStore указать полное длинное имя ключа и библиотека будет искать ключ по указанному имени. Та же ситуация с TrustStore.
Проверяем ключи
Для проверки наличия в системе ключей и правильности их установки необходимо запустить keytool с дополнительными параметрами, определяющими провайдер для криптоконтейнера
$ cd jcp-2.0.41940-A
$ keytool -J-Dkeytool.compat=true -J-Duse.cert.stub=true -providerpath JCP.jar:ASN1P.jar:asn1rt.jar:forms_rt.jar:JCPRequest.jar:JCPRevCheck.jar:JCPRevTools.jar -list -v -provider ru.CryptoPro.JCP.JCP -keypass 12345678 -storepass 12345678 -storetype HDImageStore -keystore NONE
Если всё проинициализируется корректно, то вы увидите вот такую картинку
Dec 01, 2024 11:41:23 AM ru.CryptoPro.JCP.tools.Starter <init>
INFO: Loading JCP 2.0.41940-A
Dec 01, 2024 11:41:23 AM ru.CryptoPro.JCP.tools.Starter <init>
INFO: JCP has been loaded.
Keystore type: HDIMAGESTORE
Keystore provider: JCP
Your keystore contains 1 entry
Alias name: cfa32f2ab-cbcc-0192-7526-800bb263116
Creation date: Nov 29, 2024
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Test Certificate
Issuer: CN="Тестовый УЦ ООО \"КРИПТО-ПРО\"", O="ООО \"КРИПТО-ПРО\"", L=Москва, ST=г. Москва, C=RU, STREET=ул. Сущёвский вал д. 18, OID.1.2.643.3.131.1.1=#120c303031323334353637383930, OID.1.2.643.100.1=#120d31323334353637383930313233
Serial number: 7c0017a4b6df77756d6c303272000a0017a4b6
Valid from: Fri Nov 29 09:03:09 MSK 2024 until: Sat Jan 04 15:32:02 MSK 2025
Certificate fingerprints:
SHA1: B7:C3:67:82:13:99:A2:54:A5:E9:89:6A:6F:13:C6:95:0E:15:A7:50
SHA256: AD:07:89:A8:40:A5:F8:67:EB:DB:9A:88:EC:B9:29:F3:4B:73:3D:06:54:B1:9E:34:1E:57:9D:9A:F6:7D:D5:21
Signature algorithm name: GOST3411_2012_256WITHGOST3410_2012_256
Subject Public Key Algorithm: GOST3410_2012_256 key of unknown size
Version: 3
Extensions:
#1: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false
AuthorityInfoAccess [
[
accessMethod: ocsp
accessLocation: URIName: http://testgost2012.cryptopro.ru/ocsp2012g/ocsp.srf
,
accessMethod: ocsp
accessLocation: URIName: http://testgost2012.cryptopro.ru/ocsp2012gst/ocsp.srf
,
accessMethod: caIssuers
accessLocation: URIName: http://testgost2012.cryptopro.ru/CertEnroll/testgost2012(10).crt
,
accessMethod: caIssuers
accessLocation: URIName: http://testgost2012.cryptopro.ru/CertEnroll/testroot.p7b
]
]
#2: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: E4 C0 80 96 E4 B4 78 34 12 3C 22 B9 75 CD 96 20 ......x4.<".u..
0010: 43 30 B0 23 C0.#
]
]
#3: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
[DistributionPoint:
[URIName: http://testgost2012.cryptopro.ru/CertEnroll/!0422!0435!0441!0442!043e!0432!044b!0439%20!0423!0426%20!041e!041e!041e%20!0022!041a!0420!0418!041f!0422!041e-!041f!0420!041e!0022(10).crl, URIName: http://testgost2012.cryptopro.ru/CertEnroll/testgost2012(10).crl]
]]
#4: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
DigitalSignature
Non_repudiation
Key_Encipherment
Data_Encipherment
]
#5: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 48 CE CF 7A FD 83 87 A3 52 DB 4A EA 42 46 BF 7D H..z....R.J.BF..
0010: BC 99 FC 89 ....
]
]
*******************************************
*******************************************
Если получили ошибку, то проверьте правильность расположения ключей, права на файлы ключевого контейнера, пароли и доступность библиотек JCP
Пробуем загрузиться
Команду для старта я вынес в jmeter-run.sh, так удобнее отлаживаться.
#!/bin/bash
export JMETER_OPTS='-Djava.security.properties=java.security -Dkeytool.compat=true -Duse.cert.stub=true -Djavax.net.ssl.keyStore=NONE -Djavax.net.ssl.keyStoreType=HDImageStore -Djavax.net.ssl.keyStorePassword=12345678 -Djava.security.debug="jar,jca,keystore,provider,x509,properties"'
bin/jmeter
Первичный запуск с добавленными провайдерами, но без указания пути к библиотекам, приводит к ошибке.
/projects/jmeter_docker/apache-jmeter-6.0.0-GOST$ ./jmeter-run.sh
properties: java.security
properties: Initial security property: jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, DSA keySize < 1024, SHA1 denyAfter 2019-01-01
properties: Initial security property: jdk.security.legacyAlgorithms=SHA1, RSA keySize < 2048, DSA keySize < 2048
properties: Initial security property: crypto.policy=unlimited
properties: Initial security property: jceks.key.serialFilter=java.base/java.lang.Enum;java.base/java.security.KeyRep;java.base/java.security.KeyRep$Type;java.base/javax.crypto.spec.SecretKeySpec;!*
properties: Initial security property: login.configuration.provider=sun.security.provider.ConfigFile
properties: Initial security property: security.overridePropertiesFile=true
properties: Initial security property: jdk.tls.legacyAlgorithms=NULL, anon, RC4, DES, 3DES_EDE_CBC
properties: Initial security property: security.provider.7=SunSASL
properties: Initial security property: security.provider.8=XMLDSig
properties: Initial security property: security.provider.9=SunPCSC
properties: Initial security property: jdk.security.caDistrustPolicies=SYMANTEC_TLS
properties: Initial security property: security.provider.1=SUN
properties: Initial security property: security.provider.2=SunRsaSign
properties: Initial security property: security.provider.3=SunEC
properties: Initial security property: security.provider.4=SunJSSE
properties: Initial security property: networkaddress.cache.negative.ttl=10
properties: Initial security property: jdk.tls.alpnCharset=ISO_8859_1
properties: Initial security property: security.provider.5=SunJCE
properties: Initial security property: security.provider.6=SunJGSS
properties: Initial security property: ssl.KeyManagerFactory.algorithm=SunX509
properties: Initial security property: ssl.TrustManagerFactory.algorithm=PKIX
properties: Initial security property: policy.allowSystemProperty=true
properties: Initial security property: jdk.io.permissionsUseCanonicalPath=false
properties: Initial security property: package.access=sun.misc.,sun.reflect.,org.GNOME.Accessibility.
properties: Initial security property: package.definition=sun.misc.,sun.reflect.
properties: Initial security property: security.provider.13=ru.CryptoPro.JCP.JCP
properties: Initial security property: security.provider.12=SunPKCS11
properties: Initial security property: security.provider.15=ru.CryptoPro.Crypto.CryptoProvider
properties: Initial security property: security.provider.14=ru.CryptoPro.reprov.RevCheck
properties: Initial security property: policy.provider=sun.security.provider.PolicyFile
properties: Initial security property: policy.url.1=file:${java.home}/conf/security/java.policy
properties: Initial security property: policy.url.2=file:${user.home}/.java.policy
properties: Initial security property: securerandom.source=file:/dev/random
properties: Initial security property: jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, SHA1 usage SignedJAR & denyAfter 2019-01-01
properties: Initial security property: jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL
properties: Initial security property: policy.ignoreIdentityScope=false
properties: Initial security property: keystore.type.compat=true
properties: Initial security property: security.provider.11=JdkSASL
properties: Initial security property: security.provider.10=JdkLDAP
properties: Initial security property: jdk.sasl.disabledMechanisms=
....
ProviderConfig: Loading provider ru.CryptoPro.JCP.JCP
ProviderConfig: Attempt to load ru.CryptoPro.JCP.JCP using SL
ProviderConfig: Found SL Provider named JdkSASL
ProviderConfig: Found SL Provider named XMLDSig
ProviderConfig: Found SL Provider named SunPCSC
ProviderConfig: Found SL Provider named SunJGSS
ProviderConfig: Found SL Provider named SunEC
ProviderConfig: Found SL Provider named SunPKCS11
ProviderConfig: Found SL Provider named SunSASL
ProviderConfig: Found SL Provider named JdkLDAP
ProviderConfig: Loading legacy provider: ru.CryptoPro.JCP.JCP
ProviderConfig: Error loading legacy provider ru.CryptoPro.JCP.JCP
java.lang.ClassNotFoundException: ru.CryptoPro.JCP.JCP
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
....
2024-11-29 21:50:55,312 DEBUG o.a.h.i.e.MainClientExec: Opening connection {s}->https://www.cryptopro.ru:443
2024-11-29 21:50:55,423 INFO o.a.j.p.h.s.h.LazyLayeredConnectionSocketFactory: Setting up HTTPS TrustAll Socket Factory
2024-11-29 21:50:55,438 DEBUG o.a.j.p.h.s.HTTPHC4Impl$JMeterDefaultHttpClientConnectionOperator: Connecting to www.cryptopro.ru/193.37.157.43:443
2024-11-29 21:50:55,438 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Connecting socket to www.cryptopro.ru/193.37.157.43:443 with timeout 0
2024-11-29 21:50:55,447 DEBUG o.a.j.u.JsseSSLManager: Creating threadLocal SSL context for: Thread Group 1-1
2024-11-29 21:50:55,632 INFO o.a.j.u.SSLManager: JmeterKeyStore Location: NONE type HDImageStore
2024-11-29 21:50:55,646 DEBUG o.a.h.i.c.DefaultManagedHttpClientConnection: http-outgoing-0: Shutdown connection
2024-11-29 21:50:55,647 DEBUG o.a.h.i.e.MainClientExec: Connection discarded
2024-11-29 21:50:55,647 DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager: Connection released: [id: 0][route: {s}->https://www.cryptopro.ru:443][total available: 0; ro
ute allocated: 0 of 2; total allocated: 0 of 20]
2024-11-29 21:50:55,647 DEBUG o.a.j.p.h.s.HTTPHC4Impl: RuntimeException
java.lang.IllegalArgumentException: Could not create keystore: HDImageStore not found
at org.apache.jmeter.util.SSLManager.getKeyStore(SSLManager.java:133) ~[ApacheJMeter_core.jar:6.0.0-SNAPSHOT]
at org.apache.jmeter.util.JsseSSLManager.createContext(JsseSSLManager.java:235) ~[ApacheJMeter_core.jar:6.0.0-SNAPSHOT]
Это говорит о том, что Java не поняла наших настроек и не загрузила JCP.
Любые попытки загрузить классы путём добавления/изменения флагов/properties, чтоб их увидел jmeter ничем хорошим обычно не заканчиваются. Можно положить КриптоПро JCP библиотеки в lib/ext, но данный метод работает очень нестабильно.
Можно попробовать обойти указанную проблему через загрузку main класса
java -cp "*:bin/*:../lib/*:../lib/ext/*:../jcp-2.0.41940-A/*" -Dkeytool.compat=true -Duse.cert.stub=true -Djava.util.logging.ConsoleHandler.level=ALL -Dru.CryptoPro.ssl.SSLLogger.level=ALL -Dru.CryptoPro.ssl.SSLLogger.handlers=java.util.logging.ConsoleHandler -Djava.security.debug="jar,jca,keystore,provider,x509,properties" -Djavax.net.ssl.keyStore=NONE -Djavax.net.ssl.keyStoreType=HDImageStore -Djavax.net.ssl.keyStorePassword=12345678 -Djavax.net.ssl.trustStore=NONE -Djavax.net.ssl.trustStoreType=HDImageStore -Djavax.net.ssl.trustStorePassword=12345678 -Djavax.net.ssl.provider=ru.CryptoPro.JCP.JCP -Djava.security.properties=../java.security org.apache.jmeter.NewDriver
И jmeter даже увидит ключи
2024-11-29 22:34:34,653 DEBUG o.a.j.p.h.s.HTTPHC4Impl: Start : sample https://www.cryptopro.ru/certsrv/a3.gif method GET followingRedirect false depth 0
2024-11-29 22:34:34,753 DEBUG o.a.j.p.h.s.HTTPHC4Impl: Created new HttpClient: @1829529146 https://www.cryptopro.ru
2024-11-29 22:34:34,759 DEBUG o.a.j.p.h.c.HC4CookieHandler: Found 0 cookies for https://www.cryptopro.ru/certsrv/a3.gif
2024-11-29 22:34:34,759 DEBUG o.a.j.p.h.s.HTTPHC4Impl: Storing in HttpContext the user token: Thread Group 1-1
2024-11-29 22:34:34,780 DEBUG o.a.h.c.p.RequestAddCookies: CookieSpec selected: default
2024-11-29 22:34:34,781 DEBUG o.a.h.c.p.RequestAddCookies: Unsupported cookie policy: default
2024-11-29 22:34:34,781 DEBUG o.a.h.c.p.RequestAuthCache: Auth cache not set in the context
2024-11-29 22:34:34,783 DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager: Connection request: [route: {s}->https://www.cryptopro.ru:443][state: Thread Group 1-1][total available: 0; route allocated: 0 of 2; total allocated: 0 of 20]
2024-11-29 22:34:34,804 DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager: Connection leased: [id: 0][route: {s}->https://www.cryptopro.ru:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
2024-11-29 22:34:34,808 DEBUG o.a.h.i.e.MainClientExec: Opening connection {s}->https://www.cryptopro.ru:443
2024-11-29 22:34:34,827 INFO o.a.j.p.h.s.h.LazyLayeredConnectionSocketFactory: Setting up HTTPS TrustAll Socket Factory
2024-11-29 22:34:34,838 INFO o.a.j.u.JsseSSLManager: Using default SSL protocol: TLS
2024-11-29 22:34:34,838 INFO o.a.j.u.JsseSSLManager: SSL session context: per-thread
2024-11-29 22:34:34,838 INFO o.a.j.u.JsseSSLManager: SSL providers list: null
2024-11-29 22:34:34,853 DEBUG o.a.j.p.h.s.HTTPHC4Impl$JMeterDefaultHttpClientConnectionOperator: Connecting to www.cryptopro.ru/193.37.157.43:443
2024-11-29 22:34:34,853 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Connecting socket to www.cryptopro.ru/193.37.157.43:443 with timeout 0
2024-11-29 22:34:34,862 INFO o.a.j.u.SSLManager: Init null SSLManager
2024-11-29 22:34:34,864 DEBUG o.a.j.u.JsseSSLManager: ssl Provider = null
2024-11-29 22:34:34,869 DEBUG o.a.j.u.JsseSSLManager: SSL stuff all set
2024-11-29 22:34:34,869 DEBUG o.a.j.u.JsseSSLManager: JsseSSLManager installed
2024-11-29 22:34:34,869 INFO o.a.j.u.SSLManager: Reuse SSLManager: org.apache.jmeter.util.JsseSSLManager@3769c4b0
2024-11-29 22:34:34,870 DEBUG o.a.j.u.JsseSSLManager: Creating threadLocal SSL context for: Thread Group 1-1
2024-11-29 22:34:34,989 INFO o.a.j.u.SSLManager: JmeterKeyStore Location: NONE type HDImageStore
2024-11-29 22:34:35,579 INFO o.a.j.u.SSLManager: KeyStore created OK
2024-11-29 22:34:35,579 WARN o.a.j.u.SSLManager: No password provided, and no GUI present so cannot prompt
2024-11-29 22:34:37,137 DEBUG o.a.j.u.k.JmeterKeyStore: Certificate at index 1 with alias cfa32f2ab-cbcc-0192-7526-800bb263116
2024-11-29 22:34:37,479 DEBUG o.a.j.u.k.JmeterKeyStore: Subject DN: CN=Test Certificate
2024-11-29 22:34:37,480 DEBUG o.a.j.u.k.JmeterKeyStore: Issuer DN: CN="Тестовый УЦ ООО \"КРИПТО-ПРО\"", O="ООО \"КРИПТО-ПРО\"", L=Москва, ST=г. Москва, C=RU, STREET=ул. Сущёвский вал д. 18, OID.1.2.643.3.131.1.1=#120c303031323334353637383930, OID.1.2.643.100.1=#120d31323334353637383930313233
2024-11-29 22:34:37,481 DEBUG o.a.j.u.k.JmeterKeyStore: Not valid before: 2024-11-29T06:03:09Z
2024-11-29 22:34:37,482 DEBUG o.a.j.u.k.JmeterKeyStore: Not valid after: 2025-01-04T12:32:02Z
2024-11-29 22:34:38,522 INFO o.a.j.u.SSLManager: Total of 1 aliases loaded OK from PKCS11
2024-11-29 22:34:38,522 DEBUG o.a.j.u.SSLManager: JmeterKeyStore type: class org.apache.jmeter.util.keystore.JmeterKeyStore
2024-11-29 22:34:38,523 DEBUG o.a.j.u.JsseSSLManager: JmeterKeyStore type: class org.apache.jmeter.util.keystore.JmeterKeyStore
2024-11-29 22:34:38,525 INFO o.a.j.u.SSLManager: TrustStore Location: NONE
2024-11-29 22:34:38,529 INFO o.a.j.u.SSLManager: TrustStore created OK, Type: JKS
2024-11-29 22:34:38,529 WARN o.a.j.u.SSLManager: Truststore file not found, loading empty truststore
Но во первых это не очень красиво, во вторых не решает проблему ГОСТ TLS трафика, т.к. ключ грузится от КриптоПро, а соединение устанавливается через RSA TLS
2024-11-29 22:34:38,552 DEBUG o.a.j.u.JsseSSLManager: Supported Cipher: TLS_EMPTY_RENEGOTIATION_INFO_SCSV
2024-11-29 22:34:38,553 DEBUG o.a.j.u.JsseSSLManager: Using threadLocal SSL context for: Thread Group 1-1
2024-11-29 22:34:38,637 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Enabled protocols: [TLSv1.3, TLSv1.2]
2024-11-29 22:34:38,638 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Enabled cipher suites:[TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
2024-11-29 22:34:38,639 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Starting handshake
2024-11-29 22:34:38,740 DEBUG o.a.j.u.CustomX509TrustManager: Server certificate 1:
Subject DN: CN=*.cryptopro.ru, O=Crypto-Pro LLC, L=Moscow, ST=Moscow, C=RU
Signature Algorithm: SHA256withRSA
Valid from: 2024-03-25T13:38:39.000+0300
Valid until: 2025-04-26T13:38:38.000+0300
Issuer: CN=GlobalSign RSA OV SSL CA 2018, O=GlobalSign nv-sa, C=BE
2024-11-29 22:34:38,740 DEBUG o.a.j.u.CustomX509TrustManager: Server certificate 2:
Subject DN: CN=GlobalSign RSA OV SSL CA 2018, O=GlobalSign nv-sa, C=BE
Signature Algorithm: SHA256withRSA
Valid from: 2018-11-21T03:00:00.000+0300
Valid until: 2028-11-21T03:00:00.000+0300
Issuer: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R3
2024-11-29 22:34:38,810 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Secure session established
2024-11-29 22:34:38,810 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: negotiated protocol: TLSv1.2
2024-11-29 22:34:38,810 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
2024-11-29 22:34:38,811 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: peer principal: CN=*.cryptopro.ru, O=Crypto-Pro LLC, L=Moscow, ST=Moscow, C=RU
2024-11-29 22:34:38,811 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: peer alternative names: [*.cryptopro.ru, cryptopro.ru]
2024-11-29 22:34:38,811 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: issuer principal: CN=GlobalSign RSA OV SSL CA 2018, O=GlobalSign nv-sa, C=BE
2024-11-29 22:34:38,812 DEBUG o.a.j.p.h.s.HTTPHC4Impl$JMeterDefaultHttpClientConnectionOperator: Connection established 192.168.68.105:54872<->193.37.157.43:443
2024-11-29 22:34:38,812 DEBUG o.a.h.i.e.MainClientExec: Executing request GET /certsrv/a3.gif HTTP/1.1
Решив найти причину такого поведения, взор был обращён на исходный код JsseSSLManager. Как оказалось, "фича" загрузки внешних провайдеров находится в статусе "TODO", ну и собственно инициализация SSLContext вызывается с пустым идентификатором провайдера. Что естественно не позволяет правильно инициализировать механизмы крипропровайдеров.
Было решено добавить механизм динамической загрузки внешних провайдеров по имени класса. Патч добавляет несколько строк и позволяет, в виде перечисления, указать через запятую список используемых провайдеров.
diff --git a/src/core/src/main/java/org/apache/jmeter/util/JsseSSLManager.java b/src/core/src/main/java/org/apache/jmeter/util/JsseSSLManager.java
index f4ca272c59..e10f6cb4a0 100644
--- a/src/core/src/main/java/org/apache/jmeter/util/JsseSSLManager.java
+++ b/src/core/src/main/java/org/apache/jmeter/util/JsseSSLManager.java
@@ -17,6 +17,7 @@
package org.apache.jmeter.util;
+import java.lang.reflect.Constructor;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.security.GeneralSecurityException;
@@ -62,6 +63,9 @@ public class JsseSSLManager extends SSLManager {
private static final boolean SHARED_SESSION_CONTEXT =
JMeterUtils.getPropDefault("https.sessioncontext.shared",false); // $NON-NLS-1$
+ private static final String SSL_PROVIDER_CLASSES_LIST =
+ JMeterUtils.getPropDefault("https.providers",null); // $NON-NLS-1$
+
/**
* Characters per second, used to slow down sockets
*/
@@ -71,6 +75,7 @@ public class JsseSSLManager extends SSLManager {
if (log.isInfoEnabled()) {
log.info("Using default SSL protocol: {}", DEFAULT_SSL_PROTOCOL);
log.info("SSL session context: {}", SHARED_SESSION_CONTEXT ? "shared" : "per-thread");
+ log.info("SSL providers list: {}", SSL_PROVIDER_CLASSES_LIST);
if (CPS > 0) {
log.info("Setting up HTTPS SlowProtocol, cps={}", CPS);
@@ -97,6 +102,23 @@ public class JsseSSLManager extends SSLManager {
*/
public JsseSSLManager(Provider provider) {
log.debug("ssl Provider = {}", provider);
+ if (SSL_PROVIDER_CLASSES_LIST != null) {
+ log.debug("ssl Provider classes list = {}", SSL_PROVIDER_CLASSES_LIST);
+ String[] providerclasses = SSL_PROVIDER_CLASSES_LIST.split(",");
+ for (String providerclass : providerclasses) {
+ if (providerclass == null) {
+ continue;
+ }
+ try {
+ Class<?> cl = Class.forName(providerclass);
+ Constructor<?> con = cl.getConstructor();
+ setProvider((Provider) con.newInstance());
+ log.info("Added provider class {}", providerclass);
+ } catch (Exception ex) {
+ log.error(ex.getMessage(), ex);
+ }
+ }
+ }
setProvider(provider);
if (null == this.rand) { // Surely this is always null in the constructor?
this.rand = new SecureRandom();
Для корректной инициализации контекста теперь достаточно добавить в user.properties два параметра: список провайдеров для загрузки и используемый протокол.
https.providers=ru.CryptoPro.ssl.Provider,ru.CryptoPro.Crypto.CryptoProvider,ru.CryptoPro.JCP.JCP,ru.CryptoPro.reprov.RevCheck
https.default.protocol=GostTLS
И всё, как по мановению волшебной палочки, начинает работать как нужно
024-11-30 20:05:09,854 DEBUG o.a.h.i.e.MainClientExec: Opening connection {s}->https://www.cryptopro.ru:443
2024-11-30 20:05:09,866 INFO o.a.j.p.h.s.h.LazyLayeredConnectionSocketFactory: Setting up HTTPS TrustAll Socket Factory
2024-11-30 20:05:09,873 INFO o.a.j.u.JsseSSLManager: Using default SSL protocol: GostTLS
2024-11-30 20:05:09,873 INFO o.a.j.u.JsseSSLManager: SSL session context: per-thread
2024-11-30 20:05:09,874 INFO o.a.j.u.JsseSSLManager: SSL providers list: ru.CryptoPro.ssl.Provider,ru.CryptoPro.Crypto.CryptoProvider,ru.CryptoPro.JCP.JCP,ru.CryptoPro.reprov.RevCheck
2024-11-30 20:05:09,888 DEBUG o.a.j.p.h.s.HTTPHC4Impl$JMeterDefaultHttpClientConnectionOperator: Connecting to www.cryptopro.ru/193.37.157.43:443
2024-11-30 20:05:09,888 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Connecting socket to www.cryptopro.ru/193.37.157.43:443 with timeout 0
2024-11-30 20:05:09,905 INFO o.a.j.u.SSLManager: Init null SSLManager
2024-11-30 20:05:09,907 DEBUG o.a.j.u.JsseSSLManager: ssl Provider = null
2024-11-30 20:05:09,907 DEBUG o.a.j.u.JsseSSLManager: ssl Provider classes list = ru.CryptoPro.ssl.Provider,ru.CryptoPro.Crypto.CryptoProvider,ru.CryptoPro.JCP.JCP,ru.CryptoPro.reprov.RevCheck
2024-11-30 20:05:10,041 INFO o.a.j.u.JsseSSLManager: Added provider class ru.CryptoPro.ssl.Provider
2024-11-30 20:05:10,047 INFO o.a.j.u.JsseSSLManager: Added provider class ru.CryptoPro.Crypto.CryptoProvider
2024-11-30 20:05:10,094 INFO o.a.j.u.JsseSSLManager: Added provider class ru.CryptoPro.JCP.JCP
2024-11-30 20:05:10,096 INFO o.a.j.u.JsseSSLManager: Added provider class ru.CryptoPro.reprov.RevCheck
2024-11-30 20:05:10,098 DEBUG o.a.j.u.JsseSSLManager: SSL stuff all set
2024-11-30 20:05:10,102 DEBUG o.a.j.u.JsseSSLManager: JsseSSLManager installed
2024-11-30 20:05:10,102 INFO o.a.j.u.SSLManager: Reuse SSLManager: org.apache.jmeter.util.JsseSSLManager@7a305e49
2024-11-30 20:05:10,102 DEBUG o.a.j.u.JsseSSLManager: Creating threadLocal SSL context for: Thread Group 1-1
2024-11-30 20:05:10,126 INFO o.a.j.u.SSLManager: JmeterKeyStore Location: NONE type HDImageStore
2024-11-30 20:05:10,128 INFO o.a.j.u.SSLManager: KeyStore created OK
2024-11-30 20:05:10,128 WARN o.a.j.u.SSLManager: No password provided, and no GUI present so cannot prompt
2024-11-30 20:05:11,119 DEBUG o.a.j.u.k.JmeterKeyStore: Certificate at index 1 with alias cfa32f2ab-cbcc-0192-7526-800bb263116
2024-11-30 20:05:11,186 DEBUG o.a.j.u.k.JmeterKeyStore: Subject DN: CN=Test Certificate
2024-11-30 20:05:11,187 DEBUG o.a.j.u.k.JmeterKeyStore: Issuer DN: CN="Тестовый УЦ ООО \"КРИПТО-ПРО\"", O="ООО \"КРИПТО-ПРО\"", L=Москва, ST=г. Москва, C=RU, STREET=ул. Сущёвский вал д. 18, OID.1.2.643.3.131.1.1=#120c303031323334353637383930, OID.1.2.643.100.1=#120d31323334353637383930313233
2024-11-30 20:05:11,188 DEBUG o.a.j.u.k.JmeterKeyStore: Not valid before: 2024-11-29T06:03:09Z
2024-11-30 20:05:11,188 DEBUG o.a.j.u.k.JmeterKeyStore: Not valid after: 2025-01-04T12:32:02Z
2024-11-30 20:05:11,514 INFO o.a.j.u.SSLManager: Total of 1 aliases loaded OK from PKCS11
2024-11-30 20:05:11,514 DEBUG o.a.j.u.SSLManager: JmeterKeyStore type: class org.apache.jmeter.util.keystore.JmeterKeyStore
2024-11-30 20:05:11,515 DEBUG o.a.j.u.JsseSSLManager: JmeterKeyStore type: class org.apache.jmeter.util.keystore.JmeterKeyStore
2024-11-30 20:05:11,598 DEBUG o.a.j.u.JsseSSLManager: Default Cipher: TLS_CIPHER_2012
2024-11-30 20:05:11,598 DEBUG o.a.j.u.JsseSSLManager: Supported Cipher: TLS_CIPHER_2012
2024-11-30 20:05:11,598 DEBUG o.a.j.u.JsseSSLManager: Default Cipher: TLS_CIPHER_2001
2024-11-30 20:05:11,599 DEBUG o.a.j.u.JsseSSLManager: Supported Cipher: TLS_CIPHER_2001
2024-11-30 20:05:11,599 DEBUG o.a.j.u.JsseSSLManager: Using threadLocal SSL context for: Thread Group 1-1
2024-11-30 20:05:11,619 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Enabled protocols: [TLSv1.2]
2024-11-30 20:05:11,619 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Enabled cipher suites:[TLS_CIPHER_2012, TLS_CIPHER_2001]
2024-11-30 20:05:11,619 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Starting handshake
2024-11-30 20:05:11,660 DEBUG o.a.j.u.CustomX509TrustManager: Server certificate 1:
Subject DN: CN="Веб-сервер ООО \"КРИПТО-ПРО\"", C=RU, ST=г. Москва, L=Москва, O="ООО \"КРИПТО-ПРО\""
Signature Algorithm: GOST3411_2012_256WITHGOST3410_2012_256
Valid from: 2024-03-26T12:47:39.000+0300
Valid until: 2025-06-26T12:47:39.000+0300
Issuer: CN=CryptoPro TLS CA, O="LLC \"Crypto-Pro\"", L=Moscow, ST=Moscow, C=RU, OID.1.2.643.100.1=#120d31303337373030303835343434, OID.1.2.643.100.4=#120a37373137313037393931
2024-11-30 20:05:11,660 DEBUG o.a.j.u.CustomX509TrustManager: Server certificate 2:
Subject DN: CN=CryptoPro TLS CA, O="LLC \"Crypto-Pro\"", L=Moscow, ST=Moscow, C=RU, OID.1.2.643.100.1=#120d31303337373030303835343434, OID.1.2.643.100.4=#120a37373137313037393931
Signature Algorithm: GOST3411_2012_256WITHGOST3410_2012_256
Valid from: 2022-12-19T16:56:08.000+0300
Valid until: 2032-12-19T16:56:08.000+0300
Issuer: CN=CryptoPro GOST Root CA, O="LLC \"Crypto-Pro\"", L=Moscow, ST=Moscow, C=RU, OID.1.2.643.3.131.1.1=#120c303037373137313037393931, OID.1.2.643.100.1=#120d31303337373030303835343434
2024-11-30 20:05:11,661 DEBUG o.a.j.u.CustomX509TrustManager: Server certificate 3:
Subject DN: CN=CryptoPro GOST Root CA, O="LLC \"Crypto-Pro\"", L=Moscow, ST=Moscow, C=RU, OID.1.2.643.3.131.1.1=#120c303037373137313037393931, OID.1.2.643.100.1=#120d31303337373030303835343434
Signature Algorithm: GOST3411_2012_256WITHGOST3410_2012_256
Valid from: 2022-12-19T18:10:59.000+0300
Valid until: 2032-12-19T18:10:59.000+0300
Issuer: CN=CryptoPro GOST Root CA, O="LLC \"Crypto-Pro\"", L=Moscow, ST=Moscow, C=RU, OID.1.2.643.3.131.1.1=#120c303037373137313037393931, OID.1.2.643.100.1=#120d31303337373030303835343434
2024-11-30 20:05:11,997 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: Secure session established
2024-11-30 20:05:11,997 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: negotiated protocol: TLSv1.2
2024-11-30 20:05:11,998 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: negotiated cipher suite: TLS_CIPHER_2012
2024-11-30 20:05:11,998 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: peer principal: CN="Веб-сервер ООО \"КРИПТО-ПРО\"", C=RU, ST=г. Москва, L=Москва, O="ООО \"КРИПТО-ПРО\""
2024-11-30 20:05:11,998 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: peer alternative names: [*.cryptopro.ru, cryptopro.ru, *.crypto-pro.ru, crypto-pro.ru, xn--h1adnadbdep.xn--p1ai]
2024-11-30 20:05:11,998 DEBUG o.a.h.c.s.SSLConnectionSocketFactory: issuer principal: CN=CryptoPro TLS CA, O="LLC \"Crypto-Pro\"", L=Moscow, ST=Moscow, C=RU, OID.1.2.643.100.1=#120d31303337373030303835343434, OID.1.2.643.100.4=#120a37373137313037393931
2024-11-30 20:05:11,999 DEBUG o.a.j.p.h.s.HTTPHC4Impl$JMeterDefaultHttpClientConnectionOperator: Connection established 192.168.68.105:50590<->193.37.157.43:443
2024-11-30 20:05:11,999 DEBUG o.a.h.i.e.MainClientExec: Executing request GET /certsrv/a3.gif HTTP/1.1
2024-11-30 20:05:11,999 DEBUG o.a.h.i.e.MainClientExec: Target auth state: UNCHALLENGED
2024-11-30 20:05:12,000 DEBUG o.a.h.i.e.MainClientExec: Proxy auth state: UNCHALLENGED
2024-11-30 20:05:12,001 DEBUG o.a.h.headers: http-outgoing-0 >> GET /certsrv/a3.gif HTTP/1.1
2024-11-30 20:05:12,001 DEBUG o.a.h.headers: http-outgoing-0 >> Connection: keep-alive
2024-11-30 20:05:12,001 DEBUG o.a.h.headers: http-outgoing-0 >> Host: www.cryptopro.ru
2024-11-30 20:05:12,001 DEBUG o.a.h.headers: http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.13)
2024-11-30 20:05:12,002 DEBUG o.a.h.wire: http-outgoing-0 >> "GET /certsrv/a3.gif HTTP/1.1[\r][\n]"
2024-11-30 20:05:12,002 DEBUG o.a.h.wire: http-outgoing-0 >> "Connection: keep-alive[\r][\n]"
2024-11-30 20:05:12,002 DEBUG o.a.h.wire: http-outgoing-0 >> "Host: www.cryptopro.ru[\r][\n]"
2024-11-30 20:05:12,002 DEBUG o.a.h.wire: http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.14 (Java/17.0.13)[\r][\n]"
2024-11-30 20:05:12,002 DEBUG o.a.h.wire: http-outgoing-0 >> "[\r][\n]"
2024-11-30 20:05:12,003 DEBUG o.a.j.p.h.s.HTTPHC4Impl: Sent 133 bytes
2024-11-30 20:05:12,018 DEBUG o.a.h.wire: http-outgoing-0 << "HTTP/1.1 200 OK[\r][\n]"
2024-11-30 20:05:12,018 DEBUG o.a.h.wire: http-outgoing-0 << "Server: nginx[\r][\n]"
2024-11-30 20:05:12,018 DEBUG o.a.h.wire: http-outgoing-0 << "Date: Sat, 30 Nov 2024 17:01:11 GMT[\r][\n]"
2024-11-30 20:05:12,018 DEBUG o.a.h.wire: http-outgoing-0 << "Content-Type: image/gif[\r][\n]"
2024-11-30 20:05:12,018 DEBUG o.a.h.wire: http-outgoing-0 << "Content-Length: 49[\r][\n]"
Если сервер поддерживает mTLS, то в логах вы увидите результаты mTLS Handshake.
Данный механизм был проверен на нескольких сайтах поддерживающих ГОСТ TLS. Тех кто будет экспериментировать с сайтом www.cryptopro.ru сразу предупреждаю, после первых 60rps вы получите permban на ваш внешний адрес. Поэтому если хотите проверять корректность работы, да простит меня компания КриптоПро, не выставляйте количество ниток более 1. Так же рекомендую вызывать для теста статический контент, например https://www.crypropro.ru/certsrv/a3.gif.
Подведём итог. Для внедрения ГОСТ криптографии в Jmeter необходимо:
Создать локальную конфигурацию java.security добавив строки с криптопровадерами из библиотек КриптоПро JCP
Добавить параметры user.classpath,https.providers,https.default.protocol в файл user.properties
Создать файл для запуска jmeter с указанием параметров ключей, либо прописать данные параметры в security.properties или user.properties
Иметь в наличии КриптоПро ГОСТ ключи в виде КриптоПро контейнера
Пересобрать необходимую версию Jmeter применив к коду указанный в статье патч
При первичной отладке выставить параметры раширенной детализации в java.security.debug
PS: Для долгосрочной промышленной эксплуатации крайне рекомендуется приобретение лицензии на право использования СКЗИ КриптоПро JCP версии 2.0 на одном рабочем месте стоимостью 1200 рублей.
Удачного тестирования!
Ghool
Респект!
теперь можно грузить ГостТЛС без прослоек-переадресаторов в виде IIS+CryptoPro+URLRewrite