Analysing ccTLD anycast

In June, I attended NPNOG in Nepal. In the evening, I had a discussion with some friends about infra hosting ccTLD. We compared how some countries in the region host their ccTLD on their own while some outsource it to larger ccTLD operators. I have a feeling that it’s pretty hard to host a ccTLD these days, not because of the tech stack, but because of DDoS concerns. The only way to take care of DDoS at large-scale is to a) Over provision on the bandwidth and b) Spread the attack surface using anycast

So to host a ccTLD reliably in 2025, one would need at least eight‑ten global locations near major data sources to take care of the attack. Something like Ashburn, Dallas, Palo Alto, Frankfurt, Amsterdam, Singapore, Hong Kong, etc. While we had the discussion - I wanted to check how many ccTLDs are actually anycasted and if my guess was correct. Seems like I was partially correct.


Understanding anycast

Anycast basically means having more than one node and using the same address. It is assumed/expected that BGP will take us to the nearest announcement. But in reality, BGP path selection is influenced by neighbor relationships. Slide 26-33 of my presentation at INNOG covers this in detail. Essentially, network operators have the highest localpref on routes they learn from customers, the second highest on routes from peers, and the lowest on routes from upstream. Thus, if one does anycast with a mix and match of upstreams, it won’t work well. To deal with this, anycast is usually done with the same set of global upstream ISPs everywhere or with a very aggressive use of BGP action communities or a mix of global + local nodes. But even with all this, there can still be cases where some networks hit a local node, some hit far off anycast node.

Thus, to deal with this specific part, I have to test from multiple providers in a given location. Anycast cannot be easily tested by just looking at the routing table. In theory, with location communities, one can get an idea, but it’s much easier to find it from latency/trace from different locations.

So I ended up putting a script to look up for IPv4 and IPv6 latency to all ccTLD nameservers from the following providers/locations:

  1. Contabo - New York and Düsseldorf
  2. Hetzner - Falkenstein, Ashburn, and Singapore
  3. Vultr - Amsterdam, Los Angeles, and Singapore

These nodes are in key cities where peering/interconnection happens. Latency from these to ccTLD auth ns can determine whether they are anycasted or not. Finding the exact number of anycast nodes is hard and need a lot more distributed measurements but one can safely assume that if an IP is anycasted across the US, EU, and Asia, one should be able to reach it in less than 80ms from these locations (more like within 40-50ms actually). If I get low latency from one provider and high from other, I consider that it proves that an anycast node exists and it’s just bad routing (which I am not measuring here).


Result of ccTLD anycast check

The table below reflects the results. I have categorized into three simple categories:

  1. All NS anycasted - All nameservers for the given ccTLD are anycasted and reachable with low latency.
  2. At least one NS doing anycast - This is a case where I see some nameservers giving consistently low latency from the US, EU & Singapore, but some with high. In most cases, it’s basically non-anycasted own servers and anycasted servers of commercial/non-profit providers.
  3. None of the NS is doing anycast - All nameservers have above 80ms latency when checked from the US, EU, and Singapore (at least two of these regions, usually lower latency where closer to the ccTLD origin country)
