Networking#

PowerShell ships first-class HTTP cmdlets and typed remoting (PSRemoting) out of the box. Invoke-RestMethod is the curl equivalent that gives back parsed objects; Invoke-Command runs a script block on one or many remote hosts and streams the typed objects back. The rest of the toolkit (DNS, TCP probes, SSH, file transfer) is the same on PowerShell as it is on bash.

HTTP#

Two cmdlets cover almost every operator need. Invoke-RestMethod is the API call that returns a parsed object; Invoke-WebRequest returns the full HttpResponse when the operator needs headers, status codes, or raw content.

Invoke-RestMethod https://api.github.com/repos/PowerShell/PowerShell |
    Select-Object stargazers_count, forks_count

$body = @{ name = 'operator' } | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri https://api.example.com/users `
    -ContentType 'application/json' -Body $body

# raw response (headers, status, body)
$r = Invoke-WebRequest https://example.com/
$r.StatusCode
$r.Headers
$r.Content                                  # the body string

Common parameters worth memorizing.

  • -MaximumRetryCount, -RetryIntervalSec, the built-in retry loop. Always set in scripts.

  • -TimeoutSec, fail rather than hang.

  • -Headers @{...}, custom headers (auth, content-type, user-agent).

  • -Authentication, -Token, -Credential, the typed auth helpers.

  • -SkipHttpErrorCheck (7+), do not throw on 4xx / 5xx; the operator inspects status manually.

  • -OutFile path, stream the response to disk.

JSON#

PowerShell parses JSON into objects natively. No jq.

$data = Invoke-RestMethod https://api.example.com/users/1
$data.name

Get-Content data.json | ConvertFrom-Json |
    Where-Object Age -gt 30 |
    Select-Object Name, Email

@{ name = 'operator' } | ConvertTo-Json -Depth 5 |
    Set-Content payload.json

-Depth matters on ConvertTo-Json; the default of 2 silently truncates deeper structures.

TCP / UDP#

Test-NetConnection (Windows-only, 5.1+) wraps ICMP, TCP, and trace-route in one cmdlet. Cross-platform, fall back to .NET sockets or Test-Connection (7+, cross-platform).

Test-NetConnection -ComputerName host -Port 22         # Windows
Test-Connection -TargetName host -TcpPort 22 -Quiet   # 7+ cross-platform

For low-level work, .NET sockets are always available.

$client = [System.Net.Sockets.TcpClient]::new()
$client.Connect('host', 22)
$client.Connected
$client.Close()

# listener
$listener = [System.Net.Sockets.TcpListener]::new('0.0.0.0', 4444)
$listener.Start()
$sock = $listener.AcceptTcpClient()

DNS#

Resolve-DnsName on Windows; cross-platform fall back to [System.Net.Dns].

Resolve-DnsName example.com                          # Windows
Resolve-DnsName example.com -Type AAAA
Resolve-DnsName example.com -Server 8.8.8.8

[System.Net.Dns]::GetHostAddresses('example.com')    # cross-platform

PSRemoting (SSH / WinRM)#

PowerShell remoting runs script blocks on remote hosts and streams typed objects back. Transport is WinRM on Windows and SSH cross-platform (with -HostName instead of -ComputerName). Cleaner than ssh host 'cmd' because the remote output is real objects, not text the operator has to parse.

Interactive session.

Enter-PSSession -ComputerName server01                # WinRM
Enter-PSSession -HostName server01 -UserName operator  # SSH

Run a script block on many hosts.

Invoke-Command -ComputerName server01, server02 -ScriptBlock {
    Get-Service nginx
}

# over SSH; results come back as typed ServiceController objects
Invoke-Command -HostName web01, web02 -UserName operator -ScriptBlock {
    Get-Process | Where-Object WorkingSet -gt 100MB
} |
    Group-Object PSComputerName |
    Select-Object Name, Count

Persistent sessions cut connection overhead.

$sess = New-PSSession -HostName web01, web02 -UserName operator
Invoke-Command -Session $sess -ScriptBlock { hostname }
Remove-PSSession $sess

SSH and File Transfer#

Native cmdlets, then external tools when they fit better.

ssh user@host 'systemctl status nginx'
scp file user@host:/path/
rsync -aP src/ user@host:/path/

# over PSRemoting (typed result)
Invoke-Command -HostName host -UserName user -ScriptBlock {
    Get-Service nginx | Select-Object Name, Status
}

Authentication Tokens#

Don’t put tokens on the command line; they leak through ps, history, and logs.

$token = Get-Content ~/.config/myapp/token -Raw
Invoke-RestMethod -Uri https://api.example.com -Authentication Bearer -Token (
    ConvertTo-SecureString $token -AsPlainText -Force
)

$cred = Get-Credential                       # prompt
Invoke-RestMethod -Authentication Basic -Credential $cred -Uri ...

# built-in: read a token from env
Invoke-RestMethod -Headers @{ Authorization = "Bearer $env:API_TOKEN" } -Uri ...

Diagnostics#

Test-Connection -TargetName host -Count 3
Test-NetConnection -ComputerName host -TraceRoute
Get-NetTCPConnection                                    # Windows
ss -tulpn                                               # Linux native
tcpdump -ni any port 443                                # Linux native

For “is this URL up and what does it look like”.

$sw = [System.Diagnostics.Stopwatch]::StartNew()
$r = Invoke-WebRequest https://example.com/ -SkipHttpErrorCheck
$sw.Stop()
"http=$($r.StatusCode) time=$($sw.Elapsed.TotalSeconds)s"

References#