-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4b6c7d2
commit 46bb79f
Showing
1 changed file
with
142 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,170 @@ | ||
# Forward a Client IP in the X-Forwarded-For Header | ||
# Use the XFF Header to Configure IP-Based Access to a Workload | ||
|
||
Learn what the X-Forwarded-For (XFF) header is. Use it to forward client attributes to destination workloads. | ||
|
||
## Prerequisites | ||
|
||
* You have the Istio module added. | ||
* To use CLI instruction, you must install [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) and [curl](https://curl.se/). Alternatively, you can use Kyma dashboard. | ||
* You have Istio Ingress Gateway set up. See [Set Up a TLS Gateway in Simple Mode](https://kyma-project.io/#/api-gateway/user/tutorials/01-20-set-up-tls-gateway). | ||
* You have the Istio and API Gateway modules added. | ||
* You have a deployed workload. | ||
* To use CLI instructions, you must install [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) and [curl](https://curl.se/). Alternatively, you can use Kyma dashboard. | ||
* You have Istio Ingress Gateway set up. See [Set Up a TLS Gateway in Simple Mode](https://kyma-project.io/#/api-gateway/user/tutorials/01-20-set-up-tls-gateway). Alternatively, you can use the default simple TLS Kyma Gateway `kyma-system/kyma-gateway`. | ||
|
||
## Context | ||
|
||
To function correctly, many applications must be provided with the client IP address of an originating request. This is often needed in cases where a workload must restrict access based on the client IP address. Reverse proxies pass client attributes to destination workloads using the XFF header. | ||
To function correctly, many applications must be provided with the client IP address of an originating request. This is often needed in cases where a workload must restrict access based on the client IP address. | ||
|
||
The XFF header conveys the client IP address and the chain of intermediary proxies that the request traverses to reach the Istio service mesh. The header might not include all IP addresses if an intermediary proxy does not support modifying the header. Due to [technical limitations of AWS Classic ELBs](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-proxy-protocol.html#proxy-protocol), when using an IPv4 connection, the header does not include the public IP of the load balancer in front of Istio Ingress Gateway. Moreover, Istio Ingress Gateway's Envoy does not append the private IP address of the load balancer to the XFF header, effectively removing this information from the request. For more information on XFF, see the [IETF’s RFC documentation](https://datatracker.ietf.org/doc/html/rfc7239) and [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for). | ||
|
||
To use the XFF header, you must configure the corresponding settings in the Istio custom resource (CR). | ||
To use the XFF header, you must configure the corresponding settings in the Istio custom resource (CR). To restrict access to an exposed workload based on the client IP adress, you must create an AuthorisationPolicy resource. | ||
|
||
## Procedure | ||
|
||
<!-- tabs:start --> | ||
#### **Kyma Dashboard** | ||
1. Go to **Cluster Details**. | ||
2. Choose **Modify Modules**. | ||
2. Select the Istio module. | ||
3. Choose **Edit**. | ||
4. In the `General` section, add the number of trusted proxies. | ||
Due to the variety of network topologies, the Istio CR must specify the number of trusted proxies deployed in front of the Istio Ingress Gateway proxy in the Istio CR, so that the client address can be extracted correctly. | ||
6. If you use a GCP or Azure cluster, navigate to the Gateway section and set the Gateway traffic policy to Local. If you use a different cloud service provider, skip this step. | ||
>[!WARNING] | ||
> For production Deployments, it is strongly recommended to deploy Istio Ingress Gateway Pod to multiple nodes if you enable externalTrafficPolicy : Local. For more information, see [Network Load Balancer](https://istio.io/latest/docs/tasks/security/authorization/authz-ingress/#network). | ||
> | ||
>Default Istio installation profile configures PodAntiAffinity to ensure that Ingress Gateway Pods are evenly spread across all nodes and, if possible, across different zones. This guarantees that the above requirement is satisfied if your IngressGateway autoscaling configuration minReplicas is equal to or greater than the number of nodes. You can configure autoscaling options in the Istio CR using the field spec.config.components.ingressGateway.k8s.hpaSpec.minReplicas.<br> | ||
1. To use the XFF header, configure the number of trusted proxies in the Istio custom resource. | ||
1. Go to **Cluster Details** and choose **Modify Modules**. | ||
2. Select the Istio module and choose **Edit**. | ||
3. In the `General` section, set the number of trusted proxies to `1`. | ||
Due to the variety of network topologies, the Istio CR must specify the number of trusted proxies deployed in front of the Istio Ingress Gateway proxy in the Istio CR, so that the client address can be extracted correctly. | ||
4. If you use a GCP or Azure cluster, navigate to the Gateway section and set the Gateway traffic policy to Local. If you use a different cloud service provider, skip this step. | ||
>[!WARNING] | ||
> For production Deployments, it is strongly recommended to deploy Istio Ingress Gateway Pod to multiple nodes if you enable externalTrafficPolicy : Local. For more information, see [Network Load Balancer](https://istio.io/latest/docs/tasks/security/authorization/authz-ingress/#network). | ||
> | ||
>Default Istio installation profile configures PodAntiAffinity to ensure that Ingress Gateway Pods are evenly spread across all nodes and, if possible, across different zones. This guarantees that the above requirement is satisfied if your IngressGateway autoscaling configuration minReplicas is equal to or greater than the number of nodes. You can configure autoscaling options in the Istio CR using the field spec.config.components.ingressGateway.k8s.hpaSpec.minReplicas.<br> | ||
>[!TIP] | ||
> If you use a GCP or Azure cluster, you can find your load balancer's IP address in the field status.loadBalancer.ingress of the ingress-gateway Service. | ||
5. Choose **Save**. | ||
2. To expose your workload, create an APIRule custom resource with the `noAuth` access strategy. | ||
1. Go to **Discovery and Network > API Rules** and choose **Create**. | ||
2. Provide all the required configuration details. | ||
3. Add a rule with the following configuration: | ||
- **Path**: `/headers` | ||
- **Handler**: `no_auth` | ||
- **Methods**: `GET` | ||
4. Choose **Create**. | ||
|
||
>[!TIP] | ||
> If you use a GCP or Azure cluster, you can find your load balancer's IP address in the field status.loadBalancer.ingress of the ingress-gateway Service. | ||
7. Choose **Save**. | ||
**Step result:** When you go to `https:/{SUBDOMAIN}.{DOMAIN}/headers`, the response contains the **X-Forwarded-For** and **X-Envoy-External-Address** headers with your public IP address. See an example response for the Client IP `165.1.187.197`: | ||
```json | ||
{ | ||
"args": { | ||
"show_env": "true" | ||
}, | ||
"headers": { | ||
"Accept": "...", | ||
"Host": "...", | ||
"User-Agent": "...", | ||
"X-Envoy-Attempt-Count": "...", | ||
"X-Envoy-External-Address": "165.1.187.197", | ||
"X-Forwarded-Client-Cert": "...", | ||
"X-Forwarded-For": "165.1.187.197", | ||
"X-Forwarded-Proto": "...", | ||
"X-Request-Id": "..." | ||
}, | ||
"origin": "165.1.187.197", | ||
"url": "..." | ||
} | ||
``` | ||
>[!TIP] | ||
> You can check your public IP address at https://api.ipify.org. | ||
|
||
3. To configure IP-based access to the exposed workload, create an AuthorizationPolicy resource. | ||
1. Go to **Istio > Authorization Policies** and choose `Create`. | ||
2. Add a selector to specify the workload for which access should be configured. | ||
3. Add a rule with a `From` field. | ||
4. In the **RemoteIpBlocks** field, specify the IP addresses that should be allowed access to the workload. | ||
5. Choose **Create**. | ||
|
||
|
||
#### **kubectl** | ||
1. In the following command, replace the placeholder with the number of trusted proxies deployed in front of the Istio Ingress Gateway proxy. Run the command: | ||
```bash | ||
kubectl patch istios/default -n kyma-system --type merge -p '{"spec":{"config":{"numTrustedProxies": NUM_OF_TRUSTED_PROXIES}}}' | ||
``` | ||
Due to the variety of network topologies, the Istio CR must specify the configuration property **numTrustedProxies**, so that the client IP address can be extracted correctly. | ||
1. To use the XFF header, configure the number of trusted proxies in the Istio custom resource. | ||
1. Run the following command: | ||
```bash | ||
kubectl patch istios/default -n kyma-system --type merge -p '{"spec":{"config":{"numTrustedProxies": 1}}}' | ||
``` | ||
Due to the variety of network topologies, the Istio CR must specify the configuration property **numTrustedProxies**, so that the client IP address can be extracted correctly. | ||
|
||
2. If you use a GCP or Azure cluster, run the following command to set the traffic policy to Local. If you use a different cloud service provider, skip this step. | ||
|
||
2. If you use a GCP or Azure cluster, run the following command to set the traffic policy to Local. If you use a different cloud service provider, skip this step. | ||
```bash | ||
kubectl patch istios/default -n kyma-system --type merge -p '{"spec":{"config":{"gatewayExternalTrafficPolicy": "Local"}}}' | ||
``` | ||
>[!WARNING] | ||
> For production Deployments, it is strongly recommended to deploy Istio Ingress Gateway Pod to multiple nodes if you `enable externalTrafficPolicy : Local`. For more information, see [Network Load Balancer](https://istio.io/latest/docs/tasks/security/authorization/authz-ingress/#network). | ||
> | ||
>Default Istio installation profile configures **PodAntiAffinity** to ensure that Ingress Gateway Pods are evenly spread across all nodes and, if possible, across different zones. This guarantees that the above requirement is satisfied if your IngressGateway autoscaling configuration **minReplicas** is equal to or greater than the number of nodes. You can configure autoscaling options in the Istio CR using the field **spec.config.components.ingressGateway.k8s.hpaSpec.minReplicas**. | ||
|
||
>[!TIP] | ||
> If you use a GCP or Azure cluster, you can find your load balancer's IP address in the field **status.loadBalancer.ingress of the ingress-gateway** Service. | ||
2. To expose your workload, create an APIRule custom resource with the `noAuth` access strategy. | ||
```bash | ||
kubectl patch istios/default -n kyma-system --type merge -p '{"spec":{"config":{"gatewayExternalTrafficPolicy": "Local"}}}' | ||
cat <<EOF | kubectl apply -f - | ||
apiVersion: gateway.kyma-project.io/v2alpha1 | ||
kind: APIRule | ||
metadata: | ||
name: {APIRULE_NAME} | ||
namespace: {APIRULE_NAMESPACE} | ||
spec: | ||
hosts: | ||
- {SUBDOMAIN}.{DOMAIN} | ||
service: | ||
name: {SERVICE_NAME} | ||
namespace: {SERVICE_NAMESPACE} | ||
port: {SERVICE_PORT} | ||
gateway: {GATEWAY_NAMESPACE}/{GATEWAY_NAME} | ||
rules: | ||
- path: /headers | ||
methods: ["GET"] | ||
noAuth: true | ||
EOF | ||
``` | ||
>[!WARNING] | ||
> For production Deployments, it is strongly recommended to deploy Istio Ingress Gateway Pod to multiple nodes if you `enable externalTrafficPolicy : Local`. For more information, see [Network Load Balancer](https://istio.io/latest/docs/tasks/security/authorization/authz-ingress/#network). | ||
> | ||
>Default Istio installation profile configures **PodAntiAffinity** to ensure that Ingress Gateway Pods are evenly spread across all nodes and, if possible, across different zones. This guarantees that the above requirement is satisfied if your IngressGateway autoscaling configuration **minReplicas** is equal to or greater than the number of nodes. You can configure autoscaling options in the Istio CR using the field **spec.config.components.ingressGateway.k8s.hpaSpec.minReplicas**. | ||
|
||
**Step result:** When you run `curl -ik -X GET https:/{SUBDOMAIN}.{DOMAIN}/headers`, the response contains the **X-Forwarded-For** and **X-Envoy-External-Address** headers with your public IP address. See an example response for the Client IP `165.1.187.197`: | ||
```json | ||
{ | ||
"args": { | ||
"show_env": "true" | ||
}, | ||
"headers": { | ||
"Accept": "...", | ||
"Host": "...", | ||
"User-Agent": "...", | ||
"X-Envoy-Attempt-Count": "...", | ||
"X-Envoy-External-Address": "165.1.187.197", | ||
"X-Forwarded-Client-Cert": "...", | ||
"X-Forwarded-For": "165.1.187.197", | ||
"X-Forwarded-Proto": "...", | ||
"X-Request-Id": "..." | ||
}, | ||
"origin": "165.1.187.197", | ||
"url": "..." | ||
} | ||
``` | ||
>[!TIP] | ||
> If you use a GCP or Azure cluster, you can find your load balancer's IP address in the field **status.loadBalancer.ingress of the ingress-gateway** Service. | ||
> You can check your public IP address at https://api.ipify.org. | ||
3. To configure IP-based access to the exposed workload, create an AuthorizationPolicy resource. | ||
```bash | ||
apiVersion: security.istio.io/v1beta1 | ||
kind: AuthorizationPolicy | ||
metadata: | ||
name: {AUTHORIZATIONPOLICY_NAME} | ||
namespace: {AUTHORIZATIONPOLICY_NAMESPACE} | ||
spec: | ||
action: ALLOW | ||
rules: | ||
- from: | ||
- source: | ||
ipBlocks: [] | ||
remoteIpBlocks: | ||
- {ALLOWED_IP} | ||
selector: | ||
matchLabels: | ||
{KEY}: {VALUE} | ||
``` | ||
<!-- tabs:end --> | ||
### Results | ||
When you call an exposed workload, the response contains the **X-Forwarded-For** and **X-Envoy-External-Address** headers with your public IP address. See an example response for the Client IP `165.1.187.197`: | ||
```json | ||
{ | ||
"args": { | ||
"show_env": "true" | ||
}, | ||
"headers": { | ||
"Accept": "...", | ||
"Host": "...", | ||
"User-Agent": "...", | ||
"X-Envoy-Attempt-Count": "...", | ||
"X-Envoy-External-Address": "165.1.187.197", | ||
"X-Forwarded-Client-Cert": "...", | ||
"X-Forwarded-For": "165.1.187.197", | ||
"X-Forwarded-Proto": "...", | ||
"X-Request-Id": "..." | ||
}, | ||
"origin": "165.1.187.197", | ||
"url": "..." | ||
} | ||
``` | ||
>[!TIP] | ||
> You can check your public IP address at https://api.ipify.org. | ||
Only the specified IP adresses can access the exposed workload. |