Quickstart¶
awsipranges
helps you answer simple questions fast and makes it easy for you to leverage the AWS IP range data in your Python automation scripts and infrastructure configurations.
To get started, make sure you have:
awsipranges
installedawsipranges
upgraded to the latest version
Then dive-in with this Quickstart to begin working with the AWS IP address ranges as native Python objects!
Verify server TLS certificates¶
How do I know that I am working with the authentic and latest AWS IP address ranges?
By default, if you do not provide trusted certificates, the Python urllib module (used by the awsipranges.get_ranges()
function) verifies the TLS certificate presented by the server against the system-provided certificate datastore.
It is your responsibility to verify the TLS certificate presented by the server. awsipranges
downloads the latest AWS IP address ranges from the published JSON file and makes it easy for you to verify the authenticity of the TLS certificate presented by the server.
Amazon publishes their root Certificate Authority (CA) certificates in the Amazon Trust Services Repository.
To verify the TLS certificate presented by the Amazon IP ranges server (ip-ranges.amazonaws.com):
-
Download the Amazon Root CA certificates (in PEM format) from the Amazon Trust Services Repository.
-
Prepare the certificates for use by either:
-
Stacking (concatenating) the files into a single certificate bundle (single file)
-
Storing them in a directory using OpenSSL hash filenames
You can do this with the
c_rehash
script included in many OpenSSL distributions:❯ c_rehash amazon_root_certificates/
Tip: See
tests/unit/test_data_loading.py
in theawsipranges
repository for sample Python functions that download the Amazon Root CA certificates and prepare the certificates as both a stacked certificate bundle file and as a directory with OpenSSL hash filenames. -
-
Pass the path to the prepared certificates to the
awsipranges.get_ranges()
function using thecafile
orcapath
parameters:-
cafile=
path to the stacked certificate bundle file -
capath=
path to the directory containing the certificates with OpenSSL hashed filenames
>>> import awsipranges # Using a stacked certificate bundle >>> aws_ip_ranges = awsipranges.get_ranges(cafile="amazon_root_certificates.pem") # Using directory containing the certificates with OpenSSL hashed filenames >>> aws_ip_ranges = awsipranges.get_ranges(capath="amazon_root_certificates/")
-
Download AWS IP address ranges¶
One line of code (okay, two if you count the import statement) is all it takes to download and parse the AWS IP address ranges into a pythonic data structure:
>>> import awsipranges
>>> aws_ip_ranges = awsipranges.get_ranges()
The awsipranges.get_ranges()
function returns an AWSIPPrefixes
object, which is a structured collection of AWS IP prefixes.
You can access the create_date
and sync_token
attributes of the AWSIPPrefixes
collection to check the version of the downloaded JSON file and verify the integrity of the file with the md5
attribute:
>>> aws_ip_ranges.create_date
datetime.datetime(2021, 10, 1, 16, 33, 13, tzinfo=datetime.timezone.utc)
>>> aws_ip_ranges.sync_token
'1633105993'
>>> aws_ip_ranges.md5
'59e4cd7f4757a9f380c626d772a5eef2'
You can access the IPv4 and IPv6 address prefixes with the ipv4_prefixes
and ipv6_prefixes
attributes:
>>> aws_ip_ranges.ipv4_prefixes
(AWSIPv4Prefix('3.0.0.0/15', region='ap-southeast-1', network_border_group='ap-southeast-1', services=('AMAZON', 'EC2')),
AWSIPv4Prefix('3.0.5.32/29', region='ap-southeast-1', network_border_group='ap-southeast-1', services=('EC2_INSTANCE_CONNECT',)),
AWSIPv4Prefix('3.0.5.224/27', region='ap-southeast-1', network_border_group='ap-southeast-1', services=('ROUTE53_RESOLVER',)),
AWSIPv4Prefix('3.2.0.0/24', region='us-east-1', network_border_group='us-east-1-iah-1', services=('AMAZON', 'EC2')),
AWSIPv4Prefix('3.2.2.0/24', region='us-east-1', network_border_group='us-east-1-mia-1', services=('AMAZON', 'EC2')),
...)
>>> aws_ip_ranges.ipv6_prefixes
(AWSIPv6Prefix('2400:6500:0:9::1/128', region='ap-southeast-3', network_border_group='ap-southeast-3', services=('AMAZON',)),
AWSIPv6Prefix('2400:6500:0:9::2/128', region='ap-southeast-3', network_border_group='ap-southeast-3', services=('AMAZON',)),
AWSIPv6Prefix('2400:6500:0:9::3/128', region='ap-southeast-3', network_border_group='ap-southeast-3', services=('AMAZON',)),
AWSIPv6Prefix('2400:6500:0:9::4/128', region='ap-southeast-3', network_border_group='ap-southeast-3', services=('AMAZON',)),
AWSIPv6Prefix('2400:6500:0:7000::/56', region='ap-southeast-1', network_border_group='ap-southeast-1', services=('AMAZON',)),
...)
...and if that's all this library did, it would be pretty boring.
Check an IP address or network¶
How can I check to see if an IP address or network is contained in the AWS IP address ranges?
AWSIPPrefixes
works like a standard python collection. You can check to see if an IP address, interface, or network is contained in the collection by using the Python in
operator:
>>> '52.94.5.15' in aws_ip_ranges
True
>>> '43.195.173.0/24' in aws_ip_ranges
True
>>> IPv4Network('13.50.0.0/16') in aws_ip_ranges
True
>>> '1.1.1.1' in aws_ip_ranges
False
Find an AWS IP prefix¶
How can I find the AWS IP prefix that contains an IP address or network?
You can get the longest-match prefix that contains an IP address or network by indexing into the AWSIPPrefixes
collection or using the get()
method just like you do with a Python dictionary:
>>> aws_ip_ranges['52.94.5.15']
AWSIPv4Prefix('52.94.5.0/24', region='eu-west-1', network_border_group='eu-west-1', services=('AMAZON', 'DYNAMODB'))
>>> aws_ip_ranges.get('52.94.5.15')
AWSIPv4Prefix('52.94.5.0/24', region='eu-west-1', network_border_group='eu-west-1', services=('AMAZON', 'DYNAMODB'))
>>> aws_ip_ranges.get('1.1.1.1', default='Nope')
'Nope'
The AWS IP address ranges contain supernet and subnet prefixes, so an IP address or network may be contained in more than one AWS IP prefix. Use the get_prefix_and_supernets()
method to retrieve all IP prefixes that contain an IP address or network:
>>> aws_ip_ranges.get_prefix_and_supernets('3.218.180.73')
(AWSIPv4Prefix('3.208.0.0/12', region='us-east-1', network_border_group='us-east-1', services=('AMAZON', 'EC2')),
AWSIPv4Prefix('3.218.180.0/22', region='us-east-1', network_border_group='us-east-1', services=('DYNAMODB',)),
AWSIPv4Prefix('3.218.180.0/25', region='us-east-1', network_border_group='us-east-1', services=('DYNAMODB',)))
Filter AWS IP prefixes¶
How can I filter the AWS IP prefixes by Region, network border group, or service?
The filter()
method allows you to select a subset of AWS IP prefixes from the collection. You can filter on regions
, network_border_groups
, IP versions
(4, 6), and services
. The filter()
method returns a new AWSIPPrefixes
object that contains the subset of IP prefixes that match your filter criteria.
You may pass a single value (regions='eu-central-2'
) or a sequence of values (regions=['eu-central-1', 'eu-central-2']
) to the filter parameters. The filter()
method returns the prefixes that match all the provided parameters; selecting prefixes where the prefix's attributes intersect the provided set of values.
For example, filter(regions=['eu-central-1', 'eu-central-2'], services='EC2', versions=4)
will select all IP version 4
prefixes that have EC2
in the prefix's list of services and are in the eu-central-1
or eu-central-2
Regions.
>>> aws_ip_ranges.filter(regions='eu-central-2', services='EC2', versions=4)
{'create_date': datetime.datetime(2021, 9, 16, 17, 43, 14, tzinfo=datetime.timezone.utc),
'ipv4_prefixes': (AWSIPv4Prefix('3.5.52.0/22', region='eu-central-2', network_border_group='eu-central-2', services=('AMAZON', 'EC2', 'S3')),
AWSIPv4Prefix('16.62.0.0/15', region='eu-central-2', network_border_group='eu-central-2', services=('AMAZON', 'EC2')),
AWSIPv4Prefix('52.94.250.0/28', region='eu-central-2', network_border_group='eu-central-2', services=('AMAZON', 'EC2')),
AWSIPv4Prefix('99.151.80.0/21', region='eu-central-2', network_border_group='eu-central-2', services=('AMAZON', 'EC2'))),
'ipv6_prefixes': (),
'sync_token': '1631814194'}
Tip: You can view the set of all regions, network border groups, and services contained in an
AWSIPPrefixes
collection with theregions
,network_border_groups
, andservices
attributes.
>>> aws_ip_ranges.services
frozenset({'AMAZON',
'AMAZON_APPFLOW',
'AMAZON_CONNECT',
'API_GATEWAY',
'CHIME_MEETINGS',
'CHIME_VOICECONNECTOR',
'CLOUD9',
'CLOUDFRONT',
'CODEBUILD',
'DYNAMODB',
'EBS',
'EC2',
'EC2_INSTANCE_CONNECT',
'GLOBALACCELERATOR',
'KINESIS_VIDEO_STREAMS',
'ROUTE53',
'ROUTE53_HEALTHCHECKS',
'ROUTE53_HEALTHCHECKS_PUBLISHING',
'ROUTE53_RESOLVER',
'S3',
'WORKSPACES_GATEWAYS'})
Work with AWS IP prefix objects¶
My router/firewall wants IP networks in a net-mask or host-mask format. Do the AWS IP prefix objects provide a way for me to get the prefix in the format I need?
AWSIPv4Prefix
and AWSIPv6Prefix
objects are proxies around IPv4Network
and IPv6Network
objects from the Python standard library (see the ipaddress
module). They support all the attributes and methods available on the IPv4Network
and IPv6Network
objects. They also inherit additional attributes (like region
, network_border_group
, and services
) and additional functionality from the AWSIPPrefix
base class.
Combining the functionality provided by the standard library objects with the rich collection capabilities provided by the awsipranges
library allows you to complete complex tasks easily:
Like adding routes to the DYNAMODB
prefixes in the eu-west-1
Region to a router:
>>> for prefix in aws_ip_ranges.filter(regions='eu-west-1', services='DYNAMODB'):
... print(f"ip route {prefix.network_address} {prefix.netmask} 1.1.1.1")
...
ip route 52.94.5.0 255.255.255.0 1.1.1.1
ip route 52.94.24.0 255.255.254.0 1.1.1.1
ip route 52.94.26.0 255.255.254.0 1.1.1.1
ip route 52.119.240.0 255.255.248.0 1.1.1.1
Or, configuring an access control list to allow traffic to the S3
prefixes in eu-north-1
:
>>> for prefix in aws_ip_ranges.filter(regions='eu-north-1', services='S3', versions=4):
... print(f"permit tcp any {prefix.network_address} {prefix.hostmask} eq 443")
...
permit tcp any 3.5.216.0 0.0.3.255 eq 443
permit tcp any 13.51.71.176 0.0.0.15 eq 443
permit tcp any 13.51.71.192 0.0.0.15 eq 443
permit tcp any 52.95.169.0 0.0.0.255 eq 443
permit tcp any 52.95.170.0 0.0.1.255 eq 443
These are only a couple possibilities. Python and awsipranges
allow you to use the AWS IP ranges in your automation scripts to accomplish powerful tasks simply.
What about IPv6?¶
All the functionality and examples shown in this Quickstart also work with IPv6 prefixes! 😎