ipauth
all systems live
Sign in
// SETUP

Wire IPAuth into your server.

Pick your OS / firewall. Each setup is a drop-in script plus a cron / scheduled-task line. You already have your auth URL + server URL — paste the server key in the script, save, schedule, done.

Don't have a pair yet?

Linux with ufw

Tested on Ubuntu 22.04 / 24.04, Debian 12. The most common modern Linux setup.

01

Save the update script

Drop this at /usr/local/bin/ipauth-update.sh. Replace YOUR_SERVER_KEY with the server key from your pair; change PORT if you're not gating SSH.

#!/bin/sh
SERVER_URL="https://ipauth.net/serverquery/?key=YOUR_SERVER_KEY"
PORT=22

CURIP=$(curl --max-time 5 -fsS "$SERVER_URL" | grep -oE '"ipaddress":"[0-9.]+' | cut -d'"' -f4)
[ -z "$CURIP" ] && exit 0

if ! ufw status | grep -q "$CURIP.*$PORT/tcp"; then
    ufw allow from "$CURIP" to any port "$PORT" proto tcp comment "ipauth"
fi
sudo chmod +x /usr/local/bin/ipauth-update.sh
02

Schedule it (every 2 minutes)

sudo crontab -e

*/2 * * * * /usr/local/bin/ipauth-update.sh
03

Verify

Click your auth URL, wait 2 min, then check:

sudo ufw status | grep ipauth

Linux with bare iptables

For systems without ufw — older distros, embedded Linux, or anything where you manage iptables directly. Persistence depends on your distro (iptables-persistent, netfilter-persistent, or saved via init).

01

Save the update script

Save as /usr/local/bin/ipauth-update.sh:

#!/bin/sh
SERVER_URL="https://ipauth.net/serverquery/?key=YOUR_SERVER_KEY"
PORT=22
COMMENT="ipauth"

CURIP=$(curl --max-time 5 -fsS "$SERVER_URL" | grep -oE '"ipaddress":"[0-9.]+' | cut -d'"' -f4)
[ -z "$CURIP" ] && exit 0

# Remove any prior ipauth allow rules for this port, then add fresh.
iptables -S INPUT | grep -- "--comment \"$COMMENT\"" | sed 's/^-A /-D /' | while read R; do
    iptables $R 2>/dev/null
done
iptables -I INPUT -p tcp --dport "$PORT" -s "$CURIP" -m comment --comment "$COMMENT" -j ACCEPT
sudo chmod +x /usr/local/bin/ipauth-update.sh
02

Schedule it

*/2 * * * * /usr/local/bin/ipauth-update.sh

If you use iptables-persistent, also run netfilter-persistent save after the rule lands, OR add a second cron entry to do it.

03

Verify

sudo iptables -L INPUT -n --line-numbers | grep ipauth

Windows Server / Windows 11 Pro

Uses Windows Firewall via PowerShell + Task Scheduler. Run PowerShell as Administrator.

01

Save the update script

Save as C:\Scripts\ipauth-update.ps1:

# ipauth-update.ps1
$ServerUrl = "https://ipauth.net/serverquery/?key=YOUR_SERVER_KEY"
$Port      = 22
$RuleName  = "IPAuth-Allow-$Port"

try {
    $resp = Invoke-RestMethod -Uri $ServerUrl -TimeoutSec 5
    if (-not $resp.ipaddress) { exit 0 }
    $ip = $resp.ipaddress
} catch { exit 0 }

Get-NetFirewallRule -DisplayName $RuleName -ErrorAction SilentlyContinue | Remove-NetFirewallRule
New-NetFirewallRule -DisplayName $RuleName `
    -Direction Inbound -Action Allow `
    -Protocol TCP -LocalPort $Port `
    -RemoteAddress $ip `
    -Profile Any | Out-Null
02

Schedule it (every 2 minutes)

$action  = New-ScheduledTaskAction -Execute "powershell.exe" `
    -Argument "-NoProfile -ExecutionPolicy Bypass -File C:\Scripts\ipauth-update.ps1"
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
    -RepetitionInterval (New-TimeSpan -Minutes 2) `
    -RepetitionDuration (New-TimeSpan -Days 3650)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest

Register-ScheduledTask -TaskName "IPAuth-Update" `
    -Action $action -Trigger $trigger -Principal $principal `
    -Description "Updates Windows Firewall rule from IPAuth"
03

Verify

Get-NetFirewallRule -DisplayName "IPAuth-Allow-*" |
    Get-NetFirewallAddressFilter |
    Select-Object RemoteAddress
04

Alternative: register on PowerShell startup (laptop / workstation pattern)

If you're using IPAuth from a Windows laptop (not a server), you probably want it to register your IP every time you open PowerShell — so new SSH sessions to your remote boxes work immediately after a network change. This is what we use ourselves.

Open your $PROFILE:

notepad $PROFILE
# (if the file doesn't exist yet, PowerShell will offer to create it)

Add a $Servers hash table and a startup loop that hits each auth URL (not server URL — this is the client-side click equivalent) and prints a status line:

$Servers = @{
    'webprod' = @{
        IPAuthAuth = 'https://ipauth.net/whitelist/?key=YOUR_AUTH_KEY_HERE'
        HealthURL  = 'https://web.example.com/'
    }
    # add more boxes as @{ IPAuthAuth = '...'; HealthURL = '...' }
}

try {
    $publicIP = Invoke-RestMethod 'https://api.ipify.org' -TimeoutSec 5
} catch { $publicIP = '(lookup failed)' }
Write-Host "Your public IP is: " -NoNewline
Write-Host $publicIP -ForegroundColor Cyan

