Last active
April 3, 2018 16:26
-
-
Save gravejester/5041912 to your computer and use it in GitHub Desktop.
For some reason I wanted to write a trace route script in PowerShell, but decided to run it through Google first to see if it had been done. Surprisingly few results came up, and as far as I can tell, only one true PowerShell script doing Trace Route without just being a wrapper for tracert or something similar: https://snoj.us/75/traceroute-wit…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Trace-Route { | |
<# | |
.SYNOPSIS | |
Trace the route between source computer and a target machine. | |
.DESCRIPTION | |
Trace the route between source computer and a target machine. | |
.EXAMPLE | |
Trace-Route Computer01 | |
Perform trace route to Computer01 | |
.EXAMPLE | |
Trace-Route -Target www.microsoft.com -ResolveHostname | |
Perform trace route to www.microsoft.com and try to resolve hostname for each hop. | |
Note! This will slow down the function somewhat. | |
.NOTES | |
Author: Øyvind Kallstad | |
Date: 28.10.2014 | |
Version: 1.1 | |
#> | |
[CmdletBinding()] | |
param( | |
# Hostname or IP to trace to. | |
[Parameter(Position = 0, ValueFromPipeline = $true)] | |
[string] $Target = $env:COMPUTERNAME, | |
# Set starting hop. | |
[Parameter()] | |
[int] $BeginHop = 1, | |
# Set maximum number of hops. | |
[Parameter()] | |
[int] $MaxHops = 30, | |
# Define timeout in milliseconds. | |
[Parameter()] | |
[int] $Timeout = 1000, | |
# Try to resolve hostname for IP in each hop. | |
[Parameter()] | |
[switch] $ResolveHostname = $false | |
) | |
# verify that we can reach target system | |
try{ | |
$ping = New-Object System.Net.NetworkInformation.Ping | |
$pingResult = $ping.Send($Target) | |
if(-not($pingResult.Status -eq 'Success')){ | |
Write-Warning "Unable to resolve target system $Target" | |
exit | |
} | |
} | |
catch{ | |
Write-Warning "Unable to resolve target system $Target" | |
exit | |
} | |
# define some data to send | |
$sendBytes = @([byte][char]'a'..[byte][char]'z') | |
for($i = $BeginHop; $i -lt $MaxHops; $i++) { | |
# define ping options; set start hop and fragmentation to true | |
$pingOptions = new-object System.Net.NetworkInformation.PingOptions $i, $true | |
# perform ping | |
$pingReply = $ping.Send($Target, $Timeout, $sendBytes, $pingOptions) | |
# get ip for current hop if possible | |
if($pingReply.Address -ne $null){ | |
$ip = $pingReply.Address | |
} | |
else{ | |
$ip = '*' | |
} | |
# get roundtrip time | |
$roundtripTime = $pingReply.RoundtripTime | |
# get status | |
$hopStatus = $pingReply.Status | |
# resolve hostname | |
if ($ResolveHostname) { | |
try{ | |
$resolvedHostname = "[$(([System.Net.Dns]::GetHostEntry($ip)).HostName)]" | |
} | |
catch{ | |
$resolvedHostname = '' | |
} | |
} | |
# create custom object and send to pipeline | |
Write-Output ([PSCustomObject] [Ordered] @{ | |
Hop = $i.ToString() | |
IP = "$($ip) $($resolvedHostname)" | |
Status = $hopStatus | |
RoundtripTime = $roundtripTime | |
}) | |
# clean up | |
Remove-Variable ip, roundtripTime, hopStatus, resolvedHostname -ErrorAction 'SilentlyContinue' | |
# stop loop if current ip matches the target ip | |
if($pingReply.Address -eq $pingResult.Address){break} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Machammarj,
Here is a way to do a specific IP address in BATCH and not in powershell as I needed to do the same thing. You will need an input file with a list of IP address on a new line.
`@echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=ips.txt
set IP_FILE=output.txt
set VIP_FILE=EXTERNAL_VIP.txt
set DC=""
set temp=""
set route_address=""
for /f %%k in (%VIP_FILE%) do (
tracert.exe -4 -d -h 15 -w 300 %%k|Findstr /C:"ms" > %OUTPUT_FILE%
::setting max hops to 20 and timeout to 50
for /f "tokens=8 delims= " %%i in (%OUTPUT_FILE%) do (
set route_ip="%%i"
ECHO !route_ip! | Findstr /C:"10.1." >nul & IF ERRORLEVEL 1 ( set temp="" ) else ( set DC=AT
set route_address=!route_ip!)
ECHO !route_ip! | Findstr /C:"10.6." >nul & IF ERRORLEVEL 1 ( set temp="" ) else ( set DC=ORD
set route_address=!route_ip!)
)
echo %%k is routing from !route_address! in !DC!>>%IP_FILE%
set DC=""
set route_address=""
)
%IP_FILE%`