content/en/blog/2020/show-source-ip/index.md
This blog presents my latest experience about how to configure and enable proxy protocol with stack of AWS NLB and Istio Ingress gateway. The Proxy Protocol was designed to chain proxies and reverse-proxies without losing the client information. The proxy protocol prevents the need for infrastructure changes or NATing firewalls, and offers the benefits of being protocol agnostic and providing good scalability. Additionally, we also enable the X-Forwarded-For HTTP header in the deployment to make the client IP address easy to read. In this blog, traffic management of Istio ingress is shown with an httpbin service on ports 80 and 443 to demonstrate the use of proxy protocol. Note that both v1 and v2 of the proxy protocol work for the purpose of this example, but because the AWS NLB currently only supports v2, proxy protocol v2 is used in the rest of this blog by default. The following image shows the use of proxy protocol v2 with an AWS NLB.
{{< tip >}} A receiver may be configured to support both version 1 and version 2 of the protocol. Identifying the protocol version is easy:
If the incoming byte count is 16 or more and the first 13 bytes match the protocol signature block \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x02, the protocol is version 2.
Otherwise, if the incoming byte count is 8 or more, and the 5 first characters match the US-ASCII representation of "PROXY"(\x50\x52\x4F\x58\x59), then the protocol must be parsed as version 1.
Otherwise the protocol is not covered by this specification and the connection must be dropped. {{< /tip >}}
{{< image width="100%" link="./aws-proxy-protocol.png" caption="AWS NLB portal to enable proxy protocol" >}}
Before going through the following steps, an AWS environment that is configured with the proper VPC, IAM, and Kubernetes setup is assumed.
The blog Configuring Istio Ingress with AWS NLB provides detailed steps to set up AWS IAM roles and enable the usage of AWS NLB by Helm. You can also use other automation tools, such as Terraform, to achieve the same goal. In the following example, more complete configurations are shown in order to enable proxy protocol and X-Forwarded-For at the same time.
{{< text yaml >}} apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*" service.beta.kubernetes.io/aws-load-balancer-type: "nlb" proxy.istio.io/config: '{"gatewayTopology" : { "numTrustedProxies": 2 } }' labels: app: istio-ingressgateway istio: ingressgateway release: istio name: istio-ingressgateway {{< /text >}}
{{< text yaml >}} apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: proxy-protocol namespace: istio-system spec: workloadSelector: labels: istio: ingressgateway configPatches:
X-Forwarded-For headerThis blog includes several samples of configuring Gateway Network Topology. In the following example, the configurations are tuned to enable X-Forwarded-For without any middle proxy.
{{< text yaml >}} apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: ingressgateway-settings namespace: istio-system spec: configPatches:
{{< warning>}} When following the secure ingress setup, macOS users must add an additional patch to generate certificates for TLS. {{< /warning >}}
{{< text yaml >}} apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway # use Istio default gateway implementation servers:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts:
{{< text yaml >}} apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: mygateway2 spec: selector: istio: ingressgateway # use istio default ingress gateway servers:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts:
Check port 443 (80 will be similar) and compare the cases with and without proxy protocol.
{{< text yaml >}} //////with proxy_protocal enabled in the stack
GET /headers?show_env=1 HTTP/2 Host: a25fa0b4835b.elb.us-west-2.amazonaws.com User-Agent: curl/7.64.1 Accept: /
{{< text yaml >}} //////////without proxy_protocal
GET /headers?show_env=1 HTTP/2 Host: a25fa0b4835b.elb.us-west-2.amazonaws.com User-Agent: curl/7.64.1 Accept: /
This blog presents the deployment of a stack that consists of an AWS NLB and Istio ingress gateway that are enabled with proxy-protocol. We hope it is useful to you if you are interested in protocol enabling in an anecdotal, experiential, and more informal way. However, note that the X-Forwarded-For header should be used only for the convenience of reading in test, as dealing with fake X-Forwarded-For attacks is not within the scope of this blog.