Fast cloud provider IP detection for Go. Determine if an IP address belongs to AWS, GCP, Azure, Cloudflare, DigitalOcean, or Oracle Cloud with sub-microsecond lookup times.
- Fast lookups - Sub-microsecond performance using Patricia trie
- Multiple providers - AWS, GCP, Azure, Cloudflare, DigitalOcean, Oracle
- Automatic updates - Optional background refresh from cloudip-db
- Offline support - Works without network using embedded data
- Thread-safe - Concurrent lookups with lock-free reads
- Zero config - First run fetches latest data and caches it; works offline afterwards
- Embedded fallback - Includes compiled-in data for air-gapped environments
go get github.com/rezmoss/go-cloudippackage main
import (
"fmt"
"github.com/rezmoss/go-cloudip"
)
func main() {
// Simple provider detection
if cloudip.IsAWS("52.94.76.1") {
fmt.Println("This is an AWS IP")
}
// Get provider name
provider := cloudip.GetProvider("34.64.0.1")
fmt.Println("Provider:", provider) // "gcp"
// Check if any cloud provider
if cloudip.IsCloudProvider("104.16.0.1") {
fmt.Println("This is a cloud IP")
}
// Detailed lookup with region and service info
result := cloudip.Lookup("52.94.76.1")
if result.Found {
fmt.Printf("Provider: %s, Region: %s, Service: %s\n",
result.Provider, result.Region, result.Service)
}
}On initialization, the detector loads IP range data with this priority:
- Network - Fetches latest data from cloudip-db and caches locally
- Cache - Uses previously cached data if network unavailable
- Embedded - Falls back to compiled-in data (for air-gapped environments)
This means:
- First run: Automatically downloads latest IP ranges and caches them (~/.cache/go-cloudip)
- Subsequent runs: Still tries network first, but has cache as reliable fallback
- Offline/air-gapped: Use
WithOffline()to skip network entirely
These use a default global detector that initializes automatically:
// Provider detection
cloudip.IsAWS(ip string) bool
cloudip.IsGCP(ip string) bool
cloudip.IsAzure(ip string) bool
cloudip.IsCloudflare(ip string) bool
cloudip.IsDigitalOcean(ip string) bool
cloudip.IsOracle(ip string) bool
cloudip.IsCloudProvider(ip string) bool
// Get provider
cloudip.GetProvider(ip string) Provider
// Detailed lookup
cloudip.Lookup(ip string) LookupResult
// Metadata
cloudip.Version() string
cloudip.RangeCount() int
cloudip.Providers() []string
// Updates
cloudip.Update(ctx context.Context) error
cloudip.CheckUpdate(ctx context.Context) (bool, *VersionInfo, error)For more control, create a custom detector:
detector, err := cloudip.NewDetector(
cloudip.WithDataDir("./cache"),
cloudip.WithAutoUpdate(24 * time.Hour),
)
if err != nil {
log.Fatal(err)
}
defer detector.Close()
result := detector.Lookup("52.94.76.1")| Option | Description |
|---|---|
WithDataDir(dir) |
Set cache directory (default: ~/.cache/go-cloudip) |
WithAutoUpdate(interval) |
Enable background updates (minimum: 1 hour) |
WithOffline() |
Disable network, use embedded data only |
WithHTTPClient(client) |
Custom HTTP client for requests |
WithDataURL(url) |
Custom data URL (for mirrors) |
WithVersionURL(url) |
Custom version URL |
WithNoCache() |
Disable file caching |
// Provider represents a cloud provider
type Provider string
const (
ProviderAWS Provider = "aws"
ProviderGCP Provider = "gcp"
ProviderAzure Provider = "azure"
ProviderCloudflare Provider = "cloudflare"
ProviderDigitalOcean Provider = "digitalocean"
ProviderOracle Provider = "oracle"
ProviderUnknown Provider = ""
)
// LookupResult contains detailed information about an IP
type LookupResult struct {
Found bool // Whether IP was found
Provider Provider // Cloud provider
Region string // Geographic region (e.g., "us-east-1")
Service string // Service name (e.g., "EC2", "S3")
CIDR string // Matched IP range
}For air-gapped environments:
detector, _ := cloudip.NewDetector(cloudip.WithOffline())
defer detector.Close()
// Uses only embedded data, no network requests
result := detector.Lookup("52.94.76.1")Keep data fresh automatically:
detector, _ := cloudip.NewDetector(
cloudip.WithDataDir("/var/cache/cloudip"),
cloudip.WithAutoUpdate(24 * time.Hour),
)
defer detector.Close()
// Data refreshes in background every 24 hoursFor high-performance scenarios:
import "net/netip"
addr, _ := netip.ParseAddr("52.94.76.1")
result := cloudip.LookupAddr(addr)
isAWS := cloudip.IsAWSAddr(addr)ctx := context.Background()
hasUpdate, info, err := cloudip.CheckUpdate(ctx)
if hasUpdate {
fmt.Printf("New version: %s (%d ranges)\n", info.Version, info.Ranges)
cloudip.Update(ctx) // Apply update
}| Operation | Time |
|---|---|
| IPv4 Lookup | ~200-300 ns |
| IPv6 Lookup | ~200-300 ns |
| LookupAddr (netip.Addr) | ~200-250 ns |
| Data load + parse | ~50 ms |
All lookups are sub-microsecond. Memory usage: ~10-15 MB for all providers loaded.
IP ranges are sourced from cloud-provider-ip-addresses and compiled daily into MessagePack format by cloudip-db.
MIT License - see LICENSE file.