Can't get my Tomcat to connect using port 443 (https) - ssl

for the past two days I've been trying to do one thing, be able to access my webapp (localhost:8080/evop) as www.gestao.com.br and furthermore enable https on my web server so that https://www.gestao.com.br also works.
Summary
I need to have a localhost web application showing the https in front of it's URL (not the crossed red https).
PS: Using Tomcat as the web server and Windows and the host OS.
Explanation
We install Tomcat on each client so they can run our webapp locally at their companies, after sometime we started receiving some complaints that the connection is not secure, even though they are locally, so in order to please our client we decided to enable SSL on their Tomcat servers locally.
Using the keytool provided with JDK it was quite easy to enable https on the server, however the https was crossed by a read line because it was self-signed. At this point I knew a CA was needed to sign the certificate, but since this was all done locally and there were no real domains bought, using a CA like LetsEncrypt was not possible.
So enough of a background story, basically I have a Tomcat server on a Windows 10 machine and it needs to have a signed SSL certificate so the applications hosted on that server have https in front of their urls (not the crossed https)
What I did
In order to do that I found out I was gonna have to be my own CA. Here are my steps:
1. Being able to access my webapp using only a local domain www.gestao.com.br
My webapp url was localhost:8080/evop; However, I changed C:\Windows\System32\drivers\etc\hosts by adding 127.0.0.1 www.gestao.com.br to the end of the file, so I could access it using www.gestao.com.br:8080/evop
I solved the port in the URL problem by editing the server.xml on Tomcat conf folder and adding:
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" />
With that I was able to access it using www.gestao.com.br/evop
Last step was to change the folder called evop on Tomcat's webapps folder to ROOT and I was able to load my application with wwww.gestao.com.br
2. Becoming my own CA
Created a private key with:
openssl genrsa -des3 -out rootSSL.key 2048
Created the root certificate file:
openssl req -x509 -new -nodes -key rootSSL.key -sha256 -days 1024 -out rootSSL.pem
Added my new created root certificate to Microsoft Management Console (MMC) so Windows knows it can trust certificates signed by me.
3. Creating and signing a certificate for my own application
Created a private key for the new local domain with:
openssl req -new -sha256 -nodes -out gestao.csr -newkey rsa:2048 -keyout gestao.key -subj "/C=BR/ST=MS/L=Campo Grande/O=Evop/OU=Dev/CN=www.gestao.com.br/emailAddress=dev#evop.com.br"
Issue the certificate with:
openssl x509 -req -in gestao.csr -CA rootSSL.pem -CAkey rootSSL.key -CAcreateserial -out gestao.crt -days 500 -sha256 -extensions "authorityKeyIdentifier=keyid,issuer\n basicConstraints=CA:FALSE\n keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment\n subjectAltName=DNS:www.gestao.com.br"
4. Configure Tomcat to use the certificate
I tried this two ways, first I opened a powershell on Tomcat conf folder to use rootSSL.pem to create a keystore using JDK's keytool with:
keytool -import -alias root -keystore tomcat.jks -trustcacerts -file rootSSL.pem
Then I also added the local domain certificate with:
keytool -import -alias tomcat -keystore tomcat.jks -file gestao.crt
After that I configured a connector on server.xml like so:
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="443" />
<Connector port="443" protocol="HTTP/1.1" maxThreads="150" SSLEnabled="true" compression="on" scheme="https" secure="true" keystoreFile="conf/tomcat.jks" keyAlias="tomcat" keystorePass="password" clientAuth="false" SSLVerifyClient="none" sslProtocol="TLSv1.2" />
However I was only able to access Tomcat using the 8080 port, if I tried to access it using port 443 I got a connection refused error.
Secondly I tried not using the keytool and setting the local domain certificate and key directly into the conector, like so:
<Connector port="443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/gestao.key" certificateFile="conf/gestao.crt" type="RSA" />
</SSLHostConfig>
</Connector>
However, that also did not let me connect using the 443 port.
References
Wil Brown’s article - Be your own certificate authority (CA) and issue certificates for your local development environment and get HTTPS working in Windows 10.
How to install an SSL certificate on a Tomcat server

Related

ERR_SSL_VERSION_OR_CIPHER_MISMATCH with signed certificate in Tomcat 8.5

