In our haproxy.cfg rules detailed below we wanted to handle both the case where our load balancer is hit directly by end users (in case we bypass any CDN service), and the case where the load balancer is hit via a CDN.
1) We set our own HTTP headers containing the country code as detected by geolocation based on a) the source IP (this is so we can still look at the source IP in case we bypass the CDN and hit our load balancer directly) and b) the specific CDN header containing the actual client IP (True-Client-IP in the case of Akamai):
http-request set-header X-Country-Src %[src,map_ip(/etc/haproxy/geolocation.txt)]
http-request set-header X-Country-Akamai %[req.hdr_ip(True-Client-IP,-1),map_ip(/etc/haproxy/geolocation.txt)]
2) We set an ACL that is true if we detect the presence of the True-Client-IP header, which tells us that we are hit via Akamai:
acl acl_akamai_true_client_ip_header_exists req.hdr(True-Client-IP) -m found
3) We set an ACL that is true if we detect that the country of origin (obtained via Akamai's True-Client-IP) is US:
acl acl_geoloc_akamai_true_client_ip_us req.hdr(X-Country-Akamai) -m str -i US
acl acl_geoloc_akamai_true_client_ip_us req.hdr(X-Country-Akamai) -m str -i US
4) We set an ACL that is true if we detect that the country of origin (obtained via the source IP of the client) is US:
acl acl_geoloc_src_us req.hdr(X-Country-Src) -m str -i US
5) Based on the ACLs defined above, we send non-US traffic to a specific backend, IF we are being hit via Akamai (ACL #2) AND we detected that the country of origin is non-US (negation of ACL #3) OR if we detected that the country of origin if non-US via the source IP (negation of ACL #4):
use_backend www-backend-non-us if acl_akamai_true_client_ip_header_exists !acl_geoloc_akamai_true_client_ip_us or !acl_geoloc_src_us
(note that the AND is implicit in the way haproxy looks at combinations of ACLs)
use_backend www-backend-non-us if acl_akamai_true_client_ip_header_exists !acl_geoloc_akamai_true_client_ip_us or !acl_geoloc_src_us
(note that the AND is implicit in the way haproxy looks at combinations of ACLs)
6) We also we an HTTP header called X-Country which our application inspects in order to perform country-specific logic. We first set this header to the X-Country-Src header set in rule #1, but we override it if we are getting hit via Akamai:
http-request set-header X-Country %[req.hdr(X-Country-Src)]
http-request set-header X-Country %[req.hdr(X-Country-Akamai)] if acl_akamai_true_client_ip_header_exists
This looks pretty complicated, but it works well :-)