PowerShell Proxyerkennung

Bei der Entwicklung von Rimscout sollte ich ermitteln, welche URLs über einen HTTP-Proxy routen und welche am Proxy vorbei gehen. Dabei fallen einige Besonderheiten auf.

Proxy Einstellungen

Wenn Sie ihr Windows System betrachten, dann gibt es mehrere Optionen, einen HTTP-Proxy im Betriebssystem zu konfigurieren.

Die folgenden Einstellungen gelten natürlich nur für Programme, die den Windows Proxy nutzen. Das machen immer mehr Programme aber es gibt durchaus auch eigenständige Konfigurationen.

  • Auto-Konfiguration (WPAD)
    Hierbei versucht der Client per DNS oder DHCP einen Proxy zu finden. Siehe auch WPAD - Proxy im Browser einstellen
  • Kein Proxy
    Wenn Sie den Schieber auf "AUS" stellen und die anderen Einstellungen nicht aktivieren, dann nutzt der Client nie einen Proxy
  • Per Skript
    Sie können statisch ein JavaScript vorgeben, welches abhängig von der URL dann einen passenden Proxy liefert. Das ist quasi eine statische WPAD-Konfiguration
  • Statisch
    Natürlich können Sie manuell oder per Gruppenrichtlinie auch einen Proxy Server und Ausnahmen konfigurieren.
  • app.config bei .NET
    Programme, die auf dem NET-Framework aufsetzen, können auch über Einträge in der machine.config oder app.config mit einem Proxy versehen werden.

Proxy Abfragen

Ob ihr System ein Proxy nutzt oder nicht, ist speziell bei WPAD nicht einfach in einer GUI zu erkennen. Aber Windows bietet natürlich entsprechende Schnittstellen zum Abrufen der Information an. Allerdings gibt habe ich mehrere Aufrufe gefunden, die teils unterschiedliche oder veraltete Ergebnisse liefern:

Methode Beschreibung

CMD-Shell

Per NETSH lässt sich schnell die Proxy-Konfiguration ermitteln

REM Ausgabe aus einer CMD-Shell
netsh winhttp show proxy

DefaultWebProxy

Laut Microsoft wird erst die app.config-Datei und dann der System Proxy gelesen

Ausgabe des "DefaultWebProxy"
[System.Net.WebRequest]::DefaultWebProxy

 

Die DefaultWebProxy -Eigenschaft ruft den globalen Proxy ab oder legt diese fest. Die DefaultWebProxy -Eigenschaft bestimmt den Standardproxy, den alle WebRequest Instanzen verwenden, wenn die Anforderung Proxys unterstützt und kein Proxy explizit mit der Proxy -Eigenschaft festgelegt wird. Proxys werden derzeit von FtpWebRequest und HttpWebRequestunterstützt.
Die DefaultWebProxy -Eigenschaft liest Proxyeinstellungen aus der app.config-Datei. Wenn keine Konfigurationsdatei vorhanden ist, werden die Internet Explorer-Proxyeinstellungen (Internet Explorer, IE) des aktuellen Benutzers verwendet.
Quelle: https://learn.microsoft.com/de-de/dotnet/api/system.net.webrequest.defaultwebproxy?view=net-7.0

SystemWebProxy

Liest nur die Systemeinstellungen und ignoriert eine app.config

Ausgabe des SystemWebProxy
[System.Net.WebRequest]::GetSystemWebproxy()

 

GetSystemWebProxy -Methode liest die Internet Explorer-Proxyeinstellungen (Internet Explorer, IE) des aktuellen Benutzers. Dieser Prozess umfasst die IE-Optionen, um Proxyeinstellungen automatisch zu erkennen, ein automatisches Konfigurationsskript, manuelle Proxyservereinstellungen und erweiterte manuelle Proxyservereinstellungen zu verwenden.
Quelle: https://learn.microsoft.com/de-de/dotnet/api/system.net.webrequest.getsystemwebproxy?view=net-7.0 

Webproxy (Deprectiated)

Diese Funktion ist laut Microsoft abgekündigt und sollte nicht mehr genutzt werden.

In der PowerShell 7 kommt ein Fehler:

PS C:\> [System.Net.Webproxy]::GetDefaultProxy()
MethodInvocationException: Exception calling "GetDefaultProxy" with "0" argument(s): "Operation is not supported on this platform."

In der PowerShell 5.1 auf Basis von NET 2.0 funktioniert es noch

