Blog 73

Entwicklung und mehr.

09.03.2024, 00:48 Uhr

Kann man ein ProxyScript deklarativ erstellen?

Ich habe in letzter Zeit beruflich viel mit der Erzeugung und Anpassung von PAC-Dateien zu tun.
Wikipedia: Proxy auto-config

Grundsätzlich ist es dabei schon einmal eine gute Idee, wenn man die PAC-Dateien in einem Repository ablegt, sodass man Änderungen nachvollziehen kann.

Noch besser ist es, wenn man sie vor dem Einsatz testet. Beispielsweise mit Python und PyPAC

Nun hab ich mich aber gefragt, ob man das ProxyScript auch aus einer Deklaration heraus erstellen könnte, beispielsweise mit einer YAML-Datei. Das hätte den Vorteil, dass Kollegen die Ausnahmen leichter pflegen können. Sie müssten dafür kein JavaScript mehr verstehen.

Da ich Python mag, habe ich genau das mal mit Python versucht. Zu finden ist der Code bei Github. https://github.com/73h/pypacer

Eine YAML-Datei sieht nun beispielsweise so aus. Man erfasst die Proxies und die entsprechenden Ziele. Dann benötigt man noch einen Default-Proxy und den Rest macht Python.

example.yaml:
description: My proxy script version: 1.0 proxies: - description: take the direct route route: DIRECT tags: - default # default proxy targets: - .example.com - description: take the proxy route route: PROXY company.example.com targets: - example.com - foo.example.com - 93.184.0.0/16

Mit wenigen Zeilen Python, kann man nun den Inhalt der PAC-Datei erzeugen.

import os from pypacer import PyPacer p = PyPacer() with open(os.path.join("example.yaml"), "r") as f: p.load_from_yaml(f.read()) print(p.output())

Und das Ergebnis sieht dann so aus. Das geschulte Auge erkennt vielleicht die Besonderheit, dass es eine Überschneidung der Ziele gibt. Das wird sogar beachtet und entsprechend umsortiert. So ist die Bedingung auf .example.com nach unten gerutscht. Würde sie als erstes kommen, würde sie auch foo.example.com schlucken. Auch die Übersetzung der Netzmaske 93.184.0.0/16 erleichtert die Pflege.

Das Ergebnis - example.pac:
function FindProxyForURL(url, host) { host = host.toLowerCase(); if ( localHostOrDomainIs(host, "example.com") || localHostOrDomainIs(host, "foo.example.com") || isInNet(host, "93.184.0.0", "255.255.0.0") ) { return "PROXY company.example.com"; } if ( dnsDomainIs(host, ".example.com") ) { return "DIRECT"; } return "DIRECT"; }

Mein Fazit nach ein paar Stunden Arbeit. Es geht und ich werde den Ansatz weiter verfolgen. Klar ist aber auch, das man hier nicht alles oder jede Varianz abbilden kann. Dennoch wird es für die meisten Proxy-Skripte reichen denke ich.