This is the "latest" release of Envoy Gateway, which contains the most recent commits from the main branch.
This release might not be stable.
Please refer to the /docs documentation for the most current information.
GeoIP Authorization
5 minute read
This task provides instructions for configuring GeoIP-based authorization with Envoy Gateway.
GeoIP authorization uses geolocation data derived from the client IP address to determine whether a request should be allowed or denied before it is forwarded to the backend service.
Envoy Gateway introduces a new CRD called SecurityPolicy that allows the user to configure GeoIP-based authorization. This instantiated resource can be linked to a Gateway, HTTPRoute, or GRPCRoute resource.
GeoIP authorization is configured through SecurityPolicy.spec.authorization.rules[].principal.clientIPGeoLocations.
GeoIP authorization requires:
- GeoIP provider configuration on EnvoyProxy
- client IP detection on ClientTrafficPolicy
- a SecurityPolicy attached to a Gateway, HTTPRoute or GRPCRoute
Prerequisites
Follow the steps below to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP.
Expand for instructions
Install the Gateway API CRDs and Envoy Gateway using Helm:
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespaceInstall the GatewayClass, Gateway, HTTPRoute and example app:
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/latest/quickstart.yaml -n defaultVerify Connectivity:
Get the External IP of the Gateway:
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/getThe above command should succeed with status code 200.
Get the name of the Envoy service created the by the example Gateway:
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')Get the deployment of the Envoy service created the by the example Gateway:
export ENVOY_DEPLOYMENT=$(kubectl get deploy -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')Port forward to the Envoy service:
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 &Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://localhost:8888/getThe above command should succeed with status code 200.
Configuration
Prepare the GeoIP database
Envoy reads GeoIP data from a local MaxMind .mmdb database file mounted into the proxy container.
This task uses a public MaxMind anonymous-IP test database. Apply the example manifest before continuing:
kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/geoip-anonymous-ip-db.yaml
To keep this guide readable, the full base64-encoded ConfigMap is not repeated here.
For production deployments, mount your own supported MaxMind database and update the file path in the EnvoyProxy resource accordingly.
Configure the Gateway and EnvoyProxy
The following resources create a dedicated Gateway, mount the anonymous-IP database into the Envoy proxy, and configure EnvoyProxy.spec.geoIP.provider.maxMind.anonymousIpDbSource to read it.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: geoip-authz-gateway
spec:
gatewayClassName: eg
infrastructure:
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: geoip-authz-proxy
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: geoip-authz-proxy
spec:
provider:
type: Kubernetes
kubernetes:
envoyDeployment:
pod:
volumes:
- name: geoip-db
configMap:
name: geoip-anonymous-ip-db
items:
- key: GeoIP2-Anonymous-IP-Test.mmdb
path: GeoIP2-Anonymous-IP-Test.mmdb
container:
volumeMounts:
- name: geoip-db
mountPath: /etc/envoy/geoip
readOnly: true
geoIP:
provider:
type: MaxMind
maxMind:
anonymousIpDbSource:
local:
path: /etc/envoy/geoip/GeoIP2-Anonymous-IP-Test.mmdb
EOF
Save and apply the following resources to your cluster:
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: geoip-authz-gateway
spec:
gatewayClassName: eg
infrastructure:
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: geoip-authz-proxy
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: geoip-authz-proxy
spec:
provider:
type: Kubernetes
kubernetes:
envoyDeployment:
pod:
volumes:
- name: geoip-db
configMap:
name: geoip-anonymous-ip-db
items:
- key: GeoIP2-Anonymous-IP-Test.mmdb
path: GeoIP2-Anonymous-IP-Test.mmdb
container:
volumeMounts:
- name: geoip-db
mountPath: /etc/envoy/geoip
readOnly: true
geoIP:
provider:
type: MaxMind
maxMind:
anonymousIpDbSource:
local:
path: /etc/envoy/geoip/GeoIP2-Anonymous-IP-Test.mmdb
Create the route and SecurityPolicy
The following resources create an HTTPRoute for /geo-anonymous and attach a SecurityPolicy that denies requests identified as anonymous networks while allowing other traffic.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-with-authorization-geoip-anonymous
spec:
parentRefs:
- name: geoip-authz-gateway
rules:
- matches:
- path:
type: Exact
value: /geo-anonymous
backendRefs:
- name: backend
port: 3000
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: authorization-geoip-anonymous
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-with-authorization-geoip-anonymous
authorization:
defaultAction: Allow
rules:
- action: Deny
principal:
clientIPGeoLocations:
- anonymous:
isAnonymous: true
EOF
Save and apply the following resources to your cluster:
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-with-authorization-geoip-anonymous
spec:
parentRefs:
- name: geoip-authz-gateway
rules:
- matches:
- path:
type: Exact
value: /geo-anonymous
backendRefs:
- name: backend
port: 3000
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: authorization-geoip-anonymous
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-with-authorization-geoip-anonymous
authorization:
defaultAction: Allow
rules:
- action: Deny
principal:
clientIPGeoLocations:
- anonymous:
isAnonymous: true
Verify the SecurityPolicy configuration:
kubectl get securitypolicy/authorization-geoip-anonymous -o yaml
Enable client IP detection
GeoIP authorization depends on Envoy Gateway correctly detecting the client IP address. Without ClientTrafficPolicy.spec.clientIPDetection, the clientIPGeoLocations match will not work as intended.
The following ClientTrafficPolicy tells Envoy Gateway to use the X-Forwarded-For header and trust one upstream hop:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
name: enable-client-ip-detection-geoip
spec:
clientIPDetection:
xForwardedFor:
numTrustedHops: 1
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: geoip-authz-gateway
EOF
Save and apply the following resource to your cluster:
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
name: enable-client-ip-detection-geoip
spec:
clientIPDetection:
xForwardedFor:
numTrustedHops: 1
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: geoip-authz-gateway
Verify the ClientTrafficPolicy configuration:
kubectl get clienttrafficpolicy/enable-client-ip-detection-geoip -o yaml
Testing
Ensure the GATEWAY_HOST environment variable from the Quickstart is set. If not, follow the Quickstart instructions to set the variable.
echo $GATEWAY_HOST
Send a request with a regular client IP that is not flagged as anonymous by the test database:
curl -v -H "Host: www.example.com" -H "X-Forwarded-For: 8.8.8.8" "http://${GATEWAY_HOST}/geo-anonymous"
The request should be allowed and return 200 OK.
Send a request with an IP that the anonymous-IP test database marks as anonymous:
curl -v -H "Host: www.example.com" -H "X-Forwarded-For: 6.1.0.3" "http://${GATEWAY_HOST}/geo-anonymous"
The request should be denied and return 403 Forbidden.
Clean-Up
Remove the resources created in this task:
kubectl delete clienttrafficpolicy/enable-client-ip-detection-geoip
kubectl delete securitypolicy/authorization-geoip-anonymous
kubectl delete httproute/http-with-authorization-geoip-anonymous
kubectl delete gateway/geoip-authz-gateway
kubectl delete envoyproxy/geoip-authz-proxy
If you applied the test GeoIP database ConfigMap, remove it as well:
kubectl delete configmap/geoip-anonymous-ip-db
Next Steps
Checkout the following related guides:
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.