105 lines
3.7 KiB
PowerShell
105 lines
3.7 KiB
PowerShell
# ============================================================
|
|
# Hotspot IPv6 readiness test (pure ASCII -- safe to copy/paste)
|
|
#
|
|
# Purpose:
|
|
# 1) After connecting this laptop to a PHONE HOTSPOT,
|
|
# check whether the laptop receives a global IPv6 address.
|
|
# 2) Check whether the HOME host can be reached directly over IPv6.
|
|
#
|
|
# Output: Desktop\hotspot-ipv6-result.txt
|
|
# ============================================================
|
|
|
|
# --- change these two lines if the home IPv6 address changes ---
|
|
$HOME_V6 = '240e:338:263:3600:29f1:e63f:d476:597e'
|
|
$HOME_PORT = 38443
|
|
# ---------------------------------------------------------------
|
|
|
|
$desk = [Environment]::GetFolderPath('Desktop')
|
|
if (-not $desk) { $desk = $env:TEMP }
|
|
$o = Join-Path $desk 'hotspot-ipv6-result.txt'
|
|
$L = New-Object System.Collections.Generic.List[string]
|
|
function A($s) { $L.Add([string]$s) }
|
|
function Flush() { $L -join "`r`n" | Set-Content -Path $o -Encoding UTF8 }
|
|
|
|
$okOut = $false
|
|
$okHome = $false
|
|
|
|
A ('TIME ' + (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'))
|
|
A ('HOST ' + [System.Net.Dns]::GetHostName())
|
|
A ('RESULT FILE: ' + $o)
|
|
A ''
|
|
|
|
A '[1] Global IPv6 addresses on this machine'
|
|
$ga = @(Get-NetIPAddress -AddressFamily IPv6 -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.IPAddress -notlike 'fe80*' -and $_.IPAddress -ne '::1' })
|
|
if ($ga.Count -eq 0) {
|
|
A ' NONE <-- this network gives NO global IPv6'
|
|
} else {
|
|
foreach ($a in $ga) {
|
|
A (" {0} :: {1}/{2} :: Pref={3} Suffix={4} State={5}" -f `
|
|
$a.InterfaceAlias, $a.IPAddress, $a.PrefixLength, `
|
|
$a.PrefixOrigin, $a.SuffixOrigin, $a.AddressState)
|
|
}
|
|
}
|
|
Flush
|
|
|
|
A ''
|
|
A '[2] IPv6 default route'
|
|
$r = @(Get-NetRoute -AddressFamily IPv6 -DestinationPrefix '::/0' -ErrorAction SilentlyContinue)
|
|
if ($r.Count -eq 0) { A ' NONE' } else {
|
|
foreach ($x in $r) { A (" {0} -> {1}" -f $x.InterfaceAlias, $x.NextHop) }
|
|
}
|
|
Flush
|
|
|
|
function Tcp6([string]$h, [int]$port, [int]$ms) {
|
|
try {
|
|
$a = @([System.Net.Dns]::GetHostAddresses($h) |
|
|
Where-Object { $_.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetworkV6 })
|
|
if ($a.Count -eq 0) { return 'NO-AAAA' }
|
|
$ad = $a[0]
|
|
$c = New-Object System.Net.Sockets.TcpClient($ad.AddressFamily)
|
|
$iar = $c.BeginConnect($ad, $port, $null, $null)
|
|
if (-not $iar.AsyncWaitHandle.WaitOne($ms, $false)) { $c.Close(); return 'TIMEOUT' }
|
|
try { $c.EndConnect($iar); $c.Close(); return ('OK ' + $ad.IPAddressToString) }
|
|
catch { $c.Close(); return ('FAIL ' + $_.Exception.Message) }
|
|
} catch { return ('ERR ' + $_.Exception.Message) }
|
|
}
|
|
|
|
A ''
|
|
A '[3] Outbound IPv6 test (decisive for the whole route)'
|
|
foreach ($h in @('ipv6.icanhazip.com', 'www.taobao.com')) {
|
|
$res = Tcp6 $h 443 4000
|
|
A (" {0}:443 -> {1}" -f $h, $res)
|
|
if ($res -like 'OK*') { $okOut = $true }
|
|
}
|
|
Flush
|
|
|
|
A ''
|
|
A '[4] Direct reach to HOME host over IPv6 (the real goal)'
|
|
$u = 'http://[' + $HOME_V6 + ']:' + $HOME_PORT + '/'
|
|
A (' target = ' + $u)
|
|
try {
|
|
$r2 = Invoke-WebRequest -Uri $u -UseBasicParsing -TimeoutSec 6
|
|
A (' HTTP status = ' + $r2.StatusCode)
|
|
A (' body line 1 = ' + (($r2.Content -split '\r?\n')[0]))
|
|
if ($r2.StatusCode -eq 200) { $okHome = $true }
|
|
} catch {
|
|
A (' FAILED: ' + $_.Exception.Message)
|
|
}
|
|
Flush
|
|
|
|
A ''
|
|
A '===== SUMMARY ====='
|
|
if ($okOut -and $okHome) {
|
|
A ' PASS: hotspot gives IPv6 AND home host is reachable.'
|
|
A ' -> The IPv6 direct route is viable from this laptop.'
|
|
} elseif ($okOut -and -not $okHome) {
|
|
A ' PARTIAL: IPv6 outbound OK, but home host unreachable.'
|
|
A ' -> Most likely the home gateway blocks inbound IPv6,'
|
|
A ' or the home IPv6 address/prefix has changed.'
|
|
} else {
|
|
A ' FAIL: no usable IPv6 outbound on this network.'
|
|
A ' -> The hotspot handed out no IPv6 (IPv6 sharing may be off).'
|
|
}
|
|
Flush
|