NGINX Header 설정 자습서
NGINX header 설정은 중요한 이유가 여러 가지 있습니다. 주된 이유는 보안, 성능, 사용자 경험, 로깅 및 추적, 애플리케이션의 동작 제어에 큰 영향을 미치기 때문입니다. 이번 포스트에서는 proxy_set_header와 add_header 설정에 대해 설명하겠습니다.
header는 클라이언트와 서버 간의 통신에 있어 중요한 메타데이터를 전달하는 역할을 합니다. 잘못된 헤더 설정은 보안 취약점을 유발할 수 있으며, 이를 방지하기 위한 적절한 설정은 필수입니다.
목차
1. 기본 NGINX Header
2. proxy_set_header
2-1. proxy_set_header의 사용 사례
3. add_header
3-1. add_header의 사용 사례
4. NGINX Header 설정에 대한 차이점
5. NGIXN Plus를 사용하여 NGINX Header 내에 서버 정보 제거
6. NGINX Header 결론
1. 기본 NGINX Header
우선 NGINX의 기본 응답 헤더 값을 curl 명령어를 통해 확인합니다:
# curl -I example.com
HTTP/1.1 200 OK
Server: nginx/1.25.5
Date: Tue, 22 Oct 2024 07:58:45 GMT
Content-Type: text/html
Content-Length: 781
Last-Modified: Fri, 18 Oct 2024 04:30:22 GMT
Connection: keep-alive
ETag: "6711e45e-30d"
Accept-Ranges: bytes
위의 응답 헤더 내용은 아래와 같습니다.
- HTTP/1.1 200 OK – 이 라인은 응답 상태를 나타냅니다. HTTP/1.1은 사용된 프로토콜 버전이고,
200 OK는 요청이 성공적으로 처리되었음을 의미합니다. 클라이언트가 요청한 리소스가 정상적으로 제공되었음을 나타냅니다. - Server: nginx/1.25.5 – 이 헤더는 서버 소프트웨어와 그 버전을 나타냅니다. 여기서는 NGINX 버전 1.25.5가 사용되고 있음을 보여줍니다. 이 정보는 클라이언트가 서버의 종류를 이해하는 데 도움을 줄 수 있습니다.
- Date: Tue, 22 Oct 2024 07:58:45 GMT – 이 헤더는 응답이 생성된 날짜와 시간을 나타냅니다. GMT(그리니치 표준시) 형식으로 제공되며, 클라이언트는 이를 통해 응답의 신선도를 판단할 수 있습니다.
- Content-Type: text/html – 이 헤더는 응답의 콘텐츠 유형을 지정합니다. 여기서는
text/html로 설정되어 있어, 클라이언트가 이 응답이 HTML 문서임을 알 수 있습니다. 이는 클라이언트가 적절하게 콘텐츠를 렌더링하는 데 필요합니다. - Content-Length: 781 – 이 헤더는 응답 본문의 크기를 바이트 단위로 나타냅니다. 여기서는 응답 본문의 길이가 781 바이트임을 의미하며, 클라이언트는 이를 통해 수신할 데이터의 크기를 알 수 있습니다.
- Last-Modified: Fri, 18 Oct 2024 04:30:22 GMT – 이 헤더는 해당 리소스가 마지막으로 수정된 날짜와 시간을 나타냅니다. 클라이언트는 이 정보를 사용하여 캐시를 결정하거나, 이후 요청 시 리소스가 변경되었는지 확인하는 데 사용할 수 있습니다.
- Connection: keep-alive – 이 헤더는 클라이언트와 서버 간의 연결이 지속됨을 나타냅니다.
keep-alive가 설정되어 있으면, 여러 요청을 같은 연결을 통해 처리할 수 있어 성능을 개선할 수 있습니다. 이를 통해 추가적인 연결 설정 과정을 줄이고 대역폭을 효율적으로 사용할 수 있습니다. - ETag: “6711e45e-30d” – ETag는 엔티티 태그(Entity Tag)의 약자로, 리소스의 특정 버전을 식별하는 데 사용됩니다. 클라이언트는 이 값을 사용하여 이후 요청 시 해당 리소스의 버전이 변경되었는지 확인할 수 있습니다. 이 정보는 캐시 제어에 유용합니다.
- Accept-Ranges: bytes – 이 헤더는 클라이언트가 특정 바이트 범위를 요청할 수 있음을 나타냅니다.
bytes로 설정되어 있는 경우, 클라이언트는 큰 파일을 다운로드할 때 부분적으로 다운로드할 수 있습니다. 이를 통해 다운로드 중에 실패할 경우 특정 부분만 다시 요청할 수 있는 유연성을 제공합니다.
2. proxy_set_header
proxy_set_header는 NGINX 프록시 서버가 클라이언트로부터 받은 요청을 백엔드 서버로 전달할 때, 요청의 HTTP 헤더 값을 설정하거나 수정하는 데 사용되는 디렉티브입니다. 이 설정은 주로 리버스 프록시(reverse proxy) 환경에서 클라이언트의 정보나 요청의 특정 속성을 백엔드에 전달하거나, 이를 변경할 필요가 있을 때 사용됩니다.
기본적인 구조는 아래와 같습니다:
Syntax: proxy_set_header field value;
Default: proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context: http, server, location
- field – 변경하거나 추가하려는 HTTP 헤더의 이름
- value – 해당 헤더에 설정할 값
2-1. proxy_set_header의 사용 사례
앞서 언급했듯이 proxy_set_header는 NGINX 프록시 서버가 클라이언트로 받은 요청을 백엔드 서버로 전달할 때 사용되는 디렉티브라고 설명했습니다. 가장 대표적인 사례는 클라이언트의 IP를 백엔드 서버로 전달할 때 사용됩니다.
proxy_set_header를 사용하지 않고 백엔드 서버로 요청을 넘기게 되면, 백엔드 서버의 로그에는 아래와 같이 클라이언트 IP가 아닌 프록시 서버의 IP가 기록되게 됩니다.

