아파치 톰캣 서블릿/JSP 컨테이너

아파치 톰캣 7

Version 7.0.28-dev, Oct 2 2013
Apache Logo

Links

User Guide

참고

아파치 톰캣 개발

SSL 설정 HOW-TO

Table of Contents
Quick Start

아래 설명은 환경 변수 $CATALINA_BASE 를 사용해서 기준 디렉토리를 정하고 대부분의 상대경로를 풀어가도록 했습니다. 만약 여러분이 CATALINA_BASE 디렉토리를 설정해서 여러 인스턴스로 톰캣을 설정하지 않았다면, $CATALINA_BASE는 톰캣이 설치된 디렉토리인 $CATALINA_HOME 값으로 정해질 것입니다.

톰캣에 SSL 지원을 설치해서 설정하기 위해서, 여러분은 아래의 간단한 단계들을 따라하기만 하면 됩니다. 더 자세한 정보를 원한다면, 이 HOW-TO 문서의 나머지를 읽어보세요.

  1. keystore 파일을 만들어서 서버의 개인 키와 아래 명령을 실행해서 자체 사인한 인증서를 저장합니다:

    Windows:

    %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
    

    Unix:

    $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
    

    그리고 "changeit"을 대신할 비밀번호를 정합니다.


  2. $CATALINA_BASE/conf/server.xml 파일에 있는 "SSL HTTP/1.1 Connector" 항목의 주석을 제거하고 아래 Configuration 섹션에 있는 설명을 참고해서 수정합니다.


Introduction to SSL

SSL, 또는 Secure Socket Layer (안전한 소켓 레이어)는 웹 브라우저와 웹 서버 사이에 안전한 연결 위에서 통신할 수 있도록 하는 기술입니다. 이것이 의미하는 것은 한쪽에서 암호화된 데이터가 송신되고, 전송되고, 다른 쪽에서 처리하기 전에 복호화하는 것입니다. 이것은 서버와 브라우저 모두 모든 트래픽을 보내기 전에 암호화 하는 것을 의미하는 양방향 처리입니다.

SSL 프로토콜의 다른 중요한 면은 인증입니다. 이것은 여러분이 웹 서버와 안전한 연결 상태에서 통신을 시도하는 초기에, 서버는 한 세트의 자격증명서를 "인증서" 형태로, 사이트가 누구이고 무엇을 다루는지에 대한 증명으로, 브라우저에게 보여준다는 것을 의미합니다. 어떤 경우에는, 서버가 여러분이 자격을 갖추었는지 증명하기 위해서, 여러분의 웹 브라우저로부터 인증서를 요구할 수도 있습니다. 이것은 "클라이언트 인증"으로 알려져 있는데, 실제로 이것은 개인 사용자보다는 비즈니스 to 비즈니스(B2B) 트랜잭션에 더 많이 사용되고 있습니다. 대부분의 SSL 가능한 웹 브라우저는 클라이언트 인증을 요구하지 않습니다.

SSL and Tomcat

톰캣으로 안전한 소켓의 장점을 이용하기 위한 설정을 하는 것은 톰캣만으로 웹 서버를 사용할 때에만 필요합니다. 아파치 또는 마이크로소프트 IIS 같은, 다른 웹 서버 뒤에서 톰캣을 주로 서블릿/JSP 컨테이너로 사용할 때에는, 사용자로부터 SSL 연결을 다루기 위한 설정은 메인 웹 서버에서 해야 합니다. 전형적으로, 이 서버는 모든 SSL-관련 기능을 다루게 되고, 그리고 그 요청들의 암호를 해제하고 톰캣 컨테이너에게 넘겨줍니다. 마찬가지로, 톰캣은 암호화되지 않은 응답을 반환하고, 사용자 브라우저에 되돌려지기 전에 암호화됩니다. 이런 환경에서, 톰캣은 메인 웹 서버와 클라이언트 사이에 연결이 안전한 연결(왜냐하면 여러분의 애플리케이션이 이에 대한 요청을 하기 때문에) 위에서 이루어진다는 것을 알고 있습니다만, 톰캣 스스로는 암호화와 복호화 작업에는 참여하지 않습니다.

Certificates

SSL을 구현하려면, 웹서버는 반드시 안전한 연결을 사용하려는 개별 외부 인터페이스(IP 주소)마다 관련된 인증서를 갖고 있어야 합니다. 이 설계 너머의 이론은 서버는 특히 민감한 정보를 수신하기 전에, 여러분이 생각하는 소유주가 맞다는 것에 대한 어떤 종류이든 합리적인 확신을 제공해야 한다는 것입니다. 인증서에 대한 더 자세한 설명은 이 문서의 범위를 벗어납니다만, 인증서를 인터넷 주소에 대한 "디지털 운전면허증"이라고 생각해 보세요. 사이트와 연관된 회사가 무엇인지,그 사이트 소유자 또는 관리자에 대한 기본적인 연락 정보와 함께 말해 줍니다.

