Rath World » 2012 » January

Archive

Archive for January, 2012

클라이언트 인증서로 로그인 하려면

January 27th, 2012 2 comments

앞 글에서 클라이언트 인증서 이야기를 꺼낸김에 OpenSSL을 이용해 환경구축하는 방법을 간략히 설명한다.

* Prerequisite

  1. OpenSSL
  2. Nginx

* CA 만들기 

0) 디렉토리 구조를 언급하고 시작하겠다. CA 인증서를 비롯 사용자의 인증서까지 모조리 ./certs 디렉토리를 쓸 것이다.

$ mkdir ca; cd ca
$ touch openssl.cnf (아래 2번에 있는 내용을 복사해서 붙이시길)
$ touch index.txt
$ echo “00” > serial
$ mkdir certs

1) 일단 CA 인증서를 만들어야 한다. self signed 여도 아무 문제 없다. 구매하는 실수를 저지르지 마시길.

$ openssl req -x509 -nodes -days 3650 -newkey rsa:1024 -keyout certs/ca.key -out certs/ca.cert

-nodes는 CA키를 암호화하지 않겠다는 것이다. 웬만하면 넣어라. 나중에 귀찮다.
-days 는 대충 10년 넘게 하시고, 1024는 얼마든지 올려도 좋다. 그 뒤 파라미터들은 만들 CA 인증서와 CA 비밀키 파일명이다.

위처럼 입력하고 엔터를 치면 국가코드, 주, 도시, 조직명, 부서명, 이름, 이메일주소 등을 물어본다. 아무거나 때려박으시라.

2) openssl.conf 가 필요하다.

[ ca ]
default_ca = CA_default

[ CA_default ]
dir = .
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
serial = $dir/serial
new_certs_dir = $dir/certs

certificate = $certs/ca.cert # The CA certificate
private_key = $certs/ca.key

name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options

default_days = 3650 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
policy = policy_match

# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

중간에 # The CA certificate 부분 2줄에 집중한다. 조금전에 만든 CA키, CA인증서 파일의 경로를 쓴다. policy_match 섹션은 모두 optional로 둬도 된다. 우리는 사용자에게 직접 csr 파일을 보내라고 하지 않을테고 사용자와  CA의 국가가 달라도 문제될 건 없다.

3) 사용자 인증서 생성

사용자가 막 인증서를 만들어낼 수는 없다. 사용자는 그저 인증서 서명 요청서(CSR)를 작성할 수 있을 뿐이다.

$ openssl req -new -newkey rsa:1024 -nodes -keyout my.key -out my.csr

그러면 CA 인증서를 만들었을때처럼 국가코드부터 이것저것 물어본다. 다 대충쓰시고 Common Name을 신경써서 작성해야 한다. 아이디라고 생각하는 것이 좋다. (웹서버 인증서라면 hostname이 되는 부분임) 중복 아이디들은 조직명, 부서명을 이용하여 해결해도 되고 Common Name 다음에 물어보는 email 주소를 사용할 수도 있겠다.

4) CA가 CSR에 서명함

이제 서명한다. 서명은 쉽다. 입력할 게 거의 없기 때문이다.

$ openssl ca -config openssl.conf -in my.csr

정말 서명할꺼냐고 물으면 쿨하게 y 를 눌러주자. 그럼 CA 서명까지 들어간 사용자 인증서가 만들어진다. 생성된 인증서는 serial 파일내용의 숫자.pem 으로 certs 디렉토리에 생성된다. serial 파일속의 숫자는 openssl ca가 자동으로 1씩 증가시켜준다.

5) 사용자 인증서 합체

3번에서 만든 my.key 파일과 certs/$(serial).pem 을 합쳐서 자웅동체 PKCS12 인증서를 만들 시간이다. my.csr 파일은 지워버려도 좋다. 0)에서 제시한대로 serial 파일을 만들었다면 생성된 인증서는 certs/00.pem 에 있을 것이다. 그러면

