Private/Get-NSPConditionalAccessPublicAddress.ps1

function Get-NSPConditionalAccessPublicAddress {
    <#
    .SYNOPSIS
        This computer's public IPv4 address, as the internet sees it; $null when no lookup service answers.
    .DESCRIPTION
        Asks api.ipify.org, then ifconfig.me, then icanhazip.com (the FCT troubleshooter's
        Get-FCTPublicIPAddress), each with a short timeout, and never throws. Over a VPN or
        tunnel the answer is that tunnel's exit address, not the local ISP's. Returns IP and Source.
    #>

    [CmdletBinding()]
    param(
        [ValidateRange(1, 60)][int]$TimeoutSeconds = 8
    )

    # Windows PowerShell 5.1 may not offer TLS 1.2 by default; add it without removing anything.
    try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 } catch { Write-Verbose "TLS 1.2 not set: $_" }
    $services = @('https://api.ipify.org', 'https://ifconfig.me/ip', 'https://icanhazip.com')
    foreach ($service in $services) {
        Write-NSPConditionalAccessProgress -Activity PublicAddress -Status "Asking $service"
        try {
            $candidate = "$(Invoke-RestMethod -Uri $service -TimeoutSec $TimeoutSeconds -UseBasicParsing)".Trim()
            $parsed = $null
            if ($candidate -match '^\d{1,3}(\.\d{1,3}){3}$' -and [System.Net.IPAddress]::TryParse($candidate, [ref]$parsed)) {
                Write-NSPConditionalAccessProgress -Activity PublicAddress -Completed
                return [pscustomobject]@{ IP = $candidate; Source = $service }
            }
        } catch {
            Write-Verbose "$service did not answer: $_"
        }
    }
    Write-NSPConditionalAccessProgress -Activity PublicAddress -Completed
    $null
}