2012년 3월 9일 금요일

Apache Tomcat 서버 SSL 설정

SSL 참고: http://www.ibm.com/developerworks/kr/library/ac-iscssl1/index.html

HTTPS 란 SSL 소켓을 이용한 HTTP 프로토콜이다.
TCP 소켓 대신 SSL 소켓을 이용해서 서로 통신하고 HTTP 프로토콜에 맞게 데이터를 주고 받는 방식이 되겠다.

SSL 소켓을 이용하게 되면 대략 아래와 같은 접속 순서를 갖게 된다. (자세히 설명하지 않음)

  1. 클라이언트가 서버에 접속한다.
  2. 서버가 클라이언트에 인증서를 보낸다.
  3. 클라이언트는 인증서를 검사한다.
  4. 성공인 경우 통신을 시작한다.

만약 서버측도 클라이언트를 인증해야 하는 경우 아래와 같다. (Mutual authentication)

  1. 클라이언트가 서버에 접속한다.
  2. 서버가 클라이언트에 인증서를 보낸다.
  3. 클라이언트는 인증서를 검사한다.
  4. 성공이고 서버가 클라이언트 인증서를 요구하는 경우 서버로 클라이언트 인증서를 전송한다.
  5. 서버가 클라이언트 인증서를 검사한다.
  6. 성공인 경우 통신을 시작한다.

!) 인증 당하는 주체는 key 가 필요하고 인증을 하는 주체는 key를 인증하는 인증서가 필요하다.

Apache Tomcat 서버 SSL 설정하기

1. Portecle
Keystore 생성/편집 작업을 편리하게 해주는 도구
다운로드: http://portecle.sourceforge.net/
key 저장소를 만들 수도 있고 신뢰할 수 있는 인증서 저장소를 만들 수도 있다.

2. Keystore 만들기
서버 key 저장소를 만든다. Tomcat 서버가 클라이언트로 보낼 key 를 만든다.
2.1. portecle 를 실행한다.


2.2. JKS 저장소를 생성한다.


2.3. key 를 생성한다.



Common Name 에 호스트 이름을 적어준다.
Hostname 을 비교하는 클라이언트의 경우 Common Name 이 접속한 hostname 과 다르면 연결 실패하는 경우가 있다.

Alias 는 원하는대로 정한다.



2.4. JKS 저장소를 저장한다.

3. [Tomcat 설정] server.xml 수정
예) [Tomcat 경로]/keystore/ 에 server-keystore.jks 라는 파일명으로 keystore 를 저장했다.

3.1. [Tomcat 경로]/conf/server.xml 파일 수정
  • 아래 내용을 찾아 주석을 풀어준다.

<!--
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
    maxThreads="150" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS" />
-->

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
    maxThreads="150" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS" />

3.2. keystore 파일 위치와 keystore 비밀번호를 설정

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
    keystoreFile="keystore/server-keystore.jks" keystorePass="changeit"
    maxThreads="150" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS" />

3.3. Tomcat server 를 시작
 [Tomcat 경로]/bin/startup.bat 또는 startup.sh 를 실행

!) Tomcat 시작 중 APR 관련 에러 발생 시

4. 테스트
4.1. 크롬 브라우저로 접속
!) 포트 번호에 주의한다. 위 server.xml 파일 수정한 부분에 port 번호로 접속해야 한다.

4.2. 개인이 만든 인증서 이기 때문에 안전하지 않다는 메시지를 보게 될 것이다.

4.3. 무시하면 접속이 된다.

서버에 접속하게 되면 서버가 클라이언트로 서버측 인증서를 전송하게 된다.
클라이언트는 자신이 갖고 있는 신뢰할 수 있는 인증서 목록을 이용하여 인증서를 검사한다.



추가 사항)

curl 로 테스트하기

공인 인증 기관으로 부터 인증된 서버에 접속할 때는 공인 인증된 인증서 파일을 이용해서 인증할 수 있다.
curl 용 인증서 파일은 아래에서 다운로드 받을 수 있다. PEM 포맷이다.
대부분의 인터넷에 공개된 사이트들은 위 인증서 파일로 인증 가능할 것이다.

curl 실행시 인증서 파일을 지정하려면 -- cacert 옵션을 이용한다.
--cacert 옵션
예) curl --cacert cacert.pem https://<url>:<port>

구글에 접속해 보았다.
$ curl --cacert caert.pem https://www.google.com

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="https://www.google.co.kr/">here</A>.
</BODY></HTML>

302 (redirect) 코드를 따라 가려면 -L 옵션을 주면 된다.
$ curl --cacert caert.pem -L https://www.google.com

JKS 저장소 를 PEM 으로 변환해야 curl 에서 사용할 수 있다.
 - JKS 를 PEM 파일로 변환하기
참고: http://www.swview.org/node/191
 ㄱ. Portecle 를 이용해 JKS 파일을 PKCS#12 형태로 export 한다.
 ㄴ. openssl 을 이용해서 pem 파일로 변환한다.
  예) $ openssl pkcs12 -in mystore.p12 -out mystore.pem -passin pass:mysecret -passout pass:mysecret
 ㄷ. 당연한 이야기 이지만 pem 파일의 읽기 권한을 줘야 한다.
  예) $ chmod 655 mystore.pem

!) JKS 를 PKCS#12로 변경하려 할 때 에러가 나는 경우가 있다.
참고: http://tjjava.blogspot.com/2011/07/invalidkeyexception-illegal-key-size.html

 - 자바 사이트에서 JCE(Java Cryptography Extension) 를 다운로드 받아 덮어쓰기 하면 된다.

설치된 Java 버전에 맞는 파일을 다운로드 받는다.

[JRE 경로]/lib/security/ 에 덮어쓰기한다. (혹시 모르니 기존 파일을 백업해 두자)
 - Mac OS JRE 경로 : /Library/Java/Home
 - 윈도 JRE 경로 : c:/program files/java/jre

테스트 예)
$ curl --cacert mystore.pem https://localhost:8443


추가 사항)


서버측도 클라이언트를 인증 하고자 하는 경우(Mutual authentication)

ㄱ. Trust store (신뢰할 수 있는 인증서 저장소) 만들기
  1) 우선 해당 클라이언트를 검증할 인증서 파일이 필요하다. 검증 가능한 인증서는 key 를 갖고 있는 주체가 생성하여 전달해야 한다.
  2) keystore 를 만드는 과정과 비슷하다. Portecle 를 이용해 JKS 저장소를 만들고 클라이언트 인증서 파일을 import 하면 된다.
ㄴ. server.xml 파일 수정
  - truststore 의 위치와 패스워드를 입력한다.
  - clientAuth 를 true 로 설정해야 한다.

예) [tomcat 경로]/keystore/ 에 truststorejks 라고 저장했다고 가정

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
    keystoreFile="keystore/server-keystore.jks" keystorePass="changeit"
   truststoreFile="keystore/truststore.jks" truststorePass="changeit"
    maxThreads="150" scheme="https" secure="true"
    clientAuth="true" sslProtocol="TLS" />

댓글 없음:

댓글 쓰기