I have a tomcat server for which I needed a signed certificate. I generated a key using
openssl req -new -newkey rsa:2048 -nodes -out sample_bfc_org.csr -keyout sample_bfc_org.key -subj "/C=BD/ST=Dhaka/L=Dhaka/O=Bangladesh Finance Corporatiobn/OU=IT/CN=sample.bfc.org"
and then generated a CSR and sent it to my company admin.
They gave me back a CER file with the signed certificate and certificate chain.
But when I import the certificate file in tomcat, I am getting the following error:
This site can’t provide a secure connectionehls.bhbfc.org uses an unsupported protocol.
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Unsupported protocol
The client and server don't support a common SSL protocol version or cipher suite.
My tomcat server.xml configuration is as follows:
<Connector executor="tomcatThreadPool"
port="443"
protocol="org.apache.coyote.http11.Http11AprProtocol"
connectionTimeout="20000"
acceptCount="100"
maxKeepAliveRequests="15"
SSLCACertificateFile="${catalina.base}/SSL/DigiCertCA.crt"
SSLCertificateFile="${catalina.base}/SSL/sample_bfc_org.crt"
SSLCertificateKeyFile="${catalina.base}/SSL/sample_bfc_org.key"
SSLPassword="123456"
SSLEnabled="true"
scheme="https"
secure="true"
sslProtocol="TLS"
/>
But still, the error exists. What can I do to solve the following error?
This site can’t provide a secure connectionehls.bhbfc.org uses an unsupported protocol.
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Unsupported protocol
The client and server don't support a common SSL protocol version or cipher suite.

Using Let's encrypt with Apache and Apache Tomcat

On same machine is running Apache on port 80 and Tomcat on port 8080.
Apache include html;css;js; files and make calls to tomcat services.
Basically exampledomain.com calls exampledomain.com:8080 to receive data.
Now i upgraded the protocol from http to https using Let's Encrypt certbot to generate the certificate, this certificate will be updated every 3 months by certbot. Apache is running fine on port 443 but Tomcat still use port 8080, i can use same certificate to run tomcat on port 8443 but.. for doing this the certificate needs to be converted to Java Keystore.
My question is, if i will convert the certificate it will expire after 3 month and i need to convert the new generated certificate by certbot to Java Keystore again ?
Yes, you have to convert the certificate every time it expires.
Tomcat accept .jks and .pfx certificates and you can make it easy to autoconvert everytime certbot generates new certificate by writing a script and make it run with certbot renewal-hooks.
Script:
#!/bin/bash
# Adjust these variables as necessary
# Where you want to final PKCS12 file to be stored.
CERT_PATH="/opt/app/certificate.pfx"
# Password to encrypt the PKCS12 file.
CERT_PW="ShoobyDooby"
# Path to LE files, RENEWED_LINEAGE provided by CertBot
PRIV_KEY_PEM="$RENEWED_LINEAGE/privkey.pem"
CERT_PEM="$RENEWED_LINEAGE/cert.pem"
CHAIN_PEM="$RENEWED_LINEAGE/chain.pem"
# If there's already a .pfx file, back it up
if [[ -f "$CERT_PATH" ]]; then
now=`date +%Y-%m-%d-%T`
mv $CERT_PATH $CERT_PATH.bak.$now
fi
# Le Conversion
openssl pkcs12 -export -out $CERT_PATH -inkey $PRIV_KEY_PEM -in $CERT_PEM -certfile $CHAIN_PEM -password pass:$CERT_PW
Place this script in /etc/letsencrypt/renewal-hooks/deploy/auto_pfx.sh
Don't forget to chmod! If the script isn't executable, it's ignored.
Automatic PKCS12 Conversion for Let's Encrypt Certificates
The answer is yes and no:
yes, if you want to keep your certificate in PKCS12 or JKS format, you'll have to convert it after every renewal, like in your answer,
no, converting to PKCS12 is not necessary on any supported version of Tomcat, except 7.0 (which reaches end-of-life in two months anyway). Tomcat 8.5, 9.0 and the upcoming 10.0 have no problem reading PEM-encoded certificates, just configure it like this:
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeyFile="/etc/letsencrypt/live/example.org/privkey.pem"
certificateFile="/etc/letsencrypt/live/example.org/cert.pem"
certificateChainFile="/etc/letsencrypt/live/example.org/chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
This works on all three types of connector (NIO, NIO2 and APR). On the other hand the APR connector never supported PKCS12 and JKS keystores.

Debian 9 Tomcat 9 Let's Encrypt SSL config