$ openssl pkcs12 -in certs/00.pem -inkey my.key -export -out my.p12

하면 export password를 정해달라고 한다. 고객님의 소중한 인증서이므로 비밀번호를 정해두자. 이제 최종 결과물인 my.p12이 생겼다. 짝짝짝

6) 사용자 인증서 설치

윈도우즈라면 아마 확장자를 pfx로 바꿔야할지도 모르겠고, Mac OSX 이라면 .p12 그대로 둬도 좋다. 탐색기나 Finder 에서 더블클릭하여 간단한 절차를 따라주면 시스템에 이 인증서가 설치된다. 이 과정에서 5)에서 지정했던 비밀번호를 묻게 된다. 입력해주자.

7) Nginx 설정 변경

SSL 기본설정은 되어있다고 가정하고, 클라이언트 인증서를 체크하기 위한 부분만 설명한다. 일단 1) 에서 만든 CA 인증서 파일을 적당한 디렉토리 ($nginx/conf/certs)로 복사한다. 이 파일명이 ca.cert 일 경우

ssl_client_certificate  certs/ca.cert;
ssl_verify_client on;
ssl_verify_depth 1;

을 추가한다. 이러면 사용자들 인증서들의 Issuer (인증서 발급해준 분)가 ca.cert 이기 때문에  4) 과정을 거친 사용자인증서들만 verify가 성공하고 나머지는 모두 실패하게 된다.

이제 application_server로 가는 proxy_pass가 있는 location 블럭에 헤더 하나를 추가한다.

proxy_set_header  X-SSL-Subject  $ssl_client_s_dn;

이로서 Nginx 설정 끝

8 ) Application Server 에서 사용자 DN 가져오기

request.headers[‘X-SSL-Subject’]에 클라이언트 인증서의 DN이 담겨온다. 이런식이다.

/C=GB, ST=England, O=Adrenaline, OU=Users, CN=rath /emailAddress=rath@xrath.com

여기서 필요한 부분만 파싱해서 쓰면 된다. 파싱하기 가장 편한 /emailAddress=(.*) 추천.

 

Categories: Development Tags:

로그인

January 27th, 2012 1 comment

혼자 또는 측근들과 사용할 웹서비스를 만드는 경우 인증이 항상 번거로운 존재가 된다.

* 세션

내가 이 웹서비스를 쓰다가 화장실을 들렀다가 부엌에 가서 커피를 내려왔을 때 ‘세션이 만료되었습니다’ 를 보게 되는 거지같은 경험을 받고 싶지 않다.

문맥(혼자 또는 측근들과 사용하는 웹서비스)에 어긋남이 있긴 하지만 확장성 이슈가 있고, session persistence 설정을 따로 하지 않을 경우 개발도중에 서버 내렸다 올리면 세션이 사라져서 개발편의성도 떨어진다. 개발자가 지쳐가는 시점부터는 세션에 아무거나 쑤셔넣기 시작하는데 (open된 fd를 넣는다거나) 세션서버 분리시점에 뒤늦게 깨달아 후회하여 고치면 그나마 다행이나, serialize 가능한 객체라 세션서버가 분리되도 상관없다면 ‘에이 뭐 serialize하는데 얼마나 걸리겠어?’ 하게 되어 서버가 서서히 지쳐가게 된다.

* 쿠키

쿠키에 User ID를 넣었을 때 hijacking을 막으려면 내용 전체를 shared key로 암호화(언제 깨질지 모름)하거나, Play! 처럼 내용물은 plain으로 하되 스푸핑을 막기 위해 signature를 넣을 수도 있다. 무엇을 선택하더라도 서버코드쪽에 최소한 검증을 위한 로직이 들어가야 한다. 귀찮다.

* 인증서

