Reverse Proxy
실 운영 환경에서는 80, 443 빼고는 inbound를 막아두는 경우가 많아서
iptables 써서 80 -> xxxx로 포워딩하거나, nginx써서 80 -> xxxx로 포워딩한다.
후자를 더 많이 사용하는데 그 이유는
- nginx를 쓰면 설정이 좀 귀찮기는 하지만, 한 장비에 여러 인스턴스를 띄우고 이들을 domain(혹은 location)으로 구분하므로 모두 80으로 받을 수 있다.
- jenkins나 sonarqube 등 설정 파일에서 home location (ex, /jenkins)을 설정할 수 있도록 지원하는 것이 이 것 때문.
- 어차피 server IP가 변경될 상황을 대비해서 도메인을 쓰긴 써야하니 그럴 바에 nginx로 리버스 프록시하는게 낫다.
- IP로 hook 같은거 막 등록해놨다가 서버 이전이나 인스턴스 분리하는 순간이 오면... 다 찾아가서 바꿔줘야 하니 난감함.
proxy_pass 설정하면?
```
a.b.c:80, d.e.f:80 모두 nginx에서 받아서,
a.b.c:80 -> localhost:8080
d.e.f:80 -> localhost:9001
```
로 포워딩이 가능하다. (nginx, 인스턴스들 모두 같은 물리장비에 위치)
domain 뿐만 아니라 location으로도 구분할 수 있다.
설정 예시
```nginx
server {
listen 80;
server_name aaaa.bbbb.ccc.com;
location /http_stub_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
location ~ /WEB-INF/ {
access_log off;
log_not_found off;
deny all;
}
location / {
if ($request_method !~ ^(GET|POST|PUT|DELETE)$ ) {
return 444;
}
add_header X-XSS-Protection "1; mode=block";
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_connect_timeout 3600;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
proxy_pass http://localhost:8080/;
}
```
참고
https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/
https://docs.sonarqube.org/latest/setup/operate-server/
Upstream ( 부하 분산, load balancing )
https://opentutorials.org/module/384/4328
Rate Limiting
https://yobi.navercorp.com/phoenix_tf/posts/11
https://www.nginx.com/blog/rate-limiting-nginx/
https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-proxied-http/
- NGINX는 요청 한도를 ms 단위로 쪼개서 관리한다.
- 즉, 5r/s이면 1초에 5개를 보장하는게 아니라 200ms 당 1개씩 요청을 수용한다.
- 따라서 200ms 안에 요청 5개가 한꺼번에 오면 1개만 처리하고 4개는 503 응답 나간다.
- 1r/s인데 1초 안에 요청이 2개 들어왔다면? 뒤에 들어온건 503이 나가겠지만, 이렇게 넘치는 요청을 버리지 않고 대기 Queue에 넣고 싶을 수 있음. 이 옵션이 바로 burst
- 10r/s, burst=20으로 설정되어 있는데 100ms 안에 요청 25개가 들어오는 경우,
- 1개는 바로 업스트림으로 전달
- 20개는 대기큐로 간 다음 100ms 마다 1개 씩 꺼내서 업스트림으로 전달
- 4개는 503 거절
- nodelay 옵션은 대기큐에 있는걸 100ms 마다 꺼내서 전달하면 대기큐 맨 마지막에 있는 애는 너무 늦게 서빙되니까, 애초에 처음에는 대기큐에 안넣고 burst 개수 만큼 바로바로 전송해버리자. 라는 것임.
- 페이지 로딩 시 정적 리소스가 여러개 필요할 수 있는데 이런 애들 하나 당 rate에 설정된 시간만큼 씩 기다려야 한다면 페이지 로딩이 무지 느리다.
- 10r/s, burst=20, nodelay인데 100ms 안에 25개가 들어오는 경우,
- 21개 즉시 전달하고, 대신 20개의 대기슬롯에 taken표시.
- taken 표시 되어 있는 슬롯은 못쓴다. 100ms 마다 1개씩 슬롯 taken 표시 해제.
- delay 옵션은 읽어보는게 나을 듯.
- 단순 초기 리소스 한꺼번에 받아오기 위함이라면 nodelay보다 delay가 나을 수 있음.
- https://www.nginx.com/blog/rate-limiting-nginx/#Two-Stage-Rate-Limiting
rate limit for each uri
```nginx
limit_req_zone $server_name zone=slow:10m rate=10r/s;
limit_req_zone $server_name zone=fast:10m rate=100r/s;
이렇게 설정하면?
모든 요청에 대해서, slow, fast zone에 카운트가 추가되고...
모든 요청이 10r/s를 넘어가는 경우 => slow 지정된 것들은 block된다.
모든 요청이 100r/s를 넘어가는 경우 => fast 지정된 것들이 이제서야 block됨.
그니까 카운트하는건 모든 요청에 대해서라 이렇게는 안될 것 같고...
각 uri 별로 다 다르게 주고 싶다면
limit_req_zone $uri zone=slow:10m rate=10r/s;
limit_req_zone $uri zone=fast:10m rate=100r/s;
각 uri 별로 카운트를 따로 함. (한 uri에 대해서 slow, fast 둘 다 카운트가 올라가긴 한다)
한 uri에 대한 요청이 10r/s를 넘어가는 경우 => slow로 지정된 location이라면 block
ㅇㅇ 이렇게 하면 될 듯.
```
근데 WAS 단에서도 설정하는게 있는데... 어디서 하는게 더 나은건지
https://stackoverflow.com/questions/39002090/spring-boot-limit-on-number-of-connections-created
https://docs.bmc.com/docs/brid91/en/tomcat-container-workload-configuration-825210082.html
location 지정
- 한 uri에 매치되는 여러 개의 location이 있으면 가장 긴 prefix 매칭을 찾아 그 블럭을 타게 된다.
- 이 것도 우선순위가 있어서 그게 먼저이긴 함.
- https://hyeonguj.github.io/2019/02/01/nginx-location%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC/
- http://nginx.org/en/docs/varindex.html
- 정규식 사용하려면 `` ~``, case-insensitive 정규식은 `` ~*``
- 정규식 쓸 때는 패턴에 `` ^ $`` 안붙여주면 중간에서 등장하더라도 다 매칭된다.
특정 url은 일부 ip만 허용하고 나머지는 block
```nginx
location ~* ^/somepath(\/.*)?$ {
allow 10.0.0.0/8;
deny all;
}
```
'DevOps & Server' 카테고리의 다른 글
SonarQube (0) | 2020.12.08 |
---|---|
NGINX (0) | 2020.12.04 |
[tomcat] 톰캣, jvm 실행 인자 (0) | 2020.03.05 |
젠킨스 Jenkins (0) | 2019.05.09 |
[Gradle] build, jar 배포, IntelliJ 설정 (0) | 2019.04.10 |
vagrant (0) | 2018.11.02 |