# 요약
envoy 는 기본적으로 cluster 로부터의 302 응답이 오면 그대로 클라이언트에게 전달하지만, route action 에 internal redirection 옵션(internal_redirect_policy)을 설정한 경우 cluster 로부터 리디렉션 응답을 받는 경우 location 헤더의 url 을 프록시하여 클라이언트에게 응답한다.
# 일반적인 리버스 프록시의 동작 구조는
envoy 뿐만 아니라 nginx, apache, haproxy 등 리버스 프록시로 사용할 수 있는 많은 프록시들은 백엔드에서 3xx 리디렉션 응답이 발생하는 경우 해당 응답을 그대로 클라이언트에게 전달한다. 예를 들면 아래와 같을 것이다.
1. Client 가 Proxy(https://www.example.com/)로 요청 전송
2. Proxy 가 요청을 Backend 로 전달
3. Backend 가 302 응답을 Proxy 로 전달(location: https://www.example.com/foo)
4. Proxy 가 Client 로 302 응답을 전달
5. Client 가 Proxy(https://www.example.com/foo)로 요청 전송
6. Proxy 가 요청을 Backend 로 전달
7. Backend 가 200 응답을 Proxy 로 전달
8. Proxy 가 Client 로 200 응답을 전달
-> 클라이언트는 프록시로 총 2번의 요청(최초 / 경로에 대한 요청, 이후 location 헤더에 있는 /foo 경로에 대한 요청)을 전송하게 된다.
# envoy internal redirect
envoy 에서도 기본적으로 위와 같이 동작하나 internal redirect 관련 옵션을 route action 에 설정하는 경우 백엔드에서 수신하는 3xx 리디렉션 응답을 클라이언트로 전달하는 대신, 자신이 리디렉션 대상 location 으로 요청하여 응답을 클라이언트에게 전달하는 방식으로 동작한다. 예를 들면 아래와 같을 것이다.
1. Client 가 Proxy(https://www.example.com/)로 요청 전송
2. Proxy 가 요청을 Backend 로 전달
3. Backend 가 302 응답을 Proxy 로 전달(location: https://www.example.com/foo)
4. Proxy 가 Backend(https://www.example.com/foo)로 요청 전송
5. Backend 가 200 응답을 Proxy 로 전달
6. Proxy 가 Client 로 200 응답을 전달
-> 클라이언트는 프록시로 총 1번의 요청만 전송하게 된다.
# envoy config 작성
아래 샘플 config 는 httpbin.org 주소를 프록시하는 설정이다. 중요한 설정은 internal_redirect_policy 부분이니 이 부분을 참고한다.
vim envoy-redirect.yaml
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
host_rewrite_literal: httpbin.org
cluster: service_httpbin_org
# 이 부분부터
internal_redirect_policy:
max_internal_redirects: 1
redirect_response_codes: [302]
allow_cross_scheme_redirect: true
response_headers_to_copy: []
# 여기까지
clusters:
- name: service_httpbin_org
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
load_assignment:
cluster_name: service_httpbin_org
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: httpbin.org
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: httpbin.org
# 컨테이너 실행
docker run --rm -it \
-v $(pwd)/envoy-redirect.yaml:/envoy-custom.yaml \
-p 9901:9901 \
-p 10000:10000 \
envoyproxy/envoy:v1.35.0 \
-c /envoy-custom.yaml
# 테스트
테스트에 사용한 "https://httpbin.org/redirect-to?url=https://ifconfig.me/ip" 요청은 location 헤더에 "https://ifconfig.me/ip"를 값으로 설정하여 클라이언트에게 302 응답을 주는 테스트 경로이다.
이 테스트 경로에 대한 정보는 아래 페이지를 참고한다.
https://httpbin.org/#/Redirects
curl -v "http://127.0.0.1:10000/redirect-to?url=https://ifconfig.me/ip"
## internal redirection 옵션 설정 전
➜ [~] curl -v "http://127.0.0.1:10000/redirect-to?url=https://ifconfig.me/ip"
* Trying 127.0.0.1:10000...
* Connected to 127.0.0.1 (127.0.0.1) port 10000
> GET /redirect-to?url=https://ifconfig.me/ip HTTP/1.1
> Host: 127.0.0.1:10000
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 302 Found
< date: Sat, 04 Apr 2026 15:26:56 GMT
< content-type: text/html; charset=utf-8
< content-length: 0
< server: envoy
< location: https://ifconfig.me/ip
< access-control-allow-origin: *
< access-control-allow-credentials: true
< x-envoy-upstream-service-time: 799
<
* Connection #0 to host 127.0.0.1 left intact
## internal redirection 옵션 설정 후
➜ [~] curl -v "http://127.0.0.1:10000/redirect-to?url=https://ifconfig.me/ip"
* Trying 127.0.0.1:10000...
* Connected to 127.0.0.1 (127.0.0.1) port 10000
> GET /redirect-to?url=https://ifconfig.me/ip HTTP/1.1
> Host: 127.0.0.1:10000
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< date: Sat, 04 Apr 2026 15:27:53 GMT
< content-type: application/json
< content-length: 32
< server: envoy
< access-control-allow-origin: *
< access-control-allow-credentials: true
< x-envoy-upstream-service-time: 194
<
{
"origin": "x.x.x.x"
}
* Connection #0 to host 127.0.0.1 left intact
(참고) istio 를 사용하는 경우
istio 에는 EnvoyFilter 를 통해 사이드카 프록시에 설정을 넣어 internal_redirect 가 발생하는 것까지는 확인했으나, location 헤더에 있는 실제 호스트가 아닌 무조건 애플리케이션 컨테이너쪽으로 트래픽을 전달하는 현상이 있어 제대로 작동하지 못했다.
-> istio 1.29 버전과 anthos service mesh 1.28 버전에서 정상적으로 작동하지 않음을 확인했다.
-> cluster 설정 중 cluster type 이 ORIGINAL_DST 인 부분이 영향이지 않을까 추측하고 있다.
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: redirect
namespace: test
spec:
workloadSelector:
labels:
app: my-app
configPatches:
- applyTo: HTTP_ROUTE
match:
context: SIDECAR_INBOUND
routeConfiguration:
vhost:
route:
name: "default"
patch:
operation: MERGE
value:
route:
internal_redirect_policy:
max_internal_redirects: 1
redirect_response_codes: [302]
allow_cross_scheme_redirect: true
response_headers_to_copy: []
# 유의사항
언뜻보면 무조건 유용한 기능처럼 보이지만 프록시에서 경로를 rewrite 하는 것과 동일하게 클라이언트는 모르게 프록시와 백엔드 사이의 통신을 조작하는 것이기에, 만약 클라이언트(브라우저)에서 추가적인 리소스를 요청해야하는 경우(예를 들어 웹페이지에 포함된 javascript 나 css 등의 파일을 추가로 불러와야하는 경우 등) 경로 상의 문제로 인해 정상적으로 작동하지 않을 가능성이 크다. 인증된 API 요청에 대한 응답으로 다른 경로를 호출하는 등의 특수한 케이스에는 활용할 수 있는 기능일 것 같다.
# 참고 사이트
https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/http_connection_management#internal-redirects
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-routeaction
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-internalredirectpolicy
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#enum-config-route-v3-routeaction-internalredirectaction
'envoy' 카테고리의 다른 글
| Envoy Lua 필터 (0) | 2026.04.04 |
|---|