전제 조건은 아래와 같습니다.
- Client IP – 175.196.233.10
- Proxy server IP – 192.168.201.100
왼쪽 로그(프록시 서버)를 확인해보면 프록시 서버는 클라이언트 IP를 받는 것을 확인할 수 있는 반면, 오른쪽 로그(백엔드 서버)는 클라이언트 IP가 아닌 프록시 서버의 IP를 받는 것을 확인할 수 있습니다. 이런 상황의 경우 백엔드의 서버에서는 클라이언트의 IP를 모르게됩니다.
이런 상황일 때, proxy_set_header 디렉티브를 사용하여 클라이언트 IP를 백엔드 서버에 전달할 수 있습니다.
upstream backend_server {
server 192.168.201.80:8111;
}
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/header.log header;
location / {
proxy_pass http://backend_server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
여기서 각 proxy_set_header의 역할은 아래와 같습니다.
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for – 클라이언트 IP 주소를 X-Forwarded-For 헤더에 추가하여 백엔드 서버에 전달합니다.
결과는 아래와 같이 백엔드 서버에서도 $proxy_add_x_forwarded_for를 통해 클라이언트 IP를 받고 동시에 프록시 서버 IP도 전달 받는 것을 확인할 수 있습니다.

3. add_header
add_header는 NGINX에서 클라이언트에게 응답을 보낼 때 HTTP 헤더를 추가하는 데 사용되는 디렉티브입니다. 이 디렉티브는 주로 보안, 캐싱, 사용자 정의 HTTP 응답 헤더를 설정하는 데 사용됩니다.
기본적인 구조는 아래와 같습니다.
Syntax: add_header name value [always];
Default: —
Context: http, server, location, if in location
- name – 응답에 추가하고자 하는 HTTP 헤더의 이름.
- value – 해당 HTTP 헤더에 할당될 값.
- always – always 매개변수를 지정한 경우 응답코드와 관계없이 헤더 필드를 추가합니다.
3-1. add_header의 사용 사례
add_header는 다양한 상황에 사용되며, 특히 보안, 캐싱, 사용자 정의 응답에 자주 활용됩니다.
보안 헤더 추가:
upstream backend_server {
server 192.168.201.80:8111;
}
server {
listen 80;
server_name 175.196.233.104;
location / {
proxy_pass http://backend_server;
# 클라이언트로 전달될 응답 헤더 설정 (add_header)
add_header X-Frame-Options "SAMEORIGIN";
}
}
위에서 설정된 add_header의 역할은 아래와 같습니다.
- add_header X-Frame-Options “SAMEORIGIN” – 클릭재킹 공격을 방지하기 위한 헤더입니다. 이 헤더가 설정되면, 같은 출처의 페이지에서만 이 페이지를 iframe으로 포함할 수 있습니다.
이와 같이 클라이언트에게 추가 정보를 제공하고, 보안 헤더를 통해 클릭재킹과 같은 공격을 방지할 수 있습니다.
응답이 성공했을 때의 응답 헤더:
# curl -I example.com
HTTP/1.1 200 OK
Server: nginx/1.25.5
Date: Thu, 24 Oct 2024 07:04:37 GMT
Content-Type: text/html
Content-Length: 2246
Connection: keep-alive
Last-Modified: Wed, 23 Oct 2024 07:25:36 GMT
ETag: "6718a4f0-8c6"
Accept-Ranges: bytes
X-Frame-Options: SAMEORIGIN
클릭재킹이란, 공격자가 사용자를 속여 보이지 않는 요소를 클릭하도록 할 때 발생합니다. 해당 요소는 사용자 인터페이스에 숨겨져 있어 찾기 어렵습니다. 클릭재킹은 UI 수정이라고도 합니다.
4. NGINX Header 설정에 대한 차이점
proxy_set_header는 클라이언트의 요청을 백엔드 서버로 전달할 때, 특정 HTTP 헤더를 설정하거나 변경하는 데 사용됩니다.
- 헤더 전달 – 클라이언트의 요청에서 가져온 헤더를 백엔드 서버로 전달할 수 있습니다.
- 보안 강화 – 클라이언트 IP 주소나 요청의 원래 Host등을 전달하여, 백엔드 서버에서 실제 요청을 정확하게 처리할 수 있도록 합니다.
- 유연한 설정 – 요청 헤더를 수정하여 백엔드 서버에서 요구하는 형식으로 데이터를 전달할 수 있습니다. 이로 인해 다양한 상황에 맞게 서버를 구성할 수 있습니다.
add_header는 NGINX가 클라이언트에게 보내는 응답에 추가적인 HTTP 헤더를 설정하는 데 사용됩니다.
- 응답 헤더 설정 – 클라이언트에게 전송되는 응답에 사용자 정의 헤더를 추가하여 추가 정보를 제공할 수 있습니다.
- 보안 향상 – X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security와 같은 보안 관련 헤더를 추가하여 웹 애플리케이션의 보안을 강화합니다.
- 버전 관리: 버전 정보나 API status 등을 클라이언트에게 명시적으로 전달하여 클라이언트의 이해를 돕습니다.
차이점 요약:
| 특징 | proxy_set_header | add_header |
| 목적 | 요청 헤더를 수정하여 백엔드 서버로 전달 | 응답 헤더를 추가하여 클라이언트에게 전송 |
| 사용 시점 | 클라이언트 요청이 백엔드 서버로 전달될 때 | 서버가 클라이언트에게 응답을 보낼 때 |
| 예시 | 클라이언트 IP를 백엔드 서버로 전달 | 보안 헤더를 클라이언트에게 추가 |
5. NGIXN Plus를 사용하여 NGINX Header 내에 서버 정보 제거
proxy_set_header와 add_header 외에 Headers-More 모듈을 사용하여 헤더에서 NGINX 서버 정보를 제거할 수 있습니다.
기존에는 아래와 같이 서버 정보가 노출되었습니다:
# curl -I example.com
HTTP/1.1 200 OK
Server: nginx/1.25.5
Date: Thu, 24 Oct 2024 07:08:27 GMT
Content-Type: text/html
Content-Length: 2246
Connection: keep-alive
Last-Modified: Wed, 23 Oct 2024 07:25:36 GMT
ETag: "6718a4f0-8c6"
Accept-Ranges: bytes
여기서 Headers-More 모듈을 사용하면 간단하게 서버 정보를 제거할 수 있습니다. Headers-More 모듈을 활성화하는 방법은 여기를 클릭하여 확인하세요.
Syntax: more_clear_headers Server;
Default: no
Context: http, server, location, location if
아래와 같이 허용된 Context 내에 more_clear_headers Server; 지시문을 추가합니다.
...
# Headers-More 모듈 활성화
load_module modules/ngx_http_headers_more_filter_module.so;
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
more_clear_headers Server;
...
NGINX Plus를 reload 또는 restart 한 후 헤더를 확인해보면 아래와 같이 서버 정보가 사라진 것을 확인할 수 있습니다.
# curl -I example.com
HTTP/1.1 200 OK
Date: Thu, 24 Oct 2024 07:16:31 GMT
Content-Type: text/html
Content-Length: 2246
Connection: keep-alive
Last-Modified: Wed, 23 Oct 2024 07:25:36 GMT
ETag: "6718a4f0-8c6"
Accept-Ranges: bytes
6. NGINX Header 결론
NGINX에서 proxy_set_header와 add_header는 각각 요청과 응답을 관리하는 데 필수적인 역할을 수행합니다. proxy_set_header는 클라이언트의 요청 헤더를 백엔드 서버로 전달하는 데 사용되어, 원활한 통신과 데이터 처리를 보장합니다. 이를 통해 클라이언트의 IP 주소와 Host 정보를 정확하게 전달함으로써 백엔드 서버의 로그 및 요청 처리의 정확성을 높입니다.
반면에, add_header는 클라이언트에게 보내는 응답에 추가적인 헤더를 설정하는 데 사용되며, 보안과 관련된 여러 중요한 헤더를 추가함으로써 웹 애플리케이션의 보안을 강화합니다. 예를 들어, 클릭재킹을 방지하기 위한 X-Frame-Options나 MIME 스니핑을 방지하는 X-Content-Type-Options 같은 헤더는 웹 애플리케이션의 보안성을 크게 향상시킵니다.
이 두 지시문은 함께 사용될 때, NGINX의 리버스 프록시 기능을 극대화하고 보안성을 높이는 데 기여합니다. 따라서, 올바른 설정과 활용을 통해 웹 애플리케이션의 성능과 안전성을 확보할 수 있습니다. NGINX의 강력한 기능을 통해 더욱 안전하고 효율적인 웹 서비스를 구축해 보시기 바랍니다.
NGINX Plus를 직접 사용해 보시려면 30일 무료 평가판을 신청하거나 NGINX STORE에 연락하여 논의하십시오.
댓글을 달려면 로그인해야 합니다.