I'm having trouble setting up a reverse proxy through nginx to a websocket application with client certificate authentication; so far I've gotten the server SSL cert to work no problem. Here are my steps so far for the client auth:
Create the client cert:
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
openssl genrsa -out client.key 1024
openssl req -new -key client.key -out client.csr
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey \
ca.key -set_serial 01 -out client.crt
Configure nginx:
daemon off;
events {
worker_connections 4096;
}
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443;
ssl on;
server_name rserve;
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
# ssl_client_certificate /etc/nginx/certs/ca.crt;
# ssl_verify_client on;
location / {
proxy_pass http://localhost:8081;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
If I enable the ssl client stuff things stop working. On the client I'm using a jetty implementation (java), I import the client cert into a keystore with this line:
keytool -import -trustcacerts -keystore keystore.jks \
-storepass changeit -noprompt -alias client -file client.crt
This procedure worked for a selfsigned server cert. The failure is reported on the client as a failure to switch protocols, this is in line with my previous failures on behalf of the SSL handshake - the proxied application is websocket only.
You created the private key outside of the keystore and have now imported just the certificate. The client application needs access to both the private and public parts.
Either import the private key or generate the certificate signing request using keytool rather than openssl.
Related
I have been provided with:
A private key (-----BEGIN RSA PRIVATE KEY-----)
Intermediate CA cert (-----BEGIN CERTIFICATE-----)
Root CA cert (-----BEGIN CERTIFICATE-----)
SSL connectivity exists and I have proven this successfully using curl;
curl -vv https://thirdparty.service.com --key private.pem --cert cert.crt
However, I wish to establish this SSL connection using Java. Given this, I know I need to import these certificates and key into my Java keystore.
I initially imported the Intermediate and Root CA certs only into my Java keystore but I could not establish a successful SSL connection to the third party service. Based on my curl command, I realised that I need to somehow import the private key into the Java keystore.
I have tried many openssl/keytool commands and this is the current combination/command I have running. I still cannot establish an SSL connection using Java.
cat cert.crt cachain.crt > import.pem
echo "pazzword" > pazzword.txt
openssl pkcs12 -export -in import.pem -inkey privkey.pem -name my_bundle -passout file:pazzword.txt > server.p12
${JAVA_HOME}/bin/keytool -importkeystore -srckeystore server.p12 -destkeystore ${JAVA_HOME}/jre/lib/security/cacerts -srcstoretype pkcs12 -srcstorepass pazzword -deststorepass changeit
Versions:
openjdk version "1.8.0_345"
OpenSSL 3.0.7 1 Nov 2022 (Library: OpenSSL 3.0.7 1 Nov 2022)
Can someone please help clarify what I should be doing with the certs and key I have above?
A successful SSL connection using my Java
I'am running Appium java test cases to fetch some api but the api doesn't accessible and return an error
javax.mail.MessangingException: Connect Failed; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
I've created a certificate for my website www.example.com from here.
openssl req \
-x509 -nodes -days 365 -sha256 \
-newkey rsa:2048 -keyout mycert.pem -out mycert.pem
then try to import mycert.pem to jre via
$JAVA_HOME/bin/keytool -import -alias mycertificate -keystore path_to_keystore -file certificate_file
but got another error
keytool input not an x.509 certificate
i've check the certificate is not corrupted with
openssl x509 -in mycert.pem -text
I have Spring Boot (backend) application which is running on Tomcat (port 8080) and Angular app (frontend) (port 4200).
Frontend consumes rest API from backend. How can I secure my applications using Nginx with SSL?
I have heard i could configure my Spring Boot as reverse proxy in nginx and then secure it with SSL but i dont know how to do it.
both spring boot and nginx should configure to get https.
for java and spring boot you should create certificate file using keytool that you can find it in jdk/bin.
keytool -genkey -alias <desired certificate alias>
-keystore <path to keystore.pfx>
-storetype PKCS12
-keyalg RSA
-storepass <password>
-validity 730
-keysize 2048
then put .p12 file beside application.properties.
for spring boot you should add this in your application.properties or application.yml:
server.ssl.enabled=true
server.ssl.key-store=classpath:client.p12
server.ssl.key-store-password=<password>
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=<desired certificate alias>
after that we should create certificate file for angular and nginx and add some configuration to nginx.conf.
for creating certificate file you can use openssl tool.
create openssl-custom.cnf file add put blow code in that:
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn
[dn]
C = US
ST = utah
L = US
O = IT
OU = IT Section
emailAddress = info#example.com
CN = localhost
[v3_req]
subjectAltName = #alt_names
[alt_names]
DNS.1 = *.localhost
DNS.2 = localhost
and then open terminal or cmd and run this command:
#!/bin/bash
openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.key \
-new \
-out server.crt \
-config ./openssl-custom.cnf \
-sha256 \
-days 365
then put server.key and server.crt in you angular project and add these code to nginx.conf:
listen 443 ssl;
ssl_certificate <path to .crt file>/server.crt;
ssl_certificate_key <path to .key file>/server.key;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
! for using ssl in nginx you should use port 443 not 80;
! for testing your angular open new tab and don't use your old tab
I'm trying to send an X.509 client certificate with outgoing requests for zuul forwardproxy. Certificate is included in the keystore which i'm loading with loadKeyMaterial() on SSLContext.
Here's the code:
#Bean
public CloseableHttpClient httpClient() throws Throwable {
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(new File(keyStorePath), keyStorePass, keyStorePass, new PrivateKeyStrategy() {
#Override
public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) {
return alias;
}
})
.loadTrustMaterial(new File(keyStorePath), keyStorePass, new TrustSelfSignedStrategy())
.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[] { "TLSv1.3" },
new String[] { "TLS_DHE_RSAWITH_AES_256_GCM_SHA384" },
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
return HttpClients.custom().setSSLSocketFactory(sslsf)
.build();
}
when i make a test request i'm getting Received fatal alert: handshake_failure and on the verbose logs i see the message No X.509 certificate for client authentication, use empty Certificate message instead. How i can make the httpClient send the certificate as X.509 client certificate?
I had encountered simmilar problem in my case it was two part solution.
Import correcly certificate,
I had incorrectly created keystore:
keytool -importcert -keystore keystore.jks -alias client-cert -file client-cert.pem -storepass password
What helped me was:
openssl pkcs12 -export -chain -in client-cert.pem -inkey client-key.pem -out keystore.p12 -name client-cert -CAfile ca-cert.pem
keytool -importkeystore -destkeystore keystore.jks -srckeystore keystore.p12 -alias client-cert
I found this here:
https://blogs.oracle.com/jtc/installing-trusted-certificates-into-a-java-keystore
Problem with spring-cloud-starter-zuul 1.1.5.RELEASE. Zuul did not used my custom CloseableHttpClient, this issue was solved in https://github.com/spring-cloud/spring-cloud-netflix/issues/2026 and after upgrading to 1.4.2.RELEASE this problem was fixed.
i want to configure SSL for mutual authentication.
I work with eclipse + tomcat 8.
I do this passages:
I created private keys in this way:
openssl genrsa -des3 -out client_key.pem 2048
openssl genrsa -des3 -out server_key.pem 2048
I created self-signed certificates:
openssl req -new -x509 -key client_key.pem -out client.pem -days 365 -config <path to>\openssl.cnf
openssl req -new -x509 -key server_key.pem -out server.pem -days 365 -config <path to>\openssl.cnf
I created truststore and import certificates:
keytool –importcert -trustcacerts –keystore clienttruststore.jks –storetype jks –storepass <truststore_password> -file <path-to-file>\server.pem
keytool –importcert -trustcacerts –keystore servertruststore.jks –storetype jks –storepass <server_truststore_password> -file <path-to-file>\client.pem
I combined the certificate and the private key for the server and client respectively:
openssl pkcs12 –export –inkey client_key.pem –in client.pem –out client.p12
openssl pkcs12 –export –inkey server_key.pem –in server.pem –out server.p12
and finally i converted the keystore in pkcs12 format:
keytool –importkeystore –srckeystore client.p12 –srcstoretype pkcs12 –destkeystore client.jks –deststoretype jks
keytool –importkeystore –srckeystore server.p12 –srcstoretype pkcs12 –destkeystore server.jks –deststoretype jks
After this, i configured configure SSL/TLS support on Tomcat. So, i configured server.xml in Servers folder and setup the connector in this way:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="path\to\server.jks" keystorePass="*******" keystoreType="JKS"
truststoreFile="path\to\servertruststore.jks" truststorePass="********" truststoreType="JKS" />
Finally i clean and build the project.
I created a Dynamic Web Project in Eclipse that called "myproject". It works well.
The problem is that when myproject runs on server at URL https://localhost:8443/myproject
Google Chrome shows the red triangle (This page is insecure (broken HTTPS)).
What's wrong?
Where do i put client.jks e clienttruststore.jks in my project?
This picture shows problem:
Your certificates are self signed, meaning they are not signed by CA, meaning Chrome cannot trust them unless you approve them manually.
When generating certificate did you provide CN? It must match the hostname that you are using (in your case it's localhost), if CN doesn't match, Chrome will not allow SSL unless you approve it manually.
You said you want the mutual authentication, but you configured clientAuth="false" It should be true. As for the keystore, you supposed to use the same keystore for the certificates, therefore when client connects with it's certificate, tomcat will validate that corresponding certificate is located in the keystore.
Hope it helps.