Die Autokonfigurationsdatei Namens proxy.pac ermöglicht es dem Administrator, über eine zentrale Datei den Zugang zum Internet zu steuern. So können abhängig vom Netzwerk (isInNet), der Domain (dnsDomainIs) oder etwa einer Zeichenfolge (shExpMatch) in der aufgerufenen URL individuelle Regel angewandt werden. Die Herausforderung an einer proxy.pac ist jedoch, dass selbst der kleinste Fehler dazu führt, dass Clients, welche diese Datei verwenden, nicht mehr ins Internet kommen. Zusätzlich kommt erschwerend hinzu, dass es für den Administrator keine GUI gibt, um die Datei zu erstellen oder zu verwalten oder gar zu debuggen.
Aus diesem Grund habe ich mich etwas intensiver mit einem meiner Meinung nach sinnvollen Aufbau einer Proxy.pac Datei beschäftigt, welchen ich nachfolgend Schritt für Schritt erklären werden. Das Ziel war, eine Datei zu erstellen, die sich einfach administrieren lässt, übersichtlich ist, um die Fehleranfälligkeit zu reduzieren, und eine Debuging-Option bietet.
Daher definieren ich zu Beginn einige Variablen. "Version" enthält die fortlaufende Versionsnummer, die im Debugging-Fall angezeigt wird. Dies ermöglicht es später zu erkennen, ob die neue oder noch eine zwischengespeicherte Version vom Browser verwendet wird. "debug" ist die Variable, welche steuert, ob Debug-Meldungen bei der Verarbeitung angezeigt werden sollen oder nicht. Dann folgen mehrere Variablen nach dem Schema "pr_xxx", welche die verschiedenen Proxies darstellen, insofern es mehrere gibt. Die darauf folgenden Variablen werden verwendet, um die Verarbeitungsgeschwindigkeit zu verbessern, da die entsprechenden Funktionen, wie das Auflösen der Zieldomain etc. nur einmal durchgeführt werden müssen.
/////// var definitions /////// // modified by: Christian Scholz Version = "2015-05-30-01"; var debug = 0; var pr_no = "DIRECT"; var pr_server1 = "PROXY server1.suffix.local:8080"; var pr_server2 = "PROXY server2.suffix.local:8080"; var pr_server3 = "PROXY server3.suffix.local:8080"; var str_host = host.toLowerCase(); var target_ip = dnsResolve(str_host); var client_ip = myIpAddress(); var client_ip_ary = client_ip.split(".");
Anschließend erfolgt die Erstellung des Debug-Dialogs, mit einigen Informationen, welche bei der Fehlersuche später helfen sollen.
debugPAC ="PAC Debug Information (" + Version + ")n"; if (debug) { debugPAC +="-----------------------------------n"; debugPAC +="Machine IP: " + client_ip + "n"; debugPAC +="Target-Hostname: " + str_host + "n"; debugPAC +="Target-IP: " + target_ip + "n"; debugPAC +="Domain Levels: " + dnsDomainLevels(str_host) + "n"; if (url.substring(0,5)=="http:") {protocol="http";} else if (url.substring(0,6)=="https:") {protocol="https";} else if (url.substring(0,4)=="ftp:") {protocol="ftp";} else {protocol="Unknown";} debugPAC +="Protocol: " + protocol + "n"; debugPAC +="URL: " + url + "n"; }
Nun folgt der eigentlich Hauptteil. Zuerst wird geprüft, wie viele Domain-Level die aufgerufene Adresse hat. Wird z.B. nur ein Hostname oder Suffix angegeben, wird immer davon ausgegangen, dass sich die Zieladresse im lokalen Netzwerk befindet.
// #0 if (dnsDomainLevels(str_host) == 0) { debugPAC +="Proxy: " + "no (#0 singlename-match)" + "n"; if (debug) {alert(debugPAC);} return pr_no; }
Nun ein Abschnitt mit Adressen, welche immer lokal erreichbar sind.
// #1 if (target_ip == "1.1.1.1" || target_ip == "127.0.0.1") { debugPAC +="Proxy: " + "no #1" + "n"; if (debug) {alert(debugPAC);} return pr_no; }
Befindet sich die Zieldomaine in einer der angegebenen Netze, wird kein Proxy verwendet.
//#2 if (isInNet(target_ip, "10.0.0.0","255.0.0.0") || isInNet(target_ip, "172.10.0","255.255.255.0") || isInNet(target_ip, "192.168.0","255.255.255.0")) { debugPAC +="Proxy: " + "no (#2 net-match)" + "n"; if (debug) {alert(debugPAC);} return pr_no; }
Entspricht einer der Ausdrücke der aufgerufenen URL, oder enthält die URL den Ausdruck, wird ebenfalls kein Proxy verwendet.
// #3 if (shExpMatch(url,"citrix.suffix.local*") || shExpMatch(url,"webserver1.intra.local*")) { debugPAC +="Proxy: " + "no (#3 exp-match)" + "n"; if (debug) {alert(debugPAC);} return pr_no; }
Gehört der Client, welcher die Zielseite aufruft, zu einer der Domains, wird auch kein Proxy verwendet.
// #4 if (dnsDomainIs(str_host, ".suffix.local") || dnsDomainIs(str_host, ".intra.local")) { debugPAC +="Proxy: " + "no (#4 dns-match)" + "n"; if (debug) {alert(debugPAC);} return pr_no; }
Versucht der Client eine FTP-Verbindung aufzubauen, wird eine entsprechende Meldung angezeigt, dass direkte FTP-Verbindungen nicht erlaubt sind, sondern nur FTP-über-HTTP im read-only modus.
// #5 if(url.substring(0, 4) == "ftp:"){ FTPPac ="FTP Verbindungsinformationn"; FTPPac +="-----------------------------------n"; FTPPac +="Sollte die Verbindung zum FTP-Server nicht n"; FTPPac +="funktionieren, verwenden Sie bitte folgende Syntax:n"; FTPPac +="n"; FTPPac +="ftp://<user>:<password>@<host>:<port>/<url-path>n"; {alert(FTPPac);} return pr_server1; }
Nunr folgen mehre Teile, in denen abhängig vom Netz, in dem sich der aufrufende Client befindet, jeweils ein anderer Proxy zurückgegeben wird.
// #6.1 check client IP - Range 1 if (isInNet(client_ip, "10.1.0.0","255.255.0.0") || isInNet(client_ip, "10.2.0.0","255.255.0.0")) { debugPAC +="Proxy: " + "pr_server1 (#6.1 IP - Range 1)" + "n"; if (debug) {alert(debugPAC);} return pr_server1; }
… und sollte bis hierhin keine Regel gepasst haben, gibt es den Fallback-Proxy
// #7 else { debugPAC +="Proxy: " + "pr_server1 (#7 fallback)" + "n"; if (debug) {alert(debugPAC);} return pr_server1; }
Darüber hinaus gibt es noch die Möglichkeit, den Zugriff, Datums-, Zeit– und Wochentag-gesteuert zu konfigurieren.
Proxy.pac Caching (IE)
Nicht alle Browser verhalten sich im Umgang mit der proxy.pac-Datei gleich. Der Internet-Explorer speichert diese z.B. zwischen, was bedeutet, dass ein Schließend und erneutes Öffnen des Browsers nicht automatisch zum Neuladen der proxy.pac führt. Dies kann man jedoch über einen entsprechenden reg-Eintrag deaktivieren.
[HKEY_CURRENT_USERSoftwarePoliciesMicrosoftWindowsCurrentVersionInternet Settings]" EnableAutoProxyResultCache"=dword:00000000"
2 Kommentare
Hi,
vielen Dank für diese Arbeit. War mir eine große Hilfe!
Eintrag ist zwar schon über ein Jahr alt, jedoch vllt. für andere….
In deinem Script ist noch ein „kleiner“ Fehler:
Abschnitt #2, hier fehlen zwei PIPE-Zeichen:
isInNet(target_ip, „172.10.0“,“255.255.255.0″) || <-hier!
Grüße,
Mario
Vielen Dank für den Hinweis. Ich habe den Fehler behoben.
Gruß Christian