# ========================= # Configuration du script # ========================= Set-StrictMode -Version Latest $script:DebugEnabled = $false $script:ConfigFile = Join-Path $PSScriptRoot "socks-browser.config.psd1" $script:LogFile = Join-Path $env:TEMP "socks-browser.log" # ========================= # Fonction de journalisation # ========================= function Write-DebugLog { param ( [Parameter(Mandatory)] [string]$Message ) if (-not $script:DebugEnabled) { return } $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logEntry = "[DEBUG $timestamp] $Message" # Affiche à l'écran Write-Host $logEntry -ForegroundColor DarkGray # Écrit dans le fichier de log (dans %TEMP%) try { $logEntry | Out-File -FilePath $script:LogFile -Encoding UTF8 -Append -ErrorAction SilentlyContinue } catch { # Ignore les erreurs d'écriture (ex: droits, disque plein) } } # ========================= # Fonctions principales # ========================= function Get-Configuration { if (-not (Test-Path $script:ConfigFile)) { throw "Fichier de configuration introuvable : $script:ConfigFile" } $config = Import-PowerShellDataFile $script:ConfigFile $requiredKeys = @( "SshExe", "AskPassExe", "HostAlias", "LocalPort", "BrowserExe", "BrowserProcessName" ) foreach ($key in $requiredKeys) { if (-not $config.ContainsKey($key) -or [string]::IsNullOrWhiteSpace($config[$key])) { throw "Valeur de configuration manquante ou vide : $key" } } return $config } function Test-PortAvailable { param ([int]$Port) $existing = Get-NetTCPConnection -LocalPort $Port -State Listen -ErrorAction SilentlyContinue return (-not $existing) } function Start-SshTunnel { param ( [string]$SshExe, [int]$LocalPort, [string]$HostAlias, [string]$AskPassExe ) $env:SSH_ASKPASS = $AskPassExe $env:SSH_ASKPASS_REQUIRE = "force" $env:DISPLAY = "dummy" Write-DebugLog "Démarrage du tunnel SSH : ssh -N -D $LocalPort $HostAlias" Start-Process $SshExe -ArgumentList "-N -D $LocalPort $HostAlias" -WindowStyle Hidden for ($attempt = 0; $attempt -lt 10; $attempt++) { if (Get-NetTCPConnection -LocalPort $LocalPort -State Listen -ErrorAction SilentlyContinue) { Write-DebugLog "Le tunnel SSH écoute sur le port $LocalPort" return $true } Start-Sleep 1 } return $false } function Stop-SshTunnelByPort { param ([int]$LocalPort) Write-DebugLog "Arrêt du tunnel SSH sur le port $LocalPort" $sshProcessIds = Get-NetTCPConnection -LocalPort $LocalPort -State Listen -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess -Unique foreach ($sshPid in $sshProcessIds) { try { $proc = Get-Process -Id $sshPid -ErrorAction Stop if ($proc.ProcessName -eq "ssh") { Write-DebugLog "Arrêt du processus SSH PID $sshPid" Stop-Process -Id $sshPid -ErrorAction SilentlyContinue } } catch {} } for ($attempt = 0; $attempt -lt 5; $attempt++) { if (-not (Get-NetTCPConnection -LocalPort $LocalPort -State Listen -ErrorAction SilentlyContinue)) { break } Start-Sleep 1 } } function Create-TemporaryBrowserProfile { param ([int]$LocalPort) $tempProfile = Join-Path $env:TEMP ("browser-socks-" + [guid]::NewGuid()) New-Item -ItemType Directory -Path $tempProfile | Out-Null $userJs = @" user_pref("network.proxy.type", 1); user_pref("network.proxy.socks", "127.0.0.1"); user_pref("network.proxy.socks_port", $LocalPort); user_pref("network.proxy.socks_version", 5); user_pref("network.proxy.socks_remote_dns", true); user_pref("network.proxy.no_proxies_on", ""); user_pref("network.proxy.allow_hijacking_localhost", false); user_pref("network.trr.mode", 3); user_pref("network.trr.uri", "https://hard.dnsforge.de/dns-query "); user_pref("network.trr.bootstrapAddress", "88.198.122.154"); user_pref("network.trr.confirmationNS", ""); user_pref("media.peerconnection.enabled", false); user_pref("media.peerconnection.ice.default_address_only", true); user_pref("media.peerconnection.ice.no_host", true); user_pref("geo.enabled", false); user_pref("geo.provider.network.url", ""); user_pref("geo.provider.ms-windows-location", false); user_pref("geo.provider.use_corelocation", false); user_pref("geo.provider.use_gpsd", false); user_pref("browser.search.suggest.enabled", false); user_pref("browser.urlbar.suggest.searches", false); user_pref("toolkit.telemetry.enabled", false); user_pref("datareporting.healthreport.uploadEnabled", false); user_pref("browser.ping-centre.telemetry", false); user_pref("browser.tabs.loadInBackground", false); user_pref("privacy.resistFingerprinting", true); user_pref("privacy.trackingprotection.enabled", true); user_pref("privacy.trackingprotection.pbmode.enabled", true); user_pref("plugin.state.flash", 0); user_pref("plugin.state.java", 0); user_pref("browser.privatebrowsing.autostart", true); user_pref("signon.rememberSignons", false); user_pref("browser.formfill.enable", false); user_pref("browser.sessionstore.resume_from_crash", false); user_pref("browser.sessionstore.max_tabs_undo", 0); user_pref("browser.sessionstore.max_windows_undo", 0); user_pref("browser.cache.disk.enable", false); user_pref("browser.cache.disk.capacity", 0); user_pref("browser.cache.disk.smart_size.enabled", false); user_pref("browser.cache.offline.enable", false); user_pref("app.update.auto", false); user_pref("app.update.enabled", false); user_pref("extensions.autoDisableScopes", 15); user_pref("extensions.enabledScopes", 0); user_pref("browser.privateWindowSeparation.enabled", true); user_pref("browser.aboutwelcome.enabled", false); user_pref("startup.homepage_welcome_url", ""); user_pref("startup.homepage_welcome_url.additional", ""); "@ Set-Content -Path (Join-Path $tempProfile "user.js") -Value $userJs -Encoding ASCII Write-DebugLog "Profil temporaire créé : $tempProfile" return $tempProfile } function Launch-BrowserAndWaitForInstance { param ( [string]$BrowserExe, [string]$BrowserProcessName, [string]$ProfilePath ) $existingProcessIds = Get-Process -Name $BrowserProcessName -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Id Write-DebugLog "Lancement du navigateur avec profil temporaire" Start-Process $BrowserExe -ArgumentList "--no-remote --private-window --profile `"$ProfilePath`"" -WindowStyle Hidden for ($attempt = 0; $attempt -lt 15; $attempt++) { Start-Sleep 1 $currentProcessIds = Get-Process -Name $BrowserProcessName -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Id $newProcessIds = $currentProcessIds | Where-Object { $_ -notin $existingProcessIds } if ($newProcessIds) { $tempBrowserProcessId = $newProcessIds | Select-Object -First 1 Write-DebugLog "Instance temporaire détectée (PID $tempBrowserProcessId)" return $tempBrowserProcessId } } throw "Impossible de détecter l'instance temporaire du navigateur" } function Wait-ForProcessExit { param ([int]$ProcessId) while (Get-Process -Id $ProcessId -ErrorAction SilentlyContinue) { Start-Sleep 1 } } function Remove-TemporaryProfile { param ([string]$ProfilePath) for ($attempt = 0; $attempt -lt 5; $attempt++) { try { if (Test-Path $ProfilePath) { Remove-Item -Recurse -Force $ProfilePath -ErrorAction Stop } break } catch { Start-Sleep 1 } } } # ========================= # Orchestrateur principal # ========================= try { # Ajouter une ligne de séparation dans le log à chaque exécution if ($script:DebugEnabled) { $separator = "=" * 60 $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" "[$timestamp] SESSION START" | Out-File -FilePath $script:LogFile -Encoding UTF8 -Append -ErrorAction SilentlyContinue $separator | Out-File -FilePath $script:LogFile -Encoding UTF8 -Append -ErrorAction SilentlyContinue } if (-not (Test-PortAvailable -Port $config.LocalPort)) { $ownerPid = (Get-NetTCPConnection -LocalPort $config.LocalPort -State Listen).OwningProcess $ownerProc = Get-Process -Id $ownerPid -ErrorAction SilentlyContinue $procName = if ($ownerProc) { "$($ownerProc.Name) (PID $ownerPid)" } else { "PID $ownerPid" } throw "Le port $($config.LocalPort) est déjà utilisé par $procName" } if (-not (Start-SshTunnel -SshExe $config.SshExe -LocalPort $config.LocalPort -HostAlias $config.HostAlias -AskPassExe $config.AskPassExe)) { throw "Échec de l'établissement du tunnel SSH" } Write-Output "Tunnel SSH actif sur 127.0.0.1:$($config.LocalPort)" $tempProfile = Create-TemporaryBrowserProfile -LocalPort $config.LocalPort $browserProcessId = Launch-BrowserAndWaitForInstance -BrowserExe $config.BrowserExe -BrowserProcessName $config.BrowserProcessName -ProfilePath $tempProfile Write-Output "Instance temporaire du navigateur détectée (PID $browserProcessId)" Wait-ForProcessExit -ProcessId $browserProcessId Write-Output "Navigateur temporaire fermé" Remove-TemporaryProfile -ProfilePath $tempProfile Stop-SshTunnelByPort -LocalPort $config.LocalPort Write-Output "Tunnel SSH arrêté proprement" } catch { $errorMessage = "ERREUR: $($_.Exception.Message)" Write-Error $errorMessage # Journaliser aussi l'erreur dans le fichier if ($script:DebugEnabled) { $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" "[$timestamp] $errorMessage" | Out-File -FilePath $script:LogFile -Encoding UTF8 -Append -ErrorAction SilentlyContinue } exit 1 }