ccTLDCategory
awAll NS anycasted
bhAll NS anycasted
fmAll NS anycasted
foAll NS anycasted
gdAll NS anycasted
inAll NS anycasted
laAll NS anycasted
nlAll NS anycasted
pwAll NS anycasted
toAll NS anycasted
vgAll NS anycasted
acAtleast one NS doing anycast
adAtleast one NS doing anycast
aeAtleast one NS doing anycast
afAtleast one NS doing anycast
agAtleast one NS doing anycast
aiAtleast one NS doing anycast
alAtleast one NS doing anycast
amAtleast one NS doing anycast
aoAtleast one NS doing anycast
aqAtleast one NS doing anycast
arAtleast one NS doing anycast
asAtleast one NS doing anycast
atAtleast one NS doing anycast
auAtleast one NS doing anycast
axAtleast one NS doing anycast
azAtleast one NS doing anycast
baAtleast one NS doing anycast
bbAtleast one NS doing anycast
bdAtleast one NS doing anycast
beAtleast one NS doing anycast
bfAtleast one NS doing anycast
bgAtleast one NS doing anycast
biAtleast one NS doing anycast
bjAtleast one NS doing anycast
blAtleast one NS doing anycast
bmAtleast one NS doing anycast
bnAtleast one NS doing anycast
boAtleast one NS doing anycast
brAtleast one NS doing anycast
bsAtleast one NS doing anycast
btAtleast one NS doing anycast
bwAtleast one NS doing anycast
bzAtleast one NS doing anycast
caAtleast one NS doing anycast
ccAtleast one NS doing anycast
cdAtleast one NS doing anycast
cfAtleast one NS doing anycast
cgAtleast one NS doing anycast
chAtleast one NS doing anycast
ciAtleast one NS doing anycast
clAtleast one NS doing anycast
cmAtleast one NS doing anycast
cnAtleast one NS doing anycast
coAtleast one NS doing anycast
crAtleast one NS doing anycast
cuAtleast one NS doing anycast
cvAtleast one NS doing anycast
cwAtleast one NS doing anycast
cxAtleast one NS doing anycast
cyAtleast one NS doing anycast
czAtleast one NS doing anycast
deAtleast one NS doing anycast
djAtleast one NS doing anycast
dkAtleast one NS doing anycast
dmAtleast one NS doing anycast
doAtleast one NS doing anycast
dzAtleast one NS doing anycast
ecAtleast one NS doing anycast
eeAtleast one NS doing anycast
egAtleast one NS doing anycast
erAtleast one NS doing anycast
esAtleast one NS doing anycast
euAtleast one NS doing anycast
fiAtleast one NS doing anycast
fkAtleast one NS doing anycast
frAtleast one NS doing anycast
gaAtleast one NS doing anycast
gbAtleast one NS doing anycast
gfAtleast one NS doing anycast
ggAtleast one NS doing anycast
giAtleast one NS doing anycast
glAtleast one NS doing anycast
gmAtleast one NS doing anycast
gnAtleast one NS doing anycast
gpAtleast one NS doing anycast
gqAtleast one NS doing anycast
grAtleast one NS doing anycast
gtAtleast one NS doing anycast
guAtleast one NS doing anycast
gwAtleast one NS doing anycast
gyAtleast one NS doing anycast
hkAtleast one NS doing anycast
hmAtleast one NS doing anycast
hnAtleast one NS doing anycast
hrAtleast one NS doing anycast
htAtleast one NS doing anycast
huAtleast one NS doing anycast
idAtleast one NS doing anycast
ieAtleast one NS doing anycast
ilAtleast one NS doing anycast
imAtleast one NS doing anycast
ioAtleast one NS doing anycast
iqAtleast one NS doing anycast
irAtleast one NS doing anycast
isAtleast one NS doing anycast
itAtleast one NS doing anycast
jeAtleast one NS doing anycast
jmAtleast one NS doing anycast
joAtleast one NS doing anycast
jpAtleast one NS doing anycast
keAtleast one NS doing anycast
kgAtleast one NS doing anycast
khAtleast one NS doing anycast
kiAtleast one NS doing anycast
knAtleast one NS doing anycast
kwAtleast one NS doing anycast
kyAtleast one NS doing anycast
kzAtleast one NS doing anycast
lbAtleast one NS doing anycast
lcAtleast one NS doing anycast
liAtleast one NS doing anycast
lkAtleast one NS doing anycast
lrAtleast one NS doing anycast
lsAtleast one NS doing anycast
ltAtleast one NS doing anycast
luAtleast one NS doing anycast
lvAtleast one NS doing anycast
lyAtleast one NS doing anycast
maAtleast one NS doing anycast
mcAtleast one NS doing anycast
mdAtleast one NS doing anycast
meAtleast one NS doing anycast
mgAtleast one NS doing anycast
mhAtleast one NS doing anycast
mkAtleast one NS doing anycast
mlAtleast one NS doing anycast
mmAtleast one NS doing anycast
mnAtleast one NS doing anycast
moAtleast one NS doing anycast
mqAtleast one NS doing anycast
mrAtleast one NS doing anycast
msAtleast one NS doing anycast
mtAtleast one NS doing anycast
muAtleast one NS doing anycast
mvAtleast one NS doing anycast
mwAtleast one NS doing anycast
mxAtleast one NS doing anycast
myAtleast one NS doing anycast
mzAtleast one NS doing anycast
naAtleast one NS doing anycast
ncAtleast one NS doing anycast
neAtleast one NS doing anycast
nfAtleast one NS doing anycast
ngAtleast one NS doing anycast
niAtleast one NS doing anycast
noAtleast one NS doing anycast
npAtleast one NS doing anycast
nrAtleast one NS doing anycast
nuAtleast one NS doing anycast
nzAtleast one NS doing anycast
omAtleast one NS doing anycast
paAtleast one NS doing anycast
peAtleast one NS doing anycast
pgAtleast one NS doing anycast
phAtleast one NS doing anycast
pkAtleast one NS doing anycast
plAtleast one NS doing anycast
pmAtleast one NS doing anycast
pnAtleast one NS doing anycast
prAtleast one NS doing anycast
psAtleast one NS doing anycast
ptAtleast one NS doing anycast
pyAtleast one NS doing anycast
qaAtleast one NS doing anycast
reAtleast one NS doing anycast
roAtleast one NS doing anycast
rsAtleast one NS doing anycast
ruAtleast one NS doing anycast
rwAtleast one NS doing anycast
saAtleast one NS doing anycast
sbAtleast one NS doing anycast
scAtleast one NS doing anycast
sdAtleast one NS doing anycast
seAtleast one NS doing anycast
sgAtleast one NS doing anycast
shAtleast one NS doing anycast
siAtleast one NS doing anycast
sjAtleast one NS doing anycast
skAtleast one NS doing anycast
smAtleast one NS doing anycast
snAtleast one NS doing anycast
soAtleast one NS doing anycast
stAtleast one NS doing anycast
svAtleast one NS doing anycast
sxAtleast one NS doing anycast
syAtleast one NS doing anycast
szAtleast one NS doing anycast
tcAtleast one NS doing anycast
tdAtleast one NS doing anycast
tgAtleast one NS doing anycast
thAtleast one NS doing anycast
tjAtleast one NS doing anycast
tkAtleast one NS doing anycast
tlAtleast one NS doing anycast
tmAtleast one NS doing anycast
tnAtleast one NS doing anycast
trAtleast one NS doing anycast
ttAtleast one NS doing anycast
tvAtleast one NS doing anycast
twAtleast one NS doing anycast
tzAtleast one NS doing anycast
uaAtleast one NS doing anycast
ugAtleast one NS doing anycast
ukAtleast one NS doing anycast
usAtleast one NS doing anycast
uyAtleast one NS doing anycast
uzAtleast one NS doing anycast
vaAtleast one NS doing anycast
vcAtleast one NS doing anycast
veAtleast one NS doing anycast
viAtleast one NS doing anycast
vnAtleast one NS doing anycast
vuAtleast one NS doing anycast
wfAtleast one NS doing anycast
wsAtleast one NS doing anycast
yeAtleast one NS doing anycast
ytAtleast one NS doing anycast
zaAtleast one NS doing anycast
zmAtleast one NS doing anycast
zwAtleast one NS doing anycast
byNone of NS doing anycast
ckNone of NS doing anycast
etNone of NS doing anycast
geNone of NS doing anycast
ghNone of NS doing anycast
kmNone of NS doing anycast
krNone of NS doing anycast
pfNone of NS doing anycast
srNone of NS doing anycast


Conclusion

I was partially correct (and partially incorrect). The majority of ccTLDs are not using anycast on all their nameservers but are using anycast on atleast one of their nameserver. As per this list, nameservers of 11 ccTLDs have full anycast, 9 have no anycast, and the remaining 219 have partial anycast, with some nameservers doing anycast, some not. Also, some ccTLDs are skipped from the list where all nameservers have ICMP closed. I should have probably tested with DNS latency instead of ICMP latency only.

The raw latency checks are posted here.