It drives me nuts now.
I have created sym links to the PEM files. I made the PEM files readable for the tomcat user. I set the server.xml to use SSL. And the connector fails to start.
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200"
scheme="https"
secure="true"
SSLEnabled="true"
clientAuth="false"
sslProtocol="TLS"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
defaultSSLHostConfigName="mydomain.com"
>
<SSLHostConfig hostName="mydomain.com" protocols="+TLSv1,+TLSv1.1,+TLSv1.2">
<Certificate
certificateKeyFile="conf/privkey.pem"
certificateFile="conf/cert.pem"
certificateChainFile="conf/chain.pem"
type="UNDEFINED"
/>
</SSLHostConfig>
</Connector>
I did try to change the type to RSA, to no avail. All I see in the log is:
02-Jan-2021 17:40:54.398 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-openssl-nio-8443"]
02-Jan-2021 17:40:54.466 SEVERE [main] org.apache.catalina.util.LifecycleBase.handleSubClassException Failed to initialize component [Connector[HTTP/1.1-8443]]
org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1013)
... some lines removed
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)
Caused by: java.lang.IllegalArgumentException
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:99)
... some lines are removed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1010)
... 13 more
Caused by: java.io.IOException
at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:302)
at org.apache.tomcat.util.net.openssl.OpenSSLUtil.getKeyManagers(OpenSSLUtil.java:98)
at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:247)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:97)
... 20 more
I've checked the SSLUtilBase.java code (tomcat 9.0.33):
if (certificate.getCertificateFile() == null) {
throw new IOException(sm.getString("jsse.noCertFile"));
}
I did try to copy the files instead of using sym links. No avail. Removed the comments from the cert files. No avail. It seems tomcat cannot find the files I've specified in the server.xml.
What do I miss?
Whenever you use one of the deprecated properties on a connector, Tomcat creates an <SSLHostConfig> element with hostName="_default_" and a <Connector> element inside it. The error is caused by the lack of the certificateFile on this particular element.
Remove the deprecated attributes (clientAuth, sslProtocol) from the <Connector> element and everything should work.
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
defaultSSLHostConfigName="mydomain.com">
<SSLHostConfig hostName="mydomain.com" protocols="TLSv1+TLSv1.1+TLSv1.2">
<Certificate
certificateKeyFile="conf/privkey.pem"
certificateFile="conf/cert.pem"
certificateChainFile="conf/chain.pem"
type="UNDEFINED"
/>
</SSLHostConfig>
</Connector>
Remark: the sslProtocol attribute is a characteristic of JSSE and should always be left at the default value (TLS).
I had the same issue with Ubuntu 20.04 and Tomcat 9.0.52.
Tomcat - server.xml - certificateKeyFile
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
I also tried everything that you described above and I also was not able to make the Tomcat Connector with certificateKeyFile to work.
Note, on RedHat Linux 7/8 it works fine though!!! I only got this issue in Ubuntu 20.04.
The good news is it works fine in Ubuntu 20.04 if you use a keystore instead of the certificateKeyFile.
You will need to create the keystore as the user that runs tomcat, in my case the user named "tomcat", then created the CSR using the keystore, issue the certificate, and imported the certificate into the keystore.
--Create the keystore folder and grant the proper permissions:
su - root
mkdir /rhdata/sslcert
chown -R tomcat:tomcat /rhdata/sslcert
su - tomcat
cd /rhdata/sslcert
--Create the PKCS12 keystore (must do the previous step):
su - tomcat
/usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keystore /rhdata/sslcert/.keystore
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -validity 3600 -keysize 2048 -keystore /rhdata/sslcert/.keystore
Enter keystore password: key$tom#2021
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool --list --keystore /rhdata/sslcert/.keystore -storepass 'key$tom#2021'
--Create the CSR:
su - tomcat
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -certreq -keyalg RSA -alias tomcat -file /rhdata/sslcert/keytool_cert/certreq.csr -keystore /rhdata/sslcert/.keystore -storepass 'key$tom#2021'
--Create the new certificate from the certificate authority using the CSR
--Import the new certificate into the keystore:
su - tomcat
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -import -alias tomcat -keystore /rhdata/sslcert/.keystore -storepass 'key$tom#2021' -file /rhdata/sslcert/keytool_cert/certnew.p7b
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -import -alias tomcat -keystore /rhdata/sslcert/.keystore -storepass 'key$tom#2021' -file /rhdata/sslcert/keytool_cert/certnew.cer
--This is the new Tomcat connector:
Tomcat - server.xml - keystore
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="/rhdata/sslcert/.keystore" keystorePass="key$tom#2021"
clientAuth="false" sslProtocol="TLS"/>
--Verify the new Tomcat server.xml file
su - tomcat
cd /usr/local/tomcat9/conf
/usr/local/tomcat9/bin/configtest.sh
--Then, stop/start Tomcat.
su - root
systemctl stop tomcat.service
systemctl start tomcat.service
systemctl status tomcat.service
vi /usr/local/tomcat9/logs/catalina.out <-- shall not have any errors!!!

