본문 바로가기
envoy

Envoy internal redirect

by Misan Kim 2026. 4. 11.

# 요약

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