{"slug": "i-wanted-to-see-which-subsea-cable-my-packets-cross-the-cloud-couldn-t-trace-and", "title": "I wanted to see which subsea cable my packets cross. The cloud couldn't trace, and the database put Helsinki in Phoenix", "summary": "A developer built PacketPulse, an open-source tool that runs traceroute from a user's own machine via a small local agent, then enriches the raw hops with ASN, GeoIP, subsea-cable and data-sovereignty data to draw the inferred route on a 3D globe. The project uses only free data sources — TeleGeography's 690-cable map, iptoasn, DB-IP Lite City, PeeringDB and a hand-curated law directory — and a compliance engine that checks routes against rules like GDPR Chapter V and India's RBI localization requirements. Key fixes included moving tracing off the server after Render's containers proved unable to open raw ICMP sockets, and rejecting GeoIP locations that violate the speed-of-light limit on round-trip time, which had placed Cloudflare's anycast 1.1.1.1 in Australia.", "body_md": "**The idea**\n\nWhen you open a website, your data passes through a dozen routers, a few ISPs, maybe a cable on the ocean floor, and several countries with their own data laws. None of that is visible. My pitch was:\n\nTrace packets from your own computer, work out which networks, countries, and subsea cables they cross, check the route against data-sovereignty laws like GDPR, and draw it live on a 3D Earth.\n\nThe constraints: cost $0, use only open data, and say clearly what is measured and what is guessed.\n\nLive demo: packetpulse-eta.vercel.app Code, data and tests: [github.com/Flotrpy/PacketPulse](https://dev.tourl)\n\nScoping it down so it was buildable\n\n**Measurement:** plain traceroute (ICMP/UDP with rising TTL), written from scratch in Go with raw sockets. Traceroute never sees a cable or a country; everything past the IP addresses and round-trip times is inference.\n\n**Data:** only free sources. TeleGeography's submarine cable map (690 cables), iptoasn (~580k IP ranges), DB-IP Lite City, Natural Earth borders, PeeringDB, AWS/GCP region prefixes, and a hand-curated law directory.\n\n**Laws:** a small compliance engine with profiles like \"EU personal data stays in the EEA or adequate countries\" (GDPR Chapter V) or \"Indian payment data stays in India\" (RBI).\n\n**Hosting:** free tiers only. Render runs the Go backend, Vercel serves the globe.\n\n**Iteration 1:** the server can't trace, and shouldn't\n\nThe obvious design: the user types a website, the server runs the traceroute, the globe draws it.\n\nThe first deploy came back with this in the health check:\n\n```\n{\"status\": \"ok\", \"tracing\": false}\n```\n\nRender's containers can't open raw ICMP sockets, so traceroute is impossible there. My development sandbox could trace, but its network let only 2 hops through.\n\nEven if it had worked, it would have been the wrong trace. A path from a data centre in Oregon tells you nothing about your path.\n\nLesson: sometimes the platform limit is pointing at a design flaw.\n\n**Iteration 2:** a small agent on your computer\n\nThe fix was to split the work:\n\nThe globe stays in the browser.\n\nA small agent, ppagent, runs on your computer and long-polls the server for trace jobs.\n\nYou click Trace on the website. Your agent traces from your network and public IP and posts the raw result back.\n\nThe server does all the enrichment (geolocation, ASNs, cables, compliance), so the agent stays tiny and needs no data files.\n\nOn Windows, the first real run printed one line and quit:\n\n```\nlevel=ERROR msg=\"trace failed\" target=C:\\Users\\affan\\Downloads\\ppagent.exe\n  err=\"\n```\n\n... target must be a hostname or IP address\"\n\nThe program received its own path as an argument, treated it as a website to trace, failed, and exited. The agent now ignores its own path and skips anything that isn't a hostname or IP. Setup on Windows is now one line in an Administrator PowerShell:\n\n```\nirm https://packetpulse-test.onrender.com/v1/agent/download/start-ppagent.ps1 | iex\n```\n\nLesson: the first run on someone else's machine is the real test.\n\n**Iteration 3:** 1.1.1.1 is in Australia (it isn't)\n\nWith the agent working, the first trace to 1.1.1.1 drew an arc from the US to Australia. The IP database lists Cloudflare's address under its registered location. But 1.1.1.1 is anycast: it answers from whichever site is closest, and it replied in about 3 ms.\n\nPhysics settles it. Light in fiber covers about 204 km per millisecond, so a 3 ms round trip means the server is at most about 300 km away. Every router location already had to pass this check. The destination didn't, so I added it.\n\nLesson: a free, exact constraint (the speed of light) beats any database.\n\n**Iteration 4:** the trace crossed the Atlantic, but no cable showed up\n\nThis was the real test. I traced from New Jersey to a server in Helsinki. The latency clearly jumped across the ocean, but the globe showed no subsea cable.\n\nHere is the actual trace, with what the GeoIP database said about each router:\n\nHop Router                          RTT    Database says\n\n2   lo0-100.NWRKNJ-…verizon-gni.net   4.9 ms     Newark, US\n\n6   ewr-bb2-link.ip.twelve99.net    6.6 ms     nothing\n\n7   kbn-bb6-link.ip.twelve99.net    105.9 ms   Solna, SE\n\n9   hls-b4-link.ip.twelve99.net 94.7 ms    Warsaw, PL\n\n11  hetzner-ic-….twelve99-cust.net    102.4 ms   Phoenix, US\n\n14  hel1-speed.hetzner.com          104.8 ms   Helsinki, FI\n\nThree things went wrong.\n\nThe router just before the ocean had no location. Hop 6 is the crossing point, but the database didn't know it, so the segment into hop 7 was \"unknown\". The router name knew, though: Arelion (Telia) names routers with city codes. ewr is Newark, kbn is København, hls is Helsinki, adm is Amsterdam. Some of these weren't in my lookup table. I added them, plus OVH, Hetzner and Verizon codes, and gaps are now bridged from the last router that does have a location.\n\nPhoenix. The database put a Helsinki interconnect in Arizona, which produced two fake \"subsea\" segments (Stockholm → Phoenix → Helsinki). The RTT check passed it, because 102 ms is plenty of time to reach Phoenix from New Jersey. What it didn't check was the path. Two new rules:\n\nPath check: source → previous router → this router must all fit inside the RTT.\n\nDetour check: if the route goes somewhere and comes straight back, the timings have to pay for the extra distance. Stockholm → Phoenix → Helsinki with almost no added RTT doesn't.\n\nAs a side benefit, RTT noise is handled better by using the lowest RTT seen at this hop or any later one. Slow ICMP replies only ever add delay, and the path to a later hop passes through this one.\n\nThe result:\n\n**                          Before          After**\n\nHop 6 (ewr)           unlocated         Newark\n\nHop 7 (kbn)           Solna                 Copenhagen\n\nHop 11                    Phoenix           dropped\n\nSubsea segments       2 fake ones (via Phoenix) 1: Newark → Copenhagen\n\nCable   none    Havfrue/AEC-2 (Wall Township, NJ → Blaabjerg, DK)\n\nNewark → Copenhagen is 6,200 km, so the fastest possible round trip is about 61 ms. The measured jump is 99 ms, which is typical once you add real cable routing and equipment. Havfrue/AEC-2 lands about 50 km from where the trace started, which is what the ranking rewards. This exact trace is now a regression test in the repo.\n\nLesson: test on a real trace, not the example you built the code around. My test fixture was Mumbai → Marseille over Tata's network, whose router names I'd already taught it.\n\nIteration 5: what data is it, and is that legal?\n\nKnowing the route is half the question. The other half is what is on it. Classifying traffic by reading packets is out of scope (and creepy), so traffic is tagged at ingestion from rules on what's already known: destination host, port, network, cloud provider, and an app label from the agent.\n\n```\n\"data_classification\": {\"labels\": [\"payment_system_data\"], \"source\": \"rules\",\n                        \"rule_ids\": [\"india-payment-gateways\"]}\n```\n\nThe compliance engine then walks the route point by point. For the recorded trace from Mumbai (Jio 5G) to AWS Frankfurt, tagged payment_system_data, the RBI profile raises an alert at the German destination, with the law, the entry time, and a suggested fix (\"terminate payment flows in India: use AWS ap-south-1\"). If the location is uncertain, as with the Jeddah cable landing in that example, the alert is marked suspected instead.\n\nIteration 6: making the globe look like Earth\n\nThe first globe was a blue dot-matrix sphere. It looked fine as a demo, but not like a real place. The current one uses satellite imagery lit by the real sun for the current time. Day and night, city lights, clouds and the glint on the oceans are all computed in one shader, with a few lines of solar maths (declination plus the equation of time).\n\nThe paths are the performance part. Every hop-to-hop segment is an instance of one ribbon mesh, so 1,000 paths draw in 6 draw calls, and a live latency update for one path uploads about 600 bytes.\n\nWhat I'd tell myself at the start\n\nAsk where the measurement happens before building it. The cloud couldn't trace, and the trace that mattered was never going to come from the cloud anyway.\n\nPhysics is your best validator. The speed of light in fiber rejected Australia and Phoenix for free. Databases are hints.\n\nRouter names are better geolocation than databases. Network operators name routers with airport and city codes, and those beat the free databases on backbone hops.\n\nCheck the path, not the point. Each location can look plausible on its own while the route through it is impossible.\n\nTest on real traces from real networks. A 14-hop trace from a home connection found more bugs than any fixture I wrote.\n\nHonest limits\n\nEverything past the IPs is inferred. Cable names come with probabilities. \"Havfrue/AEC-2\" is the best fit, not an observation, and I have no ground truth for which cable a packet actually used.\n\nGeolocation is city-level at best. Some routers stay unlocated, and a few wrong locations will still pass the checks.\n\nTraceroute sees only the forward path, and networks can hide hops (MPLS tunnels, filtered ICMP).\n\nThe compliance verdicts are a model, not legal advice. The law directory is informational.\n\nSmall sample. The subsea fixes were driven by one real transatlantic trace (now a regression test) plus a handful of runs to London, Amsterdam and Roubaix. The Windows agent has been run on one machine.\n\nFree hosting. The server sleeps after 15 minutes and keeps traces in memory, so the first visit is slow and restarts clear the globe.\n\n**Try it On Windows, open PowerShell as Administrator and run:**\n\n```\nirm https://packetpulse-test.onrender.com/v1/agent/download/start-ppagent.ps1 | iex\n```\n\nThen open packetpulse-eta.vercel.app and click London or Helsinki under Across the Atlantic. Traces need an agent token; the README explains how to run your own server with Docker in two commands.\n\n[git clone https://github.com/Flotrpy/PacketPulse](https://dev.tourl)\n\n```\ncd PacketPulse\ndocker build -t packetpulse .\ndocker run --rm -p 8080:8080 -e PACKETPULSE_ADMIN_TOKENS=\"me:$(openssl rand -hex 24)\" packetpulse\n```\n\nmacOS and Linux agents, the API, and how the cable detection works are all in the README.\n\nFeedback is very welcome, especially from anyone who runs a backbone network and can tell me which cable my packets actually took.", "url": "https://wpnews.pro/news/i-wanted-to-see-which-subsea-cable-my-packets-cross-the-cloud-couldn-t-trace-and", "canonical_source": "https://dev.to/affan_shaik/i-wanted-to-see-which-subsea-cable-my-packets-cross-the-cloud-couldnt-trace-and-the-database-put-4e9o", "published_at": "2026-11-05 00:19:20+00:00", "updated_at": "2026-11-05 00:22:34.584039+00:00", "lang": "en", "topics": ["developer-tools", "ai-infrastructure"], "entities": ["PacketPulse", "Cloudflare", "Render", "Vercel", "TeleGeography", "PeeringDB", "1.1.1.1", "Go"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-wanted-to-see-which-subsea-cable-my-packets-cross-the-cloud-couldn-t-trace-and", "markdown": "https://wpnews.pro/news/i-wanted-to-see-which-subsea-cable-my-packets-cross-the-cloud-couldn-t-trace-and.md", "text": "https://wpnews.pro/news/i-wanted-to-see-which-subsea-cable-my-packets-cross-the-cloud-couldn-t-trace-and.txt", "jsonld": "https://wpnews.pro/news/i-wanted-to-see-which-subsea-cable-my-packets-cross-the-cloud-couldn-t-trace-and.jsonld"}}