$statusParts = @()
foreach ($name in $Servers.Keys | Sort-Object) {
    $cfg = $Servers[$name]
    try { Invoke-RestMethod $cfg.IPAuthAuth -TimeoutSec 5 | Out-Null; $ipauthOK = $true }
    catch { $ipauthOK = $false }
    try {
        $r = Invoke-WebRequest $cfg.HealthURL -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop
        $healthOK = $r.StatusCode -eq 200
    } catch { $healthOK = $false }

    $color = if ($ipauthOK -and $healthOK) { 'Green' } elseif ($healthOK) { 'Yellow' } else { 'Red' }
    $state = if ($healthOK) { 'UP' } else { 'DOWN' }
    if (-not $ipauthOK) { $state += '(no-ipauth)' }
    $statusParts += @{ Name = $name; State = $state; Color = $color }
}
$first = $true
foreach ($p in $statusParts) {
    if (-not $first) { Write-Host " | " -NoNewline }
    Write-Host "$($p.Name): " -NoNewline
    Write-Host $p.State -ForegroundColor $p.Color -NoNewline
    $first = $false
}
Write-Host ""

Save and close. Every new PowerShell window now auto-registers your current IP with every server's IPAuth key in $Servers, prints your public IP, and shows a per-server up/down summary. If you switch networks (coffee shop → home), just open a new PS window and you're back in within the server's poll window.

Server side still needs the cron from steps 1-3 above — this client-side helper just clicks the auth URL for you. The two pieces work together.

macOS with pfctl

macOS ships pf out of the box (BSD heritage). Useful for hardened Macs or a Mac mini acting as a small server. Requires enabling pf and adding an anchor.

01

Add an IPAuth anchor to pf

Edit /etc/pf.conf (sudo):

anchor "ipauth"
load anchor "ipauth" from "/etc/pf.anchors/ipauth"

Create /etc/pf.anchors/ipauth:

table <ipauth_allow> persist
pass in proto tcp from <ipauth_allow> to any port 22 keep state

Enable pf and load:

sudo pfctl -e
sudo pfctl -f /etc/pf.conf
02

Save the update script

Save as /usr/local/bin/ipauth-update.sh:

#!/bin/sh
SERVER_URL="https://ipauth.net/serverquery/?key=YOUR_SERVER_KEY"

CURIP=$(curl --max-time 5 -fsS "$SERVER_URL" | grep -oE '"ipaddress":"[0-9.]+' | cut -d'"' -f4)
[ -z "$CURIP" ] && exit 0

pfctl -a ipauth -t ipauth_allow -T replace "$CURIP" 2>/dev/null
sudo chmod +x /usr/local/bin/ipauth-update.sh
03

Schedule it (every 2 minutes via launchd)

Save as /Library/LaunchDaemons/net.ipauth.update.plist:

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <key>Label</key><string>net.ipauth.update</string>
    <key>ProgramArguments</key>
    <array><string>/usr/local/bin/ipauth-update.sh</string></array>
    <key>StartInterval</key><integer>120</integer>
    <key>RunAtLoad</key><true/>
</dict>
</plist>
sudo launchctl load -w /Library/LaunchDaemons/net.ipauth.update.plist
04

Verify

sudo pfctl -a ipauth -t ipauth_allow -T show

OpenBSD with pf

Uses a pf table — pfctl updates it in-place, no daemon reload needed. Tested on OpenBSD 7.5+.

01

Declare the IPAuth table in pf.conf

Add to /etc/pf.conf:

table <ipauth_allow> persist
pass in on egress proto tcp from <ipauth_allow> to any port 22 keep state
doas pfctl -f /etc/pf.conf
02

Save the update script

#!/bin/sh
SERVER_URL="https://ipauth.net/serverquery/?key=YOUR_SERVER_KEY"

CURIP=$(ftp -V -M -o - "$SERVER_URL" 2>/dev/null | grep -oE '"ipaddress":"[0-9.]+' | cut -d'"' -f4)
[ -z "$CURIP" ] && exit 0

pfctl -t ipauth_allow -T replace "$CURIP" 2>/dev/null
doas chmod +x /usr/local/bin/ipauth-update.sh
03

Schedule it

Edit root's crontab via doas crontab -e:

*/2 * * * * /usr/local/bin/ipauth-update.sh
04

Verify

doas pfctl -t ipauth_allow -T show

FreeBSD with ipfw

FreeBSD's native packet filter. Use a single rule that points at a table the script updates in-place. FreeBSD also supports pf if you'd rather — same flow as the OpenBSD/macOS tabs.

01

Add the IPAuth rule

Append to /etc/ipfw.rules (or wherever your ruleset lives):

ipfw table 10 create type addr
ipfw add allow tcp from table\(10\) to any 22 in

Reload your ruleset (typically /etc/rc.d/ipfw restart).

02

Save the update script

#!/bin/sh
SERVER_URL="https://ipauth.net/serverquery/?key=YOUR_SERVER_KEY"

CURIP=$(fetch -q -T 5 -o - "$SERVER_URL" | grep -oE '"ipaddress":"[0-9.]+' | cut -d'"' -f4)
[ -z "$CURIP" ] && exit 0

# Replace table 10 contents with just the current IP.
ipfw table 10 flush
ipfw table 10 add "$CURIP"
chmod +x /usr/local/bin/ipauth-update.sh
03

Schedule it

Root's crontab:

*/2 * * * * /usr/local/bin/ipauth-update.sh
04

Verify

ipfw table 10 list
// QUESTIONS

Different stack?

The flow is the same anywhere: poll the server URL, parse the IP, update your allow list, schedule it every couple of minutes. If you're running on something exotic (nftables on Alpine, OPNsense, pfSense, IPFire, Synology, etc.) the script body changes but the structure doesn't.

Ask us about your setup →