[Nginx] 특정 IP만 접근 가능하도록 허용, 그 이외는 점검중 페이지로 redirect
TO-BE
배포 후 팀원들이 테스트하는 동안에 허용된 IP만 접근 가능하도록 하고, 그 이외의 IP 접근은 점검중 페이지로 가도록 하고 싶다.
Trouble Shooting
1. $remote_addr
- $remote_addr를 $maintenance에 mapping해준다.
- location 기본 설정에서 maintenace가 on일경우 에러 코드 503(Service Unavailable)을 반환한다.
- 아래 error_page에서 503 코드를 받아, /maintenance.html을 응답한다.
# nginx.conf
http {
...
map $remote_addr $maintenance {
default on;
127.0.0.1 off; # 원하는 IP 기입
}
server {
...
proxy_intercept_errors on;
location / {
...
if ($maintenance = on) {
return 503;
}
}
error_page 503 /maintenance.html;
location = /maintenace.html {
root /home/ec2-user/web;
internal;
}
}
}
결과
- 차단이 잘 되는지 확인하기 위해 default 설정을 on으로 하고 테스트 해보았다. 점검 중 페이지로 redirect가 잘 되는 것을 확인할 수 있었다.
- 내 ip로 들어갈 경우에는, 정상적으로 접속이 잘 되어야 하기 때문에, ipconfig를 통해 찍히는 IPv4 주소를 off로 설정하고 재접속했다. 로그인 페이지가 나타나야하는데 점검 중 페이지로 redirect 되었다.
=> 결론: default 설정은 잘 적용됨. 내 ip를 잘못 기입한 것 같았다.
2. $http_x_forwarded_for
-
IP를 찾아서
서칭을 하다 보니, ipconfig에 찍히는 ip랑, https://whatismyipaddress.com/ 에 찍히는 ip가 달랐다. 후자의 ip는 ISP의 ip, 즉 라우터의 ip인것 같았다. 이곳에 찍히는 ip를 nginx설정에 추가해주었지만 역시 제대로 동작하지 않았다.
netstat 명령어도 찍어보며 이리저리 찾아보았지만, 제대로 동작하지 않았다. -
access_log
nginx로 들어오는 로그를 찍어봐야겠다!라고 생각하고 log를 찍는 법을 찾아보았다. 로깅은 아래와 같이 설정해주면 되었다.
# nginx.conf
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;
...
}
- $remote_addr과 $http_x_forwarded_for 그리고 ELB
(로깅하는 방법을 찾고 설정하러 들어가니 이미 nginx.conf파일에 로깅이 설정되어 있는 것을 뒤늦게 발견했다.)
로그 파일로 가서 $remote_addr를 확인했는데, 두가지 IP로만 요청이 들어오고 있었다. 실제 클라이언트 IP는 $http_x_forwarded_for에 찍히고 있었고, 여기서 찍힌 ip는 https://whatismyipaddress.com/ 이곳에서 확인한 ip와 동일했다. $remote_addr이 두가지로 정해져서 들어오는 것이 AWS 설정과 관련이 있을거라 생각하고 서칭을 해보자, AWS 환경에서 웹서버의 앞단의 ELB 를 사용한 것과 연관이 있었다.
로드밸런서는 클라이언트의 ip를 자신의 ip로 변경해서 서버로 요청하기 때문에, nginx의 access_log에서 $remote_addr은 로드밸런서의 IP로 찍히고 있었던 것이다. 따라서, 로드밸런서나 프록시를 사용할 경우, 클라이언트의 원래 IP주소를 확인하려면 X-Forwarded-For 헤더를 사용해야 한다는 것을 알게되었다.
참고 Nginx에서 클라이언트 IP를 확인하는 법 ($http_x_forwarded_for)
1) Proxy 모드 로드밸런서 이용시 클라이언트 IP 로깅하기(TOAST 서비스 들여다보기)
2) ELB를 기반으로 하는 웹 서버 로그에서 클라이언트 IP 주소를 캡처하려면 어떻게 해야 합니까?
결론
nginx 설정파일에서 $remote_addr를 $http_x_forwarded_for로 바꾸니 잘 동작하는 것을 확인할 수 있었다.
최종 해결 코드
# nginx.conf
http {
...
map $http_x_forwarded_for $maintenance {
default on;
127.0.0.1 off; # 원하는 IP 기입
}
server {
...
proxy_intercept_errors on;
location / {
...
if ($maintenance = on) {
return 503;
}
}
error_page 503 /maintenance.html;
location = /maintenace.html {
root /home/ec2-user/web;
internal;
}
}
}
남은 궁금증
- 클라이언트 IP 주소가 라우터의 IP로 찍히는데, 기기별 ip 차단은 불가능한 것인가?
자동화
위의 TO-BE를 위해서는, 빌드 후 배포 전에 nginx.conf 설정에 mapping을 넣어주고, 배포 후 테스트 후에는 nginx.conf 설정에 mapping을 빼줘야 한다.
# 배포 전에는 이 부분을 넣고, 테스트 후에는 이 부분을 빼줘야 한다.
map $http_x_forwarded_for $maintenance {
default on;
127.0.0.1 off; # 원하는 IP 기입
}
빌드 -> 특정 IP 접근만 허용하는 nginx.conf 설정 -> 배포 -> 테스트 -> IP 제한 정보가 빠진 기본 nginx.conf 설정
고민하다가 nginx.conf 파일을 교체해주는 쉘 스크립트를 짜서, jenkins로 실행해주기로 했다.
Author And Source
이 문제에 관하여([Nginx] 특정 IP만 접근 가능하도록 허용, 그 이외는 점검중 페이지로 redirect), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@titu/Nginx-특정-IP만-접근-가능하도록-허용-그-이외는-점검중-페이지로-redirect저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)