이 "운전 면허증"은 암호학적으로 해당 소유자가 사인한 것이고, 그러므로 다른 누군가가 위조하기 극도로 어렵습니다. 정체성의 인증이 중요한 전자상거래 또는 다른 비즈니스 트랜잭션에 연관된 사이트를 위하여, 인증서는 전통적으로 VeriSign 또는 Thawte와 같이 잘 알려진 인증 기관 Certificate Authority(CA)에서 구매합니다. 그러한 인증서는 전자적으로 검증할 수 있습니다 -- 실제로, 인증 기관은 승인한 인증서의 확실성을 위해 보증을 하고, 그래서 만약 여러분이 그 인증서를 승인한 인증 기관을 신뢰한다면 여러분은 그 인증서가 유효하다는 것을 믿을 수 있게 됩니다.

그러나, 많은 경우 인증이 실제로 중요한 관심사는 아닙니다. 관리자는 단지 서버에 의해 전송되고 받아오는 데이터가 프라이빗으로 되고 연결에 도청을 하는 누군가에게 정보가 새나가지 않는다는 것을 확실히 하고 싶어합니다. 다행히, 자바는 상대적으로 간단한 keytoo이라는 커맨드-라인 도구를 제공하고, 이것으로 쉽게 "자체-서명된" 인증서를 만들수 있습니다. 자체-서명된 인증서는 단지 사용자가 만든 인증서이고, 잘 알려진 CA를 통해 공식적으로 등록된 것이 아니고, 그러므로 진짜로 보증되는 것은 전혀 아닙니다. 다시 말하면, 이것은 여러분의 필요에 따라서, 중요할 수도 아닐 수도 있습니다.

General Tips on Running SSL

우선 사용자는 여러분의 사이트에 안전한 페이지 접속을 시도하고, 전통적으로 사용자는 인증서 상세정보(회사와 담당자 성명과 같은)를 포함한 대화상자를 보게되고, 사용자가 인증서를 유효하다고 인정해서 트랜잭션을 계속할 것인지 질문을 받게 됩니다. 어떤 브라우저는 여러분의 사이트를 방문할 때마다 알림이 떠서 사용자를 귀찮게 하지 않도록, 주어진 인증서가 유효하다고 영원히 인정하는 옵션을 제공합니다. 다른 브라우저는 이 옵션을 제공하지 않습니다. 사용자가 한 번 승인하면, 인증서는 적어도 전체 브라우저 세션에서 유효한 것으로 간주될 것입니다.

또한, SSL 프로토콜이 효율적으로 안전한 통신이 가능하도록 설계되었지만, 성능의 관점에서 보면 암호화/복호화는 컴퓨터 연산이 많이 필요한 처리 절차입니다. 전체 웹 애플리케이션을 SSL 위에서 돌아가게 하는 것이 반드시 필요한 것은 아닙고, 실제로 개발자가 어느 페이지가 안전한 연결이 필요하고 어느 페이지가 그렇지 않은지 선택할 수 있습니다. 상당히 바쁜 사이트에서, 특정 페이지만을 SSL로 운영하는 것은 선택하기 나름이고, 다시 말하면 그러한 페이지들은 민감한 정보들이 교환되는 페이지들입니다. 여기에는 로그인 페이지, 개인 정보 페이지, 그리고 신용 카드 정보가 전송되는 쇼핑 카트 체크아웃 페이지를 포함됩니다. 웹 애플리케이션에 있는 어느 페이지이든 간단히 http: 대신에 주소줄에 https:로 시작하면 안전한 소켓을 통해서 요청될 수 있습니다. 절대로 안전한 연결이 필요한 페이지가 있다면 만약 https가 지정되지 않았을 때 페이지 요청과 관련된 프로토콜 타입을 확인하고 적절한 액션을 취해야 합니다.

