Writing / August 21, 2026

Finding a Nord WireGuard Endpoint

A long-used Nord WireGuard endpoint stopped responding and was no longer listed, turning a replacement search into a userspace probe and endpoint finder.

wireguardnetworkingrustdebugging

I had used the same Nord WireGuard endpoint for more than nine months when it stopped working. The WireGuard client kept trying to connect, but the tunnel never became usable. Its transfer counters showed bytes being sent while received remained at 0 B.

The endpoint that had worked for months no longer appeared in Nord’s public server inventory. I needed a replacement.

That should have been a small configuration change. It became a long debugging session and eventually produced two tools: the provider-neutral wgprobe verifier and the Nord-specific nordprobe endpoint finder. Both are independent tools and are not affiliated with or endorsed by Nord Security.

A laptop on a wooden desk at night, showing unanswered outgoing attempts with RX 0 B and a replacement probe with a confirmed handshake.
From unanswered attempts to a confirmed handshake.

Silence Supported Too Many Explanations

I started with Nord’s public API, selected endpoints in several cities, generated WireGuard configurations, and tried them through the normal client. I tended to choose servers reporting low load because they looked like sensible candidates. None of the first group completed a handshake, and the client received no traffic from them.

That result was difficult to interpret. WireGuard uses UDP and deliberately reveals little to unauthenticated traffic. There is no TCP-style connection refusal or open-port result to separate a missing service from a dropped packet. A client can send handshake initiations and receive nothing whether the endpoint is gone, a firewall is dropping UDP, the server key is wrong, the account identity is not accepted, or the return path is broken.

Testing through a normal VPN client also changes the machine while the test is running. It creates the tunnel, installs routes, and can remove the Internet path needed to continue debugging when the candidate does not work. Repeating that process across configurations is slow and disruptive, while every zero-receive result looks much like the previous one.

My working hypothesis was that I had selected another bad group of endpoints. When I first configured Nord over WireGuard more than nine months earlier, only a small part of my manual sample worked, so I found one endpoint that authenticated and kept using it.

This time I was using an agent to help automate the search. Instead, the investigation quickly shifted toward the private key, access token, file permissions, and generated configuration. Those were plausible explanations. After several failed endpoints, they started to look more plausible than my endpoint hypothesis.

I generated new access tokens and repeated the service-credentials exchange. Nord continued returning the same WireGuard private key for the account. I changed file permissions, regenerated configurations, and checked the inputs again without changing the result.

The agent eventually suggested contacting Nord support because something might be wrong with the account identity. I was frustrated because I had started by asking it to search a wider server list, and now we were hours into regenerating credentials and configurations without testing that hypothesis.

One Working Endpoint Changed The Investigation

After more manual sampling, I tried an endpoint near my own location and it worked. That did not explain why candidates in the cities I wanted had failed, but it changed the debugging session.

The tested account identity and private key could authenticate with at least one current endpoint. The basic configuration could work. Generating another access token and receiving the same private key was no longer the useful path to follow.

I now had one endpoint that completed the exchange and several where the client continued to show transmitted data with 0 B received. I could use those two outcomes to build a narrower test that did not change routes or create a system VPN.

A Probe Instead Of A Tunnel

I did not need to implement WireGuard from scratch. Cloudflare’s BoringTun project provided the userspace protocol implementation I could build on. From there I could create a short-lived probe around one identity, server public key, and UDP endpoint without creating a TUN interface or requiring administrator access.

The first useful version of wgprobe did one thing: attempt a WireGuard handshake and report whether a valid response arrived. I pointed it at the known-working endpoint and the ones that had stayed at 0 B received. The first authenticated; the others came back unconfirmed. That was the distinction I needed, and the tool did not pretend that silence explained why an endpoint had not answered.

I then split the run into endpoint resolution, socket setup, handshake, keepalive, ping, and DNS phases so I could see where each attempt stopped instead of getting one connected-or-failed result.

I added optional ping and DNS checks for cases where I wanted to see more than a handshake. They let me test specific packet exchanges through the session without installing a complete system VPN.

The result was a verifier I could run repeatedly without replacing routes or interrupting the connection I was using to investigate the problem. I added JSON output for automation and a --redact option for reports I wanted to share.

From One Probe To A Nord Endpoint Finder

The generic probe answered whether one known identity and endpoint could exchange WireGuard traffic. It did not solve the original selection problem. Nord publishes a large server inventory, and manually turning each candidate into a configuration was the work I wanted to remove.

I kept the provider-specific work outside the wgprobe core and built it as nordprobe. It turned Nord’s inventory into a country and city selector, then applied the same probe to a bounded list of candidates using the account identity I was already testing.

I made the search stop after it found enough working endpoints or exhausted its candidate budget. I wanted a repeatable way to search one location, not another pile of configurations to try manually.

When an endpoint authenticated, I could export its WireGuard configuration. When it did not respond, the tool moved on without adding it to a permanent list of broken servers.

The Broader Search Looked Different

When I ran the broader search, it looked nothing like my manual sample. Many endpoints authenticated, including endpoints in a city where every candidate I had selected by hand had failed. The key worked beyond the nearby endpoint, and the city I wanted contained confirmed candidates after all.

Some of the low-load servers I had treated as especially promising were among the ones that did not respond. I stopped treating low reported load as proof that an endpoint would be a good WireGuard candidate. I still did not know why any particular endpoint returned nothing.

Cherry-picking a few attractive-looking entries had given me a misleading picture of the available servers. The old endpoint was gone from the inventory, none of my first replacement candidates authenticated or responded during the tests, and the broader search found plenty of alternatives.

The agent helped generate configurations and implement both tools. It also spent hours pulling the investigation toward keys and configuration after I had started with the endpoint list. Finding one working endpoint let me stop arguing with those theories and start testing the inventory directly.

Linus Torvalds described a similar division of labor in the commit for an Intel graphics fix that required 24 debugging patches and 18 kernel boots. His agent repeatedly declared the problem impossible and suggested writing a report, but it continued adding instrumentation and analyzing the results when he pushed it. The agent supplied much of the investigative labor. Torvalds supplied the judgment that the evidence had not yet earned a decision to stop.

Now, if a Nord WireGuard endpoint disappears or stops responding, I can retrieve the current inventory, select a country and city, run a bounded candidate check, and export a configuration from a confirmed result. Endpoint selection is no longer configuration guesswork guided by load and proximity. It is a search in which each candidate has to prove that it can answer.