Public/Test-GSAPrivateAccessTunnel.ps1
|
# # Function: Test-GSAPrivateAccessTunnel # Public function for the GSA client diagnostics toolkit. # function Test-GSAPrivateAccessTunnel { <# .SYNOPSIS Tests that a Private Access target actually tunnels through the GSA client. .DESCRIPTION Opens a TCP connection to the given FQDN or IPv4 address/port. For FQDN targets, verifies the connection was routed to a synthetic 6.6.x.x address (proving GSA intercepted and tunneled the traffic) and resolves the internal address via the GSA Private DNS resolver (6.6.255.254). UDP targets cannot be tunnel-tested this way and are reported as a warning only. .PARAMETER FQDNorIP The target FQDN or IPv4 address to test. .PARAMETER Port The target port number. .PARAMETER Protocol The protocol to test (TCP or UDP). .PARAMETER PassThru Return the $true/$false test result. By default nothing is returned - only logged - so calling this function interactively doesn't echo a stray True/False after the log output. .EXAMPLE Test-GSAPrivateAccessTunnel -FQDNorIP fileserver.contoso.com -Port 445 -Protocol TCP .EXAMPLE if (Test-GSAPrivateAccessTunnel -FQDNorIP fileserver.contoso.com -Port 445 -Protocol TCP -PassThru) { ... } #> [CmdletBinding()] param ( [Parameter(Mandatory)] [string]$FQDNorIP, [Parameter(Mandatory)] [int]$Port, [Parameter(Mandatory)] [ValidateSet("TCP", "UDP")] [string]$Protocol, [switch]$PassThru, [ValidateSet("ERROR", "WARNING", "INFO", "DEBUG", "SUCCESS")] [string]$LogLevel ) if ($PSBoundParameters.ContainsKey('LogLevel')) { $script:LogLevel = $LogLevel } # Determine whether the input is an FQDN or an IPv4 address. $inputType = Test-IPorFQDN -FQDNorIP $FQDNorIP if (-not $inputType) { Write-Log "'$FQDNorIP' is not a valid IPv4 address or FQDN." "ERROR" if ($PassThru) { return $false } return } # If the input is not valid, log an error and exit. if ($Protocol -eq 'UDP') { Write-Log "UDP tunnel connectivity cannot be verified with a TCP-based probe." "WARNING" if ($PassThru) { return [PSCustomObject]@{ Passed = $true; Warnings = 1 } } return } Write-Log "Checking Private Access tunnel connectivity to ${FQDNorIP}:${Port}..." "INFO" # Attempt to establish a TCP connection to the target FQDN or IP address and port. try { $tcpClient = [System.Net.Sockets.TcpClient]::new($FQDNorIP, $Port) } catch { Write-Log "Failed to establish a tunnel connection to ${FQDNorIP}:${Port} : $($_.Exception.Message)" "ERROR" Write-Log "Recommended action: Ensure the Private Access application segment, port, and protocol are correctly configured and that the GSA client tunnel is active." "WARNING" if ($PassThru) { return $false } return } # Retrieve the synthetic GSA address assigned to the established tunnel connection. try { $syntheticAddress = $tcpClient.Client.RemoteEndPoint.Address.ToString() } finally { $tcpClient.Close() } Write-Log "Tunnel connection established. Synthetic address: $syntheticAddress" "SUCCESS" # Verify that the synthetic address corresponds to the expected GSA range for FQDN inputs. if ($inputType -eq 'FQDN') { if ($syntheticAddress -notlike '6.6.*') { Write-Log "Connection to '$FQDNorIP' did NOT resolve to a synthetic GSA address (6.6.x.x) - traffic may not be tunneled through GSA." "ERROR" Write-Log "Recommended action: Ensure the GSA client is active and this FQDN is not being resolved/routed outside the tunnel." "WARNING" if ($PassThru) { return $false } return } try { $dnsResult = Resolve-DnsName -Name $FQDNorIP -Server 6.6.255.254 -TcpOnly -ErrorAction Stop Write-Log "Internal address for '$FQDNorIP' resolved via GSA Private DNS: $($dnsResult.IPAddress -join ', ')" "SUCCESS" } catch { Write-Log "Could not resolve the internal DNS name for '$FQDNorIP' via the GSA Private DNS resolver: $($_.Exception.Message)" "ERROR" Write-Log "Recommended action: Ensure Private DNS is configured and the Private Network Connector can resolve this name." "WARNING" if ($PassThru) { return $false } return } } Write-Log "Test passed: tunnel to '$FQDNorIP' on port $Port established successfully via GSA (synthetic address: $syntheticAddress)." "SUCCESS" if ($PassThru) { return $true } } |