마지막으로, 이름 기반의 가상 호스트를 안전한 연결 위에서 사용하는 것은 문제가 발생할 수 있습니다. 이것은 SSL 프로토콜 자체적인 설계상의 한계입니다. 클라이언트 브라우저가 서버 인증서를 승인하는 SSL 연결은 HTTP 요청이 접근하기 전에 일어나야 합니다. 결과적으로, 가상 호스트 이름을 포함하는 요청 정보는 인증에 앞서 결정지어질 수 없고, 그러므로 하나의 IP 주소에 복수의 인증서를 할당할 수 없습니다. 만약 하나의 IP 주소에 있는 모든 가상 호스트가 같은 인증서에 대해서 인증이 필요하다면, 멀티 가상 호스트의 As a result, the request information containing the virtual host name cannot be determined prior to authentication, and it is therefore not possible to assign multiple certificates to a single IP address. If all virtual hosts on a single IP address need to authenticate against the same certificate, the addition of multiple virtual hosts should not interfere with normal SSL operations on the server. Be aware, however, that most client browsers will compare the server's domain name against the domain name listed in the certificate, if any (applicable primarily to official, CA-signed certificates). If the domain names do not match, these browsers will display a warning to the client user. In general, only address-based virtual hosts are commonly used with SSL in a production environment.

Configuration
Prepare the Certificate Keystore

Tomcat currently operates only on JKS, PKCS11 or PKCS12 format keystores. The JKS format is Java's standard "Java KeyStore" format, and is the format created by the keytool command-line utility. This tool is included in the JDK. The PKCS12 format is an internet standard, and can be manipulated via (among other things) OpenSSL and Microsoft's Key-Manager.

Each entry in a keystore is identified by an alias string. Whilst many keystore implementations treat aliases in a case insensitive manner, case sensitive implementations are available. The PKCS11 specification, for example, requires that aliases are case sensitive. To avoid issues related to the case sensitivity of aliases, it is not recommended to use aliases that differ only in case.

To import an existing certificate into a JKS keystore, please read the documentation (in your JDK documentation package) about keytool. Note that OpenSSL often adds readable comments before the key, keytooldoes not support that, so remove the OpenSSL comments if they exist before importing the key using keytool.

To import an existing certificate signed by your own CA into a PKCS12 keystore using OpenSSL you would execute a command like:

openssl pkcs12 -export -in mycert.crt -inkey mykey.key \
                        -out mycert.p12 -name tomcat -CAfile myCA.crt \
                        -caname root -chain
For more advanced cases, consult the OpenSSL documentation.

To create a new keystore from scratch, containing a single self-signed Certificate, execute the following from a terminal command line:

Windows:

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA

Unix:

$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA

(The RSA algorithm should be preferred as a secure algorithm, and this also ensures general compatibility with other servers and components.)

This command will create a new file, in the home directory of the user under which you run it, named ".keystore". To specify a different location or filename, add the -keystore parameter, followed by the complete pathname to your keystore file, to the keytool command shown above. You will also need to reflect this new location in the server.xml configuration file, as described later. For example:

Windows:

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA \
  -keystore \path\to\my\keystore

Unix:

$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA \
  -keystore /path/to/my/keystore

After executing this command, you will first be prompted for the keystore password. The default password used by Tomcat is "changeit" (all lower case), although you can specify a custom password if you like. You will also need to specify the custom password in the server.xml configuration file, as described later.

Next, you will be prompted for general information about this Certificate, such as company, contact name, and so on. This information will be displayed to users who attempt to access a secure page in your application, so make sure that the information provided here matches what they will expect.

Finally, you will be prompted for the key password, which is the password specifically for this Certificate (as opposed to any other Certificates stored in the same keystore file). The keytool prompt will tell you that pressing the ENTER key automatically uses the same password for the key as the keystore. You are free to use the same password or to select a custom one. If you select a different password to the keystore password, you will also need to specify the custom password in the server.xml configuration file.

If everything was successful, you now have a keystore file with a Certificate that can be used by your server.

Edit the Tomcat Configuration File

Tomcat can use two different implementations of SSL:

  • the JSSE implementation provided as part of the Java runtime (since 1.4)
  • the APR implementation, which uses the OpenSSL engine by default.
The exact configuration details depend on which implementation is being used. The implementation used by Tomcat is chosen automatically unless it is overriden as described below. If the installation uses APR - i.e. you have installed the Tomcat native library - then it will use the APR SSL implementation, otherwise it will use the Java JSSE implementation.

To avoid auto configuration you can define which implementation to use by specifying a classname in the protocol attribute of the Connector.
To define a Java (JSSE) connector, regardless of whether the APR library is loaded or not do:

<-- Define a blocking Java SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector protocol="org.apache.coyote.http11.Http11Protocol"
           port="8443" .../>

<-- Define a non-blocking Java SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
           port="8443" .../>
Alternatively, to specify an APR connector (the APR library must be available) use:
<-- Define a APR SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector protocol="org.apache.coyote.http11.Http11AprProtocol"
           port="8443" .../>

