[Inception] 5. Nginx와 SSL/TLS

aqualung·2023년 2월 27일
0

SSL / HTTPS

SSL이 적용된 URL의 프로토콜은 https이다 http에 보안(secure)을 의미하는 s가 붙은 형태이다.

SSL은 웹서버와 클라이언트 사이에 통신 암호화 프로토콜이다. 통신패킷은 제 3자에 의한 탈취가 이루어질 수 있다. SSL이 적용되어 있지 않은 경우에는 패킷 내용을 쉽게 확인할 수 있지만 SSL이 적용되어 있다면 복호화 키가 있어야만 패킷의 내용을 알 수 있기 때문에 보안유지에 매우 탁월하다.

데이터를 암호화하고 복호화 하기 위해서는 웹서버와 클라이언트는 암호화에 사용할 세션 키를 공유할 필요가 있고 이를 위한 사전 작업을 핸드셰이크(Handshake)라고 한다.

과정을 간단히 보자면 이러하다.

  1. 서버와 클라이언트가 서로 메세지를 주고 받는다. TLS버전등의 정보가 담겨 있다.

  2. 서버는 인증 기관에서 발급받은 인증서를 클라이언트에게 보낸다.

  3. 클라이언트는 인증서를 검증하고 pre-master secret를 생성하여 서버가 보낸 인증서에 포함된 공개키로 암호화하여 전송한다.

  4. 서버는 전송받은 pre-master secret를 복호화하여 master secret을 생성한다. 이 master secret으로 세션키를 생성한다. pre-master secret는 클라이언트가 생성한 것이기 때문에 스스로 세션키를 생성할 수 있다.

  5. 이제 서버와 클라이언트 모두 같은 세션키를 가지고 있으며 서로 통신할 때 이 하나의 세션키로 데이터를 암호화하고 복호화 할 수 있게 된다.

Nginx 웹 서버로 SSL통신을 하려면 인증서를 발급 받아야 한다. 하지만 인증기관에서 발급 받으려면 비용이 발생한다. 내 경우 실제 운영할 서버가 아니기 때문에 self-signed SSL 인증서를 발급하려고 한다.

링크를 따라 인증서를 발급 받자. 개인키와 인증서는 /etc/nginx/ssl 디렉토리를 만들어 보관하였다.

Nginx

Nginx는 기본적으로 80번 포트로 http프로토콜을 이용하도록 되어있다. 발급 받은 SSL인증서로 https프로토콜을 이용하도록 설정해줄 수 있다.

설정은 nginx.conf 파일 하나로만 이루어 지지만 처음엔 directives의 의미를 파악하기 쉽지 않다.

alpine linux의 경우 설정파일은 /etc/nginx/nginx.conf이다. http 트래픽에 대한 내용을 설정해주기 위해 http 블록을 살펴보면 http.d 디렉토리 내의 .conf 설정파일을 모두 불러와 사용하는 것을 알 수 있다.

http {

		...
        
        # Includes virtual hosts configs.
        include /etc/nginx/http.d/*.conf;
}

아래와 같은 내용의 /etc/nginx/http.d/default.conf을 추가하였다.

server {
	listen 443 ssl;
	listen [::]:443 ssl;
	server_name seunchoi.42.fr;
	ssl_certificate /etc/nginx/ssl/public.crt;
	ssl_certificate_key /etc/nginx/ssl/privatekey.pem;
	ssl_protocols TLSv1.2 TLSv1.3;

	location / {
		root /var/www/html/wordpress;
		index index.php index.html index.htm;
		try_files $uri $uri/ =404;
		location ~ \.php$ {
		fastcgi_pass wordpress:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include fastcgi_params;
		}
    }
}

nginx에 가상호스트를 지정하기 위해서는 server블록을 추가해야 하며 http 요청을 처리하기 위한 핵심이다.

https - SSL/TLS

listen 443 ssl;
listen [::]:443 ssl;
server_name seunchoi.42.fr;
ssl_certificate /etc/nginx/ssl/public.crt;
ssl_certificate_key /etc/nginx/ssl/privatekey.pem;
ssl_protocols TLSv1.2 TLSv1.3;

https 요청을 처리하기 위한 설정이다. 443은 https의 기본 포트번호이다.
ssl 프로토콜 사용을 위해 ssl 파라미터를 붙여 준다.

server_name은 어떤 server블록을 처리할 지 결정하는 서버의 이름이다. 보통은 도메인으로 한다.

ssl_certificatessl_certificate_key로 인증서와 개인키의 경로를 지정해준다.

ssl_protocols로 사용할 SSL/TLS버전을 지정할 수 있다.

이제 https요청에 대한 처리를 할 수 있다.

location 블록

location블록은 URL에 따라 다르게 처리할 수 있게 해준다.

location / {
		root /var/www/html/wordpress;
		index index.php index.html index.htm;
		try_files $uri $uri/ =404;
		location ~ \.php$ {
		fastcgi_pass wordpress:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include fastcgi_params;
		}
}

location 뒤에 패턴으로 URL의 sub-path를 지정할 수 있는데 자세한 패턴 정규식 표현은 링크를 참고하자.

root는 요청한 URL에 대응하는 로컬파일시스템의 파일경로를 구성한다. 예를 들어 seunchoi.42.fr/abc/ABC.html이라는 URL의 요청을 받으면 로컬에서 /var/www/html/wordpress/abc/ABC.html이라는 정적파일을 보여준다.

index는 URL에 따른 index파일로 어떤 파일을 사용할 것인지를 설정한다. seunchoi.42.fr에 접속하면 /var/www/html/wordpress/index.php 파일을 index파일로서 보여주는 것이다.

try_files $uri $uri/ =404 root폴더에 uri에 따른 폴더가 있는지 찾아보고 없다면 404에러를 띄워준다.

location ~ \.php$블록을 추가함으로써 php파일에 대한 요청을 php-fpm으로 돌릴 수 있다. 참고 문서

fastcgi_pass wordpress:9000: wordpress컨테이너의 9000번 포트로 php파일의 처리를 요청한다.

fastcgi_indexfastcgi_param의 의미에 대해서는 다음 예시를 보자.

fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;

fastcgi_index는 '/'(슬래시)로 끝나는 경로에 대한 파일을 $fastcgi_script_name의 값으로 한다. URL이 "/"인 경우 SCRIPT_FILENAME/home/www/scripts/php/index.php이 된다.

URL이 '/'(슬래시)로 끝나지 않는, 예를 들어 "/page.php"같은 경우 SCRIPT_FILENAME/home/www/scripts/php/page.php이 된다.

이로써 SSL프로토콜을 사용하며 php파일의 동적컨텐츠를 처리할 수 있는 설정은 모두 끝마쳤다.

0개의 댓글

관련 채용 정보