Tomcat Presenting SSL Credentials

I have set up my MongoDB to only accept connections over SSL. Mongo has a handle to a certificate that I generated with the following commands
openssl req -newkey rsa:2048 -new -x509 -days 365 -nodes -out server-cert.crt -keyout server-private.key
cat server-cert.crt server-private.key > /etc/ssl/mongoSSL.pem
I added the following to my /etc/mongod.cnf...
sslMode=requireSSL
sslPEMKeyFile=/etc/ssl/mongo/mongoSSL.pem
Whenever Tomcat attempts to talk to Mongo, it fails due to not presenting the SSL certificate.
I set up my /opt/tomcat/conf/server.xml to have the following
<Connector port="27017" protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" keystoreFile="/etc/ssl/mongo/mongoSSL.pem"/>
This, however does not work. Does anyone have a link to a tutorial that can further my knowledge on how this is done? I found a tutorial to configure SSL with Apache and I found the Apache Docs on SSL Support however neither seem to be for my use case.
Thanks.
Whenever Tomcat attempts to talk to Mongo, it fails due to not presenting the SSL certificate. I set up my /opt/tomcat/conf/server.xml to have the following
Your assumption is wrong,your server.xml configuration doesn't instruct Tomcat to present SSL certificate to MongoDB. It tells Tomcat to listen to secure (https) connection on port 27017 (which is occupied by MongoDB anyway). You should discard that Tomcat connector setting.
In fact sslMode=requireSSL doesn't instruct MongoDB to require a client certificate for a two ways authentication. It only instruct MongoDB to accept only secured SSL connections.
What you need to do is not to configure Tomcat, but the MongoDB driver (I assume Java here since you are using Tomcat).
Configuring the Java driver is fairly easy. You can find the instructions here

How to configure Https on Tomcat 7 with SSL certificate?

I want to configure https on my Tomcat Server. I got FreeSSL certificate. But I don't know steps to proceed.
1. I got an email from FreeSSL provider with the text of the SSL certificate
2. I copied this text into file with extension .p7b
3. I added this certificate to new keystore
4. In server.xml I inserted path to this keystore and the pass as in:
<Connector
SSLEnabled='true'
keystoreFile="/path/to/certificates/keystore"
keystorePass="password"
maxSpareThreads='75'
port='8443'
proxyPort='443'
algorithm='SunX509'
enableLookups='false'
secure='true'
maxThreads='150'
connectionTimeout='20000'
disableUploadTimeout='true'
scheme='https'
minSpareThreads='5'
maxHttpHeaderSize='8192'
sslProtocol='SSL'
acceptCount='200'
clientAuth='false'
sslEnabledProtocols="TLSv1.2,TLSv1.1,TLSv1"
ciphers="TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"
/>
But after this steps I get next error:
Cannot communicate securely with peer: no common encryption
algorithm(s). (Error code: ssl_error_no_cypher_overlap)
on FireFox and
A secure connection cannot be established because this site uses an
unsupported protocol. Error code: ERR_SSL_VERSION_OR_CIPHER_MISMATCH
on Chrome
EDIT:
When I requested SSLCertificate I created cert.csr and keystore.keystore. But now I don't use them. Can this be the problem?
EDIT2:
As was written in comments I found the initial keystore and I put in it new certificate. After this I got an error on firefox:
Secure Connection Failed
The connection to domain.com:8443 was interrupted while the page was loading.
The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
Please contact the website owners to inform them of this problem.
Here's how I set one way SSL for Tomcat 7
Hope it would be help
$Tomcat\bin>keytool -genkey -v -alias ***your alias***
-keyalg RSA -validity ***how many days***
-keystore ***your keystore file path*** keystore
-dname "CN=***www.yourdomain.com***,
OU=***Your Organizational Unit***, O=***Your Organization***,
L=***Your City***, ST=***Your State***, C=***Your Country correct***"
-storepass ***your keystore password*** -keypass ***your key password***
And in the server.xml
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="***your keystore file path***"
keystorePass="***your keystore password***" />