If you are using APR, you have the option of configuring an alternative engine to OpenSSL.

<Listener className="org.apache.catalina.core.AprLifecycleListener"
          SSLEngine="someengine" SSLRandomSeed="somedevice" />
The default value is
<Listener className="org.apache.catalina.core.AprLifecycleListener"
          SSLEngine="on" SSLRandomSeed="builtin" />
So to use SSL under APR, make sure the SSLEngine attribute is set to something other than off. The default value is on and if you specify another value, it has to be a valid engine name.
If you haven't compiled in SSL support into your Tomcat Native library, then you can turn this initialization off
<Listener className="org.apache.catalina.core.AprLifecycleListener"
          SSLEngine="off" />
SSLRandomSeed allows to specify a source of entropy. Productive system needs a reliable source of entropy but entropy may need a lot of time to be collected therefore test systems could use no blocking entropy sources like "/dev/urandom" that will allow quicker starts of Tomcat.

The final step is to configure the Connector in the $CATALINA_BASE/conf/server.xml file, where $CATALINA_BASE represents the base directory for the Tomcat instance. An example <Connector> element for an SSL connector is included in the default server.xml file installed with Tomcat. For JSSE, it should look something like this:

<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<!--
<Connector
           port="8443" maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="${user.home}/.keystore" keystorePass="changeit"
           clientAuth="false" sslProtocol="TLS"/>
-->

The example above will throw an error if you have the APR and the Tomcat Native libraries in your path, as Tomcat will try to use the APR connector. The APR connector uses different attributes for SSL keys and certificates. An example of an APR configuration is:

<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<!--
<Connector
           port="8443" maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           SSLCertificateFile="/usr/local/ssl/server.crt"
           SSLCertificateKeyFile="/usr/local/ssl/server.pem"
           clientAuth="optional" SSLProtocol="TLSv1"/>
-->

You will note that the example SSL connector elements are commented out by default. You can either remove the comment tags from around the the example SSL connector you wish to use or add a new Connector element of your own. In either case, you will need to configure the SSL Connector for your requirements and environment. The configuration options and information on which attributes are mandatory, are documented in the SSL Support section of the HTTP connector configuration reference. Make sure that you use the correct attributes for the connector you are using. The BIO and NIO connectors use JSSE whereas the APR/native connector uses APR.

The port attribute (default value is 8443) is the TCP/IP port number on which Tomcat will listen for secure connections. You can change this to any port number you wish (such as to the default port for https communications, which is 443). However, special setup (outside the scope of this document) is necessary to run Tomcat on port numbers lower than 1024 on many operating systems.

If you change the port number here, you should also change the value specified for the redirectPort attribute on the non-SSL connector. This allows Tomcat to automatically redirect users who attempt to access a page with a security constraint specifying that SSL is required, as required by the Servlet Specification.

After completing these configuration changes, you must restart Tomcat as you normally do, and you should be in business. You should be able to access any web application supported by Tomcat via SSL. For example, try:

https://localhost:8443

and you should see the usual Tomcat splash page (unless you have modified the ROOT web application). If this does not work, the following section contains some troubleshooting tips.

Installing a Certificate from a Certificate Authority

To obtain and install a Certificate from a Certificate Authority (like verisign.com, thawte.com or trustcenter.de), read the previous section and then follow these instructions:

Create a local Certificate Signing Request (CSR)

In order to obtain a Certificate from the Certificate Authority of your choice you have to create a so called Certificate Signing Request (CSR). That CSR will be used by the Certificate Authority to create a Certificate that will identify your website as "secure". To create a CSR follow these steps:

  • Create a local Certificate (as described in the previous section):
    keytool -genkey -alias tomcat -keyalg RSA \
        -keystore <your_keystore_filename>
    Note: In some cases you will have to enter the domain of your website (i.e. www.myside.org) in the field "first- and lastname" in order to create a working Certificate.
  • The CSR is then created with:
    keytool -certreq -keyalg RSA -alias tomcat -file certreq.csr \
        -keystore <your_keystore_filename>

Now you have a file called certreq.csr that you can submit to the Certificate Authority (look at the documentation of the Certificate Authority website on how to do this). In return you get a Certificate.

Importing the Certificate

