일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- ssh command
- Chef
- DevOps
- docker-compose
- 루비
- docker registry
- ubuntu
- 도커
- port
- 패키지
- driver
- golang
- AWS
- ssh
- QT
- 우분투
- 리눅스
- 방화벽체크
- sudo
- VIM
- VPN
- docker container
- docker
- opsworks
- window size
- Openswan
- Linux
- RUBY
- VMware
- 드라이버
- Today
- Total
구리의 창고
Python - HTTP Digest Authentication 서버, 클라이언트 구축 (HTTPDigestAuthHandler) 본문
Python
Python - HTTP Digest Authentication 서버, 클라이언트 구축 (HTTPDigestAuthHandler)
구리z 2017. 9. 20. 10:57머리글
HTTP 서비스를 구축 할 때, 외부에 공개되지 않도록 하기위해 인증 시스템을 도입하는 경우를 생각해보자. HTTP 프로토콜에서 기본으로 제공하는 인증 시스템이 있는데 가장 간단한 방법은 Basic Authentication이다. 이 방법은 아이디/암호를 통해 인증을 하도록 되어있는데, 만약 TLS(HTTPS) 설정이 되어있지 않다면 plain text가 노출 돼 스니핑을 당해서 아이디/암호가 노출 됐을 때, 다른 시스템까지 보안에 취약해 질 수 있어서 위험하다. 모든 서버에 TLS를 설정하면 된다고는 하지만 속도나 비용문제 등을 생각 했을 때 항상 옳은 법은 아니다. 그래서 HTTP Digest Authentication이란 인증 방법을 사용해보려고 한다.
설명
HTTP Digest Authentication의 자세한 설명은 다른 아티클에 있으니 아주 간단한게 설명하고 코드 위주로 정리 할 것이다.
1. 클라이언트가 서버에 접근 요청을 하면 Basic Authentication과 같이 401을 보냄. 이 때 헤더에 인증이나 필요한 암호화 알고리즘과 키 값을 포함해서 보냄.
2 클라이언트에서는 아이디와 암호를 서버에서 받은 키 값과 암호화 알고리즘을 이용하여 인증 요청
3. 서버에서 설정된 값이 맞는지 확인
간단하게 말하면 인증 요청 시, 서버에서 임시 키 값을 발급하고 클라이언트에서는 그 키 값을 조합해 암호화 된 값을 전송함으로써 plain text가 노출되어도 replay attack까지도 방지가 된다는 의미이다.
서버 구현 with NGINX
가장 많이 사용하는 웹 서버 엔진으로 apache2와 nginx를 들 수 있는데, 이 중 nginx를 이용해 구축하도록 할 것이다. 아직 HTTP Digest Authentication 모듈은 NGINX에 공식적으로 들어가있지 않으며 github repository에서 직접 다운 받아 설치해야한다. 기본 패키지에 포함되어있지 않아 nginx를 아래처럼 소스컴파일을 해야한다.
1) NGINX 설치
cd /usr/local/src
wget http://nginx.org/download/nginx-1.12.1.tar.gz
tar zxf nginx-1.12.1.tar.gz
git clone https://github.com/samizdatco/nginx-http-auth-digest.git
cp nginx-http-auth-digest/htdigest.py ~/htdigest.py
cd nginx-1.12.1
./configure --add-module=/usr/local/src/nginx-http-auth-digest
make && make install
2) 암호 생성
위 명령어 중 htdigest.py를 복사하는 걸 볼 수 있는데, 아이디와 암호를 생성해 파일로 만들어주는 유틸리티다. 생성을 위해서는 아이디, 암호, Realm이 필요하다. 여기서 입력하는 모든 정보는 다음 과정에서 설정 할 nginx.conf과 일치해야한다. 여기서 아이디는 guri, 암호는 1234, realm은 Guri Blog라고 입력하겠다.
$ python htdigest.py passwd guri 'Guri Blog'
/home/guri/git-repo/docker-nginx-with-vts/passwd does not exist. Create it? (y/n) y
Password for new user "guri":
Please repeat the password:
$ cat passwd
guri:Guri Blog:0247e8108bda8bd62baf454d636410b6
3) nginx.conf
127.0.0.1:3000 HTTP 서버 Reverse Proxy와 같이 설정한다고 가정하겠다. 설정에 필요한 것만 최소로 남기면 아래와 같다.
worker_processes 4;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name localhost;
auth_digest_user_file /usr/local/etc/nginx/passwd;
auth_digest_shm_size 4m;
location / {
auth_digest 'Guri Blog';
auth_digest_timeout 60s; # 인증 정보를 받기전까지 기다리는 시간
auth_digest_expires 10s; # 인증 후 또는 재사용 가능한 간격 시간
auth_digest_replays 20; # 재사용 가능 횟수
auth_digest_maxtries 5; # Status code가 200이 아닐 시 최대 시도 횟수
auth_digest_evasion_time 300s; # auth_digest_maxtries가 넘었을 때 서버에서 Deny 하는 시간
proxy_pass http://127.0.0.1:3000;
}
}
}
클라이언트 구현 with Python
urllib2.HTTPDigestAuthHandler를 사용 할 것인데 사실 코드가 너무 간단해서 구현이라고 볼 것도 없다.
import urllib2
def main():
passwd_manager = urllib2.HTTPPasswordMgr()
passwd_manager.add_password('Guri Blog', 'http://127.0.0.1/', 'guri', '1234')
digest_auth_handler = urllib2.HTTPDigestAuthHandler(passwd_manager)
opener = urllib2.build_opener(digest_auth_handler)
urllib2.install_opener(opener)
try:
res = urllib2.urlopen('http://127.0.0.1/')
print res.read()
except urllib2.HTTPError as e:
print e
if __name__ == '__main__':
main()
HTTPPasswordMgr를 사용하기 싫으면 HTTPDigestAuthHandler에 바로 아래와 같이 설정해 줄 수도 있다
digest_auth_handler.add_password(realm='Guri Blog', uri='http://127.0.0.1/', user='guri', passwd='1234')
확인
이제 127.0.0.1:3000에 HTTP서버를 띄어놓고 테스트를 해보자.
Comments