Public/network/Get-PublicIPAddress.ps1
|
function Get-PublicIPAddress { <# .SYNOPSIS Retrieves the public IP address of the local or remote computer. .DESCRIPTION Queries external HTTP APIs to determine the public-facing IPv4 and IPv6 addresses. Uses ipify.org as primary provider with ifconfig.me as fallback. For remote computers, the query is executed via Invoke-Command so the result reflects each machine's own public IP. .PARAMETER ComputerName One or more computer names to query. Defaults to the local machine. Accepts pipeline input. .PARAMETER Credential Optional credential for remote computer connections. .PARAMETER TimeoutSec HTTP request timeout in seconds. Defaults to 10. Valid range: 1–60. .PARAMETER IPv6 Also attempt to resolve the public IPv6 address. Disabled by default because many networks do not have IPv6 connectivity. .EXAMPLE Get-PublicIPAddress Returns the public IP of the local machine. .EXAMPLE Get-PublicIPAddress -ComputerName 'SRV01' -Credential (Get-Credential) Returns the public IP of remote server SRV01. .EXAMPLE 'SRV01', 'SRV02', 'SRV03' | Get-PublicIPAddress -IPv6 Returns IPv4 and IPv6 public addresses for three servers via pipeline. .NOTES Author : Franck SALLET Requires : PowerShell 5.1+ / Windows only API : https://api.ipify.org (primary), https://ifconfig.me (fallback) #> [CmdletBinding()] param ( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [string[]]$ComputerName = $env:COMPUTERNAME, [Parameter(Mandatory = $false)] [PSCredential]$Credential, [Parameter(Mandatory = $false)] [ValidateRange(1, 60)] [int]$TimeoutSec = 10, [Parameter(Mandatory = $false)] [switch]$IPv6 ) begin { # ScriptBlock executed locally or remotely to query public IP $queryBlock = { param ([int]$Timeout, [bool]$IncludeIPv6) $ipv4Address = $null $ipv6Address = $null $provider = $null # --- IPv4 --- # Primary: ipify try { $response = Invoke-RestMethod -Uri 'https://api.ipify.org?format=json' -TimeoutSec $Timeout -ErrorAction Stop $ipv4Address = $response.ip $provider = 'ipify.org' } catch { # Fallback: ifconfig.me try { $ipv4Address = (Invoke-WebRequest -Uri 'https://ifconfig.me/ip' -TimeoutSec $Timeout -UseBasicParsing -ErrorAction Stop).Content.Trim() $provider = 'ifconfig.me' } catch { $provider = 'Unavailable' } } # --- IPv6 (optional) --- if ($IncludeIPv6) { try { $response6 = Invoke-RestMethod -Uri 'https://api64.ipify.org?format=json' -TimeoutSec $Timeout -ErrorAction Stop $ipv6Address = $response6.ip # If api64 returned an IPv4, it means no IPv6 connectivity if ($ipv6Address -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$') { $ipv6Address = $null } } catch { $ipv6Address = $null } } [PSCustomObject]@{ IPv4Address = $ipv4Address IPv6Address = $ipv6Address Provider = $provider } } } process { foreach ($targetComputer in $ComputerName) { try { $isLocal = ($targetComputer -eq $env:COMPUTERNAME) -or ($targetComputer -eq 'localhost') -or ($targetComputer -eq '.') if ($isLocal) { $rawResult = & $queryBlock -Timeout $TimeoutSec -IncludeIPv6 $IPv6.IsPresent } else { $invokeParams = @{ ComputerName = $targetComputer ScriptBlock = $queryBlock ArgumentList = @($TimeoutSec, $IPv6.IsPresent) ErrorAction = 'Stop' } if ($Credential) { $invokeParams['Credential'] = $Credential } $rawResult = Invoke-Command @invokeParams } [PSCustomObject]@{ PSTypeName = 'PSWinOps.PublicIPAddress' ComputerName = $targetComputer IPv4Address = $rawResult.IPv4Address IPv6Address = $rawResult.IPv6Address Provider = $rawResult.Provider Timestamp = Get-Date -Format 'o' } } catch { Write-Error "[$($MyInvocation.MyCommand)] Failed on '$targetComputer': $_" } } } } |