nginx 쪽에서 클라이언트 인증서 verify 까지 모두 마치고 application server 에게 subject 만 (nginx|apache의 경우 $ssl_client_s_dn) 넘겨주니 application server는 nginx가 뽑아준 DN 문자열 속에서 코드 1줄로 CN을 뽑거나 emailAddress를 뽑아 믿고 쓸 수 있다. 인증서를 쓰기 시작하면 내가 만드는 모든 웹서비스에서 동일한 인증서로 로그인을 할 수 있으니 억지로 껴맞춰보자면 OpenID 스러운 장점을 가지게 된다. 도시와 국가 정보까지 제공된다!

반면 웹브라우저의 클라이언트 인증서 지원여부에 의존하게 되므로 접근성이 현저하게 떨어진다. iOS의 경우 인증서를 Mail 앱 등에서 열어서 바로 설치할 수 있지만, Android ICS (4.0) 이전의 기본 브라우저는 기 설치된 Client Certificate 사용을 지원조차 하지 않으며, 이를 지원한다는 Galaxy Nexus (ICS) 에서 직접 시도해보니 로그인에 사용할 인증서를 고르는 UI 까지는 잘 표시되지만 정작 인증서를 선택하고 접속을 시도하면 com.google.android.browser가 세폴먹고 죽는다. 이런 거지같은.

접근하는 기기로서의 문제도 있지만, 이 서비스가 public 하게 오픈될 경우 사용자들 개개인에게 인증서를 발급해줘야 하는 문제가 있다. DN  중 사용자로부터는 Common Name과 emailAddress 만 받고 나머지는 자동으로 채워 인증서를 발급하기까지는 쉽겠지만, 사용자에게 PKCS12 포맷 인증서를 다운로드 받게하여 탐색기나 Finder에서 더블클릭하여 시스템에 설치하게 해야한다. 물론 설치하고난 뒤에는 id/pw 입력보다도 훨씬 더 편하게 인증 과정을 마칠 수 있겠지만, 인증서를 잃어버리면 끝이다. 그렇다고 DB에 사용자들의 패스워드를 plain text로 저장하는 정신나간녀석들처럼 private key를 서버에 보관하고 있을 수는 없지 않은가 ㅋ. public 하게 오픈할 땐 인증서 다 걷어내고 세션|쿠키로 바꾸는 게 좋겠다.

어쨌든 SSL 처리 때문에 웹서버(nginx|apache) 성능이 현저하게 떨어진다.

* 결론 

여전히 번거롭다.

Categories: Development Tags:

Android SDK r16에서의 ant 빌드 이슈

January 25th, 2012 Comments off

Android SDK Tools r16에서 생겨난 이슈입니다.

요약하면 코드 한줄 고치고 ant 빌드했는데 apk 파일이 새로 만들어지지 않는다는 겁니다. 이런게 어떻게 릴리즈 됐고 아직도 패치가 안됐는지 참..

구글링 하다보면 r16 이 이상한거니 r15 쓰라는 말도 있고, 개발장비 성능이 좋은 개발자분들은 매번 ant clean debug 를 한다고 합니다.

com.android.ant.InputPath#ignores에서 boolean flag에 !를 실수로 붙여서 생긴 문제이므로 소스코드의 !를 빼주기만 하면 됩니다. 고치기 귀찮으시죠?

$ANDROID_SDK/tools/lib/anttasks.jar 를 덮어쓰시면 됩니다.

추가로 제가 수정한 이 anttasks.jar 파일에는 dx –no-optimize 옵션 지원을 넣은DexExecTask도 포함되어 있습니다. no-optimize는 말도 안되게 느린 안드로이드의 dex 파일 생성을 조금이라도 빨리 하기 위해 사용합니다. $ANDROID_SDK/tools/ant/build.xml 파일의 253 라인 dex element 에 nooptimize=”true”를 넣으면 30% 정도의 속도향상을 보이게 됩니다. 마켓에 배포할 때는 no-optimize 꺼주시는 것 잊지 말고요.

코드 한 바이트도 안고쳐진 외부 라이브러리들도 빌드때마다 매번 다시 처리하시는 android dx tool 에게 10초간 묵념합시다.

Categories: Development Tags: , ,