이번에 특정 클라이언트의 요청을 타 도메인을 꺾는 테스트가 필요하여 진행한 내용을 정리한다.
환경은 3scale를 사용하기때문에 staging/product 2개의 도메인이 존재한다.
그래서 특정 클라이언트 1.1.1.1 ip가 들어오면 staging도메인으로 강제로 꺾어주는 테스트를 진행한다.
네트워크 구간은 대충 아래와 같다.
[데이터요청서버] -> [아웃바운드프록시] -> [L7 Layer] -> [L4 Layer] -> [인바운드프록시] -> [3scale] -> [백엔드서버]
proxy 구간이 존재하기 때문에 remote_ip 가 아닌 x-forwarded-for 를 사용해 클라이언트의 ip를 체크해야한다.
(remote_ip 는 바로 전 라우터의 ip가 나오기 때문)
nginx.conf 설정
map
예전에 map 을 써서 특정 문자를 변수에 담는 작업을 한적이 있어,
이번에도 위에서말한 x-forwarded-for 변수의 값을 체크하도록 설정했다.
(map은 http 블럭안에 작성했다.)
map $http_x_forwarded_for $client_check {
default off;
1.1.1.1 on;
}
이러면 헤더로 넘어온 x-forwarded-for 값이 1.1.1.1 일때만, $client_check 변수에 on 이라는 데이터를 담게 된다.
upstream
이제 proxy pass를 해줄 도메인 서버를 정의하자.
(upstream도 http 블록안에 위치한다.)
upstream stg {
server localhost; # 스테이징 url
}
upstream prod {
server localhost; # 프로덕트 url
}
필자는 개인pc에서 테스트를 하고 있으므로 위와 같이 설정하였다.
각자 스테이징/프로덕트 url을 분리해서 작성하면된다.
proxy pass
이제 위에서 정의한 서버정보와 변수를 이용하여 도메인을 구분하자.
/ : 루트패스로 접근할 때를 예를 들어 설정하였고,
local pc 에서 테스트하기 때문에 /a, /b 로 컨텍스트를 나눠주었다.
location / {
if ( $client_check = on ){
proxy_pass http://stg/b$uri;
}
if ( $client_check = off ){
proxy_pass http://prod/a$uri;
}
}
$uri 를 사용하면 최초에 요청한 경로를 보존할 수 있다.
컨텍스트 분리(이건 다 아는 걸테니 접은글로)
테스트
자 이제 설정을 기반으로 요청을 해보자.
위 이미지와 같이 잘 분리가 되었다.
access log 도 확인해보면 요청한 url에 정상적으로 요청한 내역이 남아있다.
127.0.0.1 -JH- - [28/Sep/2022:14:01:01 +0900] "GET /b/v1/card/card/12312312 HTTP/1.0" 200 1 "-" - "PostmanRuntime/7.29.2" "1.1.1.1"
127.0.0.1 -JH- - [28/Sep/2022:14:01:01 +0900] "GET /v1/card/card/12312312 HTTP/1.1" 200 1 "-" - "PostmanRuntime/7.29.2" "1.1.1.1"
127.0.0.1 -JH- - [28/Sep/2022:14:01:08 +0900] "GET /a/v1/card/card/12312312 HTTP/1.0" 200 1 "-" - "PostmanRuntime/7.29.2" "1.1.1.2"
127.0.0.1 -JH- - [28/Sep/2022:14:01:08 +0900] "GET /v1/card/card/12312312 HTTP/1.1" 200 1 "-" - "PostmanRuntime/7.29.2" "1.1.1.2"
access log 맨 뒤에 출력된 ip가 x-forwarded-for 값이다.
궁금해할 사람들 위해 아래에 설정을 남겨놓겠다.
log_format main '$remote_addr -JH- $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'$http_code "$http_user_agent" "$http_x_forwarded_for"';
만약 프록시패스가 route 서버라면
추가적인 세팅사항이 있어 작성한다.
upstream stg/prod 를 작성하였는데, 만약 back단의 route 서버로 전달한다면
뒤에 route서버가 인식할 수 있는 Host를 지정해주어야한다.
Host 값은 기본적으로 클라이언트가 요청한 domain이 들어가는데,
예를들면 https://test.domain.com/v1/card/card로 호출 했을 경우 Host: test.domain.com
이라는 데이터가 들어가 있게 된다.
이상태로 route 서버에 전달을 하면 Header 데이터중 'Host' 를 찾아 또 다른 back 서버로 전달하게 된다.
그럼 이 Host를 stg url로 교체해주면 라우트에서 인식하게 된다.
# route서버에 연결할 경우의 upstream 예시
conf를 수정해보자.
new_host 라는 변수를 생성해 특정 도메인으로 지정한 뒤 proxy_set_header host 값을 변경하였다.
location / {
if ( $client_check = on ){
set $new_host 'joon95.tistory.ccc';
}
if ( $client_check = off ){
set $new_host $host;
}
proxy_pass http://route$uri;
proxy_set_header Host $new_host;
}
호출해보면 Host 데이터가 정상적으로 들어간 걸 볼 수 있다.
127.0.0.1 -JH- - [28/Sep/2022:16:31:00 +0900] "GET /b/v1/card/card/12312312 HTTP/1.0" 200 1 "-" Host: joon95.tistory.ccc - "PostmanRuntime/7.29.2" "1.1.1.1"
127.0.0.1 -JH- - [28/Sep/2022:16:31:00 +0900] "GET /v1/card/card/12312312 HTTP/1.1" 200 1 "-" Host: localhost - "PostmanRuntime/7.29.2" "1.1.1.1"
127.0.0.1 -JH- - [28/Sep/2022:16:31:08 +0900] "GET /a/v1/card/card/12312312 HTTP/1.0" 200 1 "-" Host: localhost - "PostmanRuntime/7.29.2" "1.1.1.2"
127.0.0.1 -JH- - [28/Sep/2022:16:31:08 +0900] "GET /v1/card/card/12312312 HTTP/1.1" 200 1 "-" Host: localhost - "PostmanRuntime/7.29.2" "1.1.1.2"
긴 글 읽어주셔서 감사합니다.
'엔지니어링 > 프록시' 카테고리의 다른 글
[Openresty] x-forwarded-for 설정하기 (0) | 2022.09.30 |
---|---|
[Openresty] 프록시서버 설치하기 (0) | 2022.09.30 |
[Openresty] 특정 대상 경로 우회 (0) | 2022.08.04 |
[Nginx] 쿠버네티스 망분리 proxy 서버 구축 (0) | 2022.08.03 |