AWS will begin charging for IPv4 addresses associated with AWS resources such as EC2/RDS instances, NAT gateways, and load balancers on February 1st, 2024.
The new fee is $0.005 per hour per IPv4 address (approximately $43.8/year/address), which may seem insignificant to some and costly to others. In all cases, I believe it is a good idea to investigate using IPv6 instead of IPv4 in your servers, or at the very least a dual-stack that supports both.
To learn more about IPv6, let's start with the basics.
Each of your servers/instances may have multiple IP addresses attached to them; one private IP address and one or more public IP addresses.
A private IP address is the server's local address within the virtual private network (VPC). This address does not route internet traffic and cannot be reached via the internet.
A public address, on the other hand, is used to route internet traffic. It can then be used to send data packets to the server from any device with internet access on any network.
Inside a VPC, we may have one or more sub networks (subnets). Each subnet has its own route table, which contains the routing rules for traffic.
To expose an instance within a subnet to the public internet, we must configure the subnet's route table to route traffic to an internet gateway.
The internet gateway converts an IPv4 private address (the one known by the instance) to an IPv4 public address (the one known by the internet).
To hide an instance from the internet, we place it within a subnet that does not have a route to an internet gateway. When we do this, other instances in the same VPC can communicate with this instance via its private IPv4 address, but no device on the internet can communicate with it. Even if the instance has a public IPv4 address.
For a private instance to be able to access the internet (to download libraries, use CURL, use wget, etc...), we need to install a NAT device inside the VPC.
This device is assigned one or two public IPv4 addresses. It converts the private IP address of instances attempting to connect to the internet to a public IP address.. Allowing it to send and receive data packets.
The NAT device, unlike an internet gateway, only handles traffic initiated by local instances. It does not allow internet traffic to reach the instances unless it is in response to requests made by the instances.
The pool of IPv4 addresses contains 4,294,967,296 addresses, which is insufficient to cover all internet devices (and servers). Cloud providers buy unused IP addresses and lease them to us.
As the pool of available IPv4 addresses is depleted, the price continues to rise. AWS used to provide free IPv4 addresses when they were attached to a running service (EC2 instance), but that will change in February of next year.
The IPv6 protocol is an alternative to the IPv4 protocol. It has a larger pool size that is technically impossible to exhaust in the foreseeable future.
The issue is that the IPv4 and IPv6 protocols are incompatible. In other words, a server that only has an IPv6 address cannot communicate with another server that only has an IPv4 address. Furthermore, IPv4-only devices are unable to communicate with IPv6-only servers.
For example, Vercel doesn't support IPv6 yet. That means a IPv6-only server won't be able to communicate with a site hosted on Vercel. Same for GitHub, it doesn't support IPv6.
As a result, many organizations choose to only support IPv4. Others prefer to support a dual stack with an IPv4 interface and an IPv6 interface.
Enabling IPv6 on a VPC
To enable IPv6 for a new VPC, you must define a IPv6 CIDR block:
A CIDR block defines the range of IP addresses to be allocated for the network. This helps AWS know where to route traffic coming to a certain IP.
By choosing "Amazon-provided IPv6 CIDR block", we let AWS assign a block for us from its pool.
If you have an existing VPC and want to enable IPv6: choose Actions > Edit CIDRs, and then "Add new IPv6 CIDR".
After that, you need to add an IPv6 CIDR to the subnets inside the VPC. And to do that, choose Actions > Edit IPv6 CIDRs, and then click on "Add IPv6 CIDR" under "Subnet CIDR block".
While adding a block to a subnet, you'll be asked to provide two digits to give the subnet a unique block. These two digits are hexadecimal, so the can be any digit between 0-9 or a-f. (
a1 for example, or
Attaching an IPv6 address to an EC2 instance
Choose Actions > Networking > Manage IP addresses.
Then click on "Assign new IP address" under "IPv6 Addresses".
Once the changes are saved, you'll instance will have an IPv6 address along with any public IPv4 and private IPv4 addresses it used to have.
With this setup, we have a dual stack network that can interface with IPv6 and IPv4.
Optimizing public IPv4 addresses on AWS
With the introduction of charges on IPv4 allocations in AWS, we need to optimize our usage of these addresses.
For example, suppose we have a network with multiple instances that have public IPv4 addresses. We could replace them with instances in private subnets with no IPv4 addresses, add a NAT gateway on a public subnet, and route traffic from the private subnet to the NAT gateway.
A NAT gateway costs:
- $0.045 per hour.
- $0.045 per GB of data processed.
- $0.005 for one IPv4 address.
We can determine whether this solution is more cost effective based on the number of instances and the amount of data transfer.
If some of the instances must be accessible via the internet, we could install an application load balancer and route traffic directed at specific domains to the appropriate instances.
A application load balancer costs:
- $0.0225 per hour.
- $0.008 per LCU-hour.
- $0.005 per IPv4 address (one per subnet).
You can find more details on LCU in this link.
Calculating NAT and load balancer costs can be difficult. This, in my opinion, will discourage people from using this solution unless they prefer to run their instances in private subnets for security reasons.
If all of the services with which your applications interact support IPv6, you can go IPv6-only by not assigning a public IP address to your EC2 instances and instead assigning an IPv6 address.
Public subnet route tables may direct traffic to an internet gateway, whereas private subnet route tables direct traffic to an egress-only internet gateway.
This egress-only gateway allows outbound communication but prevents inbound internet connections. It only supports the IPv6 protocol, so it cannot be used to replace the NAT gateway from the previous example.
If you're going this route, you need to ensure your local network has IPv6 support in order to connect to your instances via SSH. Alternatively, you may use an EC2 instance connect endpoint, which allows us to establish connections to our instances (public or private) via an SSH tunnel.
I believe that the new charge for IPv4 addresses will primarily affect AWS customers who run a few small instances. Large users will be unconcerned about such a small fee unless they require hundreds of IPv4 address allocations for some reason.
Additionally, serverless users connecting to private RDS databases will begin to see the additional cost of the IPv4 address assigned to their NAT gateway. They're already complaining about the cost of the NAT gateway and hoping for a price cut.
On the other hand, the change may encourage people to go IPv6-only, only to realize that they no longer need to support IPv4. We'll see what happens.
I'm Mohamed Said. I work with companies and teams all over the world to build and scale web applications in the cloud. Find me on twitter @themsaid.