Keyboard shortcuts

Press โ† or โ†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

IP Scanning

xrat includes a TCP reachability scanner for testing candidate IP addresses, useful for discovering fast CDN endpoints or Cloudflare edge IPs.

Overview

The scan command:

  1. Reads candidate IPs from CLI flags or a file
  2. Attempts TCP connection to each IP on a specified port
  3. Measures connection latency
  4. Persists results to the database
  5. Prints a summary with reachability and latency

Usage

xrat scan [flags]

Scan Specific IPs

xrat scan --ips 1.1.1.1,8.8.8.8,9.9.9.9

Scan from a File

xrat scan --file ./candidate-ips.txt

File format (one IP per line):

1.1.1.1
8.8.8.8
9.9.9.9
104.16.0.1

Custom Port and Timeout

xrat scan --ips 1.1.1.1,8.8.8.8 --port 8443 --timeout 2000

View History

xrat scan --history 20

Configuration

FlagDescriptionDefault
--ips <list>Comma-separated IPs to scan-
--file <path>File with newline-separated IPs-
--port <port>Target TCP port443
--timeout <ms>TCP connect timeout4000
--history <n>Print latest N results and exit-

Scan Process

Step 1: Load IPs

Read IPs from --ips or --file:

#![allow(unused)]
fn main() {
let ips = if !args.ips.is_empty() {
    args.ips.clone()
} else if let Some(file) = &args.file {
    std::fs::read_to_string(file)?
        .lines()
        .map(|s| s.trim().to_string())
        .filter(|s| !s.is_empty())
        .collect()
} else {
    return Err("no IPs provided");
};
}

Step 2: TCP Connect

For each IP, attempt a TCP connection:

#![allow(unused)]
fn main() {
async fn tcp_connect(ip: &str, port: u16, timeout: Duration) -> Result<Duration> {
    let start = Instant::now();
    let addr = format!("{}:{}", ip, port);

    match timeout(timeout, TcpStream::connect(&addr)).await {
        Ok(Ok(_)) => Ok(start.elapsed()),
        Ok(Err(e)) => Err(e.into()),
        Err(_) => Err(Error::Timeout),
    }
}
}

Step 3: Measure Latency

Record the connection time in milliseconds:

#![allow(unused)]
fn main() {
let latency_ms = start.elapsed().as_millis() as u64;
}

Step 4: Persist Results

Insert or update the result in cf_scan_results:

INSERT INTO cf_scan_results (ip, latency_ms, error, last_scanned_at)
VALUES (?, ?, ?, ?)
ON CONFLICT(ip) DO UPDATE SET
  latency_ms = excluded.latency_ms,
  error = excluded.error,
  last_scanned_at = excluded.last_scanned_at

Step 5: Print Summary

IP              Port    Latency    Status
1.1.1.1         443     12ms       reachable
8.8.8.8         443     15ms       reachable
9.9.9.9         443     -          timeout
104.16.0.1      443     8ms        reachable

Persistence

Scan results are persisted to the cf_scan_results table:

ColumnTypeDescription
idINTEGERPrimary key
ipTEXTIP address (unique)
latency_msINTEGERConnection latency (NULL if failed)
errorTEXTError message (NULL if successful)
last_scanned_atTIMESTAMPLast scan timestamp

Upsert Behavior

Results are upserted (insert or update on conflict):

  • New IP โ†’ insert new row
  • Existing IP โ†’ update latency, error, timestamp

This allows tracking IP reachability over time.

History

View persisted scan results:

xrat scan --history 20

Output:

Scan History (latest 20)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
IP              Latency    Last Scanned
1.1.1.1         12ms       2026-05-28 10:30:00
8.8.8.8         15ms       2026-05-28 10:30:00
104.16.0.1      8ms        2026-05-28 10:30:00
9.9.9.9         -          2026-05-28 10:30:00 (timeout)

Results are sorted by last_scanned_at descending.

Use Cases

Cloudflare IP Scanning

Discover fast Cloudflare edge IPs:

# Generate candidate IPs from Cloudflare ranges
cat > cf-ips.txt <<EOF
1.1.1.1
1.0.0.1
104.16.0.1
104.17.0.1
EOF

# Scan on port 443
xrat scan --file cf-ips.txt --port 443 --timeout 3000

# View results
xrat scan --history 10

CDN Endpoint Testing

Test CDN nodes in your region:

xrat scan --ips 151.101.1.69,151.101.65.69,151.101.129.69 --port 443

Network Reconnaissance

Discover reachable IPs in a range:

# Generate IP range
for i in {1..254}; do echo "192.168.1.$i"; done > ips.txt

# Scan on custom port
xrat scan --file ips.txt --port 8443 --timeout 1000

Output Format

Success

IP              Port    Latency    Status
1.1.1.1         443     12ms       reachable

Failure

IP              Port    Latency    Status
9.9.9.9         443     -          timeout

Error Types

ErrorDescription
timeoutConnection timed out
refusedConnection refused (port closed)
unreachableNetwork unreachable
dnsDNS resolution failed (for hostnames)
ioI/O error

Performance

Concurrency

Scans are performed sequentially to avoid overwhelming the network. For large IP lists, consider splitting into multiple runs.

Timeout

Adjust timeout based on network conditions:

  • Fast network: --timeout 2000 (2 seconds)
  • Slow network: --timeout 5000 (5 seconds)
  • High latency: --timeout 10000 (10 seconds)

Limitations

  • TCP only: Does not support UDP or ICMP
  • Single port: Scans one port at a time
  • No authentication: Does not test proxy authentication
  • Sequential: No parallel scanning (yet)