Now that you have your Certificate you can import it into you local keystore. First of all you have to import a so called Chain Certificate or Root Certificate into your keystore. After that you can proceed with importing your Certificate.

  • Download a Chain Certificate from the Certificate Authority you obtained the Certificate from.
    For Verisign.com commercial certificates go to: http://www.verisign.com/support/install/intermediate.html
    For Verisign.com trial certificates go to: http://www.verisign.com/support/verisign-intermediate-ca/Trial_Secure_Server_Root/index.html
    For Trustcenter.de go to: http://www.trustcenter.de/certservices/cacerts/en/en.htm#server
    For Thawte.com go to: http://www.thawte.com/certs/trustmap.html
  • Import the Chain Certificate into your keystore
    keytool -import -alias root -keystore <your_keystore_filename> \
        -trustcacerts -file <filename_of_the_chain_certificate>
  • And finally import your new Certificate
    keytool -import -alias tomcat -keystore <your_keystore_filename> \
        -file <your_certificate_filename>
Troubleshooting

Here is a list of common problems that you may encounter when setting up SSL communications, and what to do about them.

  • When Tomcat starts up, I get an exception like "java.io.FileNotFoundException: {some-directory}/{some-file} not found".

    A likely explanation is that Tomcat cannot find the keystore file where it is looking. By default, Tomcat expects the keystore file to be named .keystore in the user home directory under which Tomcat is running (which may or may not be the same as yours :-). If the keystore file is anywhere else, you will need to add a keystoreFile attribute to the <Factory> element in the Tomcat configuration file.

  • When Tomcat starts up, I get an exception like "java.io.FileNotFoundException: Keystore was tampered with, or password was incorrect".

    Assuming that someone has not actually tampered with your keystore file, the most likely cause is that Tomcat is using a different password than the one you used when you created the keystore file. To fix this, you can either go back and recreate the keystore file, or you can add or update the keystorePass attribute on the <Connector> element in the Tomcat configuration file. REMINDER - Passwords are case sensitive!

  • When Tomcat starts up, I get an exception like "java.net.SocketException: SSL handshake errorjavax.net.ssl.SSLException: No available certificate or key corresponds to the SSL cipher suites which are enabled."

    A likely explanation is that Tomcat cannot find the alias for the server key within the specified keystore. Check that the correct keystoreFile and keyAlias are specified in the <Connector> element in the Tomcat configuration file. REMINDER - keyAlias values may be case sensitive!

If you are still having problems, a good source of information is the TOMCAT-USER mailing list. You can find pointers to archives of previous messages on this list, as well as subscription and unsubscription information, at http://tomcat.apache.org/lists.html.

Using the SSL for session tracking in your application

This is a new feature in the Servlet 3.0 specification. Because it uses the SSL session ID associated with the physical client-server connection there are some limitations. They are:

  • Tomcat must have a connector with the attribute isSecure set to true.
  • If SSL connections are managed by a proxy or a hardware accelerator they must populate the SSL request headers (see the SSLValve) so that the SSL session ID is visible to Tomcat.
  • If Tomcat terminates the SSL connection, it will not be possible to use session replication as the SSL session IDs will be different on each node.

To enable SSL session tracking you need to use a context listener to set the tracking mode for the context to be just SSL (if any other tracking mode is enabled, it will be used in preference). It might look something like:

package org.apache.tomcat.example;

import java.util.EnumSet;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.SessionTrackingMode;

public class SessionTrackingModeListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        // Do nothing
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        ServletContext context = event.getServletContext();
        EnumSet<SessionTrackingMode> modes =
            EnumSet.of(SessionTrackingMode.SSL);

        context.setSessionTrackingModes(modes);
    }

}
    

주의: SSL 세션 트래킹은 BIO와 NIO 커넥터를 위해서만 구현되었습니다. APR 커넥터를 위해서는 아직 구현되지 않았습니다.

Miscellaneous Tips and Bits

요청으로부터 SSL 세션 ID에 접근하려면, 이렇게 합나다::
String sslID = (String)request.getAttribute("javax.servlet.request.ssl_session_id");
이 영역에 대한 추가적인 논의는 버그질라를 참고하세요.

SSL 세션을 종료하려면, 이렇게 합니다:

// 표준 HTTP 세션 무효화
session.invalidate();

// SSL 세션을 무효화합니다.
org.apache.tomcat.util.net.SSLSessionManager mgr =
    (org.apache.tomcat.util.net.SSLSessionManager)
    request.getAttribute("javax.servlet.request.ssl_session_mgr");
mgr.invalidateSession();

// 연결을 닫습니다. 왜냐하면 닫힐 때 까지 SSL 세션이 살아있기 때문입니다.
response.setHeader("Connection", "close");
    
주의할 것은 이 코드는 SSLSessionManager 클래스 사용하는 것 때문에 톰캣에 특화된 것입니다. 이것은 현재 바이너리 IO와 NIO 커넥터만을 위한 것이고, APR/네이티브 커넥터는 해당되지 않습니다.


Copyright © 1999-2013, Apache Software Foundation