mirror of
https://github.com/Andre-Bzk/tunnler.git
synced 2026-11-15 06:23:04 +01:00
git init
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\chrome.ps1"
|
||||
if errorlevel 1 pause
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\path.ps1"
|
||||
pause
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\tunnel.ps1" start
|
||||
pause
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\tunnel.ps1" status
|
||||
pause
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\tunnel.ps1" stop
|
||||
pause
|
||||
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\codex.ps1" %*
|
||||
@@ -0,0 +1,19 @@
|
||||
# Als config.ps1 speichern und ausfuellen.
|
||||
# config.ps1 enthaelt das Tunnel-Secret: nicht weitergeben, nicht committen.
|
||||
|
||||
# Geheimer Pfad, identisch mit server/restrictions.yaml und der NPM-Location
|
||||
$TunnelSecret = ''
|
||||
$TunnelServer = 'wss://deine-domain.de:443'
|
||||
|
||||
# Lokaler Proxy, auf den Chrome und Codex zeigen
|
||||
$LocalProxy = '127.0.0.1:1080'
|
||||
|
||||
# Firmen-Proxy aus der PAC-Datei, z. B. 'http://proxy.firma.de:8080'.
|
||||
# Leer = direkte Verbindung (zu Hause, Hotspot).
|
||||
$UpstreamProxy = ''
|
||||
$UpstreamProxyUser = ''
|
||||
$UpstreamProxyPassword = ''
|
||||
|
||||
# Nur auf $true setzen, wenn der Firmen-Proxy TLS aufbricht
|
||||
# (Zertifikat der eigenen Domain im Browser nicht von Let's Encrypt).
|
||||
$SkipTlsVerify = $false
|
||||
@@ -0,0 +1,19 @@
|
||||
# Startet den Tunnel (falls noetig) und ein eigenes Chrome-Profil, das komplett
|
||||
# ueber den Tunnel laeuft. Normales Chrome und alle anderen Programme bleiben direkt.
|
||||
. "$PSScriptRoot\common.ps1"
|
||||
|
||||
Start-Tunnel
|
||||
|
||||
$chrome = @(
|
||||
"$env:ProgramFiles\Google\Chrome\Application\chrome.exe",
|
||||
"${env:ProgramFiles(x86)}\Google\Chrome\Application\chrome.exe",
|
||||
"$env:LOCALAPPDATA\Google\Chrome\Application\chrome.exe"
|
||||
) | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
if (-not $chrome) { throw "chrome.exe nicht gefunden." }
|
||||
|
||||
$profileDir = Join-Path $ClientDir 'chrome-profile'
|
||||
Start-Process -FilePath $chrome -ArgumentList @(
|
||||
"--proxy-server=$ProxyUrl",
|
||||
"--user-data-dir=`"$profileDir`"",
|
||||
'--no-first-run'
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
# Startet den Tunnel (falls noetig) und Codex mit Proxy-Variablen nur fuer diesen Aufruf.
|
||||
# Alle Argumente werden an codex durchgereicht.
|
||||
. "$PSScriptRoot\common.ps1"
|
||||
|
||||
Start-Tunnel
|
||||
|
||||
$names = 'HTTPS_PROXY', 'HTTP_PROXY', 'NO_PROXY'
|
||||
$saved = @{}
|
||||
foreach ($n in $names) { $saved[$n] = [Environment]::GetEnvironmentVariable($n, 'Process') }
|
||||
try {
|
||||
$env:HTTPS_PROXY = $ProxyUrl
|
||||
$env:HTTP_PROXY = $ProxyUrl
|
||||
$env:NO_PROXY = 'localhost,127.0.0.1'
|
||||
& codex @args
|
||||
} finally {
|
||||
foreach ($n in $names) { [Environment]::SetEnvironmentVariable($n, $saved[$n], 'Process') }
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
# Gemeinsame Funktionen fuer die Tunnel-Skripte. Wird per Dot-Sourcing geladen.
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ClientDir = Split-Path $PSScriptRoot -Parent
|
||||
$ConfigPath = Join-Path $ClientDir 'config.ps1'
|
||||
if (-not (Test-Path $ConfigPath)) {
|
||||
throw "config.ps1 fehlt. config.example.ps1 nach config.ps1 kopieren und ausfuellen."
|
||||
}
|
||||
. $ConfigPath
|
||||
|
||||
$WstunnelVersion = '11.1.0' # passend zum Server-Image in server/docker-compose.yml
|
||||
$Exe = Join-Path $ClientDir 'bin\wstunnel.exe'
|
||||
$LogDir = Join-Path $ClientDir 'logs'
|
||||
$ProxyUrl = "http://$LocalProxy"
|
||||
|
||||
function Get-TunnelArgs([string]$LogLevel) {
|
||||
$tunnelArgs = @('client', '-L', "http://$LocalProxy", '-c', '2', '--log-lvl', $LogLevel)
|
||||
if (-not $SkipTlsVerify) { $tunnelArgs += '--tls-verify-certificate' }
|
||||
if ($UpstreamProxy) { $tunnelArgs += @('--http-proxy', $UpstreamProxy) }
|
||||
if ($UpstreamProxyUser) { $tunnelArgs += @('--http-proxy-login', $UpstreamProxyUser) }
|
||||
$tunnelArgs += $TunnelServer
|
||||
return $tunnelArgs
|
||||
}
|
||||
|
||||
# Secret und Proxy-Passwort gehen per Umgebung an wstunnel, damit sie nicht in
|
||||
# der Kommandozeile stehen (Prozesslisten, EDR-Protokolle). HTTP_PROXY wird
|
||||
# entfernt, weil wstunnel es sonst als Upstream-Proxy uebernimmt. NO_COLOR liest
|
||||
# wstunnel ebenfalls und akzeptiert nur true/false (ein gesetztes NO_COLOR=1 bricht den Start).
|
||||
function Invoke-WithTunnelEnv([scriptblock]$Action) {
|
||||
$names = 'WSTUNNEL_HTTP_UPGRADE_PATH_PREFIX', 'WSTUNNEL_HTTP_PROXY_PASSWORD', 'HTTP_PROXY', 'NO_COLOR'
|
||||
$saved = @{}
|
||||
foreach ($n in $names) { $saved[$n] = [Environment]::GetEnvironmentVariable($n, 'Process') }
|
||||
try {
|
||||
$env:NO_COLOR = 'true'
|
||||
$env:WSTUNNEL_HTTP_UPGRADE_PATH_PREFIX = $TunnelSecret
|
||||
if ($UpstreamProxyPassword) { $env:WSTUNNEL_HTTP_PROXY_PASSWORD = $UpstreamProxyPassword }
|
||||
Remove-Item Env:HTTP_PROXY -ErrorAction SilentlyContinue
|
||||
& $Action
|
||||
} finally {
|
||||
foreach ($n in $names) { [Environment]::SetEnvironmentVariable($n, $saved[$n], 'Process') }
|
||||
}
|
||||
}
|
||||
|
||||
function Test-TunnelListening {
|
||||
$parts = $LocalProxy.Split(':')
|
||||
$client = New-Object System.Net.Sockets.TcpClient
|
||||
try { $client.Connect($parts[0], [int]$parts[1]); return $true }
|
||||
catch { return $false }
|
||||
finally { $client.Close() }
|
||||
}
|
||||
|
||||
function Get-TunnelProcess {
|
||||
Get-Process wstunnel -ErrorAction SilentlyContinue | Where-Object { $_.Path -eq $Exe }
|
||||
}
|
||||
|
||||
# wstunnel.exe liegt nicht im Repo. Beim ersten Start wird das offizielle Release
|
||||
# geladen und gegen die checksums.txt des Releases geprueft.
|
||||
function Install-Wstunnel {
|
||||
if (Test-Path $Exe) { return }
|
||||
$base = "https://github.com/erebe/wstunnel/releases/download/v$WstunnelVersion"
|
||||
$archiveName = "wstunnel_${WstunnelVersion}_windows_amd64.tar.gz"
|
||||
$tmp = Join-Path ([IO.Path]::GetTempPath()) "tunnler-$([guid]::NewGuid())"
|
||||
New-Item -ItemType Directory -Force $tmp | Out-Null
|
||||
$oldProgress = $ProgressPreference
|
||||
try {
|
||||
Write-Host "Lade wstunnel $WstunnelVersion ..."
|
||||
$ProgressPreference = 'SilentlyContinue' # sonst ist Invoke-WebRequest in PS 5.1 sehr langsam
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
$archive = Join-Path $tmp $archiveName
|
||||
$sums = Join-Path $tmp 'checksums.txt'
|
||||
Invoke-WebRequest "$base/$archiveName" -OutFile $archive -UseBasicParsing
|
||||
Invoke-WebRequest "$base/checksums.txt" -OutFile $sums -UseBasicParsing
|
||||
$line = Get-Content $sums | Where-Object { $_ -match "\s$([regex]::Escape($archiveName))$" }
|
||||
if (-not $line) { throw "$archiveName fehlt in checksums.txt." }
|
||||
if ((Get-FileHash $archive -Algorithm SHA256).Hash -ne ($line -split '\s+')[0]) {
|
||||
throw "Pruefsumme von $archiveName stimmt nicht. Download verworfen."
|
||||
}
|
||||
& "$env:SystemRoot\System32\tar.exe" -xzf $archive -C $tmp wstunnel.exe
|
||||
if ($LASTEXITCODE -ne 0) { throw "Entpacken von $archiveName fehlgeschlagen." }
|
||||
New-Item -ItemType Directory -Force (Split-Path $Exe) | Out-Null
|
||||
Move-Item (Join-Path $tmp 'wstunnel.exe') $Exe
|
||||
} finally {
|
||||
$ProgressPreference = $oldProgress
|
||||
Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
# Startet den Client unsichtbar im Hintergrund, falls er noch nicht laeuft.
|
||||
function Start-Tunnel {
|
||||
if (-not $TunnelSecret) { throw "TunnelSecret in config.ps1 ist leer." }
|
||||
if (Test-TunnelListening) { return }
|
||||
Install-Wstunnel
|
||||
New-Item -ItemType Directory -Force $LogDir | Out-Null
|
||||
$log = Join-Path $LogDir 'wstunnel.log'
|
||||
Invoke-WithTunnelEnv {
|
||||
Start-Process -FilePath $Exe -ArgumentList (Get-TunnelArgs 'WARN') -WindowStyle Hidden `
|
||||
-RedirectStandardOutput $log -RedirectStandardError (Join-Path $LogDir 'wstunnel.err.log')
|
||||
}
|
||||
for ($i = 0; $i -lt 20; $i++) {
|
||||
if (Test-TunnelListening) { return }
|
||||
Start-Sleep -Milliseconds 250
|
||||
}
|
||||
throw "Tunnel-Client lauscht nicht auf $LocalProxy. Details: $log"
|
||||
}
|
||||
|
||||
function Stop-Tunnel {
|
||||
Get-TunnelProcess | Stop-Process -Force
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Traegt den Client-Ordner in den Benutzer-PATH ein, damit 'codexx' in jedem Terminal geht.
|
||||
# Der PATH wird roh aus der Registry gelesen, damit Eintraege wie %USERPROFILE%\... nicht
|
||||
# beim Zurueckschreiben fest aufgeloest werden.
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ClientDir = Split-Path $PSScriptRoot -Parent
|
||||
|
||||
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true)
|
||||
try {
|
||||
$raw = $key.GetValue('Path', '', 'DoNotExpandEnvironmentNames')
|
||||
if (($raw -split ';' | ForEach-Object { $_.TrimEnd('\') }) -contains $ClientDir.TrimEnd('\')) {
|
||||
Write-Host "$ClientDir steht schon im PATH."
|
||||
return
|
||||
}
|
||||
$key.SetValue('Path', (($raw.TrimEnd(';') + ";$ClientDir").TrimStart(';')), 'ExpandString')
|
||||
} finally {
|
||||
$key.Close()
|
||||
}
|
||||
|
||||
# Explorer ueber die Aenderung informieren, sonst sehen neu gestartete Programme sie erst nach einer Neuanmeldung
|
||||
Add-Type -Namespace Tunnler -Name Native -MemberDefinition '[DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern IntPtr SendMessageTimeout(IntPtr h, uint m, UIntPtr w, string l, uint f, uint t, out UIntPtr r);'
|
||||
$result = [UIntPtr]::Zero
|
||||
[Tunnler.Native]::SendMessageTimeout([IntPtr]0xffff, 0x1A, [UIntPtr]::Zero, 'Environment', 2, 5000, [ref]$result) | Out-Null
|
||||
|
||||
Write-Host "$ClientDir in den PATH eingetragen."
|
||||
Write-Host "VS Code und offene Terminals komplett neu starten, dann 'codexx' statt 'codex' eingeben."
|
||||
@@ -0,0 +1,31 @@
|
||||
# Tunnel-Client verwalten.
|
||||
# tunnel.ps1 start Client im Hintergrund starten, Proxy fuer beliebige Programme
|
||||
# tunnel.ps1 status laeuft der Client, und welche IP sieht das Internet?
|
||||
# tunnel.ps1 stop Client beenden
|
||||
# tunnel.ps1 run Client im Vordergrund mit ausfuehrlichem Log (Fehlersuche)
|
||||
param([ValidateSet('start', 'status', 'stop', 'run')][string]$Action = 'status')
|
||||
. "$PSScriptRoot\common.ps1"
|
||||
|
||||
switch ($Action) {
|
||||
'start' {
|
||||
Start-Tunnel
|
||||
Write-Host "Tunnel laeuft. In den gewuenschten Programmen als HTTP-Proxy eintragen: $LocalProxy"
|
||||
Write-Host "Beenden mit Tunnel-Stop.cmd."
|
||||
}
|
||||
'status' {
|
||||
if (-not (Test-TunnelListening)) { Write-Host "Tunnel laeuft nicht."; break }
|
||||
Write-Host "Tunnel lauscht auf $LocalProxy."
|
||||
$ip = & curl.exe -s -m 15 -x $ProxyUrl https://api.ipify.org
|
||||
if ($LASTEXITCODE -eq 0) { Write-Host "Oeffentliche IP ueber den Tunnel: $ip" }
|
||||
else { Write-Host "Keine Verbindung durch den Tunnel. Log: $(Join-Path $LogDir 'wstunnel.log')" }
|
||||
}
|
||||
'stop' {
|
||||
Stop-Tunnel
|
||||
Write-Host "Tunnel beendet."
|
||||
}
|
||||
'run' {
|
||||
Stop-Tunnel
|
||||
Install-Wstunnel
|
||||
Invoke-WithTunnelEnv { & $Exe @(Get-TunnelArgs 'INFO') }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user