The difference between IPv4 and IPv6 starts with the address. IPv4 uses 32-bit addresses written as four decimal numbers, like 203.0.113.10. IPv6 uses 128-bit addresses written as eight groups of hex, like 2001:db8::10. They’re separate protocols that don’t talk to each other directly, so most servers run both side by side.
The bigger address is the headline. What actually changes your day as an admin is the rest: no NAT, no ARP, addresses that configure themselves, and an ICMP you can’t block. Here’s what’s different and how to handle it on a server.
What is IPv4 and IPv6?
Both are versions of the Internet Protocol, the layer that addresses and routes packets. IPv4 dates from 1981 (RFC 791) and has about 4.3 billion addresses, which ran out years ago. IPv6 is the replacement; its current spec is RFC 8200. TCP, UDP, DNS and your application don’t care much which one carries them. Your firewall, your network config and your monitoring care a lot.
IPv4 vs IPv6 at a glance
| IPv4 | IPv6 | |
|---|---|---|
| Address size | 32 bits (about 4.3 billion) | 128 bits (about 3.4 × 1038) |
| Notation | Dotted decimal: 203.0.113.10 | Hex groups: 2001:db8::10 |
| Header | 20 to 60 bytes, with options and a checksum | Fixed 40 bytes, no checksum, extension headers |
| Fragmentation | Sender or any router | Sender only |
| Finding neighbors | ARP | Neighbor Discovery over ICMPv6 |
| Address setup | Static or DHCP | Static, SLAAC or DHCPv6 |
| Broadcast | Yes | No; multicast instead |
| NAT | Everywhere | Not needed |
| Minimum link MTU | 68 bytes | 1,280 bytes |
| DNS record / reverse zone | A / in-addr.arpa | AAAA / ip6.arpa |
| “Anywhere” in a firewall | 0.0.0.0/0 | ::/0 |
Addresses and notation
An IPv6 address is eight groups of four hex digits separated by colons. Two shortcuts make them readable, and RFC 5952 sets the rules for using them: drop leading zeros in each group, and replace the longest run of all-zero groups with ::, once per address. Write hex in lowercase.
2001:0db8:0000:0000:0000:0000:0000:0010 full form
2001:db8:0:0:0:0:0:10 leading zeros dropped
2001:db8::10 zeros collapsed (canonical)2001:db8::1::5 is invalid, because the reader couldn’t tell how many zeros each :: stands for. In a URL, wrap the address in brackets so the port isn’t mistaken for part of it: https://[2001:db8::10]:8443/.
Subnetting works the same way as IPv4 CIDR, but the sizes are different. A normal LAN or server subnet is a /64, because SLAAC (below) builds the last 64 bits of the address itself. Don’t try to save addresses by carving a /120 out of it. There are 18 quintillion addresses in a single /64; scarcity isn’t the problem anymore.
Every IPv6 interface also gets a link-local address in fe80::/10, even before you configure anything. It only works on the local segment and routers never forward it. Neighbor discovery and router advertisements use it, which is why a server with IPv6 enabled shows an fe80:: address next to its global one. That’s normal.
One thing people search for: you can’t derive an IPv4 address from an IPv6 one or the other way round, because they’re unrelated numbers. You’ll see IPv4 embedded in IPv6 in two places. A dual-stack socket shows an IPv4 client as ::ffff:203.0.113.10, an IPv4-mapped address (RFC 4291). NAT64 gateways use the well-known prefix 64:ff9b::/96 to reach IPv4 hosts from IPv6-only networks (RFC 6052).
Header differences
The IPv6 header is a fixed 40 bytes: version, traffic class, a 20-bit flow label, payload length, next header, hop limit, and the two addresses. Anything optional goes into extension headers chained after it. IPv4’s header runs 20 to 60 bytes depending on options.
Three changes matter in practice. There’s no header checksum, so routers don’t recompute one at every hop, and UDP checksums become mandatory instead. TTL is renamed hop limit and works the same way. Most important, routers never fragment IPv6 packets. If a packet is too big for the next link, the router drops it and sends an ICMPv6 Packet Too Big message back to the sender, which has to resend smaller pieces. Block that message and large transfers hang while small ones work fine, one of the most confusing failures you’ll ever debug.
NAT, and why IPv6 doesn’t need it
IPv4 survived this long on NAT: a whole office or a rack of containers shares one public address. IPv6 has enough space that every device gets a globally routable address of its own, so NAT disappears. Peer-to-peer, VoIP and logging get simpler, because the address in the log is the real one.
The catch is that NAT was quietly acting as a firewall. Without it, nothing stops inbound connections except your actual firewall. On IPv6, a stateful firewall with a default-deny inbound policy isn’t optional. That’s the right design anyway; NAT was never a security feature.
SLAAC vs DHCPv6
IPv4 hosts get an address by static config or DHCP. IPv6 has three options:
- Static. What most servers should use. You set the address, prefix length and gateway yourself.
- SLAAC (stateless address autoconfiguration, RFC 4862). The router sends Router Advertisements with the prefix, and the host builds its own address. No server, no lease database.
- DHCPv6 (RFC 8415). Works much like DHCP, either handing out addresses or only extra settings such as DNS servers. It also does prefix delegation, which is how a router gets a whole block to hand out downstream.
Even on a statically configured server, the default route often comes from a Router Advertisement. If IPv6 works after boot and then drops out a while later, check whether something is blocking RAs.
ICMPv6 must not be blanket-blocked
A lot of IPv4 firewalls drop all ICMP out of habit. Do that on IPv6 and it breaks. Neighbor Discovery, the replacement for ARP, runs on ICMPv6. So do router advertisements and the Packet Too Big messages that path MTU discovery depends on.
RFC 4890 lists what to let through. For a server, the short version is:
- Errors: Destination Unreachable (type 1), Packet Too Big (2), Time Exceeded (3), Parameter Problem (4).
- Echo: Request and Reply (128, 129). Rate-limit them if you like, but don’t drop them.
- Neighbor Discovery: Router Solicitation and Advertisement (133, 134), Neighbor Solicitation and Advertisement (135, 136), on the local link.
If IPv6 “seems broken” right after you add it to a server, check the firewall before anything else.
Dual stack in practice
Dual stack means running both protocols at once, each with its own address, gateway and firewall rules. IPv6 doesn’t inherit anything from IPv4. An IPv4 default gateway does nothing for IPv6, even when it’s the same router.
Clients pick a protocol with Happy Eyeballs (RFC 8305): they try IPv6 first and fall back to IPv4 quickly if it stalls. That’s why a broken IPv6 setup often shows up as “the site is slow sometimes” rather than as an outage. Two rules keep you out of trouble. Only publish an AAAA record for a service that really answers on IPv6. And write firewall rules for both families, because the classic dual-stack hole is a locked-down IPv4 ruleset next to a wide-open IPv6 one.
IPv6 adoption in 2026
IPv6 isn’t a future thing anymore. Google’s IPv6 statistics show roughly 46% to 51% of its users connecting over IPv6 in September 2026, with weekends at the top of that range. For the United States, Google’s per-country figure was 54.55% as of September 30, 2026.
About half your visitors could be reaching you over IPv6 right now, if your server answers on it.
Why IPv4 addresses cost money now
The registries ran dry years ago. ARIN, which covers North America, issued the last addresses in its free pool on September 24, 2015, and since then new IPv4 space mostly comes from a waiting list or the transfer market. Providers pass that cost on. The clearest public example is AWS. Since February 1, 2024, it has charged $0.005 per hour for every public IPv4 address, and in that announcement AWS said the cost to acquire a single public IPv4 address had risen more than 300% over the previous five years.
A worked example: one address for a full year is 8,760 hours × $0.005, or $43.80. Ten addresses on a small fleet is $438 a year before you’ve run anything on them. The charge covers public IPv4 only, which is a strong nudge toward IPv6.
Anywhere-IPv4 vs Anywhere-IPv6 in AWS
If you searched “anywhere ipv4 vs ipv6 aws”, you’ve seen the two options in the security group rule editor. Per the AWS VPC docs, Anywhere-IPv4 is 0.0.0.0/0 and allows traffic from all IPv4 addresses; Anywhere-IPv6 is ::/0 and allows traffic from all IPv6 addresses.
They’re separate rules. Opening port 443 to 0.0.0.0/0 doesn’t open it to IPv6 clients, and the reverse is also true. If your instance has an IPv6 address and the site should be public, add both. If it’s SSH or a database port, use neither: AWS’s own advice is to allow only the address ranges that need access. And the default security group only gets its ::/0 outbound rule if the VPC has an IPv6 CIDR block associated.
The same idea applies on any firewall, cloud or bare metal: “anywhere” means one thing per address family.
Commands to check IPv6 on a server
On Linux (iproute2 and iputils, same on AlmaLinux 9 and Ubuntu 24.04):
# addresses: look for "scope global" next to the fe80:: link-local one
ip -6 addr show
# routes: you want a "default via" line
ip -6 route show
# can you reach the IPv6 internet?
ping -6 -c 4 google.com
# does HTTPS work over IPv6?
curl -6 -sS -o /dev/null -w '%{http_code}\n' https://www.google.com
# which services are listening on IPv6?
ss -6 -tlnping6 was merged into ping back in iputils s20150815, per the ping man page; Ubuntu 24.04 still ships ping6 as an alias, but ping -6 works everywhere. curl -6 tells curl to resolve only IPv6 addresses (curl docs). On Windows, ipconfig lists the IPv6 addresses and ping -6 google.com tests them.
Firewall rules for both families
nftables. Use an inet table and one ruleset covers IPv4 and IPv6 together. A minimal server input chain, following the nftables wiki pattern with the ICMPv6 types from RFC 4890:
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state vmap { established : accept, related : accept, invalid : drop }
iifname "lo" accept
icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept
icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
tcp dport { 22, 80, 443 } accept
}
}The type names are the ones listed in the nft man page. Tighten port 22 to your own ranges before you use this for real.
firewalld (the default on AlmaLinux and Rocky 9) manages nftables for you, so use it instead of writing raw rules on those systems. A service rule applies to both families. A rich rule that names a source address needs family set, per the rich language docs:
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv6" source address="2001:db8:1234::/48" service name="ssh" accept'
sudo firewall-cmd --reloadA zone with the default target accepts ICMP and rejects everything else not allowed (firewalld.zone). If you’ve changed the target to DROP or added ICMP blocks, make sure ICMPv6 still gets through.
ufw (Ubuntu). IPv6 is on by default (IPV6=yes in /etc/default/ufw), and a rule without an address applies to both families. Its default ruleset already accepts the ICMPv6 needed for autoconfiguration and the error types, per the ufw man page:
grep IPV6 /etc/default/ufw # should print IPV6=yes
sudo ufw allow 443/tcp # IPv4 and IPv6
sudo ufw allow from 2001:db8:1234::/48 to any port 22 proto tcp
sudo ufw status verboseIn ufw status, rules marked (v6) are the IPv6 copies. If they’re missing, IPv6 is set to no, and ufw then accepts IPv6 only on loopback, so your AAAA record points at a closed door.
So which one should you use?
Both. IPv4 isn’t going away soon, since plenty of networks still don’t have IPv6, and IPv6 is already how about half of Google’s users connect. Run dual stack, give each family its own firewall rules, and leave ICMPv6 alone. If you’re building something new, make sure it works on IPv6 from day one; retrofitting it later is the painful version.
Planning servers and want to talk through addressing for a dual-stack setup? Tell us what you’re building and we’ll go through the options with you.


