EC2인스턴스NGINX+HTTPS
지식이 부족해서 많은 삽질을 했다ㅋㅋㅋㅋ
ACM을 통해서 인증서를 받아놓는거는(Route53에 확인용 레코드를 추가 하거나 해야함) 받아놨긴 했는데. 결국 그건 CloudFront / ALB 같은 아마존 로드밸런서 서비스와 함께 사용하는 것이다
-_-;;; 로드밸런서는.. 무료가 아니므로.. 그리고 봇을 돌리기만 할꺼고 ip 로 인바운드 제한을 한거라면 그닥...
아니 오버 스펙이 되어버린다
아무튼 EC2 + Nginx(ALB안씀) 조합으로 HTTPS 를 하려면 자체 인증서를 발행해야 한다는 결론
EC2 인스턴스에서 openssl 을 통해서 자체 인증서를 발행하고
그 crt파일을 nginx 설정에서 로드하는 식으로 해줘야 한다
증명서를 작성할 곳으로 디렉토리 이동하자
ex)
cd /etc/pki/nginx
자체 인증서 발행
openssl 을 사용한다
원래 증명서 발급의 순서는 다음과 같다
- 서버에서 비밀키를 작성한다
- 작성한 비밀키에 대한 공개키를 작성한다
- 서명요구증명서(CSR) 을 작성한다. (내용은 공개키+회사정보 및 연락처 등의 정보)
- CSR을 인증기관에 제출하고, 인증기관의 비밀키에 서명한다(CSR의 내용은 해쉬화 하여, 해쉬값에 대한 비밀키로 서명한다)
- 발행된 증명서를 받고, 서버에 보관한다
증명기관에 제출을 하고, 공적인 증명을 받기 위해서는 비용이 들기때문에 자체 서명식으로(나만 쓸꺼라서) 진행한다
비밀키 생성
RSA의 2048비트로 비밀키를 생성
openssl genrsa 2048 > private.key
genpkey옵션을 비밀키를 이용할 수 있으나 귀찮아서 genrsa 커맨드를 사용
자기 증명서를 생성
자긴자신의 비밀키로 서명을 한 증명서. 즉 내가 인증국이 되어 내가 요청한것을 내가 서명하는.. -_-;; 커맨드
openssl req -new -x509 -days 3650 -key private.key -sha512 -out server.crt
- req : 증명서 서명요구 및 증명서 생성 유틸리티
- -new : 새롭게 증명서 서명 요구를 작성한다. -key 에 지정한 비밀키를 이용하여 공개키를 작성한다
- -x509 : 증명서 서명요구 대신에 자기서명 증명서를 출력한다
- -out : 출력할 파일명을 지정한다
- sha512 증명서의 메세지 다이제스트를 작성하기 위한 알고리즘을 지정한다
- 인증기간은 365일(1년) 3650(10년)으로 생성할 수 있다. 6자리 설정이라 최대 999999(2739년) 설정도 가능하다
증명서 확인
openssl x509 -in server.crt -noout -text
증명서 작성과 설정에 관련된것은 일본분을 참고했는데
조금더 자세하게 잘 설명되어 있는분은 이분이다
인증서 자가작성 : 한국분 블로그
작성된 키와 CRT를 nginx.conf쪽에..
일단 증명서 작성을 하면 그 디렉토리에
- private.key
- server.crt
이렇게 두개가 생성됐을 것이다. 그것을 nginx.conf 에서 불러오게끔 적절히 수정한다
ssl 서버 부분이다.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name _;
root /usr/share/nginx/html;
# 요기서 위에 작성한 crt와 key 파일을 적절히 지정
ssl_certificate "/etc/pki/nginx/server.crt";
ssl_certificate_key "/etc/pki/nginx/private.key";
# 요 옵션들은 세부적으로 ! 좀더 공부후에...
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
# 365 무중단 리버스 프록시는 요놈이 불러옴.
include /etc/nginx/conf.d/service_addr.inc;
location / {
proxy_pass $service_addr;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
전체
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
return 301 https://$host$request_uri;
# root /usr/share/nginx/html;
# add
# include /etc/nginx/conf.d/service_addr.inc;
# location / {
# proxy_pass $service_addr;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# }
# add
# Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
# error_page 404 /404.html;
# location = /404.html {
# }
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
}
# Settings for a TLS enabled server.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name _;
root /usr/share/nginx/html;
# 요기서 위에 작성한 crt와 key 파일을 적절히 지정
ssl_certificate "/etc/pki/nginx/server.crt";
ssl_certificate_key "/etc/pki/nginx/private.key";
# 요 옵션들은 세부적으로 ! 좀더 공부후에...
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
# 365 무중단 리버스 프록시는 요놈이 불러옴.
include /etc/nginx/conf.d/service_addr.inc;
location / {
proxy_pass $service_addr;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
포인트
http (80) 으로 접속할경우 자동으로 https(443) 로 리다이렉트 하게 해주는것은
server {
listen 80;
server_name [도메인명];
return 301 https://$host$request_uri;
}
요 내용이다
총정리.
EC2에서는 80과 443을 열어야한다.
다만, nginx.conf 를 할 때 애시당초 처음부터 https만 허용하도록 한다.(80으로 온건 전부 443으로 리다이렉트)
그러면 80으로 접속해도 443으로 리다이렉트 될것이고
클라이언트 쪽에서는 https 만을 접속해서 보게된다.
nginx.conf 에서 https로 들어온 요청에 대해서 최종적으로 서버를 띄워놓은 포트로 리다이렉트 하게끔 해주면 된다
인바운드와 실제 접속까지 흐름
- 80/443 만 인바운드 해놨으므로 80/443 이외의 포트로는 접속 불가
- http(80)접속 -> nginx에서 https(443)으로 리다이렉트
- https(443)접속 -> 443으로 온것을 실제 어플리케이션 포트로(8080) 리다이렉트
요렇게 되는것이다. !! 그러하다 !!
추가 nginx.conf 보안을 신경쓴 컨피그
어떤분 블로그에서 퍼옴 ㅎ
[참고]
- listen 443 ssl : SSL-TLS 서비스를 제공할 포트를 지정합니다.
- ssl on : SSL-TLS 를 켭니다.
- ssl_protocols : 사용할 SSL-TLS 버전을 지정합니다.
- ssl_ciphers : 사용할 암호 알고리즘을 지정합니다.
- ssl_prefer_server_ciphers : SSL-TLS 협상 과정에서 서버에 설정한 암호 알고리즘을 우선하며 off 일 경우 알고리즘을 약화시켜서 공격할 수가 있으므로 on 으로 설정합니다.
server {
listen 80;
listen 443 ssl;
server_name 도메인;
ssl_password_file /home/SSL/ssl.pass;
ssl_certificate /home/SSL/cert.pem;
ssl_certificate_key /home/SSL/key.pem;
ssl_session_timeout 5m;
# TLS1, SSLv2, SSLv3는 보안에 취약하므로 사용하지 마세요
ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1;
# 사용하지 않을 암호 알고리즘은 !로 명시적으로 지정할 수 있습니다.(블랙리스트 방식)
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
location ~ /\.ht {
deny all;
}
}