Zscaler gateway named directly instead of through ${GATEWAY}
low
Zscaler discourages hard-coded gateway addresses because they can change. The ${GATEWAY} variables are resolved per request by the PAC server to the closest healthy Public Service Edge; a literal gateway.<cloud>.net host or IP is static and skips that logic.
Why it matters
Zscaler writes that IP addresses “are generally discouraged because they can change at any time”
and recommends ${GATEWAY} and ${SECONDARY_GATEWAY} instead, including the subcloud and _HOST
forms. A literal Zscaler host name such as gateway.zscaler.net works, but it is answered by
anycast or DNS-based selection rather than by the per-client geolocation of the PAC server, and it
cannot take part in the _F0-_F7 / _FX load distribution. There is one documented exception:
Zscaler Client Connector lets you pin traffic for specific internal hosts to a specific data centre
by IP address, with at most two such return statements. The variables only expand when the PAC is
hosted on the Zscaler cloud, so a self-hosted file has to use host names; in that case this is
informational.
How to fix
Host the PAC on the Zscaler cloud and return "PROXY ${GATEWAY}:80; PROXY ${SECONDARY_GATEWAY}:80" (or the _HOST / subcloud forms); keep literal addresses only for the documented pin-to-data-centre case.
Examples
Bad
function FindProxyForURL(url, host) {
if (isPlainHostName(host)) {
return "DIRECT";
}
return "PROXY gateway.zscaler.net:80; PROXY gateway.zscalertwo.net:80";
}
Open bad example in checkerGood
function FindProxyForURL(url, host) {
if (isPlainHostName(host)) {
return "DIRECT";
}
return "PROXY ${GATEWAY}:80; PROXY ${SECONDARY_GATEWAY}:80";
}
Open good example in checker