We had the need to find AWS IP Addresess for a certain Service and Regions, and use them to route traffic over Amazons Direct Connect.
Luckily Amzon publishes the IP Ranges in Json Format.
Shell Code
curl https://ip-ranges.amazonaws.com/ip-ranges.json | \
jq -r '.prefixes[] | select(.service=="S3") | select(.network_border_group=="eu-central-1" ) | .ip_prefix'
Routes for cisco
We needed to have them on our Cisco Routers in a dedicated Routing instance (VRF).
Shell
# curl https://ip-ranges.amazonaws.com/ip-ranges.json | jq -r '.prefixes[] | select(.service=="S3") | select(.network_border_group=="eu-central-1" ) | .ip_prefix' | while read line ; do\
echo ip route vrf vrf-aws-connect $(echo $line | cut -d '/' -f 1) $(~/bin/ipcalc -bn ${line} | grep Netmask | cut -f 2 -d ":" | cut -f 1 -d "=" | sed -e 's/ //gm') 10.255.112.121 name SAWS-S3-EU-CENTRAL-1 \
done
AWS IP Ranges Syntax
The Syntax per Amazon, can be found here: AWS IP address ranges.
All Rights below this point belong to Amazon Web Services, Inc.
{
"syncToken": "0123456789",
"createDate": "yyyy-mm-dd-hh-mm-ss",
"prefixes": [
{
"ip_prefix": "cidr",
"region": "region",
"network_border_group": "network_border_group",
"service": "subset"
}
],
"ipv6_prefixes": [
{
"ipv6_prefix": "cidr",
"region": "region",
"network_border_group": "network_border_group",
"service": "subset"
}
]
}
Syntax
syncToken
The publication time, in Unix epoch time format.
Type: String
Example: "syncToken": "1416435608"
prefixes
The IP prefixes for the IPv4 address ranges.
Type: Array
ipv6_prefixes
The IP prefixes for the IPv6 address ranges.
Type: Array
ip_prefix
The public IPv4 address range, in CIDR notation. Note that AWS may advertise a prefix in more specific ranges. For example, prefix 96.127.0.0/17 in the file may be advertised as 96.127.0.0/21, 96.127.8.0/21, 96.127.32.0/19, and 96.127.64.0/18.
Type: String
Example: "ip_prefix": "198.51.100.2/24"
ipv6_prefix
The public IPv6 address range, in CIDR notation. Note that AWS may advertise a prefix in more specific ranges.
Type: String
Example: "ipv6_prefix": "2001:db8:1234::/64"
network_border_group
The name of the network border group, which is a unique set of Availability Zones or Local Zones from which AWS advertises IP addresses, or GLOBAL. Traffic for GLOBAL services can be attracted to or originate from multiple (up to all) Availability Zones or Local Zones from which AWS advertises IP addresses.
Type: String
Example: "network_border_group": "us-west-2-lax-1"
region
The AWS Region or GLOBAL. Traffic for GLOBAL services can be attracted to or originate from multiple (up to all) AWS Regions.
Type: String
Valid values: af-south-1 | ap-east-1 | ap-northeast-1 | ap-northeast-2 | ap-northeast-3 | ap-south-1 | ap-south-2 | ap-southeast-1 | ap-southeast-2 | ap-southeast-3 | ap-southeast-4 | ca-central-1 | cn-north-1 | cn-northwest-1 | eu-central-1 | eu-central-2 | eu-north-1 | eu-south-1 | eu-south-2 | eu-west-1 | eu-west-2 | eu-west-3 | me-central-1 | me-south-1 | sa-east-1 | us-east-1 | us-east-2 | us-gov-east-1 | us-gov-west-1 | us-west-1 | us-west-2 | GLOBAL
Example: "region": "us-east-1"
service
The subset of IP address ranges. The addresses listed for API_GATEWAY are egress only. Specify AMAZON to get all IP address ranges (meaning that every subset is also in the AMAZON subset). However, some IP address ranges are only in the AMAZON subset (meaning that they are not also available in another subset).
Type: String
Valid values: AMAZON | AMAZON_APPFLOW | AMAZON_CONNECT | API_GATEWAY | CHIME_MEETINGS | CHIME_VOICECONNECTOR | CLOUD9 | CLOUDFRONT | CLOUDFRONT_ORIGIN_FACING | CODEBUILD | DYNAMODB | EBS | EC2 | EC2_INSTANCE_CONNECT | GLOBALACCELERATOR | KINESIS_VIDEO_STREAMS | MEDIA_PACKAGE_V2 | ROUTE53 | ROUTE53_HEALTHCHECKS | ROUTE53_HEALTHCHECKS_PUBLISHING | ROUTE53_RESOLVER | S3 | WORKSPACES_GATEWAYS
Example: "service": "AMAZON"
Filtering the JSON file
Linux
Example 1. Get the creation date
$ jq .createDate < ip-ranges.json "2016-02-18-17-22-15"
Example 2. Get the information for a specific Region
$ jq '.prefixes[] | select(.region=="us-east-1")' < ip-ranges.json
{
"ip_prefix": "23.20.0.0/14",
"region": "us-east-1",
"network_border_group": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "50.16.0.0/15",
"region": "us-east-1",
"network_border_group": "us-east-1",
"service": "AMAZON"
},
{
"ip_prefix": "50.19.0.0/16",
"region": "us-east-1",
"network_border_group": "us-east-1",
"service": "AMAZON"
},
...
Example 6. Get all IPv4 addresses for a specific service in a specific Region
$ jq -r '.prefixes[] | select(.region=="us-east-1") | select(.service=="CODEBUILD") | .ip_prefix' < ip-ranges.json 34.228.4.208/28
Example 7. Get information for a certain network border group
$ jq -r '.prefixes[] | select(.region=="us-west-2") | select(.network_border_group=="us-west-2-lax-1") | .ip_prefix' < ip-ranges.json 70.224.192.0/18 52.95.230.0/24 15.253.0.0/16 ...
Python
The following python script shows you how to get the IP addresses that are in the AMAZON list but not the EC2 list. Copy the script and save it in a file named get_ips.py.
#!/usr/bin/env python
import requests
ip_ranges = requests.get('https://ip-ranges.amazonaws.com/ip-ranges.json').json()['prefixes']
amazon_ips = [item['ip_prefix'] for item in ip_ranges if item["service"] == "AMAZON"]
ec2_ips = [item['ip_prefix'] for item in ip_ranges if item["service"] == "EC2"]
amazon_ips_less_ec2=[]
for ip in amazon_ips:
if ip not in ec2_ips:
amazon_ips_less_ec2.append(ip)
for ip in amazon_ips_less_ec2: print(str(ip))
You can run this script as follows:
$ python ./get_ips.py
13.32.0.0/15
13.35.0.0/16
13.248.0.0/20
13.248.16.0/21
13.248.24.0/22
13.248.28.0/22
27.0.0.0/22
43.250.192.0/24
43.250.193.0/24
...
Links
- https://aws.amazon.com/directconnect/
- https://docs.aws.amazon.com/vpc/latest/userguide/aws-ip-ranges.html
- https://ip-ranges.amazonaws.com/ip-ranges.json
Photo by Taylor Vick on Unsplash

