pax_global_header 0000666 0000000 0000000 00000000064 13732170323 0014513 g ustar 00root root 0000000 0000000 52 comment=7ff5a0e84593dad6fbd50551343618d7956b3c71
cidranger-1.0.2/ 0000775 0000000 0000000 00000000000 13732170323 0013451 5 ustar 00root root 0000000 0000000 cidranger-1.0.2/.gitignore 0000664 0000000 0000000 00000000014 13732170323 0015434 0 ustar 00root root 0000000 0000000 vendor
.idea cidranger-1.0.2/.travis.yml 0000664 0000000 0000000 00000000425 13732170323 0015563 0 ustar 00root root 0000000 0000000 language: go
go:
- 1.13.x
- 1.14.x
- tip
before_install:
- travis_retry go get github.com/mattn/goveralls
script:
- go test -v -covermode=count -coverprofile=coverage.out ./...
- travis_retry $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci
cidranger-1.0.2/Gopkg.lock 0000664 0000000 0000000 00000001771 13732170323 0015400 0 ustar 00root root 0000000 0000000 # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = "UT"
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
pruneopts = "UT"
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
digest = "1:f85e109eda8f6080877185d1c39e98dd8795e1780c08beca28304b87fd855a1c"
name = "github.com/stretchr/testify"
packages = ["assert"]
pruneopts = "UT"
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
version = "v1.2.1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = ["github.com/stretchr/testify/assert"]
solver-name = "gps-cdcl"
solver-version = 1
cidranger-1.0.2/Gopkg.toml 0000664 0000000 0000000 00000001345 13732170323 0015420 0 ustar 00root root 0000000 0000000 # Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.1"
[prune]
go-tests = true
unused-packages = true
cidranger-1.0.2/LICENSE 0000664 0000000 0000000 00000002046 13732170323 0014460 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2017 Yulin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
cidranger-1.0.2/README.md 0000664 0000000 0000000 00000012512 13732170323 0014731 0 ustar 00root root 0000000 0000000 # cidranger
Fast IP to CIDR block(s) lookup using trie in Golang, inspired by [IPv4 route lookup linux](https://vincent.bernat.im/en/blog/2017-ipv4-route-lookup-linux). Possible use cases include detecting if a IP address is from published cloud provider CIDR blocks (e.g. 52.95.110.1 is contained in published AWS Route53 CIDR 52.95.110.0/24), IP routing rules, etc.
[](https://godoc.org/github.com/yl2chen/cidranger)
[](https://travis-ci.org/yl2chen/cidranger)
[](https://coveralls.io/github/yl2chen/cidranger?branch=master)
[](https://goreportcard.com/report/github.com/yl2chen/cidranger)
This is visualization of a trie storing CIDR blocks `128.0.0.0/2` `192.0.0.0/2` `200.0.0.0/5` without path compression, the 0/1 number on the path indicates the bit value of the IP address at specified bit position, hence the path from root node to a child node represents a CIDR block that contains all IP ranges of its children, and children's children.

Visualization of trie storing same CIDR blocks with path compression, improving both lookup speed and memory footprint.

## Getting Started
Configure imports.
```go
import (
"net"
"github.com/yl2chen/cidranger"
)
```
Create a new ranger implemented using Path-Compressed prefix trie.
```go
ranger := NewPCTrieRanger()
```
Inserts CIDR blocks.
```go
_, network1, _ := net.ParseCIDR("192.168.1.0/24")
_, network2, _ := net.ParseCIDR("128.168.1.0/24")
ranger.Insert(NewBasicRangerEntry(*network1))
ranger.Insert(NewBasicRangerEntry(*network2))
```
To attach any additional value(s) to the entry, simply create custom struct
storing the desired value(s) that implements the RangerEntry interface:
```go
type RangerEntry interface {
Network() net.IPNet
}
```
The prefix trie can be visualized as:
```
0.0.0.0/0 (target_pos:31:has_entry:false)
| 1--> 128.0.0.0/1 (target_pos:30:has_entry:false)
| | 0--> 128.168.1.0/24 (target_pos:7:has_entry:true)
| | 1--> 192.168.1.0/24 (target_pos:7:has_entry:true)
```
To test if given IP is contained in constructed ranger,
```go
contains, err = ranger.Contains(net.ParseIP("128.168.1.0")) // returns true, nil
contains, err = ranger.Contains(net.ParseIP("192.168.2.0")) // returns false, nil
```
To get all the networks given is contained in,
```go
containingNetworks, err = ranger.ContainingNetworks(net.ParseIP("128.168.1.0"))
```
To get all networks in ranger,
```go
entries, err := ranger.CoveredNetworks(*AllIPv4) // for IPv4
entries, err := ranger.CoveredNetworks(*AllIPv6) // for IPv6
```
## Benchmark
Compare hit/miss case for IPv4/IPv6 using PC trie vs brute force implementation, Ranger is initialized with published AWS ip ranges (889 IPv4 CIDR blocks and 360 IPv6)
```go
// Ipv4 lookup hit scenario
BenchmarkPCTrieHitIPv4UsingAWSRanges-4 5000000 353 ns/op
BenchmarkBruteRangerHitIPv4UsingAWSRanges-4 100000 13719 ns/op
// Ipv6 lookup hit scenario, counter-intuitively faster then IPv4 due to less IPv6 CIDR
// blocks in the AWS dataset, hence the constructed trie has less path splits and depth.
BenchmarkPCTrieHitIPv6UsingAWSRanges-4 10000000 143 ns/op
BenchmarkBruteRangerHitIPv6UsingAWSRanges-4 300000 5178 ns/op
// Ipv4 lookup miss scenario
BenchmarkPCTrieMissIPv4UsingAWSRanges-4 20000000 96.5 ns/op
BenchmarkBruteRangerMissIPv4UsingAWSRanges-4 50000 24781 ns/op
// Ipv6 lookup miss scenario
BenchmarkPCTrieHMissIPv6UsingAWSRanges-4 10000000 115 ns/op
BenchmarkBruteRangerMissIPv6UsingAWSRanges-4 100000 10824 ns/op
```
## Example of IPv6 trie:
```
::/0 (target_pos:127:has_entry:false)
| 0--> 2400::/14 (target_pos:113:has_entry:false)
| | 0--> 2400:6400::/22 (target_pos:105:has_entry:false)
| | | 0--> 2400:6500::/32 (target_pos:95:has_entry:false)
| | | | 0--> 2400:6500::/39 (target_pos:88:has_entry:false)
| | | | | 0--> 2400:6500:0:7000::/53 (target_pos:74:has_entry:false)
| | | | | | 0--> 2400:6500:0:7000::/54 (target_pos:73:has_entry:false)
| | | | | | | 0--> 2400:6500:0:7000::/55 (target_pos:72:has_entry:false)
| | | | | | | | 0--> 2400:6500:0:7000::/56 (target_pos:71:has_entry:true)
| | | | | | | | 1--> 2400:6500:0:7100::/56 (target_pos:71:has_entry:true)
| | | | | | | 1--> 2400:6500:0:7200::/56 (target_pos:71:has_entry:true)
| | | | | | 1--> 2400:6500:0:7400::/55 (target_pos:72:has_entry:false)
| | | | | | | 0--> 2400:6500:0:7400::/56 (target_pos:71:has_entry:true)
| | | | | | | 1--> 2400:6500:0:7500::/56 (target_pos:71:has_entry:true)
| | | | | 1--> 2400:6500:100:7000::/54 (target_pos:73:has_entry:false)
| | | | | | 0--> 2400:6500:100:7100::/56 (target_pos:71:has_entry:true)
| | | | | | 1--> 2400:6500:100:7200::/56 (target_pos:71:has_entry:true)
| | | | 1--> 2400:6500:ff00::/64 (target_pos:63:has_entry:true)
| | | 1--> 2400:6700:ff00::/64 (target_pos:63:has_entry:true)
| | 1--> 2403:b300:ff00::/64 (target_pos:63:has_entry:true)
```
cidranger-1.0.2/brute.go 0000664 0000000 0000000 00000007026 13732170323 0015126 0 ustar 00root root 0000000 0000000 package cidranger
import (
"net"
rnet "github.com/yl2chen/cidranger/net"
)
// bruteRanger is a brute force implementation of Ranger. Insertion and
// deletion of networks is performed on an internal storage in the form of
// map[string]net.IPNet (constant time operations). However, inclusion tests are
// always performed linearly at no guaranteed traversal order of recorded networks,
// so one can assume a worst case performance of O(N). The performance can be
// boosted many ways, e.g. changing usage of net.IPNet.Contains() to using masked
// bits equality checking, but the main purpose of this implementation is for
// testing because the correctness of this implementation can be easily guaranteed,
// and used as the ground truth when running a wider range of 'random' tests on
// other more sophisticated implementations.
type bruteRanger struct {
ipV4Entries map[string]RangerEntry
ipV6Entries map[string]RangerEntry
}
// newBruteRanger returns a new Ranger.
func newBruteRanger() Ranger {
return &bruteRanger{
ipV4Entries: make(map[string]RangerEntry),
ipV6Entries: make(map[string]RangerEntry),
}
}
// Insert inserts a RangerEntry into ranger.
func (b *bruteRanger) Insert(entry RangerEntry) error {
network := entry.Network()
key := network.String()
if _, found := b.ipV4Entries[key]; !found {
entries, err := b.getEntriesByVersion(entry.Network().IP)
if err != nil {
return err
}
entries[key] = entry
}
return nil
}
// Remove removes a RangerEntry identified by given network from ranger.
func (b *bruteRanger) Remove(network net.IPNet) (RangerEntry, error) {
networks, err := b.getEntriesByVersion(network.IP)
if err != nil {
return nil, err
}
key := network.String()
if networkToDelete, found := networks[key]; found {
delete(networks, key)
return networkToDelete, nil
}
return nil, nil
}
// Contains returns bool indicating whether given ip is contained by any
// network in ranger.
func (b *bruteRanger) Contains(ip net.IP) (bool, error) {
entries, err := b.getEntriesByVersion(ip)
if err != nil {
return false, err
}
for _, entry := range entries {
network := entry.Network()
if network.Contains(ip) {
return true, nil
}
}
return false, nil
}
// ContainingNetworks returns all RangerEntry(s) that given ip contained in.
func (b *bruteRanger) ContainingNetworks(ip net.IP) ([]RangerEntry, error) {
entries, err := b.getEntriesByVersion(ip)
if err != nil {
return nil, err
}
results := []RangerEntry{}
for _, entry := range entries {
network := entry.Network()
if network.Contains(ip) {
results = append(results, entry)
}
}
return results, nil
}
// CoveredNetworks returns the list of RangerEntry(s) the given ipnet
// covers. That is, the networks that are completely subsumed by the
// specified network.
func (b *bruteRanger) CoveredNetworks(network net.IPNet) ([]RangerEntry, error) {
entries, err := b.getEntriesByVersion(network.IP)
if err != nil {
return nil, err
}
var results []RangerEntry
testNetwork := rnet.NewNetwork(network)
for _, entry := range entries {
entryNetwork := rnet.NewNetwork(entry.Network())
if testNetwork.Covers(entryNetwork) {
results = append(results, entry)
}
}
return results, nil
}
// Len returns number of networks in ranger.
func (b *bruteRanger) Len() int {
return len(b.ipV4Entries) + len(b.ipV6Entries)
}
func (b *bruteRanger) getEntriesByVersion(ip net.IP) (map[string]RangerEntry, error) {
if ip.To4() != nil {
return b.ipV4Entries, nil
}
if ip.To16() != nil {
return b.ipV6Entries, nil
}
return nil, ErrInvalidNetworkInput
}
cidranger-1.0.2/brute_test.go 0000664 0000000 0000000 00000012473 13732170323 0016167 0 ustar 00root root 0000000 0000000 package cidranger
import (
"net"
"sort"
"testing"
"github.com/stretchr/testify/assert"
)
func TestInsert(t *testing.T) {
ranger := newBruteRanger().(*bruteRanger)
_, networkIPv4, _ := net.ParseCIDR("0.0.1.0/24")
_, networkIPv6, _ := net.ParseCIDR("8000::/96")
entryIPv4 := NewBasicRangerEntry(*networkIPv4)
entryIPv6 := NewBasicRangerEntry(*networkIPv6)
ranger.Insert(entryIPv4)
ranger.Insert(entryIPv6)
assert.Equal(t, 1, len(ranger.ipV4Entries))
assert.Equal(t, entryIPv4, ranger.ipV4Entries["0.0.1.0/24"])
assert.Equal(t, 1, len(ranger.ipV6Entries))
assert.Equal(t, entryIPv6, ranger.ipV6Entries["8000::/96"])
}
func TestInsertError(t *testing.T) {
bRanger := newBruteRanger().(*bruteRanger)
_, networkIPv4, _ := net.ParseCIDR("0.0.1.0/24")
networkIPv4.IP = append(networkIPv4.IP, byte(4))
err := bRanger.Insert(NewBasicRangerEntry(*networkIPv4))
assert.Equal(t, ErrInvalidNetworkInput, err)
}
func TestRemove(t *testing.T) {
ranger := newBruteRanger().(*bruteRanger)
_, networkIPv4, _ := net.ParseCIDR("0.0.1.0/24")
_, networkIPv6, _ := net.ParseCIDR("8000::/96")
_, notInserted, _ := net.ParseCIDR("8000::/96")
insertIPv4 := NewBasicRangerEntry(*networkIPv4)
insertIPv6 := NewBasicRangerEntry(*networkIPv6)
ranger.Insert(insertIPv4)
deletedIPv4, err := ranger.Remove(*networkIPv4)
assert.NoError(t, err)
ranger.Insert(insertIPv6)
deletedIPv6, err := ranger.Remove(*networkIPv6)
assert.NoError(t, err)
entry, err := ranger.Remove(*notInserted)
assert.NoError(t, err)
assert.Nil(t, entry)
assert.Equal(t, insertIPv4, deletedIPv4)
assert.Equal(t, 0, len(ranger.ipV4Entries))
assert.Equal(t, insertIPv6, deletedIPv6)
assert.Equal(t, 0, len(ranger.ipV6Entries))
}
func TestRemoveError(t *testing.T) {
r := newBruteRanger().(*bruteRanger)
_, invalidNetwork, _ := net.ParseCIDR("0.0.1.0/24")
invalidNetwork.IP = append(invalidNetwork.IP, byte(4))
_, err := r.Remove(*invalidNetwork)
assert.Equal(t, ErrInvalidNetworkInput, err)
}
func TestContains(t *testing.T) {
r := newBruteRanger().(*bruteRanger)
_, network, _ := net.ParseCIDR("0.0.1.0/24")
_, network1, _ := net.ParseCIDR("8000::/112")
r.Insert(NewBasicRangerEntry(*network))
r.Insert(NewBasicRangerEntry(*network1))
cases := []struct {
ip net.IP
contains bool
err error
name string
}{
{net.ParseIP("0.0.1.255"), true, nil, "IPv4 should contain"},
{net.ParseIP("0.0.0.255"), false, nil, "IPv4 houldn't contain"},
{net.ParseIP("8000::ffff"), true, nil, "IPv6 shouldn't contain"},
{net.ParseIP("8000::1:ffff"), false, nil, "IPv6 shouldn't contain"},
{append(net.ParseIP("8000::1:ffff"), byte(0)), false, ErrInvalidNetworkInput, "Invalid IP"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
contains, err := r.Contains(tc.ip)
if tc.err != nil {
assert.Equal(t, tc.err, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tc.contains, contains)
}
})
}
}
func TestContainingNetworks(t *testing.T) {
r := newBruteRanger().(*bruteRanger)
_, network1, _ := net.ParseCIDR("0.0.1.0/24")
_, network2, _ := net.ParseCIDR("0.0.1.0/25")
_, network3, _ := net.ParseCIDR("8000::/112")
_, network4, _ := net.ParseCIDR("8000::/113")
entry1 := NewBasicRangerEntry(*network1)
entry2 := NewBasicRangerEntry(*network2)
entry3 := NewBasicRangerEntry(*network3)
entry4 := NewBasicRangerEntry(*network4)
r.Insert(entry1)
r.Insert(entry2)
r.Insert(entry3)
r.Insert(entry4)
cases := []struct {
ip net.IP
containingNetworks []RangerEntry
err error
name string
}{
{net.ParseIP("0.0.1.255"), []RangerEntry{entry1}, nil, "IPv4 should contain"},
{net.ParseIP("0.0.1.127"), []RangerEntry{entry1, entry2}, nil, "IPv4 should contain both"},
{net.ParseIP("0.0.0.127"), []RangerEntry{}, nil, "IPv4 should contain none"},
{net.ParseIP("8000::ffff"), []RangerEntry{entry3}, nil, "IPv6 should constain"},
{net.ParseIP("8000::7fff"), []RangerEntry{entry3, entry4}, nil, "IPv6 should contain both"},
{net.ParseIP("8000::1:7fff"), []RangerEntry{}, nil, "IPv6 should contain none"},
{append(net.ParseIP("8000::1:7fff"), byte(0)), nil, ErrInvalidNetworkInput, "Invalid IP"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
networks, err := r.ContainingNetworks(tc.ip)
if tc.err != nil {
assert.Equal(t, tc.err, err)
} else {
assert.NoError(t, err)
assert.Equal(t, len(tc.containingNetworks), len(networks))
for _, network := range tc.containingNetworks {
assert.Contains(t, networks, network)
}
}
})
}
}
func TestCoveredNetworks(t *testing.T) {
for _, tc := range coveredNetworkTests {
t.Run(tc.name, func(t *testing.T) {
ranger := newBruteRanger()
for _, insert := range tc.inserts {
_, network, _ := net.ParseCIDR(insert)
err := ranger.Insert(NewBasicRangerEntry(*network))
assert.NoError(t, err)
}
var expectedEntries []string
for _, network := range tc.networks {
expectedEntries = append(expectedEntries, network)
}
sort.Strings(expectedEntries)
_, snet, _ := net.ParseCIDR(tc.search)
networks, err := ranger.CoveredNetworks(*snet)
assert.NoError(t, err)
var results []string
for _, result := range networks {
net := result.Network()
results = append(results, net.String())
}
sort.Strings(results)
assert.Equal(t, expectedEntries, results)
})
}
}
cidranger-1.0.2/cidranger.go 0000664 0000000 0000000 00000005230 13732170323 0015736 0 ustar 00root root 0000000 0000000 /*
Package cidranger provides utility to store CIDR blocks and perform ip
inclusion tests against it.
To create a new instance of the path-compressed trie:
ranger := NewPCTrieRanger()
To insert or remove an entry (any object that satisfies the RangerEntry
interface):
_, network, _ := net.ParseCIDR("192.168.0.0/24")
ranger.Insert(NewBasicRangerEntry(*network))
ranger.Remove(network)
If you desire for any value to be attached to the entry, simply
create custom struct that satisfies the RangerEntry interface:
type RangerEntry interface {
Network() net.IPNet
}
To test whether an IP is contained in the constructed networks ranger:
// returns bool, error
containsBool, err := ranger.Contains(net.ParseIP("192.168.0.1"))
To get a list of CIDR blocks in constructed ranger that contains IP:
// returns []RangerEntry, error
entries, err := ranger.ContainingNetworks(net.ParseIP("192.168.0.1"))
To get a list of all IPv4/IPv6 rangers respectively:
// returns []RangerEntry, error
entries, err := ranger.CoveredNetworks(*AllIPv4)
entries, err := ranger.CoveredNetworks(*AllIPv6)
*/
package cidranger
import (
"fmt"
"net"
)
// ErrInvalidNetworkInput is returned upon invalid network input.
var ErrInvalidNetworkInput = fmt.Errorf("Invalid network input")
// ErrInvalidNetworkNumberInput is returned upon invalid network input.
var ErrInvalidNetworkNumberInput = fmt.Errorf("Invalid network number input")
// AllIPv4 is a IPv4 CIDR that contains all networks
var AllIPv4 = parseCIDRUnsafe("0.0.0.0/0")
// AllIPv6 is a IPv6 CIDR that contains all networks
var AllIPv6 = parseCIDRUnsafe("0::0/0")
func parseCIDRUnsafe(s string) *net.IPNet {
_, cidr, _ := net.ParseCIDR(s)
return cidr
}
// RangerEntry is an interface for insertable entry into a Ranger.
type RangerEntry interface {
Network() net.IPNet
}
type basicRangerEntry struct {
ipNet net.IPNet
}
func (b *basicRangerEntry) Network() net.IPNet {
return b.ipNet
}
// NewBasicRangerEntry returns a basic RangerEntry that only stores the network
// itself.
func NewBasicRangerEntry(ipNet net.IPNet) RangerEntry {
return &basicRangerEntry{
ipNet: ipNet,
}
}
// Ranger is an interface for cidr block containment lookups.
type Ranger interface {
Insert(entry RangerEntry) error
Remove(network net.IPNet) (RangerEntry, error)
Contains(ip net.IP) (bool, error)
ContainingNetworks(ip net.IP) ([]RangerEntry, error)
CoveredNetworks(network net.IPNet) ([]RangerEntry, error)
Len() int
}
// NewPCTrieRanger returns a versionedRanger that supports both IPv4 and IPv6
// using the path compressed trie implemention.
func NewPCTrieRanger() Ranger {
return newVersionedRanger(newPrefixTree)
}
cidranger-1.0.2/cidranger_test.go 0000664 0000000 0000000 00000022036 13732170323 0017000 0 ustar 00root root 0000000 0000000 package cidranger
import (
"encoding/json"
"io/ioutil"
"math/rand"
"net"
"testing"
"time"
"github.com/stretchr/testify/assert"
rnet "github.com/yl2chen/cidranger/net"
)
/*
******************************************************************
Test Contains/ContainingNetworks against basic brute force ranger.
******************************************************************
*/
func TestContainsAgainstBaseIPv4(t *testing.T) {
testContainsAgainstBase(t, 100000, randIPv4Gen)
}
func TestContainingNetworksAgaistBaseIPv4(t *testing.T) {
testContainingNetworksAgainstBase(t, 100000, randIPv4Gen)
}
func TestCoveredNetworksAgainstBaseIPv4(t *testing.T) {
testCoversNetworksAgainstBase(t, 100000, randomIPNetGenFactory(ipV4AWSRangesIPNets))
}
// IPv6 spans an extremely large address space (2^128), randomly generated IPs
// will often fall outside of the test ranges (AWS public CIDR blocks), so it
// it more meaningful for testing to run from a curated list of IPv6 IPs.
func TestContainsAgaistBaseIPv6(t *testing.T) {
testContainsAgainstBase(t, 100000, curatedAWSIPv6Gen)
}
func TestContainingNetworksAgaistBaseIPv6(t *testing.T) {
testContainingNetworksAgainstBase(t, 100000, curatedAWSIPv6Gen)
}
func TestCoveredNetworksAgainstBaseIPv6(t *testing.T) {
testCoversNetworksAgainstBase(t, 100000, randomIPNetGenFactory(ipV6AWSRangesIPNets))
}
func testContainsAgainstBase(t *testing.T, iterations int, ipGen ipGenerator) {
if testing.Short() {
t.Skip("Skipping memory test in `-short` mode")
}
rangers := []Ranger{NewPCTrieRanger()}
baseRanger := newBruteRanger()
for _, ranger := range rangers {
configureRangerWithAWSRanges(t, ranger)
}
configureRangerWithAWSRanges(t, baseRanger)
for i := 0; i < iterations; i++ {
nn := ipGen()
expected, err := baseRanger.Contains(nn.ToIP())
assert.NoError(t, err)
for _, ranger := range rangers {
actual, err := ranger.Contains(nn.ToIP())
assert.NoError(t, err)
assert.Equal(t, expected, actual)
}
}
}
func testContainingNetworksAgainstBase(t *testing.T, iterations int, ipGen ipGenerator) {
if testing.Short() {
t.Skip("Skipping memory test in `-short` mode")
}
rangers := []Ranger{NewPCTrieRanger()}
baseRanger := newBruteRanger()
for _, ranger := range rangers {
configureRangerWithAWSRanges(t, ranger)
}
configureRangerWithAWSRanges(t, baseRanger)
for i := 0; i < iterations; i++ {
nn := ipGen()
expected, err := baseRanger.ContainingNetworks(nn.ToIP())
assert.NoError(t, err)
for _, ranger := range rangers {
actual, err := ranger.ContainingNetworks(nn.ToIP())
assert.NoError(t, err)
assert.Equal(t, len(expected), len(actual))
for _, network := range actual {
assert.Contains(t, expected, network)
}
}
}
}
func testCoversNetworksAgainstBase(t *testing.T, iterations int, netGen networkGenerator) {
if testing.Short() {
t.Skip("Skipping memory test in `-short` mode")
}
rangers := []Ranger{NewPCTrieRanger()}
baseRanger := newBruteRanger()
for _, ranger := range rangers {
configureRangerWithAWSRanges(t, ranger)
}
configureRangerWithAWSRanges(t, baseRanger)
for i := 0; i < iterations; i++ {
network := netGen()
expected, err := baseRanger.CoveredNetworks(network.IPNet)
assert.NoError(t, err)
for _, ranger := range rangers {
actual, err := ranger.CoveredNetworks(network.IPNet)
assert.NoError(t, err)
assert.Equal(t, len(expected), len(actual))
for _, network := range actual {
assert.Contains(t, expected, network)
}
}
}
}
/*
******************************************************************
Benchmarks.
******************************************************************
*/
func BenchmarkPCTrieHitIPv4UsingAWSRanges(b *testing.B) {
benchmarkContainsUsingAWSRanges(b, net.ParseIP("52.95.110.1"), NewPCTrieRanger())
}
func BenchmarkBruteRangerHitIPv4UsingAWSRanges(b *testing.B) {
benchmarkContainsUsingAWSRanges(b, net.ParseIP("52.95.110.1"), newBruteRanger())
}
func BenchmarkPCTrieHitIPv6UsingAWSRanges(b *testing.B) {
benchmarkContainsUsingAWSRanges(b, net.ParseIP("2620:107:300f::36b7:ff81"), NewPCTrieRanger())
}
func BenchmarkBruteRangerHitIPv6UsingAWSRanges(b *testing.B) {
benchmarkContainsUsingAWSRanges(b, net.ParseIP("2620:107:300f::36b7:ff81"), newBruteRanger())
}
func BenchmarkPCTrieMissIPv4UsingAWSRanges(b *testing.B) {
benchmarkContainsUsingAWSRanges(b, net.ParseIP("123.123.123.123"), NewPCTrieRanger())
}
func BenchmarkBruteRangerMissIPv4UsingAWSRanges(b *testing.B) {
benchmarkContainsUsingAWSRanges(b, net.ParseIP("123.123.123.123"), newBruteRanger())
}
func BenchmarkPCTrieHMissIPv6UsingAWSRanges(b *testing.B) {
benchmarkContainsUsingAWSRanges(b, net.ParseIP("2620::ffff"), NewPCTrieRanger())
}
func BenchmarkBruteRangerMissIPv6UsingAWSRanges(b *testing.B) {
benchmarkContainsUsingAWSRanges(b, net.ParseIP("2620::ffff"), newBruteRanger())
}
func BenchmarkPCTrieHitContainingNetworksIPv4UsingAWSRanges(b *testing.B) {
benchmarkContainingNetworksUsingAWSRanges(b, net.ParseIP("52.95.110.1"), NewPCTrieRanger())
}
func BenchmarkBruteRangerHitContainingNetworksIPv4UsingAWSRanges(b *testing.B) {
benchmarkContainingNetworksUsingAWSRanges(b, net.ParseIP("52.95.110.1"), newBruteRanger())
}
func BenchmarkPCTrieHitContainingNetworksIPv6UsingAWSRanges(b *testing.B) {
benchmarkContainingNetworksUsingAWSRanges(b, net.ParseIP("2620:107:300f::36b7:ff81"), NewPCTrieRanger())
}
func BenchmarkBruteRangerHitContainingNetworksIPv6UsingAWSRanges(b *testing.B) {
benchmarkContainingNetworksUsingAWSRanges(b, net.ParseIP("2620:107:300f::36b7:ff81"), newBruteRanger())
}
func BenchmarkPCTrieMissContainingNetworksIPv4UsingAWSRanges(b *testing.B) {
benchmarkContainingNetworksUsingAWSRanges(b, net.ParseIP("123.123.123.123"), NewPCTrieRanger())
}
func BenchmarkBruteRangerMissContainingNetworksIPv4UsingAWSRanges(b *testing.B) {
benchmarkContainingNetworksUsingAWSRanges(b, net.ParseIP("123.123.123.123"), newBruteRanger())
}
func BenchmarkPCTrieHMissContainingNetworksIPv6UsingAWSRanges(b *testing.B) {
benchmarkContainingNetworksUsingAWSRanges(b, net.ParseIP("2620::ffff"), NewPCTrieRanger())
}
func BenchmarkBruteRangerMissContainingNetworksIPv6UsingAWSRanges(b *testing.B) {
benchmarkContainingNetworksUsingAWSRanges(b, net.ParseIP("2620::ffff"), newBruteRanger())
}
func benchmarkContainsUsingAWSRanges(tb testing.TB, nn net.IP, ranger Ranger) {
configureRangerWithAWSRanges(tb, ranger)
for n := 0; n < tb.(*testing.B).N; n++ {
ranger.Contains(nn)
}
}
func benchmarkContainingNetworksUsingAWSRanges(tb testing.TB, nn net.IP, ranger Ranger) {
configureRangerWithAWSRanges(tb, ranger)
for n := 0; n < tb.(*testing.B).N; n++ {
ranger.ContainingNetworks(nn)
}
}
/*
******************************************************************
Helper methods and initialization.
******************************************************************
*/
type ipGenerator func() rnet.NetworkNumber
func randIPv4Gen() rnet.NetworkNumber {
return rnet.NetworkNumber{rand.Uint32()}
}
func randIPv6Gen() rnet.NetworkNumber {
return rnet.NetworkNumber{rand.Uint32(), rand.Uint32(), rand.Uint32(), rand.Uint32()}
}
func curatedAWSIPv6Gen() rnet.NetworkNumber {
randIdx := rand.Intn(len(ipV6AWSRangesIPNets))
// Randomly generate an IP somewhat near the range.
network := ipV6AWSRangesIPNets[randIdx]
nn := rnet.NewNetworkNumber(network.IP)
ones, bits := network.Mask.Size()
zeros := bits - ones
nnPartIdx := zeros / rnet.BitsPerUint32
nn[nnPartIdx] = rand.Uint32()
return nn
}
type networkGenerator func() rnet.Network
func randomIPNetGenFactory(pool []*net.IPNet) networkGenerator {
return func() rnet.Network {
return rnet.NewNetwork(*pool[rand.Intn(len(pool))])
}
}
type AWSRanges struct {
Prefixes []Prefix `json:"prefixes"`
IPv6Prefixes []IPv6Prefix `json:"ipv6_prefixes"`
}
type Prefix struct {
IPPrefix string `json:"ip_prefix"`
Region string `json:"region"`
Service string `json:"service"`
}
type IPv6Prefix struct {
IPPrefix string `json:"ipv6_prefix"`
Region string `json:"region"`
Service string `json:"service"`
}
var awsRanges *AWSRanges
var ipV4AWSRangesIPNets []*net.IPNet
var ipV6AWSRangesIPNets []*net.IPNet
func loadAWSRanges() *AWSRanges {
file, err := ioutil.ReadFile("./testdata/aws_ip_ranges.json")
if err != nil {
panic(err)
}
var ranges AWSRanges
err = json.Unmarshal(file, &ranges)
if err != nil {
panic(err)
}
return &ranges
}
func configureRangerWithAWSRanges(tb testing.TB, ranger Ranger) {
for _, prefix := range awsRanges.Prefixes {
_, network, err := net.ParseCIDR(prefix.IPPrefix)
assert.NoError(tb, err)
ranger.Insert(NewBasicRangerEntry(*network))
}
for _, prefix := range awsRanges.IPv6Prefixes {
_, network, err := net.ParseCIDR(prefix.IPPrefix)
assert.NoError(tb, err)
ranger.Insert(NewBasicRangerEntry(*network))
}
}
func init() {
awsRanges = loadAWSRanges()
for _, prefix := range awsRanges.IPv6Prefixes {
_, network, _ := net.ParseCIDR(prefix.IPPrefix)
ipV6AWSRangesIPNets = append(ipV6AWSRangesIPNets, network)
}
for _, prefix := range awsRanges.Prefixes {
_, network, _ := net.ParseCIDR(prefix.IPPrefix)
ipV4AWSRangesIPNets = append(ipV4AWSRangesIPNets, network)
}
rand.Seed(time.Now().Unix())
}
cidranger-1.0.2/example/ 0000775 0000000 0000000 00000000000 13732170323 0015104 5 ustar 00root root 0000000 0000000 cidranger-1.0.2/example/custom-ranger-asn.go 0000664 0000000 0000000 00000004034 13732170323 0021001 0 ustar 00root root 0000000 0000000 /*
Example of how to extend github.com/yl2chen/cidranger
This adds ASN as a string field, along with methods to get the ASN and the CIDR as strings
Thank you to yl2chen for his assistance and work on this library
*/
package main
import (
"fmt"
"net"
"os"
"github.com/yl2chen/cidranger"
)
// custom structure that conforms to RangerEntry interface
type customRangerEntry struct {
ipNet net.IPNet
asn string
}
// get function for network
func (b *customRangerEntry) Network() net.IPNet {
return b.ipNet
}
// get function for network converted to string
func (b *customRangerEntry) NetworkStr() string {
return b.ipNet.String()
}
// get function for ASN
func (b *customRangerEntry) Asn() string {
return b.asn
}
// create customRangerEntry object using net and asn
func newCustomRangerEntry(ipNet net.IPNet, asn string) cidranger.RangerEntry {
return &customRangerEntry{
ipNet: ipNet,
asn: asn,
}
}
// entry point
func main() {
// instantiate NewPCTrieRanger
ranger := cidranger.NewPCTrieRanger()
// Load sample data using our custom function
_, network, _ := net.ParseCIDR("192.168.1.0/24")
ranger.Insert(newCustomRangerEntry(*network, "0001"))
_, network, _ = net.ParseCIDR("128.168.1.0/24")
ranger.Insert(newCustomRangerEntry(*network, "0002"))
// Check if IP is contained within ranger
contains, err := ranger.Contains(net.ParseIP("128.168.1.7"))
if err != nil {
fmt.Println("ranger.Contains()", err.Error())
os.Exit(1)
}
fmt.Println("Contains:", contains)
// request networks containing this IP
ip := "192.168.1.42"
entries, err := ranger.ContainingNetworks(net.ParseIP(ip))
if err != nil {
fmt.Println("ranger.ContainingNetworks()", err.Error())
os.Exit(1)
}
fmt.Printf("Entries for %s:\n", ip)
for _, e := range entries {
// Cast e (cidranger.RangerEntry to struct customRangerEntry
entry, ok := e.(*customRangerEntry)
if !ok {
continue
}
// Get network (converted to string by function)
n := entry.NetworkStr()
// Get ASN
a := entry.Asn()
// Display
fmt.Println("\t", n, a)
}
}
cidranger-1.0.2/go.mod 0000664 0000000 0000000 00000000131 13732170323 0014552 0 ustar 00root root 0000000 0000000 module github.com/yl2chen/cidranger
go 1.13
require github.com/stretchr/testify v1.4.0
cidranger-1.0.2/go.sum 0000664 0000000 0000000 00000001710 13732170323 0014603 0 ustar 00root root 0000000 0000000 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
cidranger-1.0.2/net/ 0000775 0000000 0000000 00000000000 13732170323 0014237 5 ustar 00root root 0000000 0000000 cidranger-1.0.2/net/ip.go 0000664 0000000 0000000 00000015661 13732170323 0015207 0 ustar 00root root 0000000 0000000 /*
Package net provides utility functions for working with IPs (net.IP).
*/
package net
import (
"encoding/binary"
"fmt"
"math"
"net"
)
// IPVersion is version of IP address.
type IPVersion string
// Helper constants.
const (
IPv4Uint32Count = 1
IPv6Uint32Count = 4
BitsPerUint32 = 32
BytePerUint32 = 4
IPv4 IPVersion = "IPv4"
IPv6 IPVersion = "IPv6"
)
// ErrInvalidBitPosition is returned when bits requested is not valid.
var ErrInvalidBitPosition = fmt.Errorf("bit position not valid")
// ErrVersionMismatch is returned upon mismatch in network input versions.
var ErrVersionMismatch = fmt.Errorf("Network input version mismatch")
// ErrNoGreatestCommonBit is an error returned when no greatest common bit
// exists for the cidr ranges.
var ErrNoGreatestCommonBit = fmt.Errorf("No greatest common bit")
// NetworkNumber represents an IP address using uint32 as internal storage.
// IPv4 usings 1 uint32, while IPv6 uses 4 uint32.
type NetworkNumber []uint32
// NewNetworkNumber returns a equivalent NetworkNumber to given IP address,
// return nil if ip is neither IPv4 nor IPv6.
func NewNetworkNumber(ip net.IP) NetworkNumber {
if ip == nil {
return nil
}
coercedIP := ip.To4()
parts := 1
if coercedIP == nil {
coercedIP = ip.To16()
parts = 4
}
if coercedIP == nil {
return nil
}
nn := make(NetworkNumber, parts)
for i := 0; i < parts; i++ {
idx := i * net.IPv4len
nn[i] = binary.BigEndian.Uint32(coercedIP[idx : idx+net.IPv4len])
}
return nn
}
// ToV4 returns ip address if ip is IPv4, returns nil otherwise.
func (n NetworkNumber) ToV4() NetworkNumber {
if len(n) != IPv4Uint32Count {
return nil
}
return n
}
// ToV6 returns ip address if ip is IPv6, returns nil otherwise.
func (n NetworkNumber) ToV6() NetworkNumber {
if len(n) != IPv6Uint32Count {
return nil
}
return n
}
// ToIP returns equivalent net.IP.
func (n NetworkNumber) ToIP() net.IP {
ip := make(net.IP, len(n)*BytePerUint32)
for i := 0; i < len(n); i++ {
idx := i * net.IPv4len
binary.BigEndian.PutUint32(ip[idx:idx+net.IPv4len], n[i])
}
if len(ip) == net.IPv4len {
ip = net.IPv4(ip[0], ip[1], ip[2], ip[3])
}
return ip
}
// Equal is the equality test for 2 network numbers.
func (n NetworkNumber) Equal(n1 NetworkNumber) bool {
if len(n) != len(n1) {
return false
}
if n[0] != n1[0] {
return false
}
if len(n) == IPv6Uint32Count {
return n[1] == n1[1] && n[2] == n1[2] && n[3] == n1[3]
}
return true
}
// Next returns the next logical network number.
func (n NetworkNumber) Next() NetworkNumber {
newIP := make(NetworkNumber, len(n))
copy(newIP, n)
for i := len(newIP) - 1; i >= 0; i-- {
newIP[i]++
if newIP[i] > 0 {
break
}
}
return newIP
}
// Previous returns the previous logical network number.
func (n NetworkNumber) Previous() NetworkNumber {
newIP := make(NetworkNumber, len(n))
copy(newIP, n)
for i := len(newIP) - 1; i >= 0; i-- {
newIP[i]--
if newIP[i] < math.MaxUint32 {
break
}
}
return newIP
}
// Bit returns uint32 representing the bit value at given position, e.g.,
// "128.0.0.0" has bit value of 1 at position 31, and 0 for positions 30 to 0.
func (n NetworkNumber) Bit(position uint) (uint32, error) {
if int(position) > len(n)*BitsPerUint32-1 {
return 0, ErrInvalidBitPosition
}
idx := len(n) - 1 - int(position/BitsPerUint32)
// Mod 31 to get array index.
rShift := position & (BitsPerUint32 - 1)
return (n[idx] >> rShift) & 1, nil
}
// LeastCommonBitPosition returns the smallest position of the preceding common
// bits of the 2 network numbers, and returns an error ErrNoGreatestCommonBit
// if the two network number diverges from the first bit.
// e.g., if the network number diverges after the 1st bit, it returns 131 for
// IPv6 and 31 for IPv4 .
func (n NetworkNumber) LeastCommonBitPosition(n1 NetworkNumber) (uint, error) {
if len(n) != len(n1) {
return 0, ErrVersionMismatch
}
for i := 0; i < len(n); i++ {
mask := uint32(1) << 31
pos := uint(31)
for ; mask > 0; mask >>= 1 {
if n[i]&mask != n1[i]&mask {
if i == 0 && pos == 31 {
return 0, ErrNoGreatestCommonBit
}
return (pos + 1) + uint(BitsPerUint32)*uint(len(n)-i-1), nil
}
pos--
}
}
return 0, nil
}
// Network represents a block of network numbers, also known as CIDR.
type Network struct {
net.IPNet
Number NetworkNumber
Mask NetworkNumberMask
}
// NewNetwork returns Network built using given net.IPNet.
func NewNetwork(ipNet net.IPNet) Network {
return Network{
IPNet: ipNet,
Number: NewNetworkNumber(ipNet.IP),
Mask: NetworkNumberMask(NewNetworkNumber(net.IP(ipNet.Mask))),
}
}
// Masked returns a new network conforming to new mask.
func (n Network) Masked(ones int) Network {
mask := net.CIDRMask(ones, len(n.Number)*BitsPerUint32)
return NewNetwork(net.IPNet{
IP: n.IP.Mask(mask),
Mask: mask,
})
}
// Contains returns true if NetworkNumber is in range of Network, false
// otherwise.
func (n Network) Contains(nn NetworkNumber) bool {
if len(n.Mask) != len(nn) {
return false
}
if nn[0]&n.Mask[0] != n.Number[0] {
return false
}
if len(nn) == IPv6Uint32Count {
return nn[1]&n.Mask[1] == n.Number[1] && nn[2]&n.Mask[2] == n.Number[2] && nn[3]&n.Mask[3] == n.Number[3]
}
return true
}
// Contains returns true if Network covers o, false otherwise
func (n Network) Covers(o Network) bool {
if len(n.Number) != len(o.Number) {
return false
}
nMaskSize, _ := n.IPNet.Mask.Size()
oMaskSize, _ := o.IPNet.Mask.Size()
return n.Contains(o.Number) && nMaskSize <= oMaskSize
}
// LeastCommonBitPosition returns the smallest position of the preceding common
// bits of the 2 networks, and returns an error ErrNoGreatestCommonBit
// if the two network number diverges from the first bit.
func (n Network) LeastCommonBitPosition(n1 Network) (uint, error) {
maskSize, _ := n.IPNet.Mask.Size()
if maskSize1, _ := n1.IPNet.Mask.Size(); maskSize1 < maskSize {
maskSize = maskSize1
}
maskPosition := len(n1.Number)*BitsPerUint32 - maskSize
lcb, err := n.Number.LeastCommonBitPosition(n1.Number)
if err != nil {
return 0, err
}
return uint(math.Max(float64(maskPosition), float64(lcb))), nil
}
// Equal is the equality test for 2 networks.
func (n Network) Equal(n1 Network) bool {
return n.String() == n1.String()
}
func (n Network) String() string {
return n.IPNet.String()
}
// NetworkNumberMask is an IP address.
type NetworkNumberMask NetworkNumber
// Mask returns a new masked NetworkNumber from given NetworkNumber.
func (m NetworkNumberMask) Mask(n NetworkNumber) (NetworkNumber, error) {
if len(m) != len(n) {
return nil, ErrVersionMismatch
}
result := make(NetworkNumber, len(m))
result[0] = m[0] & n[0]
if len(m) == IPv6Uint32Count {
result[1] = m[1] & n[1]
result[2] = m[2] & n[2]
result[3] = m[3] & n[3]
}
return result, nil
}
// NextIP returns the next sequential ip.
func NextIP(ip net.IP) net.IP {
return NewNetworkNumber(ip).Next().ToIP()
}
// PreviousIP returns the previous sequential ip.
func PreviousIP(ip net.IP) net.IP {
return NewNetworkNumber(ip).Previous().ToIP()
}
cidranger-1.0.2/net/ip_test.go 0000664 0000000 0000000 00000035040 13732170323 0016237 0 ustar 00root root 0000000 0000000 package net
import (
"math"
"net"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewNetworkNumber(t *testing.T) {
cases := []struct {
ip net.IP
nn NetworkNumber
name string
}{
{nil, nil, "nil input"},
{net.IP([]byte{1, 1, 1, 1, 1}), nil, "bad input"},
{net.ParseIP("128.0.0.0"), NetworkNumber([]uint32{2147483648}), "IPv4"},
{
net.ParseIP("2001:0db8::ff00:0042:8329"),
NetworkNumber([]uint32{536939960, 0, 65280, 4358953}),
"IPv6",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.nn, NewNetworkNumber(tc.ip))
})
}
}
func TestNetworkNumberAssertion(t *testing.T) {
cases := []struct {
ip NetworkNumber
to4 NetworkNumber
to6 NetworkNumber
name string
}{
{NetworkNumber([]uint32{1}), NetworkNumber([]uint32{1}), nil, "is IPv4"},
{NetworkNumber([]uint32{1, 1, 1, 1}), nil, NetworkNumber([]uint32{1, 1, 1, 1}), "is IPv6"},
{NetworkNumber([]uint32{1, 1}), nil, nil, "is invalid"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.to4, tc.ip.ToV4())
assert.Equal(t, tc.to6, tc.ip.ToV6())
})
}
}
func TestNetworkNumberBit(t *testing.T) {
cases := []struct {
ip NetworkNumber
ones map[uint]bool
name string
}{
{NewNetworkNumber(net.ParseIP("128.0.0.0")), map[uint]bool{31: true}, "128.0.0.0"},
{NewNetworkNumber(net.ParseIP("1.1.1.1")), map[uint]bool{0: true, 8: true, 16: true, 24: true}, "1.1.1.1"},
{NewNetworkNumber(net.ParseIP("8000::")), map[uint]bool{127: true}, "8000::"},
{NewNetworkNumber(net.ParseIP("8000::8000")), map[uint]bool{127: true, 15: true}, "8000::8000"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
for i := uint(0); i < uint(len(tc.ip)*BitsPerUint32); i++ {
bit, err := tc.ip.Bit(i)
assert.NoError(t, err)
if _, isOne := tc.ones[i]; isOne {
assert.Equal(t, uint32(1), bit)
} else {
assert.Equal(t, uint32(0), bit)
}
}
})
}
}
func TestNetworkNumberBitError(t *testing.T) {
cases := []struct {
ip NetworkNumber
position uint
err error
name string
}{
{NewNetworkNumber(net.ParseIP("128.0.0.0")), 0, nil, "IPv4 index in bound"},
{NewNetworkNumber(net.ParseIP("128.0.0.0")), 31, nil, "IPv4 index in bound"},
{NewNetworkNumber(net.ParseIP("128.0.0.0")), 32, ErrInvalidBitPosition, "IPv4 index out of bounds"},
{NewNetworkNumber(net.ParseIP("8000::")), 0, nil, "IPv6 index in bound"},
{NewNetworkNumber(net.ParseIP("8000::")), 127, nil, "IPv6 index in bound"},
{NewNetworkNumber(net.ParseIP("8000::")), 128, ErrInvalidBitPosition, "IPv6 index out of bounds"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, err := tc.ip.Bit(tc.position)
assert.Equal(t, tc.err, err)
})
}
}
func TestNetworkNumberEqual(t *testing.T) {
cases := []struct {
n1 NetworkNumber
n2 NetworkNumber
equals bool
name string
}{
{NetworkNumber{math.MaxUint32}, NetworkNumber{math.MaxUint32}, true, "IPv4 equals"},
{NetworkNumber{math.MaxUint32}, NetworkNumber{math.MaxUint32 - 1}, false, "IPv4 does not equal"},
{NetworkNumber{1, 1, 1, 1}, NetworkNumber{1, 1, 1, 1}, true, "IPv6 equals"},
{NetworkNumber{1, 1, 1, 1}, NetworkNumber{1, 1, 1, 2}, false, "IPv6 does not equal"},
{NetworkNumber{1}, NetworkNumber{1, 2, 3, 4}, false, "Version mismatch"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.equals, tc.n1.Equal(tc.n2))
})
}
}
func TestNetworkNumberNext(t *testing.T) {
cases := []struct {
ip string
next string
name string
}{
{"0.0.0.0", "0.0.0.1", "IPv4 basic"},
{"0.0.0.255", "0.0.1.0", "IPv4 rollover"},
{"0.255.255.255", "1.0.0.0", "IPv4 consecutive rollover"},
{"8000::0", "8000::1", "IPv6 basic"},
{"0::ffff", "0::1:0", "IPv6 rollover"},
{"0:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "1::", "IPv6 consecutive rollover"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
ip := NewNetworkNumber(net.ParseIP(tc.ip))
expected := NewNetworkNumber(net.ParseIP(tc.next))
assert.Equal(t, expected, ip.Next())
})
}
}
func TestNeworkNumberPrevious(t *testing.T) {
cases := []struct {
ip string
previous string
name string
}{
{"0.0.0.1", "0.0.0.0", "IPv4 basic"},
{"0.0.1.0", "0.0.0.255", "IPv4 rollover"},
{"1.0.0.0", "0.255.255.255", "IPv4 consecutive rollover"},
{"8000::1", "8000::0", "IPv6 basic"},
{"0::1:0", "0::ffff", "IPv6 rollover"},
{"1::0", "0:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "IPv6 consecutive rollover"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
ip := NewNetworkNumber(net.ParseIP(tc.ip))
expected := NewNetworkNumber(net.ParseIP(tc.previous))
assert.Equal(t, expected, ip.Previous())
})
}
}
func TestLeastCommonBitPositionForNetworks(t *testing.T) {
cases := []struct {
ip1 NetworkNumber
ip2 NetworkNumber
position uint
err error
name string
}{
{
NetworkNumber([]uint32{2147483648}),
NetworkNumber([]uint32{3221225472, 0, 0, 0}),
0, ErrVersionMismatch, "Version mismatch",
},
{
NetworkNumber([]uint32{2147483648}),
NetworkNumber([]uint32{3221225472}),
31, nil, "IPv4 31st position",
},
{
NetworkNumber([]uint32{2147483648}),
NetworkNumber([]uint32{2147483648}),
0, nil, "IPv4 0th position",
},
{
NetworkNumber([]uint32{2147483648}),
NetworkNumber([]uint32{1}),
0, ErrNoGreatestCommonBit, "IPv4 diverge at first bit",
},
{
NetworkNumber([]uint32{2147483648, 0, 0, 0}),
NetworkNumber([]uint32{3221225472, 0, 0, 0}),
127, nil, "IPv6 127th position",
},
{
NetworkNumber([]uint32{2147483648, 1, 1, 1}),
NetworkNumber([]uint32{2147483648, 1, 1, 1}),
0, nil, "IPv6 0th position",
},
{
NetworkNumber([]uint32{2147483648, 0, 0, 0}),
NetworkNumber([]uint32{0, 0, 0, 1}),
0, ErrNoGreatestCommonBit, "IPv6 diverge at first bit",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
pos, err := tc.ip1.LeastCommonBitPosition(tc.ip2)
assert.Equal(t, tc.err, err)
assert.Equal(t, tc.position, pos)
})
}
}
func TestNewNetwork(t *testing.T) {
_, ipNet, _ := net.ParseCIDR("192.128.0.0/24")
n := NewNetwork(*ipNet)
assert.Equal(t, *ipNet, n.IPNet)
assert.Equal(t, NetworkNumber{3229614080}, n.Number)
assert.Equal(t, NetworkNumberMask{math.MaxUint32 - uint32(math.MaxUint8)}, n.Mask)
}
func TestNetworkMasked(t *testing.T) {
cases := []struct {
network string
mask int
maskedNetwork string
}{
{"192.168.0.0/16", 16, "192.168.0.0/16"},
{"192.168.0.0/16", 14, "192.168.0.0/14"},
{"192.168.0.0/16", 18, "192.168.0.0/18"},
{"192.168.0.0/16", 8, "192.0.0.0/8"},
{"8000::/128", 96, "8000::/96"},
{"8000::/128", 128, "8000::/128"},
{"8000::/96", 112, "8000::/112"},
{"8000:ffff::/96", 16, "8000::/16"},
}
for _, testcase := range cases {
_, network, _ := net.ParseCIDR(testcase.network)
_, expected, _ := net.ParseCIDR(testcase.maskedNetwork)
n1 := NewNetwork(*network)
e1 := NewNetwork(*expected)
assert.True(t, e1.String() == n1.Masked(testcase.mask).String())
}
}
func TestNetworkEqual(t *testing.T) {
cases := []struct {
n1 string
n2 string
equal bool
name string
}{
{"192.128.0.0/24", "192.128.0.0/24", true, "IPv4 equals"},
{"192.128.0.0/24", "192.128.0.0/23", false, "IPv4 not equals"},
{"8000::/24", "8000::/24", true, "IPv6 equals"},
{"8000::/24", "8000::/23", false, "IPv6 not equals"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, ipNet1, _ := net.ParseCIDR(tc.n1)
_, ipNet2, _ := net.ParseCIDR(tc.n2)
assert.Equal(t, tc.equal, NewNetwork(*ipNet1).Equal(NewNetwork(*ipNet2)))
})
}
}
func TestNetworkContains(t *testing.T) {
cases := []struct {
network string
firstIP string
lastIP string
name string
}{
{"192.168.0.0/24", "192.168.0.0", "192.168.0.255", "192.168.0.0/24 contains"},
{"8000::0/120", "8000::0", "8000::ff", "8000::0/120 contains"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, net1, _ := net.ParseCIDR(tc.network)
network := NewNetwork(*net1)
ip := NewNetworkNumber(net.ParseIP(tc.firstIP))
lastIP := NewNetworkNumber(net.ParseIP(tc.lastIP))
assert.False(t, network.Contains(ip.Previous()))
assert.False(t, network.Contains(lastIP.Next()))
for ; !ip.Equal(lastIP.Next()); ip = ip.Next() {
assert.True(t, network.Contains(ip))
}
})
}
}
func TestNetworkContainsVersionMismatch(t *testing.T) {
cases := []struct {
network string
ip string
name string
}{
{"192.168.0.0/24", "8000::0", "IPv6 in IPv4 network"},
{"8000::0/120", "192.168.0.0", "IPv4 in IPv6 network"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, net1, _ := net.ParseCIDR(tc.network)
network := NewNetwork(*net1)
assert.False(t, network.Contains(NewNetworkNumber(net.ParseIP(tc.ip))))
})
}
}
func TestNetworkCovers(t *testing.T) {
cases := []struct {
network string
covers string
result bool
name string
}{
{"10.0.0.0/24", "10.0.0.1/25", true, "contains"},
{"10.0.0.0/24", "11.0.0.1/25", false, "not contains"},
{"10.0.0.0/16", "10.0.0.0/15", false, "prefix false"},
{"10.0.0.0/15", "10.0.0.0/16", true, "prefix true"},
{"10.0.0.0/15", "10.0.0.0/15", true, "same"},
{"10::0/15", "10.0.0.0/15", false, "ip version mismatch"},
{"10::0/15", "10::0/16", true, "ipv6"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, n, _ := net.ParseCIDR(tc.network)
network := NewNetwork(*n)
_, n, _ = net.ParseCIDR(tc.covers)
covers := NewNetwork(*n)
assert.Equal(t, tc.result, network.Covers(covers))
})
}
}
func TestNetworkLeastCommonBitPosition(t *testing.T) {
cases := []struct {
cidr1 string
cidr2 string
expectedPos uint
expectedErr error
name string
}{
{"0.0.1.0/24", "0.0.0.0/24", uint(9), nil, "IPv4 diverge before mask pos"},
{"0.0.0.0/24", "0.0.0.0/24", uint(8), nil, "IPv4 diverge after mask pos"},
{"0.0.0.128/24", "0.0.0.0/16", uint(16), nil, "IPv4 different mask pos"},
{"128.0.0.0/24", "0.0.0.0/24", 0, ErrNoGreatestCommonBit, "IPv4 diverge at 1st pos"},
{"8000::/96", "8000::1:0:0/96", uint(33), nil, "IPv6 diverge before mask pos"},
{"8000::/96", "8000::8:0/96", uint(32), nil, "IPv6 diverge after mask pos"},
{"8000::/96", "8000::/95", uint(33), nil, "IPv6 different mask pos"},
{"ffff::0/24", "0::1/24", 0, ErrNoGreatestCommonBit, "IPv6 diverge at 1st pos"},
}
for _, c := range cases {
_, cidr1, err := net.ParseCIDR(c.cidr1)
assert.NoError(t, err)
_, cidr2, err := net.ParseCIDR(c.cidr2)
assert.NoError(t, err)
n1 := NewNetwork(*cidr1)
pos, err := n1.LeastCommonBitPosition(NewNetwork(*cidr2))
if c.expectedErr != nil {
assert.Equal(t, c.expectedErr, err)
} else {
assert.Equal(t, c.expectedPos, pos)
}
}
}
func TestMask(t *testing.T) {
cases := []struct {
mask NetworkNumberMask
ip NetworkNumber
masked NetworkNumber
err error
name string
}{
{NetworkNumberMask{math.MaxUint32}, NetworkNumber{math.MaxUint32}, NetworkNumber{math.MaxUint32}, nil, "nop IPv4 mask"},
{NetworkNumberMask{math.MaxUint32 - math.MaxUint16}, NetworkNumber{math.MaxUint16 + 1}, NetworkNumber{math.MaxUint16 + 1}, nil, "nop IPv4 mask"},
{NetworkNumberMask{math.MaxUint32 - math.MaxUint16}, NetworkNumber{math.MaxUint32}, NetworkNumber{math.MaxUint32 - math.MaxUint16}, nil, "IPv4 masked"},
{NetworkNumberMask{math.MaxUint32, 0, 0, 0}, NetworkNumber{math.MaxUint32, 0, 0, 0}, NetworkNumber{math.MaxUint32, 0, 0, 0}, nil, "nop IPv6 mask"},
{NetworkNumberMask{math.MaxUint32 - math.MaxUint16, 0, 0, 0}, NetworkNumber{math.MaxUint16 + 1, 0, 0, 0}, NetworkNumber{math.MaxUint16 + 1, 0, 0, 0}, nil, "nop IPv6 mask"},
{NetworkNumberMask{math.MaxUint32 - math.MaxUint16, 0, 0, 0}, NetworkNumber{math.MaxUint32, 0, 0, 0}, NetworkNumber{math.MaxUint32 - math.MaxUint16, 0, 0, 0}, nil, "IPv6 masked"},
{NetworkNumberMask{math.MaxUint32}, NetworkNumber{math.MaxUint32, 0}, nil, ErrVersionMismatch, "Version mismatch"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
masked, err := tc.mask.Mask(tc.ip)
assert.Equal(t, tc.masked, masked)
assert.Equal(t, tc.err, err)
})
}
}
func TestNextIP(t *testing.T) {
cases := []struct {
ip string
next string
name string
}{
{"0.0.0.0", "0.0.0.1", "IPv4 basic"},
{"0.0.0.255", "0.0.1.0", "IPv4 rollover"},
{"0.255.255.255", "1.0.0.0", "IPv4 consecutive rollover"},
{"8000::0", "8000::1", "IPv6 basic"},
{"0::ffff", "0::1:0", "IPv6 rollover"},
{"0:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "1::", "IPv6 consecutive rollover"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, net.ParseIP(tc.next), NextIP(net.ParseIP(tc.ip)))
})
}
}
func TestPreviousIP(t *testing.T) {
cases := []struct {
ip string
next string
name string
}{
{"0.0.0.1", "0.0.0.0", "IPv4 basic"},
{"0.0.1.0", "0.0.0.255", "IPv4 rollover"},
{"1.0.0.0", "0.255.255.255", "IPv4 consecutive rollover"},
{"8000::1", "8000::0", "IPv6 basic"},
{"0::1:0", "0::ffff", "IPv6 rollover"},
{"1::0", "0:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "IPv6 consecutive rollover"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, net.ParseIP(tc.next), PreviousIP(net.ParseIP(tc.ip)))
})
}
}
/*
*********************************
Benchmarking ip manipulations.
*********************************
*/
func BenchmarkNetworkNumberBitIPv4(b *testing.B) {
benchmarkNetworkNumberBit(b, "52.95.110.1", 6)
}
func BenchmarkNetworkNumberBitIPv6(b *testing.B) {
benchmarkNetworkNumberBit(b, "2600:1ffe:e000::", 44)
}
func BenchmarkNetworkNumberEqualIPv4(b *testing.B) {
benchmarkNetworkNumberEqual(b, "52.95.110.1", "52.95.110.1")
}
func BenchmarkNetworkNumberEqualIPv6(b *testing.B) {
benchmarkNetworkNumberEqual(b, "2600:1ffe:e000::", "2600:1ffe:e000::")
}
func BenchmarkNetworkContainsIPv4(b *testing.B) {
benchmarkNetworkContains(b, "52.95.110.0/24", "52.95.110.1")
}
func BenchmarkNetworkContainsIPv6(b *testing.B) {
benchmarkNetworkContains(b, "2600:1ffe:e000::/40", "2600:1ffe:f000::")
}
func benchmarkNetworkNumberBit(b *testing.B, ip string, pos uint) {
nn := NewNetworkNumber(net.ParseIP(ip))
for n := 0; n < b.N; n++ {
nn.Bit(pos)
}
}
func benchmarkNetworkNumberEqual(b *testing.B, ip1 string, ip2 string) {
nn1 := NewNetworkNumber(net.ParseIP(ip1))
nn2 := NewNetworkNumber(net.ParseIP(ip2))
for n := 0; n < b.N; n++ {
nn1.Equal(nn2)
}
}
func benchmarkNetworkContains(b *testing.B, cidr string, ip string) {
nn := NewNetworkNumber(net.ParseIP(ip))
_, ipNet, _ := net.ParseCIDR(cidr)
network := NewNetwork(*ipNet)
for n := 0; n < b.N; n++ {
network.Contains(nn)
}
}
cidranger-1.0.2/testdata/ 0000775 0000000 0000000 00000000000 13732170323 0015262 5 ustar 00root root 0000000 0000000 cidranger-1.0.2/testdata/aws_ip_ranges.json 0000664 0000000 0000000 00000407470 13732170323 0021012 0 ustar 00root root 0000000 0000000 {
"syncToken": "1502143334",
"createDate": "2017-08-07-22-02-14",
"prefixes": [
{
"ip_prefix": "13.32.0.0/15",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "13.54.0.0/15",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "13.56.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "13.57.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "13.58.0.0/15",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "13.112.0.0/14",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "13.124.0.0/16",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "13.125.0.0/16",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "13.126.0.0/15",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "13.209.0.0/16",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "13.210.0.0/15",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "13.228.0.0/15",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "13.230.0.0/15",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "13.232.0.0/14",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "13.236.0.0/14",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "13.250.0.0/15",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "18.194.0.0/15",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "18.196.0.0/15",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "18.216.0.0/14",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "18.220.0.0/14",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "18.231.0.0/16",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "23.20.0.0/14",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "27.0.0.0/22",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "34.192.0.0/12",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "34.208.0.0/12",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "34.224.0.0/12",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "34.240.0.0/13",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "34.248.0.0/13",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "35.154.0.0/16",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "35.155.0.0/16",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "35.156.0.0/14",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "35.160.0.0/13",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "35.168.0.0/13",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "35.176.0.0/15",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "35.178.0.0/15",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "35.180.0.0/15",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "35.182.0.0/15",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "43.250.192.0/24",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "43.250.193.0/24",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "46.51.128.0/18",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "46.51.192.0/20",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "46.51.216.0/21",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "46.51.224.0/19",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "46.137.0.0/17",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "46.137.128.0/18",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "46.137.192.0/19",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "46.137.224.0/19",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "50.16.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "50.18.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "50.19.0.0/16",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "50.112.0.0/16",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.0.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.2.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.4.0.0/14",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.8.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.9.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.10.0.0/15",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.12.0.0/15",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.14.0.0/16",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.15.0.0/16",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.16.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.18.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.20.0.0/14",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.24.0.0/14",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.28.0.0/16",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.29.0.0/16",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.30.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.32.0.0/14",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.36.0.0/14",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.40.0.0/14",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.44.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.46.0.0/18",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "52.46.64.0/20",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.46.80.0/21",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.46.88.0/22",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.46.92.0/22",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.47.0.0/16",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.48.0.0/14",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.52.0.0/15",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.54.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.56.0.0/16",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.57.0.0/16",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.58.0.0/15",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.60.0.0/16",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.61.0.0/16",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.62.0.0/15",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.64.0.0/17",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.64.128.0/17",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.65.0.0/16",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.66.0.0/16",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.67.0.0/16",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.68.0.0/15",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.70.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.72.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.74.0.0/16",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.76.0.0/17",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.76.128.0/17",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.77.0.0/16",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.78.0.0/16",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.79.0.0/16",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.80.0.0/16",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.82.187.0/24",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.82.188.0/22",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.82.196.0/22",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.82.200.0/25",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.82.204.0/23",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.82.208.0/20",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.83.0.0/16",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.84.0.0/15",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "52.86.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.88.0.0/15",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.90.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.0.0/20",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.16.0/20",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.32.0/22",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.39.0/24",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.40.0/21",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.48.0/22",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.52.0/22",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.56.0/22",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.60.0/22",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.64.0/22",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.68.0/22",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.72.0/22",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.76.0/22",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.80.0/22",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.84.0/22",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.88.0/22",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.248.0/22",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.92.252.0/22",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.93.0.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.93.1.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.93.2.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.93.3.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.93.4.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.93.5.0/24",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.93.8.0/22",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.93.16.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.0.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.4.0/24",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.5.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.6.0/24",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.7.0/24",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.8.0/24",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.9.0/24",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.10.0/24",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.11.0/24",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.12.0/24",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.13.0/24",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.14.0/24",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.15.0/24",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.16.0/24",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.17.0/24",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.20.0/24",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.24.0/23",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.26.0/23",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.28.0/23",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.30.0/23",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.32.0/20",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.48.0/20",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.64.0/22",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.72.0/22",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.80.0/20",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.96.0/20",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.112.0/22",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.192.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.196.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.197.0/24",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.0/28",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.16/28",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.32/28",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.48/28",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.64/28",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.80/28",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.96/28",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.112/28",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.128/28",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.198.144/28",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.199.0/24",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.200.0/24",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.204.0/23",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.206.0/23",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.208.0/21",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.216.0/21",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.224.0/20",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.240.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.244.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.0/28",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.16/28",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.32/28",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.48/28",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.64/28",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.80/28",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.96/28",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.112/28",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.128/28",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.144/28",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.160/28",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.176/28",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.192/28",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.208/28",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.248.224/28",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.249.0/28",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.249.16/28",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.249.32/28",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.249.64/28",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.249.80/28",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.252.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.94.254.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.0.0/20",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.16.0/21",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.24.0/22",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.28.0/24",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.30.0/23",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.34.0/24",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.35.0/24",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.36.0/22",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.40.0/24",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.48.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.56.0/22",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.60.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.61.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.62.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.63.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.64.0/20",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.80.0/20",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.96.0/22",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.100.0/22",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.104.0/22",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.108.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.110.0/24",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.111.0/24",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.112.0/20",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.128.0/21",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.136.0/23",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.138.0/24",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.142.0/23",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.144.0/24",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.145.0/24",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.146.0/23",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.148.0/23",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.150.0/24",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.154.0/23",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.156.0/24",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.192.0/20",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.212.0/22",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.240.0/24",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.241.0/24",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.242.0/24",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.243.0/24",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.244.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.245.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.246.0/24",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.247.0/24",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.248.0/24",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.249.0/24",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.250.0/24",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.251.0/24",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.252.0/24",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.253.0/24",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.254.0/24",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.0/28",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.16/28",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.32/28",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.48/28",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.64/28",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.80/28",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.96/28",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.112/28",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.128/28",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.95.255.144/28",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.160.0/20",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.176.0/21",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.184.0/22",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.188.0/22",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.192.0/22",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.196.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.206.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.208.0/23",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.212.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.214.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.216.0/21",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.224.0/21",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.119.232.0/21",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.192.0.0/15",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.196.0.0/14",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.200.0.0/13",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.208.0.0/13",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.216.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.218.0.0/17",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.218.128.0/17",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.0.0/20",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.16.0/22",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.20.0/22",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.24.0/21",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.32.0/21",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.40.0/22",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.44.0/22",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.56.0/22",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.60.0/23",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.62.0/23",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.64.0/22",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.68.0/22",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.72.0/22",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.76.0/22",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.219.80.0/20",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "52.220.0.0/15",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.222.0.0/17",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "52.222.128.0/17",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "54.64.0.0/15",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.66.0.0/16",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.67.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.68.0.0/14",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.72.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.74.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.76.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.78.0.0/16",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.79.0.0/16",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.80.0.0/13",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.88.0.0/14",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.92.0.0/17",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.92.128.0/17",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.93.0.0/16",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.94.0.0/16",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.95.0.0/16",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.144.0.0/14",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.148.0.0/15",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.150.0.0/16",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.151.0.0/17",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.151.128.0/17",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.152.0.0/16",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.153.0.0/17",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.153.128.0/17",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.154.0.0/16",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.155.0.0/16",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.156.0.0/14",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.160.0.0/13",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.168.0.0/16",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.169.0.0/16",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.170.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.172.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.174.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.176.0.0/15",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.178.0.0/16",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.179.0.0/16",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.182.0.0/16",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "54.183.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.184.0.0/13",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.192.0.0/16",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "54.193.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.194.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.196.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.198.0.0/16",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.199.0.0/16",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.200.0.0/15",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.202.0.0/15",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.204.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.206.0.0/16",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.207.0.0/16",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.208.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.210.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.212.0.0/15",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.214.0.0/16",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.215.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.216.0.0/15",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.218.0.0/16",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.219.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.220.0.0/16",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.221.0.0/16",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.222.0.0/19",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.222.48.0/22",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.222.57.0/24",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.222.58.0/28",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.222.128.0/17",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.223.0.0/16",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.224.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.226.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.228.0.0/16",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.229.0.0/16",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.230.0.0/16",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.0.0/17",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.128.0/19",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.160.0/19",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.192.0/20",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.224.0/21",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.232.0/21",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.240.0/22",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.244.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.248.0/22",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.252.0/24",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.231.253.0/24",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.232.0.0/16",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.233.0.0/18",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.233.64.0/18",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.233.128.0/17",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.234.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.236.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.238.0.0/16",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.0/28",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.16/28",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.32/28",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.48/28",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.64/28",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.80/28",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.96/28",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.112/28",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.128/28",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.144/28",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.160/28",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.176/28",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.192/28",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.208/28",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.224/28",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.0.240/28",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.1.0/28",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.1.16/28",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.2.0/23",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.4.0/22",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.8.0/21",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.16.0/20",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.32.0/21",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.48.0/22",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.52.0/23",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.54.0/23",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.56.0/21",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.96.0/24",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.98.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.99.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.100.0/23",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.104.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.108.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.116.0/22",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.120.0/21",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.128.0/18",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "54.239.192.0/19",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.128.0/18",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.192.0/22",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.196.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.197.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.198.0/24",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.199.0/24",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.200.0/24",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.202.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.203.0/24",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.204.0/22",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.208.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.212.0/22",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.216.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.220.0/22",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.225.0/24",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.226.0/24",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.227.0/24",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.228.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.230.0/23",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.232.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.244.0/22",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.240.248.0/21",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.241.0.0/16",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.242.0.0/15",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.244.0.0/16",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.245.0.0/16",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.246.0.0/16",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.247.0.0/16",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.248.0.0/15",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.250.0.0/16",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.251.0.0/16",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.252.0.0/16",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.253.0.0/16",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "54.254.0.0/16",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.255.0.0/16",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "67.202.0.0/18",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "72.21.192.0/19",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "72.44.32.0/19",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "75.101.128.0/17",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "79.125.0.0/17",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "87.238.80.0/21",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "96.127.0.0/17",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "103.4.8.0/22",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "103.4.12.0/22",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "103.8.172.0/22",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ip_prefix": "103.246.148.0/23",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "103.246.150.0/23",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "107.20.0.0/14",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "122.248.192.0/18",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "172.96.97.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "172.96.98.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "174.129.0.0/16",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "175.41.128.0/18",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "175.41.192.0/18",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.32.64.0/19",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.32.96.0/21",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.32.104.0/21",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.32.112.0/21",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.32.120.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.32.125.0/25",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "176.34.0.0/19",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.34.32.0/19",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.34.64.0/18",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "176.34.128.0/17",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "177.71.128.0/17",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "177.72.240.0/21",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "178.236.0.0/20",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "184.72.0.0/18",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "184.72.64.0/18",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "184.72.128.0/17",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "184.73.0.0/16",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "184.169.128.0/17",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "185.48.120.0/22",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "185.143.16.0/24",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "203.83.220.0/22",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ip_prefix": "204.236.128.0/18",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "204.236.192.0/18",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "204.246.160.0/22",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "204.246.164.0/22",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "204.246.168.0/22",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "204.246.174.0/23",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "204.246.176.0/20",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.192.0/19",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.224.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.228.0/22",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.232.0/22",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.236.0/22",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.240.0/22",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.244.0/23",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.247.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.248.0/24",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.249.0/24",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.250.0/23",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.252.0/23",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "205.251.254.0/24",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "207.171.160.0/20",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "207.171.176.0/20",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "216.137.32.0/19",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ip_prefix": "216.182.224.0/20",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "54.183.255.128/26",
"region": "us-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.228.16.0/26",
"region": "eu-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.232.40.64/26",
"region": "sa-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.241.32.64/26",
"region": "us-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.243.31.192/26",
"region": "us-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.244.52.192/26",
"region": "us-west-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.245.168.0/26",
"region": "us-west-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.248.220.0/26",
"region": "ap-northeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.250.253.192/26",
"region": "ap-northeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.251.31.128/26",
"region": "ap-southeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.252.79.128/26",
"region": "ap-southeast-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.252.254.192/26",
"region": "ap-southeast-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "54.255.254.192/26",
"region": "ap-southeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "107.23.255.0/26",
"region": "us-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "176.34.159.192/26",
"region": "eu-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "177.71.207.128/26",
"region": "sa-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ip_prefix": "52.82.188.0/22",
"region": "cn-northwest-1",
"service": "S3"
},
{
"ip_prefix": "52.92.0.0/20",
"region": "ap-northeast-2",
"service": "S3"
},
{
"ip_prefix": "52.92.16.0/20",
"region": "us-east-1",
"service": "S3"
},
{
"ip_prefix": "52.92.32.0/22",
"region": "us-west-2",
"service": "S3"
},
{
"ip_prefix": "52.92.39.0/24",
"region": "sa-east-1",
"service": "S3"
},
{
"ip_prefix": "52.92.40.0/21",
"region": "eu-west-1",
"service": "S3"
},
{
"ip_prefix": "52.92.48.0/22",
"region": "us-west-1",
"service": "S3"
},
{
"ip_prefix": "52.92.52.0/22",
"region": "ap-southeast-2",
"service": "S3"
},
{
"ip_prefix": "52.92.56.0/22",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ip_prefix": "52.92.60.0/22",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ip_prefix": "52.92.64.0/22",
"region": "sa-east-1",
"service": "S3"
},
{
"ip_prefix": "52.92.68.0/22",
"region": "eu-central-1",
"service": "S3"
},
{
"ip_prefix": "52.92.72.0/22",
"region": "sa-east-1",
"service": "S3"
},
{
"ip_prefix": "52.92.76.0/22",
"region": "us-east-2",
"service": "S3"
},
{
"ip_prefix": "52.92.80.0/22",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ip_prefix": "52.92.84.0/22",
"region": "ca-central-1",
"service": "S3"
},
{
"ip_prefix": "52.92.88.0/22",
"region": "eu-west-2",
"service": "S3"
},
{
"ip_prefix": "52.92.248.0/22",
"region": "ap-south-1",
"service": "S3"
},
{
"ip_prefix": "52.92.252.0/22",
"region": "us-gov-west-1",
"service": "S3"
},
{
"ip_prefix": "52.95.128.0/21",
"region": "ap-southeast-2",
"service": "S3"
},
{
"ip_prefix": "52.95.136.0/23",
"region": "sa-east-1",
"service": "S3"
},
{
"ip_prefix": "52.95.138.0/24",
"region": "sa-east-1",
"service": "S3"
},
{
"ip_prefix": "52.95.142.0/23",
"region": "us-gov-west-1",
"service": "S3"
},
{
"ip_prefix": "52.95.144.0/24",
"region": "us-gov-west-1",
"service": "S3"
},
{
"ip_prefix": "52.95.145.0/24",
"region": "ca-central-1",
"service": "S3"
},
{
"ip_prefix": "52.95.146.0/23",
"region": "ca-central-1",
"service": "S3"
},
{
"ip_prefix": "52.95.148.0/23",
"region": "eu-west-2",
"service": "S3"
},
{
"ip_prefix": "52.95.150.0/24",
"region": "eu-west-2",
"service": "S3"
},
{
"ip_prefix": "52.95.154.0/23",
"region": "eu-west-3",
"service": "S3"
},
{
"ip_prefix": "52.95.156.0/24",
"region": "eu-west-3",
"service": "S3"
},
{
"ip_prefix": "52.216.0.0/15",
"region": "us-east-1",
"service": "S3"
},
{
"ip_prefix": "52.218.0.0/17",
"region": "eu-west-1",
"service": "S3"
},
{
"ip_prefix": "52.218.128.0/17",
"region": "us-west-2",
"service": "S3"
},
{
"ip_prefix": "52.219.0.0/20",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ip_prefix": "52.219.16.0/22",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ip_prefix": "52.219.20.0/22",
"region": "us-west-1",
"service": "S3"
},
{
"ip_prefix": "52.219.24.0/21",
"region": "us-west-1",
"service": "S3"
},
{
"ip_prefix": "52.219.32.0/21",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ip_prefix": "52.219.40.0/22",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ip_prefix": "52.219.44.0/22",
"region": "eu-central-1",
"service": "S3"
},
{
"ip_prefix": "52.219.56.0/22",
"region": "ap-northeast-2",
"service": "S3"
},
{
"ip_prefix": "52.219.60.0/23",
"region": "ap-northeast-2",
"service": "S3"
},
{
"ip_prefix": "52.219.62.0/23",
"region": "ap-south-1",
"service": "S3"
},
{
"ip_prefix": "52.219.64.0/22",
"region": "ap-south-1",
"service": "S3"
},
{
"ip_prefix": "52.219.68.0/22",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ip_prefix": "52.219.72.0/22",
"region": "eu-central-1",
"service": "S3"
},
{
"ip_prefix": "52.219.76.0/22",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ip_prefix": "52.219.80.0/20",
"region": "us-east-2",
"service": "S3"
},
{
"ip_prefix": "54.222.20.0/22",
"region": "cn-north-1",
"service": "S3"
},
{
"ip_prefix": "54.222.48.0/22",
"region": "cn-north-1",
"service": "S3"
},
{
"ip_prefix": "54.231.0.0/17",
"region": "us-east-1",
"service": "S3"
},
{
"ip_prefix": "54.231.128.0/19",
"region": "eu-west-1",
"service": "S3"
},
{
"ip_prefix": "54.231.160.0/19",
"region": "us-west-2",
"service": "S3"
},
{
"ip_prefix": "54.231.192.0/20",
"region": "eu-central-1",
"service": "S3"
},
{
"ip_prefix": "54.231.224.0/21",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ip_prefix": "54.231.232.0/21",
"region": "us-west-1",
"service": "S3"
},
{
"ip_prefix": "54.231.240.0/22",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ip_prefix": "54.231.248.0/22",
"region": "ap-southeast-2",
"service": "S3"
},
{
"ip_prefix": "54.231.252.0/24",
"region": "ap-southeast-2",
"service": "S3"
},
{
"ip_prefix": "54.231.253.0/24",
"region": "sa-east-1",
"service": "S3"
},
{
"ip_prefix": "13.54.0.0/15",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "13.56.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "13.57.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "13.58.0.0/15",
"region": "us-east-2",
"service": "EC2"
},
{
"ip_prefix": "13.112.0.0/14",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "13.124.0.0/16",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ip_prefix": "13.125.0.0/16",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ip_prefix": "13.126.0.0/15",
"region": "ap-south-1",
"service": "EC2"
},
{
"ip_prefix": "13.209.0.0/16",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ip_prefix": "13.210.0.0/15",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "13.228.0.0/15",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "13.230.0.0/15",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "13.232.0.0/14",
"region": "ap-south-1",
"service": "EC2"
},
{
"ip_prefix": "13.236.0.0/14",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "13.250.0.0/15",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "18.194.0.0/15",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "18.196.0.0/15",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "18.216.0.0/14",
"region": "us-east-2",
"service": "EC2"
},
{
"ip_prefix": "18.220.0.0/14",
"region": "us-east-2",
"service": "EC2"
},
{
"ip_prefix": "18.231.0.0/16",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "23.20.0.0/14",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "34.192.0.0/12",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "34.208.0.0/12",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "34.224.0.0/12",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "34.240.0.0/13",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "34.248.0.0/13",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "35.154.0.0/16",
"region": "ap-south-1",
"service": "EC2"
},
{
"ip_prefix": "35.155.0.0/16",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "35.156.0.0/14",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "35.160.0.0/13",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "35.168.0.0/13",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "35.176.0.0/15",
"region": "eu-west-2",
"service": "EC2"
},
{
"ip_prefix": "35.178.0.0/15",
"region": "eu-west-2",
"service": "EC2"
},
{
"ip_prefix": "35.180.0.0/15",
"region": "ca-central-1",
"service": "EC2"
},
{
"ip_prefix": "35.182.0.0/15",
"region": "ca-central-1",
"service": "EC2"
},
{
"ip_prefix": "46.51.128.0/18",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "46.51.192.0/20",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "46.51.216.0/21",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "46.51.224.0/19",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "46.137.0.0/17",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "46.137.128.0/18",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "46.137.192.0/19",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "46.137.224.0/19",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "50.16.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "50.18.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "50.19.0.0/16",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "50.112.0.0/16",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.0.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.2.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.4.0.0/14",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.8.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.9.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.10.0.0/15",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.12.0.0/15",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.14.0.0/16",
"region": "us-east-2",
"service": "EC2"
},
{
"ip_prefix": "52.15.0.0/16",
"region": "us-east-2",
"service": "EC2"
},
{
"ip_prefix": "52.16.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.18.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.20.0.0/14",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.24.0.0/14",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.28.0.0/16",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "52.29.0.0/16",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "52.30.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.32.0.0/14",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.36.0.0/14",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.40.0.0/14",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.44.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.47.0.0/16",
"region": "eu-west-3",
"service": "EC2"
},
{
"ip_prefix": "52.48.0.0/14",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.52.0.0/15",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.54.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.56.0.0/16",
"region": "eu-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.57.0.0/16",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "52.58.0.0/15",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "52.60.0.0/16",
"region": "ca-central-1",
"service": "EC2"
},
{
"ip_prefix": "52.61.0.0/16",
"region": "us-gov-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.62.0.0/15",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.64.0.0/17",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.64.128.0/17",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.65.0.0/16",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.66.0.0/16",
"region": "ap-south-1",
"service": "EC2"
},
{
"ip_prefix": "52.67.0.0/16",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.68.0.0/15",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.70.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.72.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.74.0.0/16",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.76.0.0/17",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.76.128.0/17",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.77.0.0/16",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.78.0.0/16",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.79.0.0/16",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.80.0.0/16",
"region": "cn-north-1",
"service": "EC2"
},
{
"ip_prefix": "52.83.0.0/16",
"region": "cn-northwest-1",
"service": "EC2"
},
{
"ip_prefix": "52.86.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.88.0.0/15",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.90.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.240.0/24",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.241.0/24",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.95.242.0/24",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.243.0/24",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.244.0/24",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.245.0/24",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.246.0/24",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.247.0/24",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.95.248.0/24",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.249.0/24",
"region": "ap-south-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.250.0/24",
"region": "ca-central-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.251.0/24",
"region": "us-east-2",
"service": "EC2"
},
{
"ip_prefix": "52.95.252.0/24",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.95.253.0/24",
"region": "eu-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.95.254.0/24",
"region": "eu-west-3",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.0/28",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.16/28",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.32/28",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.48/28",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.64/28",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.80/28",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.96/28",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.112/28",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.128/28",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.255.144/28",
"region": "cn-north-1",
"service": "EC2"
},
{
"ip_prefix": "52.192.0.0/15",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.196.0.0/14",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.200.0.0/13",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.208.0.0/13",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "52.220.0.0/15",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "52.222.0.0/17",
"region": "us-gov-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.64.0.0/15",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.66.0.0/16",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "54.67.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.68.0.0/14",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.72.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.74.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.76.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.78.0.0/16",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.79.0.0/16",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "54.80.0.0/13",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.88.0.0/14",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.92.0.0/17",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.92.128.0/17",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.93.0.0/16",
"region": "eu-central-1",
"service": "EC2"
},
{
"ip_prefix": "54.94.0.0/16",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.95.0.0/16",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.144.0.0/14",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.148.0.0/15",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.150.0.0/16",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.151.0.0/17",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.151.128.0/17",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.152.0.0/16",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.153.0.0/17",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.153.128.0/17",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "54.154.0.0/16",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.155.0.0/16",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.156.0.0/14",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.160.0.0/13",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.168.0.0/16",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.169.0.0/16",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.170.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.172.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.174.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.176.0.0/15",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.178.0.0/16",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.179.0.0/16",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.183.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.184.0.0/13",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.193.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.194.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.196.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.198.0.0/16",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.199.0.0/16",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.200.0.0/15",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.202.0.0/15",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.204.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.206.0.0/16",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "54.207.0.0/16",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.208.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.210.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.212.0.0/15",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.214.0.0/16",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.215.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.216.0.0/15",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.218.0.0/16",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.219.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.220.0.0/16",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.221.0.0/16",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.222.128.0/17",
"region": "cn-north-1",
"service": "EC2"
},
{
"ip_prefix": "54.223.0.0/16",
"region": "cn-north-1",
"service": "EC2"
},
{
"ip_prefix": "54.224.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.226.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.228.0.0/16",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.229.0.0/16",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.232.0.0/16",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.233.0.0/18",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.233.64.0/18",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.233.128.0/17",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.234.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.236.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.238.0.0/16",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.241.0.0/16",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.242.0.0/15",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "54.244.0.0/16",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.245.0.0/16",
"region": "us-west-2",
"service": "EC2"
},
{
"ip_prefix": "54.246.0.0/16",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.247.0.0/16",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "54.248.0.0/15",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.250.0.0/16",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.251.0.0/16",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.252.0.0/16",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "54.253.0.0/16",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ip_prefix": "54.254.0.0/16",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "54.255.0.0/16",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "67.202.0.0/18",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "72.44.32.0/19",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "75.101.128.0/17",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "79.125.0.0/17",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "96.127.0.0/17",
"region": "us-gov-west-1",
"service": "EC2"
},
{
"ip_prefix": "103.4.8.0/22",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "103.4.12.0/22",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "107.20.0.0/14",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "122.248.192.0/18",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "174.129.0.0/16",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "175.41.128.0/18",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ip_prefix": "175.41.192.0/18",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "176.32.64.0/19",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "176.34.0.0/19",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "176.34.32.0/19",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ip_prefix": "176.34.64.0/18",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "176.34.128.0/17",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "177.71.128.0/17",
"region": "sa-east-1",
"service": "EC2"
},
{
"ip_prefix": "184.72.0.0/18",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "184.72.64.0/18",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "184.72.128.0/17",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "184.73.0.0/16",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "184.169.128.0/17",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "185.48.120.0/22",
"region": "eu-west-1",
"service": "EC2"
},
{
"ip_prefix": "204.236.128.0/18",
"region": "us-west-1",
"service": "EC2"
},
{
"ip_prefix": "204.236.192.0/18",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "216.182.224.0/20",
"region": "us-east-1",
"service": "EC2"
},
{
"ip_prefix": "52.95.110.0/24",
"region": "GLOBAL",
"service": "ROUTE53"
},
{
"ip_prefix": "205.251.192.0/21",
"region": "GLOBAL",
"service": "ROUTE53"
},
{
"ip_prefix": "13.32.0.0/15",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "13.54.63.128/26",
"region": "ap-southeast-2",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "13.59.250.0/26",
"region": "us-east-2",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "13.113.203.0/24",
"region": "ap-northeast-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "13.228.69.0/24",
"region": "ap-southeast-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "34.195.252.0/24",
"region": "us-east-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "34.226.14.0/24",
"region": "us-east-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "35.158.136.0/24",
"region": "eu-central-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "35.162.63.192/26",
"region": "us-west-2",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "35.167.191.128/26",
"region": "us-west-2",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.15.127.128/26",
"region": "us-east-2",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.46.0.0/18",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.52.191.128/26",
"region": "us-west-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.56.127.0/25",
"region": "eu-west-2",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.57.254.0/24",
"region": "eu-central-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.66.194.128/26",
"region": "ap-south-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.78.247.128/26",
"region": "ap-northeast-2",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.84.0.0/15",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.199.127.192/26",
"region": "ap-northeast-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.212.248.0/26",
"region": "eu-west-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.220.191.0/26",
"region": "ap-southeast-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "52.222.128.0/17",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "54.182.0.0/16",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "54.192.0.0/16",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "54.230.0.0/16",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "54.233.255.128/26",
"region": "sa-east-1",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "54.239.128.0/18",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "54.239.192.0/19",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "54.240.128.0/18",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "204.246.164.0/22",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "204.246.168.0/22",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "204.246.174.0/23",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "204.246.176.0/20",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "205.251.192.0/19",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "205.251.249.0/24",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "205.251.250.0/23",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "205.251.252.0/23",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "205.251.254.0/24",
"region": "GLOBAL",
"service": "CLOUDFRONT"
},
{
"ip_prefix": "216.137.32.0/19",
"region": "GLOBAL",
"service": "CLOUDFRONT"
}
],
"ipv6_prefixes": [
{
"ipv6_prefix": "2400:6500:0:7000::/56",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6500:0:7100::/56",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6500:0:7200::/56",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6500:0:7400::/56",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6500:0:7500::/56",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6500:100:7100::/56",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6500:100:7200::/56",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6500:ff00::/64",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6700:ff00::/64",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2403:b300:ff00::/64",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da00:2000::/40",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da00:4000::/40",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da00:8000::/40",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da00:a000::/40",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da00:c000::/40",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da00:ff00::/64",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da12::/36",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da14::/36",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da18::/36",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da1a::/36",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:da1c::/36",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daa0:2000::/40",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daa0:4000::/40",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daa0:8000::/40",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daa0:a000::/40",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daa0:c000::/40",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf8:2000::/40",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf8:4000::/40",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf8:8000::/40",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf8:a000::/40",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf8:c000::/40",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf9:2000::/40",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf9:4000::/40",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf9:8000::/40",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf9:a000::/40",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daf9:c000::/40",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafa:2000::/40",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafa:4000::/40",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafa:8000::/40",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafa:a000::/40",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafa:c000::/40",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafc:2000::/40",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafc:4000::/40",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafc:8000::/40",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafc:a000::/40",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafc:c000::/40",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafe:2000::/40",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafe:4000::/40",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafe:8000::/40",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafe:a000::/40",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:dafe:c000::/40",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daff:2000::/40",
"region": "ap-northeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daff:4000::/40",
"region": "ap-northeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daff:8000::/40",
"region": "ap-southeast-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daff:a000::/40",
"region": "ap-south-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2406:daff:c000::/40",
"region": "ap-southeast-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:8000:4000::/40",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:8000:8000::/40",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:8014::/36",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:8018::/36",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80a0:4000::/40",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80a0:8000::/40",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80f8:4000::/40",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80f8:8000::/40",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80f9:4000::/40",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80f9:8000::/40",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80fa:4000::/40",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80fa:8000::/40",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80fc:4000::/40",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80fc:8000::/40",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80fe:4000::/40",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80fe:8000::/40",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80ff:4000::/40",
"region": "cn-northwest-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "240f:80ff:8000::/40",
"region": "cn-north-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f00:1000::/40",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f00:2000::/40",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f00:4000::/40",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f00:6000::/40",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f00:8000::/40",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f00:c000::/40",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f00:e000::/40",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f11::/36",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f12::/36",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f14::/35",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f16::/36",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f18::/33",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f1c::/36",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1f1e::/36",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fa0:1000::/40",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fa0:2000::/40",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fa0:4000::/40",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fa0:6000::/40",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fa0:8000::/40",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fa0:c000::/40",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fa0:e000::/40",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff8:1000::/40",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff8:2000::/40",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff8:4000::/40",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff8:6000::/40",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff8:8000::/40",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff8:c000::/40",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff8:e000::/40",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff9:1000::/40",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff9:2000::/40",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff9:4000::/40",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff9:6000::/40",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff9:8000::/40",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff9:c000::/40",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ff9:e000::/40",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffa:1000::/40",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffa:2000::/40",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffa:4000::/40",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffa:6000::/40",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffa:8000::/40",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffa:c000::/40",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffa:e000::/40",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffc:1000::/40",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffc:2000::/40",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffc:4000::/40",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffc:6000::/40",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffc:8000::/40",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffc:c000::/40",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffc:e000::/40",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffe:1000::/40",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffe:2000::/40",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffe:4000::/40",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffe:6000::/40",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffe:8000::/40",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffe:c000::/40",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1ffe:e000::/40",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fff:1000::/40",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fff:2000::/40",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fff:4000::/40",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fff:6000::/40",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fff:8000::/40",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fff:c000::/40",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:1fff:e000::/40",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2600:9000::/28",
"region": "GLOBAL",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:107:300f::/64",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:107:4000:5::/64",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:107:4000:7000::/56",
"region": "us-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:107:4000:7100::/56",
"region": "us-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:107:4000:7200::/56",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:107:4000:7400::/56",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:107:4000:7700::/56",
"region": "us-east-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:107:4000:7800::/56",
"region": "ca-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:108:7000::/44",
"region": "us-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2620:108:d000::/44",
"region": "us-gov-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2804:800:0:7000::/56",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2804:800:ff00::/64",
"region": "sa-east-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a01:578:0:7000::/56",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a01:578:0:7100::/56",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a01:578:0:7200::/56",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a01:578:3::/64",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a01:578:13::/64",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d000:2000::/40",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d000:4000::/40",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d000:8000::/40",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d000:c000::/40",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d012::/36",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d014::/36",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d018::/36",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d01c::/36",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d050:2000::/40",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d050:4000::/40",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d050:8000::/40",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d050:c000::/40",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d078:2000::/40",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d078:4000::/40",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d078:8000::/40",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d078:c000::/40",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d079:2000::/40",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d079:4000::/40",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d079:8000::/40",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d079:c000::/40",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07a:2000::/40",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07a:4000::/40",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07a:8000::/40",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07a:c000::/40",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07c:2000::/40",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07c:4000::/40",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07c:8000::/40",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07c:c000::/40",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07e:2000::/40",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07e:4000::/40",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07e:8000::/40",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07e:c000::/40",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07f:2000::/40",
"region": "eu-west-3",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07f:4000::/40",
"region": "eu-central-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07f:8000::/40",
"region": "eu-west-1",
"service": "AMAZON"
},
{
"ipv6_prefix": "2a05:d07f:c000::/40",
"region": "eu-west-2",
"service": "AMAZON"
},
{
"ipv6_prefix": "2400:6500:ff00::36fb:1f80/122",
"region": "ap-southeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2400:6500:ff00::36ff:fec0/122",
"region": "ap-southeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2400:6700:ff00::36f8:dc00/122",
"region": "ap-northeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2400:6700:ff00::36fa:fdc0/122",
"region": "ap-northeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2403:b300:ff00::36fc:4f80/122",
"region": "ap-southeast-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2403:b300:ff00::36fc:fec0/122",
"region": "ap-southeast-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:da00:ff00::36f3:1fc0/122",
"region": "us-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:da00:ff00::6b17:ff00/122",
"region": "us-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:da14:7ff:f800::/53",
"region": "ap-northeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:da14:fff:f800::/53",
"region": "ap-northeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:da18:7ff:f800::/53",
"region": "ap-southeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:da18:fff:f800::/53",
"region": "ap-southeast-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:da1c:7ff:f800::/53",
"region": "ap-southeast-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:da1c:fff:f800::/53",
"region": "ap-southeast-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2600:1f14:7ff:f800::/53",
"region": "us-west-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2600:1f14:fff:f800::/53",
"region": "us-west-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2600:1f18:3fff:f800::/53",
"region": "us-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2600:1f18:7fff:f800::/53",
"region": "us-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2600:1f1c:7ff:f800::/53",
"region": "us-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2600:1f1c:fff:f800::/53",
"region": "us-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2600:1f1e:7ff:f800::/53",
"region": "sa-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2600:1f1e:fff:f800::/53",
"region": "sa-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2620:107:300f::36b7:ff80/122",
"region": "us-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2620:107:300f::36f1:2040/122",
"region": "us-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2620:108:700f::36f4:34c0/122",
"region": "us-west-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2620:108:700f::36f5:a800/122",
"region": "us-west-2",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2804:800:ff00::36e8:2840/122",
"region": "sa-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2804:800:ff00::b147:cf80/122",
"region": "sa-east-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2a01:578:3::36e4:1000/122",
"region": "eu-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2a01:578:3::b022:9fc0/122",
"region": "eu-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2a05:d018:7ff:f800::/53",
"region": "eu-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2a05:d018:fff:f800::/53",
"region": "eu-west-1",
"service": "ROUTE53_HEALTHCHECKS"
},
{
"ipv6_prefix": "2406:daa0:2000::/40",
"region": "ap-northeast-2",
"service": "S3"
},
{
"ipv6_prefix": "2406:daa0:4000::/40",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daa0:8000::/40",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daa0:a000::/40",
"region": "ap-south-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daa0:c000::/40",
"region": "ap-southeast-2",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf8:2000::/40",
"region": "ap-northeast-2",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf8:4000::/40",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf8:8000::/40",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf8:a000::/40",
"region": "ap-south-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf8:c000::/40",
"region": "ap-southeast-2",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf9:2000::/40",
"region": "ap-northeast-2",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf9:4000::/40",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf9:8000::/40",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf9:a000::/40",
"region": "ap-south-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:daf9:c000::/40",
"region": "ap-southeast-2",
"service": "S3"
},
{
"ipv6_prefix": "2406:dafa:2000::/40",
"region": "ap-northeast-2",
"service": "S3"
},
{
"ipv6_prefix": "2406:dafa:4000::/40",
"region": "ap-northeast-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:dafa:8000::/40",
"region": "ap-southeast-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:dafa:a000::/40",
"region": "ap-south-1",
"service": "S3"
},
{
"ipv6_prefix": "2406:dafa:c000::/40",
"region": "ap-southeast-2",
"service": "S3"
},
{
"ipv6_prefix": "240f:80a0:4000::/40",
"region": "cn-northwest-1",
"service": "S3"
},
{
"ipv6_prefix": "240f:80a0:8000::/40",
"region": "cn-north-1",
"service": "S3"
},
{
"ipv6_prefix": "240f:80f8:4000::/40",
"region": "cn-northwest-1",
"service": "S3"
},
{
"ipv6_prefix": "240f:80f8:8000::/40",
"region": "cn-north-1",
"service": "S3"
},
{
"ipv6_prefix": "240f:80f9:4000::/40",
"region": "cn-northwest-1",
"service": "S3"
},
{
"ipv6_prefix": "240f:80f9:8000::/40",
"region": "cn-north-1",
"service": "S3"
},
{
"ipv6_prefix": "240f:80fa:4000::/40",
"region": "cn-northwest-1",
"service": "S3"
},
{
"ipv6_prefix": "240f:80fa:8000::/40",
"region": "cn-north-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1fa0:1000::/40",
"region": "ca-central-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1fa0:2000::/40",
"region": "us-gov-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1fa0:4000::/40",
"region": "us-west-2",
"service": "S3"
},
{
"ipv6_prefix": "2600:1fa0:6000::/40",
"region": "us-east-2",
"service": "S3"
},
{
"ipv6_prefix": "2600:1fa0:8000::/40",
"region": "us-east-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1fa0:c000::/40",
"region": "us-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1fa0:e000::/40",
"region": "sa-east-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff8:1000::/40",
"region": "ca-central-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff8:2000::/40",
"region": "us-gov-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff8:4000::/40",
"region": "us-west-2",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff8:6000::/40",
"region": "us-east-2",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff8:8000::/40",
"region": "us-east-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff8:c000::/40",
"region": "us-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff8:e000::/40",
"region": "sa-east-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff9:1000::/40",
"region": "ca-central-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff9:2000::/40",
"region": "us-gov-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff9:4000::/40",
"region": "us-west-2",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff9:6000::/40",
"region": "us-east-2",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff9:8000::/40",
"region": "us-east-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff9:c000::/40",
"region": "us-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ff9:e000::/40",
"region": "sa-east-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ffa:1000::/40",
"region": "ca-central-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ffa:2000::/40",
"region": "us-gov-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ffa:4000::/40",
"region": "us-west-2",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ffa:6000::/40",
"region": "us-east-2",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ffa:8000::/40",
"region": "us-east-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ffa:c000::/40",
"region": "us-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2600:1ffa:e000::/40",
"region": "sa-east-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d050:2000::/40",
"region": "eu-west-3",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d050:4000::/40",
"region": "eu-central-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d050:8000::/40",
"region": "eu-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d050:c000::/40",
"region": "eu-west-2",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d078:2000::/40",
"region": "eu-west-3",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d078:4000::/40",
"region": "eu-central-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d078:8000::/40",
"region": "eu-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d078:c000::/40",
"region": "eu-west-2",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d079:2000::/40",
"region": "eu-west-3",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d079:4000::/40",
"region": "eu-central-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d079:8000::/40",
"region": "eu-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d079:c000::/40",
"region": "eu-west-2",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d07a:2000::/40",
"region": "eu-west-3",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d07a:4000::/40",
"region": "eu-central-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d07a:8000::/40",
"region": "eu-west-1",
"service": "S3"
},
{
"ipv6_prefix": "2a05:d07a:c000::/40",
"region": "eu-west-2",
"service": "S3"
},
{
"ipv6_prefix": "2400:6500:ff00::/64",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ipv6_prefix": "2400:6700:ff00::/64",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ipv6_prefix": "2403:b300:ff00::/64",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da00:2000::/40",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da00:4000::/40",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da00:8000::/40",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da00:a000::/40",
"region": "ap-south-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da00:c000::/40",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da00:ff00::/64",
"region": "us-east-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da12::/36",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da14::/36",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da18::/36",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da1a::/36",
"region": "ap-south-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:da1c::/36",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ipv6_prefix": "2406:daff:2000::/40",
"region": "ap-northeast-2",
"service": "EC2"
},
{
"ipv6_prefix": "2406:daff:4000::/40",
"region": "ap-northeast-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:daff:8000::/40",
"region": "ap-southeast-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:daff:a000::/40",
"region": "ap-south-1",
"service": "EC2"
},
{
"ipv6_prefix": "2406:daff:c000::/40",
"region": "ap-southeast-2",
"service": "EC2"
},
{
"ipv6_prefix": "240f:8000:4000::/40",
"region": "cn-northwest-1",
"service": "EC2"
},
{
"ipv6_prefix": "240f:8000:8000::/40",
"region": "cn-north-1",
"service": "EC2"
},
{
"ipv6_prefix": "240f:8014::/36",
"region": "cn-northwest-1",
"service": "EC2"
},
{
"ipv6_prefix": "240f:8018::/36",
"region": "cn-north-1",
"service": "EC2"
},
{
"ipv6_prefix": "240f:80ff:4000::/40",
"region": "cn-northwest-1",
"service": "EC2"
},
{
"ipv6_prefix": "240f:80ff:8000::/40",
"region": "cn-north-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f00:1000::/40",
"region": "ca-central-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f00:2000::/40",
"region": "us-gov-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f00:4000::/40",
"region": "us-west-2",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f00:6000::/40",
"region": "us-east-2",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f00:8000::/40",
"region": "us-east-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f00:c000::/40",
"region": "us-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f00:e000::/40",
"region": "sa-east-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f11::/36",
"region": "ca-central-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f12::/36",
"region": "us-gov-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f14::/35",
"region": "us-west-2",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f16::/36",
"region": "us-east-2",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f18::/33",
"region": "us-east-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f1c::/36",
"region": "us-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1f1e::/36",
"region": "sa-east-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1fff:1000::/40",
"region": "ca-central-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1fff:2000::/40",
"region": "us-gov-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1fff:4000::/40",
"region": "us-west-2",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1fff:6000::/40",
"region": "us-east-2",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1fff:8000::/40",
"region": "us-east-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1fff:c000::/40",
"region": "us-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2600:1fff:e000::/40",
"region": "sa-east-1",
"service": "EC2"
},
{
"ipv6_prefix": "2620:107:300f::/64",
"region": "us-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2620:108:700f::/64",
"region": "us-west-2",
"service": "EC2"
},
{
"ipv6_prefix": "2620:108:d00f::/64",
"region": "us-gov-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2804:800:ff00::/64",
"region": "sa-east-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a01:578:3::/64",
"region": "eu-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a01:578:13::/64",
"region": "eu-central-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d000:2000::/40",
"region": "eu-west-3",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d000:4000::/40",
"region": "eu-central-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d000:8000::/40",
"region": "eu-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d000:c000::/40",
"region": "eu-west-2",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d012::/36",
"region": "eu-west-3",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d014::/36",
"region": "eu-central-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d018::/36",
"region": "eu-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d01c::/36",
"region": "eu-west-2",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d07f:2000::/40",
"region": "eu-west-3",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d07f:4000::/40",
"region": "eu-central-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d07f:8000::/40",
"region": "eu-west-1",
"service": "EC2"
},
{
"ipv6_prefix": "2a05:d07f:c000::/40",
"region": "eu-west-2",
"service": "EC2"
},
{
"ipv6_prefix": "2600:9000::/28",
"region": "GLOBAL",
"service": "CLOUDFRONT"
}
]
}
cidranger-1.0.2/trie.go 0000664 0000000 0000000 00000024551 13732170323 0014752 0 ustar 00root root 0000000 0000000 package cidranger
import (
"fmt"
"net"
"strings"
rnet "github.com/yl2chen/cidranger/net"
)
// prefixTrie is a path-compressed (PC) trie implementation of the
// ranger interface inspired by this blog post:
// https://vincent.bernat.im/en/blog/2017-ipv4-route-lookup-linux
//
// CIDR blocks are stored using a prefix tree structure where each node has its
// parent as prefix, and the path from the root node represents current CIDR
// block.
//
// For IPv4, the trie structure guarantees max depth of 32 as IPv4 addresses are
// 32 bits long and each bit represents a prefix tree starting at that bit. This
// property also guarantees constant lookup time in Big-O notation.
//
// Path compression compresses a string of node with only 1 child into a single
// node, decrease the amount of lookups necessary during containment tests.
//
// Level compression dictates the amount of direct children of a node by
// allowing it to handle multiple bits in the path. The heuristic (based on
// children population) to decide when the compression and decompression happens
// is outlined in the prior linked blog, and will be experimented with in more
// depth in this project in the future.
//
// Note: Can not insert both IPv4 and IPv6 network addresses into the same
// prefix trie, use versionedRanger wrapper instead.
//
// TODO: Implement level-compressed component of the LPC trie.
type prefixTrie struct {
parent *prefixTrie
children []*prefixTrie
numBitsSkipped uint
numBitsHandled uint
network rnet.Network
entry RangerEntry
size int // This is only maintained in the root trie.
}
// newPrefixTree creates a new prefixTrie.
func newPrefixTree(version rnet.IPVersion) Ranger {
_, rootNet, _ := net.ParseCIDR("0.0.0.0/0")
if version == rnet.IPv6 {
_, rootNet, _ = net.ParseCIDR("0::0/0")
}
return &prefixTrie{
children: make([]*prefixTrie, 2, 2),
numBitsSkipped: 0,
numBitsHandled: 1,
network: rnet.NewNetwork(*rootNet),
}
}
func newPathprefixTrie(network rnet.Network, numBitsSkipped uint) *prefixTrie {
version := rnet.IPv4
if len(network.Number) == rnet.IPv6Uint32Count {
version = rnet.IPv6
}
path := newPrefixTree(version).(*prefixTrie)
path.numBitsSkipped = numBitsSkipped
path.network = network.Masked(int(numBitsSkipped))
return path
}
func newEntryTrie(network rnet.Network, entry RangerEntry) *prefixTrie {
ones, _ := network.IPNet.Mask.Size()
leaf := newPathprefixTrie(network, uint(ones))
leaf.entry = entry
return leaf
}
// Insert inserts a RangerEntry into prefix trie.
func (p *prefixTrie) Insert(entry RangerEntry) error {
network := entry.Network()
sizeIncreased, err := p.insert(rnet.NewNetwork(network), entry)
if sizeIncreased {
p.size++
}
return err
}
// Remove removes RangerEntry identified by given network from trie.
func (p *prefixTrie) Remove(network net.IPNet) (RangerEntry, error) {
entry, err := p.remove(rnet.NewNetwork(network))
if entry != nil {
p.size--
}
return entry, err
}
// Contains returns boolean indicating whether given ip is contained in any
// of the inserted networks.
func (p *prefixTrie) Contains(ip net.IP) (bool, error) {
nn := rnet.NewNetworkNumber(ip)
if nn == nil {
return false, ErrInvalidNetworkNumberInput
}
return p.contains(nn)
}
// ContainingNetworks returns the list of RangerEntry(s) the given ip is
// contained in in ascending prefix order.
func (p *prefixTrie) ContainingNetworks(ip net.IP) ([]RangerEntry, error) {
nn := rnet.NewNetworkNumber(ip)
if nn == nil {
return nil, ErrInvalidNetworkNumberInput
}
return p.containingNetworks(nn)
}
// CoveredNetworks returns the list of RangerEntry(s) the given ipnet
// covers. That is, the networks that are completely subsumed by the
// specified network.
func (p *prefixTrie) CoveredNetworks(network net.IPNet) ([]RangerEntry, error) {
net := rnet.NewNetwork(network)
return p.coveredNetworks(net)
}
// Len returns number of networks in ranger.
func (p *prefixTrie) Len() int {
return p.size
}
// String returns string representation of trie, mainly for visualization and
// debugging.
func (p *prefixTrie) String() string {
children := []string{}
padding := strings.Repeat("| ", p.level()+1)
for bits, child := range p.children {
if child == nil {
continue
}
childStr := fmt.Sprintf("\n%s%d--> %s", padding, bits, child.String())
children = append(children, childStr)
}
return fmt.Sprintf("%s (target_pos:%d:has_entry:%t)%s", p.network,
p.targetBitPosition(), p.hasEntry(), strings.Join(children, ""))
}
func (p *prefixTrie) contains(number rnet.NetworkNumber) (bool, error) {
if !p.network.Contains(number) {
return false, nil
}
if p.hasEntry() {
return true, nil
}
if p.targetBitPosition() < 0 {
return false, nil
}
bit, err := p.targetBitFromIP(number)
if err != nil {
return false, err
}
child := p.children[bit]
if child != nil {
return child.contains(number)
}
return false, nil
}
func (p *prefixTrie) containingNetworks(number rnet.NetworkNumber) ([]RangerEntry, error) {
results := []RangerEntry{}
if !p.network.Contains(number) {
return results, nil
}
if p.hasEntry() {
results = []RangerEntry{p.entry}
}
if p.targetBitPosition() < 0 {
return results, nil
}
bit, err := p.targetBitFromIP(number)
if err != nil {
return nil, err
}
child := p.children[bit]
if child != nil {
ranges, err := child.containingNetworks(number)
if err != nil {
return nil, err
}
if len(ranges) > 0 {
if len(results) > 0 {
results = append(results, ranges...)
} else {
results = ranges
}
}
}
return results, nil
}
func (p *prefixTrie) coveredNetworks(network rnet.Network) ([]RangerEntry, error) {
var results []RangerEntry
if network.Covers(p.network) {
for entry := range p.walkDepth() {
results = append(results, entry)
}
} else if p.targetBitPosition() >= 0 {
bit, err := p.targetBitFromIP(network.Number)
if err != nil {
return results, err
}
child := p.children[bit]
if child != nil {
return child.coveredNetworks(network)
}
}
return results, nil
}
func (p *prefixTrie) insert(network rnet.Network, entry RangerEntry) (bool, error) {
if p.network.Equal(network) {
sizeIncreased := p.entry == nil
p.entry = entry
return sizeIncreased, nil
}
bit, err := p.targetBitFromIP(network.Number)
if err != nil {
return false, err
}
existingChild := p.children[bit]
// No existing child, insert new leaf trie.
if existingChild == nil {
p.appendTrie(bit, newEntryTrie(network, entry))
return true, nil
}
// Check whether it is necessary to insert additional path prefix between current trie and existing child,
// in the case that inserted network diverges on its path to existing child.
lcb, err := network.LeastCommonBitPosition(existingChild.network)
divergingBitPos := int(lcb) - 1
if divergingBitPos > existingChild.targetBitPosition() {
pathPrefix := newPathprefixTrie(network, p.totalNumberOfBits()-lcb)
err := p.insertPrefix(bit, pathPrefix, existingChild)
if err != nil {
return false, err
}
// Update new child
existingChild = pathPrefix
}
return existingChild.insert(network, entry)
}
func (p *prefixTrie) appendTrie(bit uint32, prefix *prefixTrie) {
p.children[bit] = prefix
prefix.parent = p
}
func (p *prefixTrie) insertPrefix(bit uint32, pathPrefix, child *prefixTrie) error {
// Set parent/child relationship between current trie and inserted pathPrefix
p.children[bit] = pathPrefix
pathPrefix.parent = p
// Set parent/child relationship between inserted pathPrefix and original child
pathPrefixBit, err := pathPrefix.targetBitFromIP(child.network.Number)
if err != nil {
return err
}
pathPrefix.children[pathPrefixBit] = child
child.parent = pathPrefix
return nil
}
func (p *prefixTrie) remove(network rnet.Network) (RangerEntry, error) {
if p.hasEntry() && p.network.Equal(network) {
entry := p.entry
p.entry = nil
err := p.compressPathIfPossible()
if err != nil {
return nil, err
}
return entry, nil
}
if p.targetBitPosition() < 0 {
return nil, nil
}
bit, err := p.targetBitFromIP(network.Number)
if err != nil {
return nil, err
}
child := p.children[bit]
if child != nil {
return child.remove(network)
}
return nil, nil
}
func (p *prefixTrie) qualifiesForPathCompression() bool {
// Current prefix trie can be path compressed if it meets all following.
// 1. records no CIDR entry
// 2. has single or no child
// 3. is not root trie
return !p.hasEntry() && p.childrenCount() <= 1 && p.parent != nil
}
func (p *prefixTrie) compressPathIfPossible() error {
if !p.qualifiesForPathCompression() {
// Does not qualify to be compressed
return nil
}
// Find lone child.
var loneChild *prefixTrie
for _, child := range p.children {
if child != nil {
loneChild = child
break
}
}
// Find root of currnt single child lineage.
parent := p.parent
for ; parent.qualifiesForPathCompression(); parent = parent.parent {
}
parentBit, err := parent.targetBitFromIP(p.network.Number)
if err != nil {
return err
}
parent.children[parentBit] = loneChild
// Attempts to furthur apply path compression at current lineage parent, in case current lineage
// compressed into parent.
return parent.compressPathIfPossible()
}
func (p *prefixTrie) childrenCount() int {
count := 0
for _, child := range p.children {
if child != nil {
count++
}
}
return count
}
func (p *prefixTrie) totalNumberOfBits() uint {
return rnet.BitsPerUint32 * uint(len(p.network.Number))
}
func (p *prefixTrie) targetBitPosition() int {
return int(p.totalNumberOfBits()-p.numBitsSkipped) - 1
}
func (p *prefixTrie) targetBitFromIP(n rnet.NetworkNumber) (uint32, error) {
// This is a safe uint boxing of int since we should never attempt to get
// target bit at a negative position.
return n.Bit(uint(p.targetBitPosition()))
}
func (p *prefixTrie) hasEntry() bool {
return p.entry != nil
}
func (p *prefixTrie) level() int {
if p.parent == nil {
return 0
}
return p.parent.level() + 1
}
// walkDepth walks the trie in depth order, for unit testing.
func (p *prefixTrie) walkDepth() <-chan RangerEntry {
entries := make(chan RangerEntry)
go func() {
if p.hasEntry() {
entries <- p.entry
}
childEntriesList := []<-chan RangerEntry{}
for _, trie := range p.children {
if trie == nil {
continue
}
childEntriesList = append(childEntriesList, trie.walkDepth())
}
for _, childEntries := range childEntriesList {
for entry := range childEntries {
entries <- entry
}
}
close(entries)
}()
return entries
}
cidranger-1.0.2/trie_test.go 0000664 0000000 0000000 00000035472 13732170323 0016015 0 ustar 00root root 0000000 0000000 package cidranger
import (
"encoding/binary"
"math/rand"
"net"
"runtime"
"testing"
"time"
"github.com/stretchr/testify/assert"
rnet "github.com/yl2chen/cidranger/net"
)
func getAllByVersion(version rnet.IPVersion) *net.IPNet {
if version == rnet.IPv6 {
return AllIPv6
}
return AllIPv4
}
func TestPrefixTrieInsert(t *testing.T) {
cases := []struct {
version rnet.IPVersion
inserts []string
expectedNetworksInDepthOrder []string
name string
}{
{rnet.IPv4, []string{"192.168.0.1/24"}, []string{"192.168.0.1/24"}, "basic insert"},
{
rnet.IPv4,
[]string{"1.2.3.4/32", "1.2.3.5/32"},
[]string{"1.2.3.4/32", "1.2.3.5/32"},
"single ip IPv4 network insert",
},
{
rnet.IPv6,
[]string{"0::1/128", "0::2/128"},
[]string{"0::1/128", "0::2/128"},
"single ip IPv6 network insert",
},
{
rnet.IPv4,
[]string{"192.168.0.1/16", "192.168.0.1/24"},
[]string{"192.168.0.1/16", "192.168.0.1/24"},
"in order insert",
},
{
rnet.IPv4,
[]string{"192.168.0.1/32", "192.168.0.1/32"},
[]string{"192.168.0.1/32"},
"duplicate network insert",
},
{
rnet.IPv4,
[]string{"192.168.0.1/24", "192.168.0.1/16"},
[]string{"192.168.0.1/16", "192.168.0.1/24"},
"reverse insert",
},
{
rnet.IPv4,
[]string{"192.168.0.1/24", "192.168.1.1/24"},
[]string{"192.168.0.1/24", "192.168.1.1/24"},
"branch insert",
},
{
rnet.IPv4,
[]string{"192.168.0.1/24", "192.168.1.1/24", "192.168.1.1/30"},
[]string{"192.168.0.1/24", "192.168.1.1/24", "192.168.1.1/30"},
"branch inserts",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
trie := newPrefixTree(tc.version).(*prefixTrie)
for _, insert := range tc.inserts {
_, network, _ := net.ParseCIDR(insert)
err := trie.Insert(NewBasicRangerEntry(*network))
assert.NoError(t, err)
}
assert.Equal(t, len(tc.expectedNetworksInDepthOrder), trie.Len(), "trie size should match")
allNetworks, err := trie.CoveredNetworks(*getAllByVersion(tc.version))
assert.Nil(t, err)
assert.Equal(t, len(allNetworks), trie.Len(), "trie size should match")
walk := trie.walkDepth()
for _, network := range tc.expectedNetworksInDepthOrder {
_, ipnet, _ := net.ParseCIDR(network)
expected := NewBasicRangerEntry(*ipnet)
actual := <-walk
assert.Equal(t, expected, actual)
}
// Ensure no unexpected elements in trie.
for network := range walk {
assert.Nil(t, network)
}
})
}
}
func TestPrefixTrieString(t *testing.T) {
inserts := []string{"192.168.0.1/24", "192.168.1.1/24", "192.168.1.1/30"}
trie := newPrefixTree(rnet.IPv4).(*prefixTrie)
for _, insert := range inserts {
_, network, _ := net.ParseCIDR(insert)
trie.Insert(NewBasicRangerEntry(*network))
}
expected := `0.0.0.0/0 (target_pos:31:has_entry:false)
| 1--> 192.168.0.0/23 (target_pos:8:has_entry:false)
| | 0--> 192.168.0.0/24 (target_pos:7:has_entry:true)
| | 1--> 192.168.1.0/24 (target_pos:7:has_entry:true)
| | | 0--> 192.168.1.0/30 (target_pos:1:has_entry:true)`
assert.Equal(t, expected, trie.String())
}
func TestPrefixTrieRemove(t *testing.T) {
cases := []struct {
version rnet.IPVersion
inserts []string
removes []string
expectedRemoves []string
expectedNetworksInDepthOrder []string
expectedTrieString string
name string
}{
{
rnet.IPv4,
[]string{"192.168.0.1/24"},
[]string{"192.168.0.1/24"},
[]string{"192.168.0.1/24"},
[]string{},
"0.0.0.0/0 (target_pos:31:has_entry:false)",
"basic remove",
},
{
rnet.IPv4,
[]string{"192.168.0.1/32"},
[]string{"192.168.0.1/24"},
[]string{""},
[]string{"192.168.0.1/32"},
`0.0.0.0/0 (target_pos:31:has_entry:false)
| 1--> 192.168.0.1/32 (target_pos:-1:has_entry:true)`,
"remove from ranger that contains a single ip block",
},
{
rnet.IPv4,
[]string{"1.2.3.4/32", "1.2.3.5/32"},
[]string{"1.2.3.5/32"},
[]string{"1.2.3.5/32"},
[]string{"1.2.3.4/32"},
`0.0.0.0/0 (target_pos:31:has_entry:false)
| 0--> 1.2.3.4/32 (target_pos:-1:has_entry:true)`,
"single ip IPv4 network remove",
},
{
rnet.IPv4,
[]string{"0::1/128", "0::2/128"},
[]string{"0::2/128"},
[]string{"0::2/128"},
[]string{"0::1/128"},
`0.0.0.0/0 (target_pos:31:has_entry:false)
| 0--> ::1/128 (target_pos:-1:has_entry:true)`,
"single ip IPv6 network remove",
},
{
rnet.IPv4,
[]string{"192.168.0.1/24", "192.168.0.1/25", "192.168.0.1/26"},
[]string{"192.168.0.1/25"},
[]string{"192.168.0.1/25"},
[]string{"192.168.0.1/24", "192.168.0.1/26"},
`0.0.0.0/0 (target_pos:31:has_entry:false)
| 1--> 192.168.0.0/24 (target_pos:7:has_entry:true)
| | 0--> 192.168.0.0/26 (target_pos:5:has_entry:true)`,
"remove path prefix",
},
{
rnet.IPv4,
[]string{"192.168.0.1/24", "192.168.0.1/25", "192.168.0.64/26", "192.168.0.1/26"},
[]string{"192.168.0.1/25"},
[]string{"192.168.0.1/25"},
[]string{"192.168.0.1/24", "192.168.0.1/26", "192.168.0.64/26"},
`0.0.0.0/0 (target_pos:31:has_entry:false)
| 1--> 192.168.0.0/24 (target_pos:7:has_entry:true)
| | 0--> 192.168.0.0/25 (target_pos:6:has_entry:false)
| | | 0--> 192.168.0.0/26 (target_pos:5:has_entry:true)
| | | 1--> 192.168.0.64/26 (target_pos:5:has_entry:true)`,
"remove path prefix with more than 1 children",
},
{
rnet.IPv4,
[]string{"192.168.0.1/24", "192.168.0.1/25"},
[]string{"192.168.0.1/26"},
[]string{""},
[]string{"192.168.0.1/24", "192.168.0.1/25"},
`0.0.0.0/0 (target_pos:31:has_entry:false)
| 1--> 192.168.0.0/24 (target_pos:7:has_entry:true)
| | 0--> 192.168.0.0/25 (target_pos:6:has_entry:true)`,
"remove non existent",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
trie := newPrefixTree(tc.version).(*prefixTrie)
for _, insert := range tc.inserts {
_, network, _ := net.ParseCIDR(insert)
err := trie.Insert(NewBasicRangerEntry(*network))
assert.NoError(t, err)
}
for i, remove := range tc.removes {
_, network, _ := net.ParseCIDR(remove)
removed, err := trie.Remove(*network)
assert.NoError(t, err)
if str := tc.expectedRemoves[i]; str != "" {
_, ipnet, _ := net.ParseCIDR(str)
expected := NewBasicRangerEntry(*ipnet)
assert.Equal(t, expected, removed)
} else {
assert.Nil(t, removed)
}
}
assert.Equal(t, len(tc.expectedNetworksInDepthOrder), trie.Len(), "trie size should match after revmoval")
allNetworks, err := trie.CoveredNetworks(*getAllByVersion(tc.version))
assert.Nil(t, err)
assert.Equal(t, len(allNetworks), trie.Len(), "trie size should match")
walk := trie.walkDepth()
for _, network := range tc.expectedNetworksInDepthOrder {
_, ipnet, _ := net.ParseCIDR(network)
expected := NewBasicRangerEntry(*ipnet)
actual := <-walk
assert.Equal(t, expected, actual)
}
// Ensure no unexpected elements in trie.
for network := range walk {
assert.Nil(t, network)
}
assert.Equal(t, tc.expectedTrieString, trie.String())
})
}
}
func TestToReplicateIssue(t *testing.T) {
cases := []struct {
version rnet.IPVersion
inserts []string
ip net.IP
networks []string
name string
}{
{
rnet.IPv4,
[]string{"192.168.0.1/32"},
net.ParseIP("192.168.0.1"),
[]string{"192.168.0.1/32"},
"basic containing network for /32 mask",
},
{
rnet.IPv6,
[]string{"a::1/128"},
net.ParseIP("a::1"),
[]string{"a::1/128"},
"basic containing network for /128 mask",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
trie := newPrefixTree(tc.version)
for _, insert := range tc.inserts {
_, network, _ := net.ParseCIDR(insert)
err := trie.Insert(NewBasicRangerEntry(*network))
assert.NoError(t, err)
}
expectedEntries := []RangerEntry{}
for _, network := range tc.networks {
_, net, _ := net.ParseCIDR(network)
expectedEntries = append(expectedEntries, NewBasicRangerEntry(*net))
}
contains, err := trie.Contains(tc.ip)
assert.NoError(t, err)
assert.True(t, contains)
networks, err := trie.ContainingNetworks(tc.ip)
assert.NoError(t, err)
assert.Equal(t, expectedEntries, networks)
})
}
}
type expectedIPRange struct {
start net.IP
end net.IP
}
func TestPrefixTrieContains(t *testing.T) {
cases := []struct {
version rnet.IPVersion
inserts []string
expectedIPs []expectedIPRange
name string
}{
{
rnet.IPv4,
[]string{"192.168.0.0/24"},
[]expectedIPRange{
{net.ParseIP("192.168.0.0"), net.ParseIP("192.168.1.0")},
},
"basic contains",
},
{
rnet.IPv4,
[]string{"192.168.0.0/24", "128.168.0.0/24"},
[]expectedIPRange{
{net.ParseIP("192.168.0.0"), net.ParseIP("192.168.1.0")},
{net.ParseIP("128.168.0.0"), net.ParseIP("128.168.1.0")},
},
"multiple ranges contains",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
trie := newPrefixTree(tc.version)
for _, insert := range tc.inserts {
_, network, _ := net.ParseCIDR(insert)
err := trie.Insert(NewBasicRangerEntry(*network))
assert.NoError(t, err)
}
for _, expectedIPRange := range tc.expectedIPs {
var contains bool
var err error
start := expectedIPRange.start
for ; !expectedIPRange.end.Equal(start); start = rnet.NextIP(start) {
contains, err = trie.Contains(start)
assert.NoError(t, err)
assert.True(t, contains)
}
// Check out of bounds ips on both ends
contains, err = trie.Contains(rnet.PreviousIP(expectedIPRange.start))
assert.NoError(t, err)
assert.False(t, contains)
contains, err = trie.Contains(rnet.NextIP(expectedIPRange.end))
assert.NoError(t, err)
assert.False(t, contains)
}
})
}
}
func TestPrefixTrieContainingNetworks(t *testing.T) {
cases := []struct {
version rnet.IPVersion
inserts []string
ip net.IP
networks []string
name string
}{
{
rnet.IPv4,
[]string{"192.168.0.0/24"},
net.ParseIP("192.168.0.1"),
[]string{"192.168.0.0/24"},
"basic containing networks",
},
{
rnet.IPv4,
[]string{"192.168.0.0/24", "192.168.0.0/25"},
net.ParseIP("192.168.0.1"),
[]string{"192.168.0.0/24", "192.168.0.0/25"},
"inclusive networks",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
trie := newPrefixTree(tc.version)
for _, insert := range tc.inserts {
_, network, _ := net.ParseCIDR(insert)
err := trie.Insert(NewBasicRangerEntry(*network))
assert.NoError(t, err)
}
expectedEntries := []RangerEntry{}
for _, network := range tc.networks {
_, net, _ := net.ParseCIDR(network)
expectedEntries = append(expectedEntries, NewBasicRangerEntry(*net))
}
networks, err := trie.ContainingNetworks(tc.ip)
assert.NoError(t, err)
assert.Equal(t, expectedEntries, networks)
})
}
}
type coveredNetworkTest struct {
version rnet.IPVersion
inserts []string
search string
networks []string
name string
}
var coveredNetworkTests = []coveredNetworkTest{
{
rnet.IPv4,
[]string{"192.168.0.0/24"},
"192.168.0.0/16",
[]string{"192.168.0.0/24"},
"basic covered networks",
},
{
rnet.IPv4,
[]string{"192.168.0.0/24"},
"10.1.0.0/16",
nil,
"nothing",
},
{
rnet.IPv4,
[]string{"192.168.0.0/24", "192.168.0.0/25"},
"192.168.0.0/16",
[]string{"192.168.0.0/24", "192.168.0.0/25"},
"multiple networks",
},
{
rnet.IPv4,
[]string{"192.168.0.0/24", "192.168.0.0/25", "192.168.0.1/32"},
"192.168.0.0/16",
[]string{"192.168.0.0/24", "192.168.0.0/25", "192.168.0.1/32"},
"multiple networks 2",
},
{
rnet.IPv4,
[]string{"192.168.1.1/32"},
"192.168.0.0/16",
[]string{"192.168.1.1/32"},
"leaf",
},
{
rnet.IPv4,
[]string{"0.0.0.0/0", "192.168.1.1/32"},
"192.168.0.0/16",
[]string{"192.168.1.1/32"},
"leaf with root",
},
{
rnet.IPv4,
[]string{
"0.0.0.0/0", "192.168.0.0/24", "192.168.1.1/32",
"10.1.0.0/16", "10.1.1.0/24",
},
"192.168.0.0/16",
[]string{"192.168.0.0/24", "192.168.1.1/32"},
"path not taken",
},
{
rnet.IPv4,
[]string{
"192.168.0.0/15",
},
"192.168.0.0/16",
nil,
"only masks different",
},
}
func TestPrefixTrieCoveredNetworks(t *testing.T) {
for _, tc := range coveredNetworkTests {
t.Run(tc.name, func(t *testing.T) {
trie := newPrefixTree(tc.version)
for _, insert := range tc.inserts {
_, network, _ := net.ParseCIDR(insert)
err := trie.Insert(NewBasicRangerEntry(*network))
assert.NoError(t, err)
}
var expectedEntries []RangerEntry
for _, network := range tc.networks {
_, net, _ := net.ParseCIDR(network)
expectedEntries = append(expectedEntries,
NewBasicRangerEntry(*net))
}
_, snet, _ := net.ParseCIDR(tc.search)
networks, err := trie.CoveredNetworks(*snet)
assert.NoError(t, err)
assert.Equal(t, expectedEntries, networks)
})
}
}
func TestTrieMemUsage(t *testing.T) {
if testing.Short() {
t.Skip("Skipping memory test in `-short` mode")
}
numIPs := 100000
runs := 10
// Avg heap allocation over all runs should not be more than the heap allocation of first run multiplied
// by threshold, picking 1% as sane number for detecting memory leak.
thresh := 1.01
trie := newPrefixTree(rnet.IPv4)
var baseLineHeap, totalHeapAllocOverRuns uint64
for i := 0; i < runs; i++ {
t.Logf("Executing Run %d of %d", i+1, runs)
// Insert networks.
for n := 0; n < numIPs; n++ {
trie.Insert(NewBasicRangerEntry(GenLeafIPNet(GenIPV4())))
}
t.Logf("Inserted All (%d networks)", trie.Len())
assert.Less(t, 0, trie.Len(), "Len should > 0")
assert.LessOrEqualf(t, trie.Len(), numIPs, "Len should <= %d", numIPs)
allNetworks, err := trie.CoveredNetworks(*getAllByVersion(rnet.IPv4))
assert.Nil(t, err)
assert.Equal(t, len(allNetworks), trie.Len(), "trie size should match")
// Remove networks.
_, all, _ := net.ParseCIDR("0.0.0.0/0")
ll, _ := trie.CoveredNetworks(*all)
for i := 0; i < len(ll); i++ {
trie.Remove(ll[i].Network())
}
t.Logf("Removed All (%d networks)", len(ll))
assert.Equal(t, 0, trie.Len(), "Len after removal should == 0")
// Perform GC
runtime.GC()
// Get HeapAlloc stats.
heapAlloc := GetHeapAllocation()
totalHeapAllocOverRuns += heapAlloc
if i == 0 {
baseLineHeap = heapAlloc
}
}
// Assert that heap allocation from first loop is within set threshold of avg over all runs.
assert.Less(t, uint64(0), baseLineHeap)
assert.LessOrEqual(t, float64(baseLineHeap), float64(totalHeapAllocOverRuns/uint64(runs))*thresh)
}
func GenLeafIPNet(ip net.IP) net.IPNet {
return net.IPNet{
IP: ip,
Mask: net.CIDRMask(32, 32),
}
}
// GenIPV4 generates an IPV4 address
func GenIPV4() net.IP {
rand.Seed(time.Now().UnixNano())
nn := rand.Uint32()
if nn < 4294967295 {
nn++
}
ip := make(net.IP, 4)
binary.BigEndian.PutUint32(ip, uint32(nn))
return ip
}
func GetHeapAllocation() uint64 {
var m runtime.MemStats
runtime.ReadMemStats(&m)
return m.HeapAlloc
}
cidranger-1.0.2/version.go 0000664 0000000 0000000 00000003215 13732170323 0015466 0 ustar 00root root 0000000 0000000 package cidranger
import (
"net"
rnet "github.com/yl2chen/cidranger/net"
)
type rangerFactory func(rnet.IPVersion) Ranger
type versionedRanger struct {
ipV4Ranger Ranger
ipV6Ranger Ranger
}
func newVersionedRanger(factory rangerFactory) Ranger {
return &versionedRanger{
ipV4Ranger: factory(rnet.IPv4),
ipV6Ranger: factory(rnet.IPv6),
}
}
func (v *versionedRanger) Insert(entry RangerEntry) error {
network := entry.Network()
ranger, err := v.getRangerForIP(network.IP)
if err != nil {
return err
}
return ranger.Insert(entry)
}
func (v *versionedRanger) Remove(network net.IPNet) (RangerEntry, error) {
ranger, err := v.getRangerForIP(network.IP)
if err != nil {
return nil, err
}
return ranger.Remove(network)
}
func (v *versionedRanger) Contains(ip net.IP) (bool, error) {
ranger, err := v.getRangerForIP(ip)
if err != nil {
return false, err
}
return ranger.Contains(ip)
}
func (v *versionedRanger) ContainingNetworks(ip net.IP) ([]RangerEntry, error) {
ranger, err := v.getRangerForIP(ip)
if err != nil {
return nil, err
}
return ranger.ContainingNetworks(ip)
}
func (v *versionedRanger) CoveredNetworks(network net.IPNet) ([]RangerEntry, error) {
ranger, err := v.getRangerForIP(network.IP)
if err != nil {
return nil, err
}
return ranger.CoveredNetworks(network)
}
// Len returns number of networks in ranger.
func (v *versionedRanger) Len() int {
return v.ipV4Ranger.Len() + v.ipV6Ranger.Len()
}
func (v *versionedRanger) getRangerForIP(ip net.IP) (Ranger, error) {
if ip.To4() != nil {
return v.ipV4Ranger, nil
}
if ip.To16() != nil {
return v.ipV6Ranger, nil
}
return nil, ErrInvalidNetworkNumberInput
}