CloudNet@에서 진행하는 Istio Study 7주차 14장 내용입니다.
📕 This chapter cover
- Using Istio’s EnvoyFilter resource to configure Envoy directly
- Using Lua to customize the request path
- Using WebAssembly to customize the request path

엔보이에서 가장 기본적인 필터는 네트워크 필터로, 바이트 스트림에서 인코딩/디코딩 작업을 한다.
스트림에서 필터가 둘 이상 순서대로 동작하도록 설정할 수 있는데, 이를 필터 체인이라고 부른다. 필터 체인을 사용하면 프록시의 기능을 구현할 수 있다.
대표적인 엔보이 프로토콜용 네트워크 필터
HTTP Connection Manager (HCM)가장 많이 사용하는 네트워크 필터 중 하나가 HttpConnectionManager 이다.
이 필터는 바이트 스트림을 HTTP 기반 프로토콜(즉, HTTP 1.1, HTTP 2, gRPC, 최근에는 HTTP 3 등)의 HTTP 헤더, 바디, 트레일러로 변환하는 것에 관한 세부 사항을 추상화하는 역할을 하며, 그림 14.3에서 볼 수 있다.

HttpConnectionManager 는 HTTP 요청을 처리할 뿐 아니라 헤더, 경로 접두사 path prefix 등 요청 속성을 바탕으로 한 요청 라우팅, 액세스 로깅, 헤더 조작도 처리한다.기본 HTTP 필터의 예시
- Cross-origin resource sharing (CORS)
- Cross-site request forgery prevention (CSRF)
- ExternalAuth 외부 인증
- RateLimit 속도 제한
- Fault injection 결합 주입
- gRPC/JSON transcoding 트랜스코딩
- Gzip
- Lua 루아
- Role-based access control (RBAC) 역할 기반 접근 제어
- Tap
- Router 라우터
- WebAssembly (Wasm) 웹어셈블리
필터 작성 등과 같이 엔보이 바이너리 자체에 변경 사항을 컴파일하지 않고도 엔보이의 HTTP 기능을 확장하는 방법이 있는데, 이 경우 다음 HTTP 필터들을 사용한다.
이런 필터를 사용하면 외부 서비스를 호출하도록 설정하거나, 루아 스크립트를 실행하거나, 커스텀 코드를 실행해 HTTP 요청이나 응답을 처리할 때 HCM의 기능을 강화할 수 있다.
다음 방법 중 하나를 사용해 엔보이 데이터 플레인의 기능을 확장한다.
- 엔보이 HTTP 필터를 이스티오 API에서 EnvoyFilter 리소스로 설정하기
- 속도 제한 서버 RLS, Rate-Limit Server 호출하기
- 루아 스크립트를 구현해 루아 HTTP 필터에 불러오기
- 웹어셈블리 HTTP 필터용 웹어셈블리 모듈(Wasm 모듈) 구현하기
Istio의 데이터 플레인을 확장하는 첫 번째 단계는 엔보이의 기존 필터가 우리가 찾고 있는 확장 유형을 달성하는 데 충분하지 파악하는 것이다.
필터가 존재하는 경우, EnvoyFilter 리소스를 사용해 이스티오의 데이터 플레인을 직접 설정할 수 있다.
Istio의 EnvoyFilter 리소스는 Istio의 고수준 API에서 노출하지 않는 엔보이의 일부를 설정하거나 조정해야 하는 고급 사용 사례를 위한 것
이 리소스는 엔보이의 거의 모든 것을 설정할 수 있으며(일부 제한 있음) 리스너, 루트, 클러스터, 필터가 포함된다.
기저 엔보이 API는 이스티오 버전 간에 언제든 달라질 수 있으니, 배포하는 모든 EnvoyFilter 의 유효성을 반드시 확인해야 한다.
이전 버전과의 호환성은 어떤 것도 가정해서는 안 된다. 이 API를 잘못 설정하면 이스티오 데이터 플레인 전체가 멈출 수도 있다.
예제 서비스 배포
kubectl get envoyfilter -A
NAMESPACE NAME AGE
istio-system stats-filter-1.13 12m
istio-system stats-filter-1.14 12m
istio-system stats-filter-1.15 12m
istio-system stats-filter-1.16 12m
istio-system stats-filter-1.17 12m
istio-system tcp-stats-filter-1.13 12m
istio-system tcp-stats-filter-1.14 12m
istio-system tcp-stats-filter-1.15 12m
istio-system tcp-stats-filter-1.16 12m
istio-system tcp-stats-filter-1.17 12m
# 배포
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction
kubectl apply -f services/webapp/istio/webapp-catalog-gw-vs.yaml -n istioinaction
kubectl apply -f ch9/sleep.yaml -n istioinaction
# 확인
kubectl get gw,vs,dr -n istioinaction
NAME AGE
gateway.networking.istio.io/coolstore-gateway 50s
NAME GATEWAYS HOSTS AGE
virtualservice.networking.istio.io/webapp-virtualservice ["coolstore-gateway"] ["webapp.istioinaction.io"] 50s
# 호출 확인 : mypc
EXT_IP=$(kubectl -n istio-system get svc istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
docker exec -it mypc curl -s -H "Host: webapp.istioinaction.io" http://$EXT_IP
docker exec -it mypc curl -s -H "Host: webapp.istioinaction.io" http://$EXT_IP/api/catalog
# 신규 터미널 : mypc 에서 반복 접속
EXT_IP=$(kubectl -n istio-system get svc istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
while true; do docker exec -it mypc curl -s -H "Host: webapp.istioinaction.io" http://$EXT_IP/api/catalog ; echo ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
# 호출 확인 : 자신의 호스트 PC
curl -s http://webapp.istioinaction.io:30000
curl -s http://webapp.istioinaction.io:30000/api/catalog
EnvoyFilter 리소스에 대해 알아야 할 첫 번째 사항은, 달리 지정하지 않은 한 네임스페이스의 모든 워크로드에 적용된다는 것이다.
EnvoyFilter 리소스에 대해 알아야 할 두 번째 사항은, 다른 이스티오 리소스가 모두 변환되고 설정된 후에야 적용된다는 것이다.
마지막으로, EnvoyFilter 리소스로 워크로드를 설정할 때 각별히 주의해야 한다.
예제에서는 그림 14.5와 같이 webapp 워크로드의 데이터 플레인을 거치는 메시지를 샘플링하도록 엔보이의 tap 필터를 설정하려고 한다 - Docs
요청이나 응답이 tap 필터를 지나 흐를 때마다 tap 필터는 그 요청/응답을 어떤 수신 에이전트로 스트리밍한다. 이 예제에서는 콘솔/CLI로 스트리밍한다.

# cat ch14/tap-envoy-filter.yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: tap-filter
namespace: istioinaction
spec:
workloadSelector:
labels:
app: webapp # 워크로드 셀렉터
configPatches:
- applyTo: HTTP_FILTER # 설정할 위치
match:
context: SIDECAR_INBOUND
listener:
portNumber: 8080
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
patch: # 엔보이 설정 패치
operation: INSERT_BEFORE
value:
name: envoy.filters.http.tap
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.tap.v3.Tap"
commonConfig:
adminConfig:
configId: tap_config
#
cat ch14/tap-envoy-filter.yaml
kubectl apply -f ch14/tap-envoy-filter.yaml
kubectl get envoyfilter -n istioinaction
NAME AGE
tap-filter 10s
#
docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/webapp.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/webapp.istioinaction --port 15006
docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/webapp.istioinaction --port 15006 -o json
...
{
"name": "envoy.filters.http.tap",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.filters.http.tap.v3.Tap",
"commonConfig": {
"adminConfig": {
"configId": "tap_config"
}
}
}
},
{
"name": "envoy.filters.http.router",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router"
}
}
...
# 터미널 1 : 포트 포워딩 설정 후 tap 시작
kubectl port-forward -n istioinaction deploy/webapp 15000 &
curl -X POST -d @./ch14/tap-config.json localhost:15000/tap
# 터미널 2 : 기존 반복 접속하는 것 활용
EXT_IP=$(kubectl -n istio-system get svc istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
docker exec -it mypc curl -s -H "Host: webapp.istioinaction.io" http://$EXT_IP/api/catalog
docker exec -it mypc curl -s -H "x-app-tap: true" -H "Host: webapp.istioinaction.io" http://$EXT_IP/api/catalog
while true; do docker exec -it mypc curl -s -H "x-app-tap: true" -H "Host: webapp.istioinaction.io" http://$EXT_IP/api/catalog ; echo ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
# 터미널 3 : 로그 확인
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/webapp -n istioinaction --level http:debug
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/webapp -n istioinaction --level tap:debug
kubectl logs -n istioinaction -l app=webapp -c istio-proxy -f

tap 을 시작한 창에 tap 출력이 표시돼야 한다. 이 출력은 헤더, 바디, 트레일러 등 요청에 대한 모드 정보를 준다.
외부 호출 기능으로 데이터 플레인을 확장하는 기본 필터들도 있다.

Istio가 데이터 플레인에 엔보이를 사용하는 것처럼, 속도 제한에 대한 특정 호출은 엔보이 HTTP 필터에서 나온다.
엔보이에서 속도 제한을 하는 방법은 여러 가지가 있지만 (네트워크 필터, 로컬 속도 제한, 글로벌 속도 제한), 우리는 특히 글로벌 속도 제한 기능을 확인한다.

x-loyalty 헤더를 검사해 판단할 수 있다.# cat ch14/rate-limit/rlsconfig.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: catalog-ratelimit-config
namespace: istioinaction
data:
config.yaml: |
domain: catalog-ratelimit
descriptors:
- key: header_match
value: no_loyalty
rate_limit:
unit: MINUTE
requests_per_unit: 1
- key: header_match
value: gold_request
rate_limit:
unit: MINUTE
requests_per_unit: 10
- key: header_match
value: silver_request
rate_limit:
unit: MINUTE
requests_per_unit: 5
- key: header_match
value: bronze_request
rate_limit:
unit: MINUTE
requests_per_unit: 3
# cat ch14/rate-limit/catalog-ratelimit-actions.yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: catalog-ratelimit-actions
namespace: istioinaction
spec:
workloadSelector:
labels:
app: catalog
configPatches:
- applyTo: VIRTUAL_HOST
match:
context: SIDECAR_INBOUND
routeConfiguration:
vhost:
route:
action: ANY
patch:
operation: MERGE
# Applies the rate limit rules.
value:
rate_limits: # 속도 제한 조치
- actions:
- header_value_match:
descriptor_value: no_loyalty
expect_match: false
headers:
- name: "x-loyalty"
- actions:
- header_value_match:
descriptor_value: bronze_request
headers:
- name: "x-loyalty"
exact_match: bronze
- actions:
- header_value_match:
descriptor_value: silver_request
headers:
- name: "x-loyalty"
exact_match: silver
- actions:
- header_value_match:
descriptor_value: gold_request
headers:
- name: "x-loyalty"
exact_match: gold

cat ch14/rate-limit/catalog-ratelimit.yaml
cat ch14/rate-limit/catalog-ratelimit-actions.yaml
kubectl apply -f ch14/rate-limit/catalog-ratelimit.yaml -n istioinaction
kubectl apply -f ch14/rate-limit/catalog-ratelimit-actions.yaml -n istioinaction
kubectl get envoyfilter -A

# sleep 앱에서 catalog 서비스를 호출 시도 : 대략 1분에 한 번 정도 호출 성공! >> x-loyalty 헤더가 없을 때 속도 제한 값!
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl http://catalog/items -v
...
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl http://catalog/items -v
...
< HTTP/1.1 429 Too Many Requests
< x-envoy-ratelimited: true
...
# silver 헤더는?
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl -H "x-loyalty: silver" http://catalog/items -v
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl -H "x-loyalty: silver" http://catalog/items -v
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl -H "x-loyalty: silver" http://catalog/items -v
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl -H "x-loyalty: silver" http://catalog/items -v
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl -H "x-loyalty: silver" http://catalog/items -v
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl -H "x-loyalty: silver" http://catalog/items -v
...
#
docker exec -it myk8s-control-plane istioctl proxy-config route deploy/catalog.istioinaction --name 'InboundPassthroughClusterIpv4'
docker exec -it myk8s-control-plane istioctl proxy-config route deploy/catalog.istioinaction --name 'InboundPassthroughClusterIpv4' -o json | grep actions
docker exec -it myk8s-control-plane istioctl proxy-config route deploy/catalog.istioinaction --name 'inbound|3000||'
docker exec -it myk8s-control-plane istioctl proxy-config route deploy/catalog.istioinaction --name 'inbound|3000||' -o json | grep actions
docker exec -it myk8s-control-plane istioctl proxy-config route deploy/catalog.istioinaction --name 'inbound|3000||' -o json
...
"rateLimits": [
{
"actions": [
{
"headerValueMatch": {
"descriptorValue": "no_loyalty",
"expectMatch": false,
"headers": [
{
"name": "x-loyalty"
}
]
}
}
]
},
{
"actions": [
{
"headerValueMatch": {
"descriptorValue": "bronze_request",
"headers": [
{
"name": "x-loyalty",
"exactMatch": "bronze"
...

Lua 소개 : 가벼운 명령형/절차적 언어로, 확장 언어로 쓰일 수 있는 스크립팅 언어를 주 목적으로 설계
Lua Programming Language
Lua는 시스템 기능을 강화할 수 있는 강력하면서도 내장 가능한 스크립트 언어다.
Lua는 동적 타입의 인터프리터 언어로, Lua 가상머신이 제공하는 메모리 자동 관리 기능을 갖추고 있다 (엔보이에서는 LuaJIT이다).

요청 바디를 검사하면 프록시에서 스트림을 처리하는 방식에 영향을 줄 수 있다.
예를 들어 바디 전체를 메모리에 적재하는 작업을 수행할 수도 있는데, 이는 성능에 영향을 줄 수 있다.
#
cat ch14/bucket-tester-service.yaml
...
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: bucket-tester
version: v1
name: bucket-tester
spec:
replicas: 1
selector:
matchLabels:
app: bucket-tester
version: v1
template:
metadata:
labels:
app: bucket-tester
version: v1
spec:
containers:
- image: hashicorp/http-echo:1.0 # 수정 https://hub.docker.com/r/hashicorp/http-echo/tags
imagePullPolicy: IfNotPresent
name: bucket-tester
args:
- "-text=dark-launch-7"
ports:
- containerPort: 5678
name: http
protocol: TCP
securityContext:
privileged: false
#
kubectl apply -f ch14/httpbin.yaml -n istioinaction
kubectl apply -f ch14/bucket-tester-service.yaml -n istioinaction
# 확인
kubectl get pod -n istioinaction
NAME READY STATUS RESTARTS AGE
bucket-tester-688c598b47-86fbr 2/2 Running 0 25s
httpbin-85d76b4bb6-dz6b5 2/2 Running 0 2m56s
...
엔보이에서는 루아 함수 envoy_on_reqest() 혹은 envoy_on_response() 를 구현해 요청과 응답 각각을 확인하고 조작할 수 있다.
httpCall() 함수를 사용하면 외부 서비스와 통신할 수 있다. 다음 스크립트는 우리의 사용 사례를 구현한 것이다.
# cat ch14/lua-filter.yaml
...
function envoy_on_request(request_handle)
local headers, test_bucket = request_handle:httpCall(
"bucket_tester",
{
[":method"] = "GET",
[":path"] = "/",
[":scheme"] = "http",
[":authority"] = "bucket-tester.istioinaction.svc.cluster.local",
["accept"] = "*/*"
}, "", 5000)
request_handle:headers():add("x-test-cohort", test_bucket)
end
function envoy_on_response(response_handle)
response_handle:headers():add("istioinaction", "it works!")
end
...
envoy_on_reqest() 함수를 구현하고, httpCall() 내장 함수를 사용해 외부 서비스와 통신하고 있다.이 스크립트를 EnvoyFilter 리소스에 추가할 수 있다.
# cat ch14/lua-filter.yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: httpbin-lua-extension
namespace: istioinaction
spec:
workloadSelector:
labels:
app: httpbin
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
portNumber: 80
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
inlineCode: |
function envoy_on_request(request_handle) # 아래 줄에 코드 입력
local headers, test_bucket = request_handle:httpCall(
"bucket_tester",
{
[":method"] = "GET",
[":path"] = "/",
[":scheme"] = "http",
[":authority"] = "bucket-tester.istioinaction.svc.cluster.local",
["accept"] = "*/*"
}, "", 5000)
request_handle:headers():add("x-test-cohort", test_bucket)
end
function envoy_on_response(response_handle) # 아래 줄에 코드 입력
response_handle:headers():add("istioinaction", "it works!")
end
- applyTo: CLUSTER
match:
context: SIDECAR_OUTBOUND
patch:
operation: ADD
value: # cluster specification
name: bucket_tester
type: STRICT_DNS
connect_timeout: 0.5s
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: bucket_tester
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
protocol: TCP
address: bucket-tester.istioinaction.svc.cluster.local
port_value: 80
kubectl apply -f ch14/lua-filter.yaml
kubectl get envoyfilter -n istioinaction
# httpbin 서비스 호출 확인!
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl http://httpbin.istioinaction:8000/ -v
...
< HTTP/1.1 503 Service Unavailable
< content-length: 39
< content-type: text/plain
< istioinaction: it works!
< date: Sun, 18 May 2025 07:59:34 GMT
< server: envoy
< x-envoy-upstream-service-time: 51
...
invalid header value for: x-test-cohort
kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl http://httpbin.istioinaction:8000/headers
...
invalid header value for: x-test-cohort
# 정상 실습 시..
{
"headers": {
"Accept": "*/*",
"Content-Length": "0",
"Host": "httpbin.istioinaction:8000",
"User-Agent": "curl/7.69.1",
"X-B3-Sampled": "1",
"X-B3-Spanid": "1d066f4b17ee147b",
"X-B3-Traceid": "1ec27110e4141e131d066f4b17ee147b",
"X-Test-Cohort": "dark-launch-7" # A/B 테스트 서비스를 호출할 때 덧붙이는 새 헤더 x-test-cohort 가 보임
}
}


웹어셈블리는 모듈로 패키징된 커스텀 코드로, 웹 브라우저 같은 대상 호스트 안의 격리된 가상머신에서 안전하게 실행할 수 있다.



wasm-cache into appropriate workloadsEnvoyFilter CRD to use the Wasm filter
EnvoyFiltersistio-agent 내부의 xDS 프록시와 Envoy의 확장 구성 검색 서비스(ECDS)를 활용하여 에 구성된 원격 HTTP 소스에서 가져온 Wasm 바이너리를 로드하는 안정적인 솔루션을 제공해 왔습니다. Istio 1.12의 새로운 Wasm API 구현에도 동일한 메커니즘이 적용됩니다. 원격 가져오기가 실패할 경우 Envoy가 잘못된 구성으로 인해 중단될 염려 없이 HTTP 원격 리소스를 안정적으로 사용할 수 있습니다.
EnvoyFilter리소스가 정의되어 있습니다. 하나는 원격 가져오기 Envoy 클러스터를 추가하는 리소스이고, 다른 하나는 HTTP 필터 체인에 Wasm 필터를 삽입하는 리소스입니다. 이 방법에는 단점이 있습니다. 잘못된 구성이나 일시적인 오류로 인해 원격 가져오기가 실패하면 Envoy가 잘못된 구성에 고정됩니다. Wasm 확장 프로그램이 fail closed 로 구성된 경우 , 잘못된 원격 가져오기로 인해 Envoy 서비스가 중단됩니다. 이 문제를 해결하려면 Envoy xDS 프로토콜을 근본적으로 변경 하여 비동기 xDS 응답을 허용해야 합니다.웹어셈블리로 엔보이 필터를 빌드하려면 어떤 언어를 사용하고 싶은지, 어떤 엔보이 버전을 사용 중인지, 그 버전에서 어떤 엔보이 ABI Abstract Binary Interace 를 지원하는지 등을 알아야 한다.
엔보이의 웹어셈블리의 지원은 실험적인 것으로 간주되므로 바뀔 수 있다.
따라서 직접 만들어 엔보이에 배포하는 웹어셈블리 모듈은 운영 환경에 들어가기 전에 모두 철저히 테스트해볼 것을 권장한다.
/api.WasmPlugin리소스를 생성하세요.# 설정 전 호출 확인
EXT_IP=$(kubectl -n istio-system get svc istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
docker exec -it mypc curl -s -H "Host: webapp.istioinaction.io" http://$EXT_IP/api/catalog -v
#
kubectl explain wasmplugins.extensions.istio.io
...
#
kubectl apply -f - <<EOF
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: basic-auth
namespace: istio-system # 모든 네임스페이스에 영향
spec:
selector:
matchLabels:
istio: ingressgateway
url: oci://ghcr.io/istio-ecosystem/wasm-extensions/basic_auth:1.12.0
phase: AUTHN
pluginConfig:
basic_auth_rules:
- prefix: "/api"
request_methods:
- "GET"
- "POST"
credentials:
- "ok:test"
- "YWRtaW4zOmFkbWluMw=="
EOF
#
kubectl get WasmPlugin -A
NAMESPACE NAME AGE
istio-system basic-auth 21s
자격 증명 없이 테스트

자격 증명으로 테스트

#
kubectl apply -f - <<EOF
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: coraza-ingressgateway
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
url: oci://ghcr.io/corazawaf/coraza-proxy-wasm
phase: AUTHN
pluginConfig:
default_directives: default
directives_map:
default:
- Include @demo-conf
- SecDebugLogLevel 9
- SecRuleEngine On
- Include @crs-setup-conf
- Include @owasp_crs/*.conf
EOF
#
kubectl logs -n istio-system -l app=istio-ingressgateway | grep -i wasm
2025-05-18T09:22:39.344842Z info wasm fetching image corazawaf/coraza-proxy-wasm from registry ghcr.io with tag latest
#
kubectl get WasmPlugin -A
NAMESPACE NAME AGE
istio-system coraza-ingressgateway 9s

#
curl -s http://webapp.istioinaction.io:30000/api/catalog
# XSS (Cross-Site Scripting) 공격 시도 : REQUEST-941-APPLICATION-ATTACK-XSS
curl -s 'http://webapp.istioinaction.io:30000/api/catalog?arg=<script>alert(0)</script>' -IL
HTTP/1.1 403 Forbidden
# 로그 모니터링
kubectl logs -n istio-system -l app=istio-ingressgateway -f
# SQLI phase 2 (reading the body request)
curl -i -X POST 'http://webapp.istioinaction.io:30000/api/catalog' --data "1%27%20ORDER%20BY%203--%2B"
HTTP/1.1 403 Forbidden
# 로그 모니터링
kubectl logs -n istio-system -l app=istio-ingressgateway -f
...



- 엔보이의 내부 아키텍처는 리스너와 필터를 중심으로 구축됐다.
- 즉시 사용할 수 있는 엔보이 필터가 많다.
- 이스티오의 데이터 플레인(엔보이 프록시)을 확장할 수 있다.
- 이스티오의 EnvoyFilter 리소스를 사용해 엔보이의 HTTP 필터 구조를 직접 구성하면 더 세밀한 설정이 가능하며, 이스티오의 API로는 노출되지 않는 엔보이의 부분들도 설정할 수 있다.
- 속도 제한이나 tap 필터 같은 기능으로 서비스 간 통신에서 엔보이의 요청 경로를 확장할 수 있다.
- 루아와 웹어셈블리를 사용하면 엔보이를 다시 빌드하지 않고도 데이터 플레인을 고급 수준에서 커스터마이징할 수 있다.