Important information about Tomcat SSL Tomcat can use two different implementations of SSL:
- Java Secure Socket Extensions (JSSE) implementation provided as part of the Java runtime (since 1.4)
Java Blocking (BIO) connector and Java Nio Blocking (NIO) SSL connector only support Java SSL and work with JKS, PKCS11 or PKCS12 format keystores.
- Apache Portable Runtime (APR) implementation, which uses the OpenSSL engine by default
APR/native SSL connector only supports OpenSSL and only work with PEM-encoded private key and certificate format. APR/native SSL connector attributes for configuring SSL are different from both BIO and NIO connectors.
Supported Tomcat versions for SSL Java SSL/OpenSSL and BIO/NIO/APR:
| BIO | NIO | APR |
Tomcat Version | 3.x onwards | 6.x onwards | 5.5.x onwards |
SSL Support | Java SSL | Java SSL | OpenSSL |
Note: The configuration discussed in this article can be applied to vFabric tc Server, ERS, and ASF Tomcat depending on the Tomcat version and the type of SSL support for your environment.
In this article, we are using vFabric tc Server-2.5.0, tomcat-6.0.32.B.RELEASE, Java 6 keytool, and OpenSSL on a Linux platform.
Create a self-signed Certificate Authority (CA)
Note: We are using OpenSSL to generate our own root Certificate Authority (CA), which is used to sign our tc Server and client certificates.
First, modify the default configuration values in the openssl.cnf file and export it according to our environment:
> cp /path/to/openssl.cnf /path/to/openssl.cnf.orig
> vi /path/to/openssl.cnf
dir = ./myca # Where everything is kept
certificate = $dir/myca.crt # The CA certificate
crl = $dir/myca.crl # The current CRL
private_key = $dir/private/myca.key # The private key
serial = $dir/serial # The current serial number
database = $dir/index.txt # database index file
> export OPENSSL_CONF=/path/to/openssl.cnf
Set up the tc Server home and instance paths:
> tcs_home=~/testings/tcserver/2.5.0
> tcs_inst=$tcs_home/instances/2wayssl-dev1
Create the tc Server instance ssl directory and sub-directories to hold our CA, tc Server, and client key and certificate files:
> mkdir -p $tcs_inst/conf/ssl/myca/{ca,newcerts}
> cd $tcs_inst/conf/ssl
Create a unique OpenSSL serial number to keep track of the certificate:
> echo "01" > myca/serial
Create a database index.txt file:
> touch myca/index.txt
Generate a 2048-bit Certificate Authority (CA) private key:
> openssl genrsa -out myca/ca/myca.key 2048
Generating RSA private key, 2048 bit long modulus
.......................................................+++
..+++
e is 65537 (0x10001)
Generate a CA certificate signing request:
> openssl req -new -key myca/ca/myca.key -out myca/ca/myca.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:us
State or Province Name (full name) [Some-State]:ca
Locality Name (eg, city) []:sf
Organization Name (eg, company) [Internet Widgits Pty Ltd]:vmware
Organizational Unit Name (eg, section) []:tse
Common (Server) Name (eg, www.example.com) []:my own root ca
Email Address []:root@localhost
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:secret
An optional company name []:
Generate a Self-Signed CA certificate:
> openssl x509 -req -days 365 -in myca/ca/myca.csr -out myca/ca/myca.crt -signkey myca/ca/myca.key
Signature ok
subject=/C=us/ST=ca/L=sf/O=vmware/OU=tse/CN=my own root ca/emailAddress=root@localhost
Getting Private key
Now that we have created our own CA, it is time to create the server certificate and configure the tc Server.
Create a self-signed server certificate and configure the tc Server
There are two methods for implementing the server certificate. Choose one of these methods depending on your server enviorment requirements: Method 1: BIO/NIO implementation
Create a certificate and configure the tc Server for the BIO-SSL or NIO-SSL connector
Create the tc Server certificate
Generate a self-signed tc Server certificate for use with the BIO-SSL/NIO-SSL connector (not for APR-SSL).
Generate the keystore and key pair (a private key and public key) for the tc Server:
> keytool -genkey -alias tcserver -keyalg RSA -keystore tcserver.jks -keysize 2048
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: porthos
What is the name of your organizational unit?
[Unknown]: tse
What is the name of your organization?
[Unknown]: vmware
What is the name of your City or Locality?
[Unknown]: sf
What is the name of your State or Province?
[Unknown]: ca
What is the two-letter country code for this unit?
[Unknown]: us
Is CN=porthos, OU=tse, O=vmware, L=sf, ST=ca, C=us correct?
[no]: yes
Enter key password for <tcserver>
(RETURN if same as keystore password):
Re-enter new password:
Note: Set the common name (CN) to the server host, machine, or fully qualified domain name. The CN is used to check/match the server portion of the URL when clients connect to the tc Server. For example: https://common_name/remainder_of_url.
Next, generate a tc Server certificate signing request (CSR):
> keytool -certreq -keyalg RSA -alias tcserver -file tcserver.csr -keystore tcserver.jks
Enter keystore password:
Note: You can submit the tcserver.csr to a commercial CA to get a signed certificate, but in this example we are signing the CSR with the CA we generated earlier.
Sign the tc Server CSR with our CA:
>openssl x509 -req -in tcserver.csr -out tcserver.crt -CA myca/ca/myca.crt -CAkey myca/ca/myca.key -days 365 -CAserial myca/serial
Signature ok
subject=/C=us/ST=ca/L=sf/O=vmware/OU=tse/CN=w1-s2porthos.eng.vmware.com
Getting CA Private Key
Verify the certificate:
> openssl verify -CAfile myca/ca/myca.crt -purpose sslserver tcserver.crt
tcserver.crt: OK
Import the CA and server certificates
First, import the root CA certificate into the tc Server keystore file:
> keytool -import -alias root -keystore tcserver.jks -trustcacerts -file myca/ca/myca.crt
Enter keystore password:
Owner: EMAILADDRESS=root@localhost, CN=my own root ca, OU=tse, O=vmware, L=sf, ST=ca, C=us
Issuer: EMAILADDRESS=root@localhost, CN=my own root ca, OU=tse, O=vmware, L=sf, ST=ca, C=us
Serial number: a61aeec2cb911331
Valid from: Wed Dec 28 11:56:23 PST 2011 until: Thu Dec 27 11:56:23 PST 2012
Certificate fingerprints:
MD5: BD:BA:AD:3B:BD:60:83:B2:0B:10:28:FA:16:3E:75:EC
SHA1: 5C:C3:CB:05:5B:B0:89:80:21:FD:7B:9F:D3:C6:35:9D:5C:05:B2:30
Signature algorithm name: SHA1withRSA
Version: 1
Trust this certificate? [no]: yes
Certificate was added to keystore
Import the self-signed tcserver.jks X509 format certificate into the tc Server keystore:
> keytool -import -alias tcserver -keystore tcserver.jks -trustcacerts -file tcserver.crt
Enter keystore password:
Certificate reply was installed in keystore
Verify that the Owner and Issuer CNs and Alias names are correct. To verify the keystore certificates:
> keytool -v -list -keystore tcserver.jks
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 2 entries
Alias name: root
Creation date: Dec 28, 2011
Entry type: trustedCertEntry
Owner: EMAILADDRESS=root@localhost, CN=my own root ca, OU=tse, O=vmware, L=sf, ST=ca, C=us
Issuer: EMAILADDRESS=root@localhost, CN=my own root ca, OU=tse, O=vmware, L=sf, ST=ca, C=us
Serial number: a61aeec2cb911331
Valid from: Wed Dec 28 11:56:23 PST 2011 until: Thu Dec 27 11:56:23 PST 2012
Certificate fingerprints:
MD5: BD:BA:AD:3B:BD:60:83:B2:0B:10:28:FA:16:3E:75:EC
SHA1: 5C:C3:CB:05:5B:B0:89:80:21:FD:7B:9F:D3:C6:35:9D:5C:05:B2:30
Signature algorithm name: SHA1withRSA
Version: 1
*******************************************
*******************************************
Alias name: tcserver
Creation date: Dec 28, 2011
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=w1-s2porthos.eng.vmware.com, OU=tse, O=vmware, L=sf, ST=ca, C=us
Issuer: EMAILADDRESS=root@localhost, CN=my own root ca, OU=tse, O=vmware, L=sf, ST=ca, C=us
Serial number: 2
Valid from: Wed Dec 28 12:05:04 PST 2011 until: Thu Dec 27 12:05:04 PST 2012
Certificate fingerprints:
MD5: 34:A1:A1:C2:16:9A:AA:35:EB:24:12:1D:6A:F2:5F:17
SHA1: 8F:30:E6:56:DF:0B:9D:5C:CE:37:B6:84:2C:2D:F1:E7:12:06:BF:C2
Signature algorithm name: SHA1withRSA
Version: 1
Certificate[2]:
Owner: EMAILADDRESS=root@localhost, CN=my own root ca, OU=tse, O=vmware, L=sf, ST=ca, C=us
Issuer: EMAILADDRESS=root@localhost, CN=my own root ca, OU=tse, O=vmware, L=sf, ST=ca, C=us
Serial number: a61aeec2cb911331
Valid from: Wed Dec 28 11:56:23 PST 2011 until: Thu Dec 27 11:56:23 PST 2012
Certificate fingerprints:
MD5: BD:BA:AD:3B:BD:60:83:B2:0B:10:28:FA:16:3E:75:EC
SHA1: 5C:C3:CB:05:5B:B0:89:80:21:FD:7B:9F:D3:C6:35:9D:5C:05:B2:30
Signature algorithm name: SHA1withRSA
Version: 1
*******************************************
*******************************************
Next, we must import the self-signed root CA certificate (
myca/ca/myca.crt) into the client browser to establish a complete chain of trust.
To import the root CA into Firefox 8:
- Click Tools > Options > Advanced > Encryption > View Certificates > Authorities > Import...
- Select myca.crt, and select all the trust boxes.
Note: Depending on the browser software and version used, the process for importing the CA certificate varies.
Configuring the tc Server connector
Choose either the BIO-SSL or NIO-SSL connector implementation and add it to
$tcs_inst/conf/server.xml.
Notes:
- Choose only one connector implementation. Do not attempt to add both.
- Be sure to configure the bio.https.port or nio.https.port port number in the $tcs_inst/conf/catalina.properties file.
- ERS / AFS Tomcat does not use an external catalina.properties file for the port number, so you must specify the port number in the port and redirectorPort attributes in server.xml.
For BIO-SSL, add:
<Connector executor="tomcatThreadPool"<br> port="${bio.https.port}"
protocol="org.apache.coyote.http11.Http11Protocol"
connectionTimeout="20000"
redirectPort="${bio.https.port}"
acceptCount="100"
maxKeepAliveRequests="15"
keystoreFile="${catalina.base}/conf/ssl/tcserver.jks"
keystoreType="jks"
keystorePass="secret"
keyAlias="tcserver"
SSLEnabled="true"
scheme="https"
secure="true"/>
For NIO-SSL, add:
<Connector executor="tomcatThreadPool"<br> port="${nio.https.port}"
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="${nio.https.port}"
acceptCount="100"
maxKeepAliveRequests="15"
keystoreFile="${catalina.base}/conf/ssl/tcserver.jks"
keystoreType="jks"
keystorePass="secret"
keyAlias="tcserver"
SSLEnabled="true"
scheme="https"
secure="true"/>
Method 2: APR implementation
Create a certificate and configure the tc Server for the APR-SSL connector
Note: Tomcat with the ARP/native SSL connector uses attributes for the SSL connector which are specific to OpenSSL. Some of these OpenSSL attributes may be familiar to those who are familiar with Apache mod_ssl.
Build and install the Tomcat APR/native library
First, build APR with OpenSSL support into the Tomcat native library.
Requirements:
- APR 1.2+ development headers (libapr1-dev package)
- OpenSSL 0.9.7+ development headers (libssl-dev package)
- JNI headers from Java compatible JDK 1.4+
- GNU development environment (gcc, make)
- tomcat-native.tar.gz (This JNI wrapper library depends on ARP, OpenSSL and the Java headers.)
Note: Tomcat and the tc Server are bundled with the JNI wrapper (bin/tomcat-native.tar.gz) source archive.
Build the JNI wrapper library for use with the Tomcat APR SSL connector:
- Create a jni-wrapper source directory in the tc Server home, and navigate into the directory:
> mkdir $tcs_home/jni-wrapper
> cd $tcs_home/jni-wrapper
- If it is not already installed, download and build the APR library:
> curl http://apache.osuosl.org/apr/apr-1.4.5.tar.gz | tar xvz
> cd apr*
> ./configure && make
- If they are not already installed, download and build the OpenSSL libraries:
> cd $tcs_home/jni-wrapper
> curl http://www.openssl.org/source/openssl-1.0.0e.tar.gz | tar xvz
> cd open*
> ./config && make
- Extract and build the tomcat JNI wrapper library (libtcnative) with ARP and Openness’ dependencies:
> cd $tcs_home/jni-wrapper
> tar xvzf $tcs_home/tomcat-6*/bin/tom*.gz
> cd tom*/jni/native
> ./configure --with-apr=../../../apr-1.4.5 --with-ssl=../../../openssl-1.0.0e && make
Note: If the vendor-distributed packages of APR and OpenSSL have been previously installed via the yum, rpm, or apt installers, it is not necessary to pass the --with-apr and --with-ssl switches to the configure command.
- After make completes in this example, the libtcnative library can be found in the /home/kymeng/testings/tcserver/2.5.0/jni-wrapper/tomcat-native-1.1.20-src/jni/native/.libs directory.
Load the
libtcnative library by adding this line to the
$tc_inst/bin/setenv.sh script:
Note: Be sure to set the libtcnative library path according to your build/install location. In this example, it is set to the path used in the previous steps.
export LD_LIBRARY_PATH=/home/kymeng/testings/tcserver/2.5.0/jni-wrapper/tomcat-native-1.1.20-src/jni/native/.libs:$LD_LIBRARY_PATH
Add the APRLifecycleListener to $tcs_inst/conf/server.xml to detect the APR-based native library:
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on"/>
Create a tc Server certificate for use with APR-SSL
Generate a private key for the tc Server:
> cd $tcs_inst/conf/ssl
> openssl genrsa -des3 -out tcserver.key 2048
Generating RSA private key, 2048 bit long modulus
............................................................+++
.................................................................+++
e is 65537 (0x10001)
Enter pass phrase for tcserver.key:
Verifying - Enter pass phrase for tcserver.key:
Generate a certificate signing request (CSR) for the tc Server:
> openssl req -new -key tcserver.key -out tcserver.csr
Enter pass phrase for tcserver.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:us
State or Province Name (full name) [Some-State]:ca
Locality Name (eg, city) []:sf
Organization Name (eg, company) [Internet Widgits Pty Ltd]:vmware
Organizational Unit Name (eg, section) []:tse
Common (Server) Name (eg, www.example.com) []:porthos
Email Address []:root@localhost
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:secret
An optional company name []:
Notes:
- Set the common name (CN) to the server host, machine, or fully qualified domain name.
- You can submit the tcserver.csr to a commercial CA to get a signed certificate, but in this example we are signing the CSR with the CA we generated earlier.
Sign the tc Server CSR with our CA:
> openssl x509 -req -days 365 -in tcserver.csr -out tcserver.crt -CA myca/ca/myca.crt -CAkey myca/ca/myca.key -CAserial myca/serial
Signature ok
subject=/C=us/ST=ca/L=sf/O=vmware/OU=tse/CN=porthos/emailAddress=root@localhost
Getting CA Private Key
Next, we must import the self-signed root CA certificate (
myca/ca/myca.crt) into the client browser to establish a complete chain of trust.
To import the root CA into Firefox 8:
- Click Tools > Options > Advanced > Encryption > View Certificates > Authorities > Import...
- Select myca.crt, and select all the trust boxes.
Note: Depending on the browser software and version used, the process for importing the CA certificate varies.
Configuring the tc Server connector
Add the APR-SSL connector and listener to the tc Server $tcs_inst/conf/server.xml file:
Notes:
- Be sure to configure the apr.https.port port number in the $tcs_inst/conf/catalina.properties file.
- ERS / AFS Tomcat does not use an external catalina.properties file for the port number, so you must specify the port number in the port and redirectorPort attributes in server.xml.
<Connector executor="tomcatThreadPool"</span>
port="${apr.https.port}"
protocol="org.apache.coyote.http11.Http11AprProtocol"
connectionTimeout="20000"
redirectPort="${apr.https.port}"
acceptCount="100"
maxKeepAliveRequests="15"
SSLCACertificateFile="${catalina.base}/conf/ssl/myca/ca/myca.crt"
SSLCertificateFile="${catalina.base}/conf/ssl/tcserver.crt"
SSLCertificateKeyFile="${catalina.base}/conf/ssl/tcserver.key"
SSLPassword="secret"
SSLEnabled="true"
scheme="https"
secure="true"/>
Create and import the client certificate
Generate a key pair for the client:
> openssl genrsa -out client.key 2048
Generating RSA private key, 2048 bit long modulus
...+++
.................................................................+++
e is 65537 (0x10001)
Generate the Client Certificate Request (CSR):
> openssl req -new -key client.key -out client.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:us
State or Province Name (full name) [Some-State]:ca
Locality Name (eg, city) []:sf
Organization Name (eg, company) [Internet Widgits Pty Ltd]:vmware
Organizational Unit Name (eg, section) []:tse
Common (Server) Name (eg, www.example.com) []:my client
Email Address []:client@localhost
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:secret
An optional company name []:
Sign the client CSR with our CA:
> openssl x509 -CAkey myca/ca/myca.key -CA myca/ca/myca.crt -CAserial myca/serial -req -in client.csr -out client.crt -days 365
Signature ok
subject=/C=us/ST=ca/L=sf/O=vmware/OU=tse/CN=my client/emailAddress=client@localhost
Getting CA Private Key
Export the client certificate to PKCS#12 so that it can be imported into the client browser:
> openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12 -name my-client
Import the
client.p12 certificate file into the client browser. To import the client certificate into Firefox 8:
- Click Tools > Options > Advanced > Encryption > View Certificates > Your Certificates > Import...
- Select and import the client.p12 file.
Note: Depending on the browser software and version used, the process for importing the CA certificate varies.
Enable tc Server client authentication
There are two methods to configure your tc Server connector for client authentication. Choose one of these methods depending on your server connector implementation:
Method 1: Configuring the tc Server for the NIO/BIO connectorTo enable client authentication, add these BIO-SSL or NIO-SSL connector attributes to the
$tcs_inst/conf/server.xml file:
truststoreFile="${catalina.base}/conf/ssl/tcserver.jks"
truststorePass="secret"
truststoreType="jks"
clientAuth="true"
You must configure the truststore on the tc Server to hold the CA public key or client certificate, which is by the server to check if the client certificate can be trusted. Generate a tc Server truststore and add the CA public key to it so that the server can establish a client certificate of trust:
- Generate a keystore containing a dummy keychain, then delete the dummy to make a clean JKS Java keystore available.
> keytool -genkey -alias dummy -keyalg RSA -keystore truststore.jks
> keytool -delete -alias dummy -keystore truststore.jks
- Import the CA public key into truststore.jks and verify the contents:
> keytool -import -v -trustcacerts -alias myca -file myca/ca/myca.crt -keystore truststore.jks
> keytool -v -list -keystore truststore.jks
Note: Alternatively, this can be accomplished by adding the certificate public key of each client to the truststore. Doing so can take a large amount of time when there are many clients, so best practice is to sign each client certificate with your own CA, and simply place the public CA key in the truststore. In this example, we are using our
tcserver.jks keystore for the truststore as it already contains our CA public key.
Method 2: Configuring the tc Server for the APR connector
To enable client authentication, add these APR-SSL connector attributes to the
$tcs_inst/conf/server.xml file:
SSLVerifyClient="require"
SSLVerifyDepth="2"
Testing the tc Server SSL with OpenSSL
With the tc Server SSL running, you can use OpenSSL to test it:
> openssl s_client -connect localhost:4443 -debug
To view the server cert and cert chain, run this command:
> openssl s_client -connect localhost:4443 -showcerts