해외서버를 이용하다보면 네트워크와 관련된 스펙은 좋은데 성능자체가 크게 좋지 않은 서버가 있는 반면, 반대로 성능자체는 좋은데 네트워크에 문제가 있는 경우가 있었다. 이것을 적절히 이용할 수 있는 방법은 없을까? 생각하여 부하가 굉장히 낮은 WAS (웹어플리케이션서버)인 nginx에 Reverse Proxy 서버를 구현해보게 되었다. 실제로 많은 리소스를 요하는 처리는 Origin Web Server에서 처리할 것이다.
on front-side server (198.51.100.32)
proxy_cache_path mycacheserver levels=1:2 keys_zone=mycacheserver:10m inactive=24h max_size=2g loader_files=1000;
upstream proxy-backend {
# keepalive는 nginx가 최대로 허용하는 업스트림 커넥션 수
keepalive 32;
keepalive_timeout 24h;
server 203.0.113.4:443;
}
server {
listen 443 ssl http2;
server_name web.kerus.net;
# $server_name 값이 항상 server_name 인자의 첫 번째 값이기 때문에 선언필요
set $vserver_name $server_name;
http2_push_preload on;
# 기본 HTTPS 서버
add_header Strict-Transport-Security "max-age=2147483647; includeSubDomains; preload" always;
add_header Content-Security-Policy "block-all-mixed-content";
ssl_certificate /etc/letsencrypt/live/kerus.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/kerus.net/privkey.pem;
# 필요에 따라 설정
#ssl_client_certificate /etc/ssl/certs/cloudflare.crt;
#ssl_verify_client off;
#ssl_stapling off;
#ssl_stapling_verify off;
#ssl_session_timeout 1d;
#ssl_session_cache shared:MozSSL:10m;
#ssl_session_tickets off;
#proxy_ssl_certificate /etc/nginx/certs/cert.pem;
#proxy_ssl_certificate_key /etc/nginx/certs/cert.key;
#proxy_ssl_verify on;
# 캐시 대상
location ~* .(ico|jpg|png|gif|jpeg|css|swf|js|woff)$ {
# 필요에 따라 설정
#access_log off;
#expires 1h;
gzip_static on;
gzip_comp_level 5;
add_header Cache-Control private;
# 이미지 배포의 경우 nopush가 좋다고 생각한다..
tcp_nopush on;
try_files $uri @cached-proxy;
}
location @cached-proxy {
# 프록시 필수 설정
proxy_ssl_server_name on;
proxy_ssl_name $vserver_name;
proxy_ssl_session_reuse on;
proxy_set_header Host $vserver_name;
proxy_pass https://proxy-backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
# 필요에 따라 설정
proxy_ssl_protocols TLSv1.3;
#proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
proxy_hide_header Strict-Transport-Security;
proxy_hide_header Content-Security-Policy;
proxy_hide_header X-Powered-By;
# 성능을 위한 설정
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering on;
proxy_max_temp_file_size 50M;
proxy_buffers 8 16K;
proxy_buffer_size 16K;
proxy_send_timeout 24h;
proxy_read_timeout 24h;
proxy_connect_timeout 10s;
# 캐시
proxy_cache mycacheserver;
proxy_cache_valid 200 1d;
proxy_cache_use_stale error timeout invalid_header updating
http_500 http_502 http_503 http_504;
proxy_cache_key $scheme$proxy_host$uri$is_args$args;
# nginx slice module 필요
proxy_set_header Range $slice_range;
# 캐시 디버깅용
add_header K-Cache-Status $upstream_cache_status;
# 이미 한 번 hide 된 헤더를 클라이언트에게 보내려면 hide_header 이후에 다시 선언해야함
add_header Strict-Transport-Security "max-age=2147483647; includeSubDomains; preload" always;
add_header Content-Security-Policy "block-all-mixed-content";
}
location ~ {
# 프록시 필수 설정
proxy_ssl_server_name on;
proxy_ssl_name $vserver_name;
proxy_ssl_session_reuse on;
proxy_set_header Host $vserver_name;
proxy_pass https://proxy-backend;
proxy_redirect off;
# 필요에 따라 설정
proxy_ssl_protocols TLSv1.3;
#proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
proxy_hide_header Strict-Transport-Security;
proxy_hide_header Content-Security-Policy;
proxy_hide_header X-Powered-By;
# 성능을 위한 설정
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering on;
proxy_max_temp_file_size 50M;
proxy_buffers 8 16K;
proxy_buffer_size 16K;
proxy_send_timeout 24h;
proxy_read_timeout 24h;
proxy_connect_timeout 10s;
# 캐시
proxy_cache off;
# nginx slice module 필요
proxy_set_header Range $slice_range;
# 캐시 디버깅용
add_header K-Cache-Status FORCE-DYNAMIC;
# 이미 한 번 hide 된 헤더를 클라이언트에게 보내려면 hide_header 이후에 다시 선언해야함
add_header Strict-Transport-Security "max-age=2147483647; includeSubDomains; preload" always;
add_header Content-Security-Policy "block-all-mixed-content";
}
}
on backend server (203.0.113.4) KEEP-ALIVE
nginx 설정 http 이나 server 내에
keepalive_timeout 24h;
위처럼 Keep-Alive를 해주는 것이 중요하다. 이 경우 악의적인 공격에 의해 세션이 메모리에 계속 남아 있으면 곤란하지만 TCP+TLS의 handshake가 발생하면 상당히 TTFB가 증가하므로 연결을 유지시켜주도록 한다.