Ausgabe WebProxy Proxy (bis Net 2.0. Depreciated
[System.Net.Webproxy]::GetDefaultProxy() 

Address :
BypassProxyOnLocal : False
BypassList : {}
Credentials :
UseDefaultCredentials : False
BypassArrayList : {}

Beachten Sie, dass die Ausgaben nicht immer in "Echtzeit" aktualisiert werden. Es kann sein, dass neue Proxy-Einstellungen erst nach dem Neustart des Programms aktiviert werden

Wenn ich die beiden PowerShell-Ausgaben mit "ToString()" konvertiere, kommt beide male ein "System.Net.Http.HttpWindowsProxy"-Objekt heraus. Die Werte "scheinen" also auf die gleiche Quelle zuzugreifen.

Proxy für Hostnamen abfragen

Wenn ich für einen einzelnen Host ermitteln möchte, ob die Zugriffe über einen Proxy laufen oder vielleicht daran vorbei geschleust werden, dann helfen folgende Befehle. Ich habe einen statischen Proxy eingetragen und dann abgefragt.

Achtung: Dies funktioniert nur mit PowerShell 7/Core

PS C:\> ([System.Net.WebRequest]::GetSystemWebproxy()).IsBypassed("https://www.rimscout.com/")
False

Diese URL wird nicht per Bypass am Proxy vorbei geroutet. Wenn ich dann einen "GetProxy" mache, dann sehe ich auch den passenden Proxy.

PS C:\> ([System.Net.WebRequest]::GetSystemWebproxy()).getproxy("https://www.rimscout.com/")

AbsolutePath : /
AbsoluteUri : http://127.0.0.1:8080/
LocalPath : /
Authority : 127.0.0.1:8080
HostNameType : IPv4
IsDefaultPort : False
IsFile : False
IsLoopback : True
PathAndQuery : /
Segments : {/}
IsUnc : False
Host : 127.0.0.1
Port : 8080
Query :
Fragment :
Scheme : http
OriginalString : http://127.0.0.1:8080
DnsSafeHost : 127.0.0.1
IdnHost : 127.0.0.1
IsAbsoluteUri : True
UserEscaped : False
UserInfo :

Ich habe das hier mit "Fiddler" auf meinem PC als Proxy nachgestellt. So kann ich vorab prüfen, welchen Proxy für eine gewisse URL aufgerufen wird, wenn ich mich an den Windows Standard-Proxy halte.

Achtung: Bei PowerShell 5 kommt immer ein Proxy-Objekte zurück, auch wenn es keinen Proxy gibt. Der Proxy ist dann die URL

Diese Information sammle ich mit Rimscout gerne ein, um die Konfiguration eines Clients hinsichtlich der Microsoft vorgaben zu überprüfen.

Default Proxy ermitteln

Neben der Anfrage für gewisse URLs, die auch auf Ausnahmen in der Proxy-Konfiguration achten, möchte man vielleicht auch die allgemeine Proxy-Konfiguration ermitteln. Das geht schon immer in der CMD-Shell einfach mit:

netsh winhttp sow proxy

Da die Einstellungen in der Registrierung liegen, können Sie diese natürlich auch dort auslesen, z.B. per PowerShell mit:

Get-ItemProperty -Path "Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings"

Auch per .NET-Klasse können Sie den Proxy ermitteln

[System.Net.WebRequest]::DefaultWebProxy

In der Dokumentation schreibt Microsoft dazu:

Die DefaultWebProxy -Eigenschaft ruft den globalen Proxy ab oder legt diese fest. Die DefaultWebProxy -Eigenschaft bestimmt den Standardproxy, den alle WebRequest Instanzen verwenden, wenn die Anforderung Proxys unterstützt und kein Proxy explizit mit der Proxy -Eigenschaft festgelegt wird. Proxys werden derzeit von FtpWebRequest und HttpWebRequest unterstützt.
Die DefaultWebProxy -Eigenschaft liest Proxyeinstellungen aus der app.config-Datei. Wenn keine Konfigurationsdatei vorhanden ist, werden die Internet Explorer-Proxyeinstellungen (Internet Explorer, IE) des aktuellen Benutzers verwendet.
Wenn die DefaultWebProxy Eigenschaft auf NULL festgelegt ist, verfügen alle nachfolgenden Instanzen der Klasse, die WebRequest mit den Create Methoden oder CreateDefault erstellt wurde, über keinen Proxy.
https://learn.microsoft.com/de-de/dotnet/api/system.net.webrequest.defaultwebproxy?view=net-7.0

Bedenken Sie, dass Änderungen am Proxy nur für danach erstellte Webrequest-Objekte gilt aber bereits instanzierte Objekte noch die bisherige Einstellungen haben.

Proxy im Request überstimmen

Da jedes Webrequest-Objekt ein eigenes Proxy-Property hat, können sie als Entwickler natürlich den Proxy individuell umstellen. Das geht auch mit Invoke-Webrequest

$pass = ConvertTo-SecureString "ProxyPassword" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList "msxfaq\proxyuser", $pass
Invoke-WebRequest `
   -URI "https://www.msxfaq.de" `
   -Proxy "http://proxy.msxfaq.de:3128" `
   -ProxyCredential $cred

Dies ist für Testfälle und Analysen schon mal hilfreich. Ansonsten würde ich aber mich immer an den Systemproxy halten.

Weitere Links