Netskope explicit proxy PAC builder
Builds a PAC file for Netskope Cloud Explicit Proxy (eproxy-<tenant>:8081) or Explicit Proxy over IPSec/GRE tunnels, with the identity-provider exception Netskope requires, DNS-free local bypasses and an http/https-only proxy rule.
Netskope’s sample template normalises the URL and host, sends plain hostnames direct, leaves a
commented block for IdP and other exceptions and returns PROXY eproxy-<tenant>:8081 for http and
https URLs. This builder fills in the exception blocks and keeps the rest.
Generated proxy.pac
[{"default":"cloud","id":"mode","label":"Deployment","options":[{"label":"Cloud Explicit Proxy: eproxy-\u003ctenant\u003e on port 8081 (SAML authentication)","value":"cloud"},{"label":"Explicit Proxy over IPSec/GRE tunnel: 163.116.128.80 and .81 on port 80","value":"epot"}],"type":"select"},{"default":"exampletenant.goskope.com","help":"Exactly as shown under Settings \u003e Security Cloud Platform \u003e Explicit Proxy \u003e Tenant Name; the sample PAC uses eproxy-\u003cTenant Name\u003e.","id":"tenant","label":"Tenant name","pattern":"^[a-z0-9][a-z0-9.-]*$","pattern_help":"letters, digits, dots and hyphens only","type":"text"},{"default":"entra","help":"Netskope relies on the IdP for the user identity and requires IdP traffic to go directly to the IdP.","id":"idp","label":"Identity provider (must not go through the proxy)","options":[{"label":"Microsoft Entra ID (login.microsoftonline.com, aadcdn.msauth.net, aadcdn.msftauth.net)","value":"entra"},{"label":"Okta (okta.com, oktacdn.com)","value":"okta"},{"label":"Google Workspace (accounts.google.com, gstatic.com)","value":"google"},{"label":"Other (list the hosts below)","value":"none"}],"type":"select"},{"default":[],"help":"One per line; the domain and all its subdomains are matched.","id":"idp_domains","item_pattern":"^[a-z0-9-]+(\\.[a-z0-9-]+)+$","label":"Additional identity-provider domains that go direct","max":20,"pattern_help":"must be a domain such as login.idp.example","type":"list"},{"default":["corp.example"],"help":"One per line, without a leading dot. With the Netskope Client installed, add the same domains as steering exceptions.","id":"internal_domains","item_pattern":"^[a-z0-9-]+(\\.[a-z0-9-]+)+$","label":"Internal DNS suffixes that go direct","max":50,"pattern_help":"must be a domain such as corp.example (no leading dot, no wildcard)","type":"list"},{"default":true,"help":"Uses an IP-literal test in front of isInNet, so host names never trigger a DNS lookup.","id":"bypass_private","label":"Plain hostnames and private (RFC 1918) addresses go direct","rules":["isinnet-on-hostname"],"type":"checkbox"},{"default":true,"help":"The explicit proxy accepts HTTP and HTTPS only and drops other protocols.","id":"ftp_direct","label":"ftp:// URLs go direct","type":"checkbox"},{"default":false,"grade_note":"Netskope describes this as fail-through when the upstream proxy or tunnel is down. It lowers the grade unless \"Accept fail-open\" is ticked in the checker settings.","id":"direct_fallback","label":"Add \"; DIRECT\" after the proxy (fail open when it is unreachable)","rules":["direct-fallback-in-proxy-list"],"type":"checkbox"}]// proxy.pac for Netskope explicit proxy, generated by findproxyforurl.net
function FindProxyForURL(url, host) {
host = host.toLowerCase();
{{#if bypass_private}}
// plain hostnames (no dot) stay on the local network
if (isPlainHostName(host)) {
return "DIRECT";
}
// RFC 1918 and loopback addresses: literal IPs only, no DNS lookup for names
if (/^\d+\.\d+\.\d+\.\d+$/.test(host) &&
(isInNet(host, "10.0.0.0", "255.0.0.0") ||
isInNet(host, "172.16.0.0", "255.240.0.0") ||
isInNet(host, "192.168.0.0", "255.255.0.0") ||
isInNet(host, "127.0.0.0", "255.0.0.0"))) {
return "DIRECT";
}
{{/if}}
{{#if internal_domains}}
// internal domains and their subdomains go direct
if ({{#each internal_domains sep=" ||\n "}}dnsDomainIs(host, ".{{.}}"){{/each}}) {
return "DIRECT";
}
{{/if}}
{{#if idp == "entra"}}
// identity provider (Microsoft Entra ID) must not go through the explicit proxy
if (host == "login.microsoftonline.com" || host == "aadcdn.msauth.net" || host == "aadcdn.msftauth.net") {
return "DIRECT";
}
{{/if}}
{{#if idp == "okta"}}
// identity provider (Okta) must not go through the explicit proxy
if (dnsDomainIs(host, ".okta.com") || dnsDomainIs(host, ".oktacdn.com")) {
return "DIRECT";
}
{{/if}}
{{#if idp == "google"}}
// identity provider (Google Workspace) must not go through the explicit proxy
if (host == "accounts.google.com" || dnsDomainIs(host, ".gstatic.com")) {
return "DIRECT";
}
{{/if}}
{{#if idp_domains}}
// identity provider hosts must not go through the explicit proxy
if ({{#each idp_domains sep=" ||\n "}}dnsDomainIs(host, ".{{.}}"){{/each}}) {
return "DIRECT";
}
{{/if}}
{{#if ftp_direct}}
// the explicit proxy accepts HTTP and HTTPS only
if (url.substring(0, 4) == "ftp:") {
return "DIRECT";
}
{{/if}}
{{#if mode == "cloud"}}
// default: everything else goes to the Netskope Cloud Explicit Proxy (port 8081 is required)
return "PROXY eproxy-{{tenant}}:8081{{#if direct_fallback}}; DIRECT{{/if}}";
{{/if}}
{{#if mode == "epot"}}
// default: everything else goes to Netskope Explicit Proxy over Tunnel (reserved addresses, port 80 recommended)
return "PROXY 163.116.128.80:80; PROXY 163.116.128.81:80{{#if direct_fallback}}; DIRECT{{/if}}";
{{/if}}
}
Deploying it
Host the file on-premises or on a web server your devices can reach, distribute the URL by GPO,
MDM or WPAD. If the Netskope Client is installed too, remember that it steers at the TCP level:
a DIRECT here bypasses the explicit proxy, not the Client, and any other proxy this file returns
must be declared under Interoperate with Proxy.
What the Netskope pack checks
Netskope ships a PAC template for its Cloud Explicit Proxy that returns
PROXY eproxy-<tenant>:8081
for http and https URLs, bypasses plain hostnames and leaves a commented block for identity-provider
and other exceptions. The explicit proxy accepts HTTP and HTTPS only and relies on the IdP for user
identity, so IdP traffic must go DIRECT. When the Netskope Client is installed as well, it steers at
the TCP level and watches HTTP CONNECT requests to on-premises proxies: a DIRECT in the PAC bypasses
your proxy, not the Client, and any other proxy the PAC returns must be declared under “Interoperate
with Proxy” so that the Client can analyse those requests.- Cloud Explicit Proxy: the browser must use port 8081; only HTTP and HTTPS belong on it.
- Explicit Proxy over Tunnel: 163.116.128.80/81 or epot.goskope.com on port 80 (recommended) or 8080; other protocols and ports are dropped.
- IdP requests must not be sent to Netskope; add the IdP to the PAC exceptions.
- A DIRECT statement at the end of the proxy list is described by Netskope as fail-through when the upstream proxy or tunnel is down; this site caps such files at B unless fail-open is accepted in the settings.
- Netskope Client: proxies the PAC returns, other than Netskope's, must be declared under Interoperate with Proxy.
- PAC-C021Netskope explicit proxy on the wrong port high
- PAC-B013PAC sends traffic to a proxy the Netskope Client may not know low
- PAC-C022Identity provider not excluded from the SSE proxy medium
- PAC-C023Non-HTTP URLs reach a proxy that only accepts HTTP and HTTPS low
- PAC-C026Plain hostnames or private addresses are sent to the cloud proxy medium
- PAC-B014DIRECT in the PAC does not bypass the vendor's agent info
- PAC-B015Selected vendor pack, but the PAC never routes to that vendor info