일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 조건문
- https
- mongoose
- Node.js
- 메소드
- 항해99
- npm
- JavaScript
- Load Balancer
- JWT
- 타입스크립트
- it
- 자바스크립트
- Nodejs
- nginx
- elb
- java
- nomadcoder
- CORS
- AWS
- Joi
- 노마드코더
- 생활코딩
- mongodb
- TypeScript
- 프로그래머스
- MYSQL
- reduce
- wil
- ubuntu
- Today
- Total
V-logue
[Nginx] Nginx 무한 404 Error가 발생하는 문제 본문
AWS ELB와 Nginx로 HTTPS 서버 구축하는 도중 서버를 테스트 하는 과정에서
문제가 발생했다.
node app.js로 서버를 시작하고나서 별다른 동작이 없는데도 불구하고, 계속해서 GET / 404요청이 들어오는 것이다.
이 문제를 해결하기 위해서 server section의 server_name과,
location section의 proxy_pass값에 문제가 있다고 인식하고 값을 수정하기로 했다.
(참고로 http Ip 주소는 실제 ip 주소말고 임의의 ip 주소를 넣었다.)
server {
listen 80;
server_name rendev.link;
// 단순히 nginx가 어떻게 http요청을 처리하는 지 알려주는 section
location / {
proxy_pass http://123.31.65.435:3000;
}
...
}
// 단순한 http request에서 수신대기중인 123.31.65.435:3000; 서버로 nginx가
// 요청을 전달하도록 지시하는 section
// Case 1 (수정전 기본값)
server {
listen 80;
server_name rendev.link;
if ($http_x_forwarded_proto = 'http'){
return 301 https://$host$request_uri;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://123.31.65.435:3000; // 임시로 붙여놓은 ip주소
proxy_redirect off;
}
}
}
server_name은 renDev. link
proxy_pass는 http://123.31.65.435:3000; // 임시로 붙여놓은 ip주소
실패
// Case 2
server {
listen 80;
server_name rendev.link;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
}
}
}
server_name : renDev.link
proxy_pass http://127.0.0.1:3000
실패
// Case3
server {
listen 80;
server_name rendev.link;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://123.31.65.435:3000; // 임시로 붙여놓은 ip주소
proxy_redirect off;
}
}
}
server_name: rendev.link;
proxy_pass http://123.31.65.435:3000; // 임시로 붙여놓은 ip주소
실패
// Case4
server {
listen 80;
server_name ~.;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
}
}
server_name ~.;
proxy_pass http://127.0.0.1:3000;
실패
// Case5
server {
listen 80;
server_name rendev.link;
# redirect https setting
if ($http_x_forwarded_proto != 'https') {
return 301 https://$host$request_uri;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# port setting , 서버의 port와 동일한 port로 pass 시켜야 합니다.
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
}
}
server_name : rendev.link;
proxy_pass http:127.0.0.1:3000;
redirect https setting추가
성공
// Basic setting
if ($http_x_forwarded_proto = 'http'){
return 301 https://$host$request_uri;
}
server_name : renDev. link
proxy_pass : http://123.31.65.435:3000; // 임시로 붙여놓은 ip주소
// Successful setting
if ($http_x_forwarded_proto != 'https') {
return 301 https://$host$request_uri;
}
server_name : rendev.link;
proxy_pass http:127.0.0.1:3000;
위 코드와 아래 코드가 달라진 것은, http일때와 https가 아닐때로 조건이 나뉘는데 사용한다면
!= https가 더 맞는 설정이라고 생각이 들었다.
reverse proxy는 외부에서 서버가 제공하는 서비스에 접근할 경우 proxy server를 통해서 접근하는 방식이다.
만약에 proxy server를 사용하게 된다면, 모든 통신이 proxy server를 통과하게 되는데
브라우저가 웹사이트와 연결된다면 다음과 같은 경로를 타게 된다.
browser <-> proxy <-> internet <-> website
브라우저에서 proxy server로의 첫 번째 hop은 로컬에서 수행되기 때문에 proxy는 컴퓨터 내부에 연결을 수신하게 되고, 그곳에서 대기하게 된다. 컴퓨터 내부 연결인 로컬 연결에서는 예약된 IP주소인 127.0.0.1인 localhost를 사용하게 된다.
이런 방식으로 통신하는 것이 direct하게 메모리와 상호작용하는 것이기 때문에 매우 빠른 속도를 보장한다.
그렇기 때문에, nginx.conf파일의 proxy_pass 값이 127.0.0.1:3000(app.js의 서버 port번호)로 사용해야 하는게
맞는 방법이다.
홉(hop)은 컴퓨터 네트워크에서 출발지와 목적지 사이에 위치한 경로의 한 부분이다. 데이터 패킷은 브리지, 라우터, 게이트웨이를 거치면서 출발지에서 목적지로 경유한다. 패킷이 다음 네트워크 장비로 이동할 때마다 홉이 하나 발생한다.
proxy_pass가 127.0.0.1:3000과 server_name이 rendev.link가 맞는 상태라면 Case2번은 왜 계속해서
404에러가 발생했을까?
그것은 https로 redirect하는 코드가 없었기 때문이다.
일단 기본적으로 요청이 어떻게 들어오는 것은 별개로하고, 404에러가 발생한 것은
location /
nginx의 location / 은 /로 들어오는 모든 코드를 proxy로 보낸다는 것을 의미하고 / 경로 하위 경로를
모두 포함하게 된다.
rendev.link로 들어오는 http:80 통신은 elb 로드밸런스 상으로 https:443으로 redirect하게 되있는데,
redirect하는 코드가 빠져있기 때문에 계속해서 404에러가 발생하지 않았을까 하는 추측이 든다.
+++
if ($http_x_forwarded_proto != 'https') {
return 301 https://$host$request_uri;
}
대부분의 서비스의 경우 API를 운용하는 백엔드 서버 앞에다 Proxy 서버를 두고 SSL에 관한 작업을 위임하게 되는데,
이를 SSL offloading이라고 한다.
Nginx로 proxy서버를 구성하는게 이런 SSL offloading의 작업이라고 할 수 있게 되는데,
https로 들어온 통신이 proxy서버를 거쳐 http통신으로 바뀌고 이를 통해 더 빠르게 통신할 수 있게 된다.
아마존 elb는 http 통신을 https로 리디렉션 시켜주는데,
Nginx가 SSL offloading을 수행하면서, http통신을 https로 리디렉션 시켜주지 않았기 때문에
발생한 오류였다. elb는 redirect 시켜주는데, nginx는 http로 내보내니 404에러가 발생했던 것
잘못된 내용이 있다면 지적해주시면 감사하겠습니다.
'Error' 카테고리의 다른 글
[ubuntu] npm missing required argument #1 (0) | 2022.07.28 |
---|---|
[AWS] EC2 503 Service Temporarily Unavailable (0) | 2022.07.26 |
[Node.js] jwt malformed (0) | 2022.07.14 |
[ubuntu] Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules' (0) | 2022.07.12 |
[Node.js] Joi [Error [ValidationError]: "" is not allowed] (0) | 2022.07.06 |