Overview
The Timus Connect Troubleshooter collects a comprehensive endpoint and network diagnostic snapshot required by Timus Support and Engineering teams to perform accurate and efficient root cause analysis.
The data gathered through this process enables investigation of:
Authentication failures
Tunnel instability
DNS resolution issues
Degraded performance
Local agent errors
By collecting a standardized dataset, we eliminate guesswork and significantly reduce time to resolution.
Collection Options
You may collect diagnostics in one of the following ways:
Option 1 – Automated Script (Recommended)
Run the provided PowerShell script as administrator to automatically collect all required diagnostics.
The script:
Collects all system and network diagnostics
Runs MTU and connectivity tests
Performs DNS and HTTP validation
Executes iPerf3 performance testing
Gathers firewall, disk, process, and event data
Organizes outputs into a structured folder automatically
Timus Connect Troubleshooter – How to Run (Windows)
1️⃣ Create the Script File
Open Notepad.
Copy the full script.
Paste it into Notepad.
Click File → Save As.
Set:
-
File name:
timus.ps1
Save as type: All Files
Encoding: UTF-8
Save it (Desktop is recommended).
2️⃣ Open PowerShell as Administrator
Right-click Start
Select PowerShell (Run as Administrator)
Administrator rights are required for network and system diagnostics.
3️⃣ Set Temporary Execution Policy
Run:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
This change applies only to the current PowerShell session.
4️⃣ Navigate to the Script Location
If saved on Desktop:
cd $env:USERPROFILE\Desktop
Or use the full path:
cd C:\Users\YourUsername\Desktop
5️⃣ Run the Script
.\timus.ps1
Here is the script:
# Timus Connect Troubleshooter - Windows
# Created: 1/7/2026
# Last Modified: 1/19/2026
# PowerShell Run as Administrator
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
Add-Type -AssemblyName System.Windows.Forms
# ==========================================================
# CONFIG / CONSTANTS
# ==========================================================
$ScriptName = "Timus Connect Troubleshooter"
$CreatedDate = "1/7/2026"
# iPerf3
$iperfUrl = "https://files.budman.pw/?file=iperf3.20_64.zip"
$tmpDir = "C:\tmp"
$zipFileName = "iperf3.zip"
# Ping packet sizes
$packetSizes = 1420,1410,1400,1390,1380,1370,1360,1350,1340,1330,1320,1310,1300,1290,1280
# DNS/CURL targets
$domains = @(
"auth.timuscloud.com",
"user.timuscloud.com",
"device.timuscloud.com",
"config.timuscloud.com",
"my.timusnetworks.com",
"localhost"
)
$urls = @(
"https://auth.timuscloud.com",
"https://user.timuscloud.com",
"https://device.timuscloud.com",
"https://config.timuscloud.com",
"https://my.timusnetworks.com",
"http://localhost:49202",
"http://localhost:49204",
"http://localhost:49202/device/info",
"http://localhost:49202/vpn/state"
)
# iPerf3 regions (edit freely)
$regions = @(
@{ Key="1"; Name="Ashburn (US)"; Host="ash.speedtest.clouvider.net"; TcpPort="5200"; UdpPort="5201" },
@{ Key="2"; Name="Frankfurt (DE)"; Host="fra.speedtest.clouvider.net"; TcpPort="5200"; UdpPort="5201" },
@{ Key="3"; Name="Amsterdam (NL)"; Host="ams.speedtest.clouvider.net"; TcpPort="5200"; UdpPort="5201" },
@{ Key="4"; Name="London (UK)"; Host="lon.speedtest.clouvider.net"; TcpPort="5200"; UdpPort="5201" }
)
# iPerf3 retry behavior
$iperfMaxAttempts = 5
$iperfBusyMaxRetries = 5
$iperfBusySleepSec = 5
$iperfAttemptSleepSec = 5
# Download retry
$downloadMaxRetries = 3
$downloadTimeoutSec = 60
$downloadRetrySleep = 5
# Event log filter
$eventLogMaxEvents = 50
$eventLogPattern = "VPN|Network"
# ==========================================================
# HELPERS (functions)
# ==========================================================
function Write-StepHeader {
param(
[Parameter(Mandatory=$true)][string]$StepId,
[Parameter(Mandatory=$true)][string]$Title
)
Write-Host ""
Write-Host ("[{0}] START: {1}" -f $StepId, $Title) -ForegroundColor Cyan
}
function Write-StepOk {
param(
[Parameter(Mandatory=$true)][string]$StepId,
[Parameter(Mandatory=$true)][string]$Title
)
Write-Host ("[{0}] COMPLETED: {1}" -f $StepId, $Title) -ForegroundColor Green
}
function Write-StepFail {
param(
[Parameter(Mandatory=$true)][string]$StepId,
[Parameter(Mandatory=$true)][string]$Title,
[Parameter(Mandatory=$true)][string]$Message
)
Write-Host ("[{0}] FAILED: {1} -> {2}" -f $StepId, $Title, $Message) -ForegroundColor Red
}
function Ensure-Directory {
param([Parameter(Mandatory=$true)][string]$Path)
if (-not (Test-Path $Path)) { New-Item -ItemType Directory -Path $Path | Out-Null }
}
function Test-IPv4 {
param([string]$ip)
return ($ip -match '^(\d{1,3}\.){3}\d{1,3}$')
}
# ==========================================================
# Region menu: only 1/2/3/4; retry on invalid; hard-fail after iperf3MaxInvalid
# ==========================================================
function Show-IperfRegionMenu {
param([array]$RegionList)
$iperf3MaxInvalid = 5
$invalidCount = 0
while ($true) {
Write-Host ""
Write-Host "Select iPerf3 region:" -ForegroundColor Cyan
foreach ($r in $RegionList) {
if ($r.Key -match '^[1-4]$') {
Write-Host (" [{0}] {1} ({2})" -f $r.Key, $r.Name, $r.Host)
}
}
Write-Host ""
Write-Host "Press 1/2/3/4..." -ForegroundColor Yellow
$k = [System.Console]::ReadKey($true).KeyChar.ToString().ToUpperInvariant()
# Invalid selection -> retry
if ($k -notmatch '^[1-4]$') {
$invalidCount++
Write-Host ""
Write-Host "Invalid region selection." -ForegroundColor Red
Write-Host "Please select a valid region (1-4). Choose the region closest to you for best results." -ForegroundColor Yellow
$remaining = $iperf3MaxInvalid - $invalidCount
if ($remaining -gt 0) {
Write-Host ("Remaining attempts: {0}" -f $remaining) -ForegroundColor Yellow
Start-Sleep -Seconds 2
continue
}
throw "Region selection failed after $iperf3MaxInvalid invalid attempts. The script could not reliably collect test data."
}
$match = $RegionList | Where-Object { $_.Key -eq $k } | Select-Object -First 1
if ($null -ne $match) {
return @($match)
}
# Safety net (should not happen)
$invalidCount++
Write-Host ""
Write-Host "Selected region is not available. Please try again." -ForegroundColor Red
$remaining2 = $iperf3MaxInvalid - $invalidCount
if ($remaining2 -gt 0) {
Write-Host ("Remaining attempts: {0}" -f $remaining2) -ForegroundColor Yellow
Start-Sleep -Seconds 2
continue
}
throw "Region selection failed after $iperf3MaxInvalid invalid attempts. The script could not reliably collect test data."
}
}
function Invoke-IperfCommandWithBusyRetry {
param(
[Parameter(Mandatory=$true)][string]$IperfDir,
[Parameter(Mandatory=$true)][string[]]$Cmd,
[Parameter(Mandatory=$true)][string]$LogFile,
[Parameter(Mandatory=$false)][int]$BusyMaxRetries = 5,
[Parameter(Mandatory=$false)][int]$BusySleepSeconds = 5
)
if (-not $Cmd -or $Cmd.Count -lt 1 -or [string]::IsNullOrWhiteSpace($Cmd[0])) {
"ERROR: Cmd is empty/invalid. Cmd = '$($Cmd -join ' ')'" | Out-File $LogFile -Append -Encoding UTF8
return @{ ExitCode = 9999; BusyExhausted = $false }
}
$busyTry = 0
while ($true) {
Push-Location $IperfDir
try {
$exe = $Cmd[0]
$args = @()
if ($Cmd.Count -gt 1) { $args = $Cmd[1..($Cmd.Count-1)] }
$output = & $exe @args 2>&1
$exit = $LASTEXITCODE
} finally {
Pop-Location
}
$output | Tee-Object -FilePath $LogFile -Append
$text = ($output | Out-String)
if ($text -match "server is busy running a test") {
$busyTry++
("iPerf3 server busy. Waiting {0} seconds (busy retry {1}/{2})..." -f $BusySleepSeconds, $busyTry, $BusyMaxRetries) |
Out-File $LogFile -Append -Encoding UTF8
if ($busyTry -ge $BusyMaxRetries) { return @{ ExitCode = $exit; BusyExhausted = $true } }
Start-Sleep -Seconds $BusySleepSeconds
continue
}
return @{ ExitCode = $exit; BusyExhausted = $false }
}
}
function Get-IperfTestsForRegion {
param($region, [string]$IperfExe)
return @(
@{Name="TCP Download"; Cmd=@($IperfExe,"-c",$region.Host,"-p",$region.TcpPort,"-t","10","-P","8","-R")},
@{Name="TCP Upload"; Cmd=@($IperfExe,"-c",$region.Host,"-p",$region.TcpPort,"-t","10","-P","8")},
@{Name="UDP Download"; Cmd=@($IperfExe,"-c",$region.Host,"-p",$region.UdpPort,"-t","10","-u","-b","1000M","-R")},
@{Name="UDP Upload"; Cmd=@($IperfExe,"-c",$region.Host,"-p",$region.UdpPort,"-t","10","-u","-b","1000M")}
)
}
# ==========================================================
# STEP 0: Folder selection
# ==========================================================
Write-StepHeader -StepId "0" -Title "Select output folder"
try {
$folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$folderBrowser.Description = "Select folder to save output files"
$folderBrowser.ShowNewFolderButton = $true
$dialogResult = $folderBrowser.ShowDialog()
if ($dialogResult -ne [System.Windows.Forms.DialogResult]::OK) { throw "User cancelled folder selection." }
$opath = $folderBrowser.SelectedPath
$savePath = Join-Path $opath $ScriptName
if (Test-Path $savePath) {
Write-Host "Existing folder detected. Clearing contents..."
Remove-Item "$savePath\*" -Recurse -Force -ErrorAction Stop
} else {
New-Item -ItemType Directory -Path $savePath -ErrorAction Stop | Out-Null
}
Write-StepOk -StepId "0" -Title "Select output folder"
} catch {
Write-StepFail -StepId "0" -Title "Select output folder" -Message $_.Exception.Message
exit
}
# ==========================================================
# STEP 0.5: iPerf3 download + extract
# ==========================================================
Write-StepHeader -StepId "0.5" -Title "Download and extract iPerf3"
try {
Ensure-Directory -Path $tmpDir
$zipFile = Join-Path $tmpDir $zipFileName
$success = $false
for ($i = 1; $i -le $downloadMaxRetries; $i++) {
try {
Write-Host ("Downloading iPerf3 (attempt {0} of {1})..." -f $i, $downloadMaxRetries)
Invoke-WebRequest -Uri $iperfUrl -OutFile $zipFile -TimeoutSec $downloadTimeoutSec -UseBasicParsing -ErrorAction Stop
if (Test-Path $zipFile) { $success = $true; break }
} catch {
Write-Host ("Download failed: {0}. Retrying in {1} seconds..." -f $_.Exception.Message, $downloadRetrySleep)
Start-Sleep -Seconds $downloadRetrySleep
}
}
if (-not $success) { throw "Failed to download iPerf3 after $downloadMaxRetries attempts." }
Write-Host "Extracting iPerf3..."
Expand-Archive -Path $zipFile -DestinationPath $tmpDir -Force -ErrorAction Stop
$iperfPath = Get-ChildItem -Path $tmpDir -Filter "iperf3.exe" -Recurse | Select-Object -First 1 | Select-Object -ExpandProperty FullName
if (-not $iperfPath) { throw "iPerf3 executable not found after extraction." }
$iperfDir = Split-Path -Parent $iperfPath
$iperfExe = Join-Path $iperfDir "iperf3.exe"
if (-not (Test-Path $iperfExe)) { throw "iPerf3 executable not found at expected path: $iperfExe" }
Write-StepOk -StepId "0.5" -Title "Download and extract iPerf3"
} catch {
Write-StepFail -StepId "0.5" -Title "Download and extract iPerf3" -Message $_.Exception.Message
exit
}
# ==========================================================
# STEP 1: Interfaces/MTU + IP config
# ==========================================================
Write-StepHeader -StepId "1" -Title "Collect network interfaces + MTU + IP configuration"
try {
$mtuFile = Join-Path $savePath "NetworkInterfaces_MTU.txt"
"netsh interface ipv4 show subinterfaces`n" | Out-File $mtuFile -Encoding UTF8
netsh interface ipv4 show subinterfaces | Out-File $mtuFile -Append -Encoding UTF8
"`n=== IP Configuration ===`n" | Out-File $mtuFile -Append -Encoding UTF8
ipconfig /all | Out-File $mtuFile -Append -Encoding UTF8
Write-StepOk -StepId "1" -Title "Collect network interfaces + MTU + IP configuration"
} catch {
Write-StepFail -StepId "1" -Title "Collect network interfaces + MTU + IP configuration" -Message $_.Exception.Message
}
# ==========================================================
# STEP 1a: Wi-Fi details
# ==========================================================
Write-StepHeader -StepId "1a" -Title "Collect Wi-Fi interface details"
try {
$wifiFile = Join-Path $savePath "WiFi_Details.txt"
"=== Wi-Fi Interface Details ===`n" | Out-File $wifiFile -Encoding UTF8
netsh wlan show interfaces | Out-File $wifiFile -Append -Encoding UTF8
Write-StepOk -StepId "1a" -Title "Collect Wi-Fi interface details"
} catch {
Write-StepFail -StepId "1a" -Title "Collect Wi-Fi interface details" -Message $_.Exception.Message
}
# ==========================================================
# STEP 1b: NIC brand/model
# ==========================================================
Write-StepHeader -StepId "1b" -Title "Collect NIC brand/model"
try {
$nicFile = Join-Path $savePath "NIC_Brand_Model.txt"
Get-CimInstance Win32_NetworkAdapter | Where-Object { $_.NetEnabled -eq $true } |
Select-Object Name, Manufacturer, InterfaceDescription |
Format-Table -AutoSize | Out-String | Out-File $nicFile -Encoding UTF8
Write-StepOk -StepId "1b" -Title "Collect NIC brand/model"
} catch {
Write-StepFail -StepId "1b" -Title "Collect NIC brand/model" -Message $_.Exception.Message
}
# ==========================================================
# STEP 1c: System version + gateways
# ==========================================================
Write-StepHeader -StepId "1c" -Title "Collect system version + default gateway info"
try {
$sysFile = Join-Path $savePath "System_Modems.txt"
"=== Computer Version ===`n" | Out-File $sysFile -Encoding UTF8
Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, BuildNumber |
Format-Table -AutoSize | Out-String | Out-File $sysFile -Append -Encoding UTF8
"`n=== Default Gateway(s) / Modem Info ===`n" | Out-File $sysFile -Append -Encoding UTF8
Get-CimInstance Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true } |
Select-Object Description, @{Name="DefaultGateway";Expression={$_.DefaultIPGateway -join ", "}} |
Format-Table -AutoSize | Out-String | Out-File $sysFile -Append -Encoding UTF8
Write-StepOk -StepId "1c" -Title "Collect system version + default gateway info"
} catch {
Write-StepFail -StepId "1c" -Title "Collect system version + default gateway info" -Message $_.Exception.Message
}
# ==========================================================
# STEP 1d: Installed Windows updates
# ==========================================================
Write-StepHeader -StepId "1d" -Title "Collect installed Windows updates"
try {
$updateFile = Join-Path $savePath "Installed_Updates.txt"
"=== Installed Windows Updates ===`n" | Out-File $updateFile -Encoding UTF8
Get-HotFix | Select-Object HotFixID, Description, InstalledOn |
Format-Table -AutoSize | Out-File $updateFile -Append -Encoding UTF8
Write-StepOk -StepId "1d" -Title "Collect installed Windows updates"
} catch {
Write-StepFail -StepId "1d" -Title "Collect installed Windows updates" -Message $_.Exception.Message
}
# ==========================================================
# STEP 2: Ping tests
# ==========================================================
Write-StepHeader -StepId "2" -Title "Gateway ping tests (MTU-ish sweep)"
try {
$pingFile = Join-Path $savePath "PingTest.txt"
do {
$gateway = Read-Host "Enter gateway IP (IPv4 only)"
if (-not (Test-IPv4 $gateway)) {
Write-Host "Invalid IP format. Please enter a valid IPv4 address." -ForegroundColor Red
$gateway = $null
}
} until ($gateway)
$pingResults=@()
foreach ($size in $packetSizes) {
$pingResults += "Pinging $gateway with packet size $size..."
$results = Test-Connection -ComputerName $gateway -Count 4 -BufferSize $size -ErrorAction SilentlyContinue
foreach ($r in $results) { $pingResults += "Reply from $($r.Address): Time=$($r.ResponseTime)ms" }
$pingResults += ""
}
$pingResults | Out-File $pingFile -Encoding UTF8
Write-StepOk -StepId "2" -Title "Gateway ping tests (MTU-ish sweep)"
} catch {
Write-StepFail -StepId "2" -Title "Gateway ping tests (MTU-ish sweep)" -Message $_.Exception.Message
}
# ==========================================================
# STEP 3: Traceroute
# ==========================================================
Write-StepHeader -StepId "3" -Title "Traceroute"
try {
$tracerFile = Join-Path $savePath "Traceroute.txt"
tracert $gateway | Out-File $tracerFile -Encoding UTF8
Write-StepOk -StepId "3" -Title "Traceroute"
} catch {
Write-StepFail -StepId "3" -Title "Traceroute" -Message $_.Exception.Message
}
# ==========================================================
# STEP 4: CPU & RAM
# ==========================================================
Write-StepHeader -StepId "4" -Title "Collect CPU and RAM usage"
try {
$cpuFile = Join-Path $savePath "CPU_Memory.txt"
"`n=== Top 20 CPU Usage ===`n" | Out-File $cpuFile -Encoding UTF8
(Get-Counter '\Process(*)\% Processor Time' -SampleInterval 1 -MaxSamples 1).CounterSamples |
Where-Object { $_.InstanceName -notmatch "_Total" } |
Sort-Object CookedValue -Descending |
Select-Object -First 20 @{Name="Name";Expression={$_.InstanceName}},@{Name="CPU(%)";Expression={[math]::Round($_.CookedValue/($env:NUMBER_OF_PROCESSORS),0)}} |
Format-Table -AutoSize | Out-String | Out-File $cpuFile -Append -Encoding UTF8
"`n=== Top 20 RAM Usage ===`n" | Out-File $cpuFile -Append -Encoding UTF8
Get-Process | Sort-Object WorkingSet -Descending |
Select-Object -First 20 Name,@{Name="CPU(%)";Expression={"N/A"}},@{Name="Memory(MB)";Expression={[math]::Floor($_.WorkingSet/1MB)}} |
Format-Table -AutoSize | Out-String | Out-File $cpuFile -Append -Encoding UTF8
Write-StepOk -StepId "4" -Title "Collect CPU and RAM usage"
} catch {
Write-StepFail -StepId "4" -Title "Collect CPU and RAM usage" -Message $_.Exception.Message
}
# ==========================================================
# STEP 5: Network/system diagnostics + DNS/CURL
# ==========================================================
Write-StepHeader -StepId "5" -Title "Collect network/system diagnostics + DNS/CURL"
try {
$ipFile = Join-Path $savePath "IP_Configuration.txt"; ipconfig /all | Out-File $ipFile -Encoding UTF8
$routeFile = Join-Path $savePath "Routing_Table.txt"; route print | Out-File $routeFile -Encoding UTF8
$arpFile = Join-Path $savePath "ARP_Table.txt"; arp -a | Out-File $arpFile -Encoding UTF8
$tcpFile = Join-Path $savePath "Active_TCP_Connections.txt"; Get-NetTCPConnection | Out-File $tcpFile -Encoding UTF8
$udpFile = Join-Path $savePath "Active_UDP_Connections.txt"; Get-NetUDPEndpoint | Out-File $udpFile -Encoding UTF8
$nicStatsFile = Join-Path $savePath "NIC_Stats.txt"; Get-NetAdapterStatistics | Out-File $nicStatsFile -Encoding UTF8
$eventFile = Join-Path $savePath "EventLog.txt"
Get-WinEvent -LogName "System" -MaxEvents $eventLogMaxEvents |
Where-Object { $_.Message -match $eventLogPattern } |
Out-File $eventFile -Encoding UTF8
$dnsFile = Join-Path $savePath "DNS_Test.txt"
$curlfile = Join-Path $savePath "Curl_Test.txt"
if (Test-Path $dnsFile) { Remove-Item $dnsFile -Force }
if (Test-Path $curlfile) { Remove-Item $curlfile -Force }
foreach ($domain in $domains) {
"`nResolving $domain..." | Out-File $dnsFile -Append -Encoding UTF8
try {
Resolve-DnsName $domain | Select-Object Name, IPAddress, QueryType |
Format-Table -AutoSize | Out-String | Out-File $dnsFile -Append -Encoding UTF8
} catch {
("Failed to resolve {0}: {1}" -f $domain, $_.Exception.Message) | Out-File $dnsFile -Append -Encoding UTF8
}
}
foreach ($url in $urls) {
"`nCURL $url..." | Out-File $curlfile -Append -Encoding UTF8
try {
Invoke-WebRequest -Uri $url -UseBasicParsing |
Select-Object -ExpandProperty Content |
Out-File $curlfile -Append -Encoding UTF8
} catch {
("Failed to fetch {0}: {1}" -f $url, $_.Exception.Message) | Out-File $curlfile -Append -Encoding UTF8
}
}
Write-Host "DNS and CURL diagnostics collected. Outputs saved in $savePath"
Write-StepOk -StepId "5" -Title "Collect network/system diagnostics + DNS/CURL"
} catch {
Write-StepFail -StepId "5" -Title "Collect network/system diagnostics + DNS/CURL" -Message $_.Exception.Message
}
# ==========================================================
# STEP 6: iPerf3 tests
# ==========================================================
Write-StepHeader -StepId "6" -Title "Run iPerf3 tests (region selection + retries)"
try {
$iperfFile = Join-Path $savePath "iPerf3_Test.txt"
$repeatSelection = $true
while ($repeatSelection) {
$selectedRegions = Show-IperfRegionMenu -RegionList $regions
if ($null -eq $selectedRegions -or $selectedRegions.Count -eq 0) {
Write-Host "`nNo region selected. Returning to the region selection menu...`n" -ForegroundColor Yellow
continue
}
$regionsToTest = $selectedRegions
"" | Out-File $iperfFile -Encoding UTF8
$hadAnyFailure = $false
$abortToMenu = $false
:RegionLoop foreach ($region in $regionsToTest) {
"`n===============================" | Out-File $iperfFile -Append -Encoding UTF8
"Region: $($region.Name) Host: $($region.Host)" | Out-File $iperfFile -Append -Encoding UTF8
"===============================`n" | Out-File $iperfFile -Append -Encoding UTF8
$tests = Get-IperfTestsForRegion -region $region -IperfExe $iperfExe
foreach ($test in $tests) {
"`n-- $($test.Name) Test ($($region.Name)) --`n" | Out-File $iperfFile -Append -Encoding UTF8
$attempt = 1
$success = $false
while (-not $success -and $attempt -le $iperfMaxAttempts) {
Write-Host ("[{0} | {1}] Attempt {2} / {3}, please wait..." -f $region.Name, $test.Name, $attempt, $iperfMaxAttempts) -ForegroundColor Yellow
$result = Invoke-IperfCommandWithBusyRetry `
-IperfDir $iperfDir `
-Cmd $test.Cmd `
-LogFile $iperfFile `
-BusyMaxRetries $iperfBusyMaxRetries `
-BusySleepSeconds $iperfBusySleepSec
if ($result.ExitCode -eq 0) {
$success = $true
break
}
if ($result.BusyExhausted) {
("[{0} | {1}] Server busy persisted after {2} retries. Marking as failed attempt.`n" -f $region.Name, $test.Name, $iperfBusyMaxRetries) |
Out-File $iperfFile -Append -Encoding UTF8
} else {
("[{0} | {1}] FAIL on attempt {2} (exit {3})`n" -f $region.Name, $test.Name, $attempt, $result.ExitCode) |
Out-File $iperfFile -Append -Encoding UTF8
}
if ($attempt -lt $iperfMaxAttempts) {
Start-Sleep -Seconds $iperfAttemptSleepSec
}
$attempt++
}
if (-not $success) {
$hadAnyFailure = $true
$abortToMenu = $true
break
}
}
if ($abortToMenu) { break RegionLoop }
}
if ($hadAnyFailure) {
Write-Host "`nAt least one test failed in the selected region(s). Please try again (the test server may be busy)." -ForegroundColor Red
Write-Host "Returning to the region selection menu...`n" -ForegroundColor Yellow
$repeatSelection = $true
} else {
$repeatSelection = $false
}
}
Write-StepOk -StepId "6" -Title "Run iPerf3 tests (region selection + retries)"
}
catch {
Write-StepFail -StepId "6" -Title "Run iPerf3 tests (region selection + retries)" -Message $_.Exception.Message
Write-Host ""
Write-Host "ERROR: The script could not reliably collect test data and will exit now." -ForegroundColor Red
Write-Host "Please review the error above, fix the issue, and re-run the script." -ForegroundColor Yellow
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Cyan
[System.Console]::ReadKey($true) | Out-Null
exit 1
}
# ==========================================================
# STEP 7: Firewall
# ==========================================================
Write-StepHeader -StepId "7" -Title "Collect firewall status"
try {
$firewallFile = Join-Path $savePath "Firewall_Status.txt"
Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction |
Out-File $firewallFile -Encoding UTF8
Write-StepOk -StepId "7" -Title "Collect firewall status"
} catch {
Write-StepFail -StepId "7" -Title "Collect firewall status" -Message $_.Exception.Message
}
# ==========================================================
# STEP 8: NIC brand/model re-check
# ==========================================================
Write-StepHeader -StepId "8" -Title "Re-check NIC brand/model"
try {
$nicFile = Join-Path $savePath "NIC_Brand_Model.txt"
Get-CimInstance Win32_NetworkAdapter | Where-Object { $_.NetEnabled -eq $true } |
Select-Object Name, Manufacturer, InterfaceDescription |
Format-Table -AutoSize | Out-String | Out-File $nicFile -Encoding UTF8
Write-StepOk -StepId "8" -Title "Re-check NIC brand/model"
} catch {
Write-StepFail -StepId "8" -Title "Re-check NIC brand/model" -Message $_.Exception.Message
}
# ==========================================================
# STEP 9: System version & gateways re-check
# ==========================================================
Write-StepHeader -StepId "9" -Title "Re-check system version + gateway info"
try {
$sysFile = Join-Path $savePath "System_Modems.txt"
"=== Computer Version ===`n" | Out-File $sysFile -Encoding UTF8
Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, BuildNumber |
Format-Table -AutoSize | Out-String | Out-File $sysFile -Append -Encoding UTF8
"`n=== Default Gateway(s) / Modem Info ===`n" | Out-File $sysFile -Append -Encoding UTF8
Get-CimInstance Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true } |
Select-Object Description, @{Name="DefaultGateway";Expression={$_.DefaultIPGateway -join ", "}} |
Format-Table -AutoSize | Out-String | Out-File $sysFile -Append -Encoding UTF8
Write-StepOk -StepId "9" -Title "Re-check system version + gateway info"
} catch {
Write-StepFail -StepId "9" -Title "Re-check system version + gateway info" -Message $_.Exception.Message
}
# ==========================================================
# STEP 10: Disk usage
# ==========================================================
Write-StepHeader -StepId "10" -Title "Check disk usage"
try {
$diskFile = Join-Path $savePath "Disk_Usage.txt"
$disks = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, `
@{Name="Total(GB)";Expression={[math]::Round($_.Size/1GB,2)}}, `
@{Name="Free(GB)";Expression={[math]::Round($_.FreeSpace/1GB,2)}}, `
@{Name="Used(GB)";Expression={[math]::Round(($_.Size - $_.FreeSpace)/1GB,2)}}, `
@{Name="Usage(%)";Expression={[math]::Round((($_.Size - $_.FreeSpace)/$_.Size)*100,2)}}
"=== Disk Usage ===`n" | Out-File $diskFile -Encoding UTF8
$disks | Format-Table -AutoSize | Out-String | Out-File $diskFile -Append -Encoding UTF8
Write-StepOk -StepId "10" -Title "Check disk usage"
} catch {
Write-StepFail -StepId "10" -Title "Check disk usage" -Message $_.Exception.Message
}
# ==========================================================
# STEP 11: Tasklist
# ==========================================================
Write-StepHeader -StepId "11" -Title "Collect detailed task list"
try {
$tasklistFile = Join-Path $savePath "tasklist.txt"
tasklist /v | Out-File $tasklistFile -Encoding UTF8
Write-StepOk -StepId "11" -Title "Collect detailed task list"
} catch {
Write-StepFail -StepId "11" -Title "Collect detailed task list" -Message $_.Exception.Message
}
# ==========================================================
# STEP 12: Public IP (ipify)
# ==========================================================
Write-StepHeader -StepId "12" -Title "Get public IP (ipify)"
try {
$publicIpFile = Join-Path $savePath "PublicIP.txt"
# Simple HTTP GET, expects plain text IP
$ip = (Invoke-WebRequest -Uri "https://api64.ipify.org/" -UseBasicParsing -TimeoutSec 20).Content
$ip = $ip.Trim()
if ([string]::IsNullOrWhiteSpace($ip)) { throw "Empty response from ipify." }
("Public IP: {0}" -f $ip) | Out-File $publicIpFile -Encoding UTF8
Write-Host ("Public IP: {0}" -f $ip) -ForegroundColor Green
Write-StepOk -StepId "12" -Title "Get public IP (ipify)"
} catch {
Write-StepFail -StepId "12" -Title "Get public IP (ipify)" -Message $_.Exception.Message
}
# ==========================================================
# Cleanup
# ==========================================================
Write-StepHeader -StepId "CLEANUP" -Title "Remove temporary iPerf3 files"
try {
if (Test-Path $tmpDir) {
Remove-Item "$tmpDir\*" -Recurse -Force -ErrorAction Stop
}
Write-StepOk -StepId "CLEANUP" -Title "Remove temporary iPerf3 files"
} catch {
Write-StepFail -StepId "CLEANUP" -Title "Remove temporary iPerf3 files" -Message $_.Exception.Message
}
Write-Host ""
Write-Host "All steps completed. All outputs saved in $savePath" -ForegroundColor GreenOption 2 – Manual Collection
Run the commands below step-by-step and save outputs into a folder named:
Timus Connect Troubleshooter
Zip the folder and send it to Timus Support.
Manual Data Collection (Script-Aligned)
Create a folder named:
Timus Connect Troubleshooter
Save each command output as a .txt file inside it.
Step 1 – Network Interfaces, MTU & IP Configuration
Purpose:
Collects active network adapters, MTU values, IP addressing, DNS servers, and gateway configuration.
This is foundational for detecting routing errors, DNS misconfiguration, or packet fragmentation issues affecting tunnel stability.
Command:
netsh interface ipv4 show subinterfaces & ipconfig /all
Step 2 – Wi-Fi Details
Purpose:
Captures SSID, signal strength, radio type, and connection state.
Required when connectivity issues occur only over Wi-Fi or appear intermittent.
Command:
netsh wlan show interfaces
Step 3 – NIC Brand & Model
Purpose:
Identifies network adapter manufacturer and interface description.
Used to detect driver conflicts or hardware-related issues.
Command:
Get-CimInstance Win32_NetworkAdapter | Where-Object {$_.NetEnabled -eq $true} | Select Name,Manufacturer,InterfaceDescriptionStep 4 – System Version & Default Gateways
Purpose:
Captures Windows build information and configured default gateways.
Ensures OS compatibility and validates correct upstream routing.
Command:
Get-CimInstance Win32_OperatingSystem | Select Caption,Version,BuildNumber; Get-CimInstance Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled -eq $true} | Select Description,@{Name="DefaultGateway";Expression={$_.DefaultIPGateway -join ", "}}Step 5 – Installed Windows Updates
Purpose:
Lists installed HotFix updates and installation dates.
Recent updates may impact VPN drivers or networking components.
Command:
Get-HotFix | Select HotFixID,Description,InstalledOn
Step 6 – Timus Gateway MTU Ping Sweep
Purpose:
Tests latency and packet behavior using multiple packet sizes.
Used to detect MTU fragmentation or packet loss toward the Timus gateway.
Use the Timus Gateway Public IP (not your local router).
Command:
ping <TIMUS_GATEWAY_PUBLIC_IP> -n 4 -l 1420
Repeat for packet sizes 1420 down to 1280 if necessary.
Step 7 – Traceroute to Timus Gateway
Purpose:
Maps the full network path from the endpoint to the Timus gateway.
Helps identify ISP routing issues or failing intermediate hops.
Command:
tracert <TIMUS_GATEWAY_PUBLIC_IP>
Step 8 – CPU & Memory Usage
Purpose:
Lists the top resource-intensive processes.
High system utilization may cause tunnel drops or degraded performance.
Command:
Get-Process | Sort-Object WorkingSet -Descending | Select -First 20 Name,@{Name="MemoryMB";Expression={[math]::Floor($_.WorkingSet/1MB)}}Step 9 – Routing & ARP Tables
Purpose:
Captures local routing decisions and ARP neighbor mappings.
Provides a snapshot of the device’s network topology.
Command:
route print & arp -a
Step 10 – Active Connections & NIC Statistics
Purpose:
Lists live TCP/UDP sessions and interface-level packet statistics.
Helps detect blocked ports, abnormal traffic, or interface instability.
Command:
Get-NetTCPConnection; Get-NetUDPEndpoint; Get-NetAdapterStatistics
Step 11 – Windows Event Logs (VPN / Network)
Purpose:
Collects recent system-level networking and VPN-related events.
Used to identify driver errors, tunnel resets, or service failures.
Command:
Get-WinEvent -LogName System -MaxEvents 50 | Where-Object {$_.Message -match "VPN|Network"}Step 12 – DNS Resolution Tests
Purpose:
Verifies that required Timus service domains resolve correctly.
Ensures DNS functionality and consistency.
Command:
Resolve-DnsName auth.timuscloud.com; Resolve-DnsName user.timuscloud.com; Resolve-DnsName device.timuscloud.com; Resolve-DnsName config.timuscloud.com; Resolve-DnsName my.timusnetworks.com; Resolve-DnsName localhost
Step 13 – HTTP Reachability Tests
Purpose:
Validates connectivity to Timus backend services and local agent endpoints.
Confirms endpoint communication and service availability.
Command:
Invoke-WebRequest https://auth.timuscloud.com -UseBasicParsing; Invoke-WebRequest https://user.timuscloud.com -UseBasicParsing; Invoke-WebRequest https://device.timuscloud.com -UseBasicParsing; Invoke-WebRequest https://config.timuscloud.com -UseBasicParsing; Invoke-WebRequest https://my.timusnetworks.com -UseBasicParsing
Local agent endpoints:
Invoke-WebRequest http://localhost:49202 -UseBasicParsing; Invoke-WebRequest http://localhost:49204 -UseBasicParsing; Invoke-WebRequest http://localhost:49202/device/info -UseBasicParsing; Invoke-WebRequest http://localhost:49202/vpn/state -UseBasicParsing
Step 14 – Firewall Status
Purpose:
Displays inbound and outbound firewall rule state.
Ensures required traffic is not being blocked locally.
Command:
Get-NetFirewallProfile | Select Name,Enabled,DefaultInboundAction,DefaultOutboundAction
Step 15 – Disk Usage
Purpose:
Checks available disk capacity.
Low storage may impact logging and service stability.
Command:
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | Select DeviceID,@{Name="TotalGB";Expression={[math]::Round($_.Size/1GB,2)}},@{Name="FreeGB";Expression={[math]::Round($_.FreeSpace/1GB,2)}},@{Name="UsagePercent";Expression={[math]::Round((($_.Size-$_.FreeSpace)/$_.Size)*100,2)}}Step 16 – Running Processes (Verbose)
Purpose:
Provides a detailed snapshot of running processes and services.
Used to detect conflicts from VPN, proxy, or security software.
Command:
tasklist /v
Step 17 – Public IP Address
Purpose:
Retrieves the externally visible IP address.
Confirms correct outbound NAT and egress routing.
Command:
(Invoke-WebRequest https://api64.ipify.org -UseBasicParsing).Content
Step 18 – iPerf3 Performance Test (Manual)
Purpose:
Measures raw TCP and UDP throughput, packet loss, and jitter to identify bandwidth limitations, congestion, or ISP-level shaping impacting tunnel performance.
18.1 Download iPerf3
Download Windows 64-bit binary:
https://iperf.fr/iperf-download.php#windows
Extract the ZIP. Place iperf3.exe in a simple path (example: C:\tmp\iperf3\).
18.2 Select Test Region
Use the region closest to the user:
| Region | Host | TCP Port | UDP Port |
|---|---|---|---|
| Ashburn (US) | ash.speedtest.clouvider.net | 5200 | 5201 |
| Frankfurt (DE) | fra.speedtest.clouvider.net | 5200 | 5201 |
| Amsterdam (NL) | ams.speedtest.clouvider.net | 5200 | 5201 |
| London (UK) | lon.speedtest.clouvider.net | 5200 | 5201 |
18.3 Run Tests (PowerShell or CMD)
Navigate to the iPerf3 directory:
cd C:\iperf3
TCP Download
iperf3.exe -c ash.speedtest.clouvider.net -p 5200 -t 10 -P 8 -R
TCP Upload
iperf3.exe -c ash.speedtest.clouvider.net -p 5200 -t 10 -P 8
UDP Download
iperf3.exe -c ash.speedtest.clouvider.net -p 5201 -t 10 -u -b 1000M -R
UDP Upload
iperf3.exe -c ash.speedtest.clouvider.net -p 5201 -t 10 -u -b 1000M
18.4 What To Collect
Save full console output of:
TCP Download
TCP Upload
UDP Download
UDP Upload
Into:
iPerf3_Test.txt
Place inside:
Timus Connect Troubleshooter
Once all steps are completed, please compress the “Timus Connect Troubleshooter” folder and send it to Timus Support along with a brief description of the issue and the exact time it occurred (including timezone).
Providing the complete diagnostic package ensures our Support and Engineering teams can perform an accurate root cause analysis and resolve the issue as quickly as possible.
Related to
Updated
Comments
0 comments
Please sign in to leave a comment.