I've been using NordLayer for a while to manage secure access for our CI runners and deployment tasks. The one thing that consistently annoys me is manually switching between gateways to find the one with the lowest latency for a specific job. It's a waste of time.
So I wrote a script. It pings all available NordLayer gateways from your current location and spits out the fastest one. Useful for scripting your connection setup, especially if you're automating deployments or data transfers where latency matters.
You'll need the `requests` library and a NordLayer account with API access enabled. The script uses their Public API to fetch the gateway list.
```python
import subprocess
import json
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
def fetch_gateways():
"""Fetch NordLayer gateway list from their public API."""
url = "https://api.nordlayer.com/v1/servers"
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
# Filter for gateways, assuming they have a 'hostname' and are not 'obfuscated'
return [gw for gw in data if gw.get('type') == 'gateway']
except requests.exceptions.RequestException as e:
print(f"Failed to fetch gateway list: {e}")
return []
def ping_host(hostname):
"""Ping a host and return average latency in ms, or None on failure."""
try:
# Linux/macOS. For Windows, change to ['ping', '-n', '3', hostname]
result = subprocess.run(
['ping', '-c', '3', hostname],
capture_output=True,
text=True,
timeout=8
)
# Parse output for avg latency. Example: "min/avg/max/mdev = 12.045/15.234/18.123/2.123 ms"
output = result.stdout
for line in output.split('n'):
if 'min/avg/max/mdev' in line:
avg_latency = line.split('/')[4]
return float(avg_latency)
except (subprocess.TimeoutExpired, ValueError, IndexError, subprocess.SubprocessError):
pass
return None
def main():
gateways = fetch_gateways()
if not gateways:
print("No gateways retrieved. Check API access.")
return
print(f"Pinging {len(gateways)} gateways...")
results = {}
# Use threading to ping multiple gateways concurrently
with ThreadPoolExecutor(max_workers=10) as executor:
future_to_gw = {executor.submit(ping_host, gw['hostname']): gw for gw in gateways}
for future in as_completed(future_to_gw):
gateway = future_to_gw[future]
latency = future.result()
if latency is not None:
results[gateway['hostname']] = latency
if results:
sorted_results = sorted(results.items(), key=lambda x: x[1])
print("nFastest gateways by latency (ms):")
for hostname, latency in sorted_results[:5]: # Top 5
print(f" {hostname}: {latency:.2f} ms")
print(f"nRecommended: {sorted_results[0][0]}")
else:
print("No successful pings. Check your network connection.")
if __name__ == "__main__":
main()
```
**Setup & Run:**
1. Get your NordLayer API token from the dashboard (Organization settings > API).
2. Set it as an environment variable: `export NORDLAYER_TOKEN='your_token'`
3. Install requests: `pip install requests`
4. Run the script.
**Caveats & Notes:**
* The public API might not list *all* gateways available in your plan. For a more accurate list, you might need to use the authenticated team-specific endpoint.
* Ping times are a basic indicator. For throughput-critical tasks, you'd want a more sophisticated test.
* This doesn't handle authentication to connect; it just identifies the fastest node. You'd integrate this with the NordLayer CLI or your connection automation.
This has saved me a bunch of headaches when our primary gateway was experiencing intermittent slowness. Now the script runs as a cron job and updates our deployment playbooks automatically.
Build once, deploy everywhere
Concurrent pings is smart, especially since you're doing this for CI. Might be worth logging those latency results somewhere over time, not just picking the fastest once.
We do something similar but pipe the ping times into a local Prometheus via the pushgateway. That way you can graph latency trends per gateway and set alerts if your "fastest" starts dipping. Could be a natural extension if you're already automating the checks.
Are you hitting any rate limits on their public API when you run this frequently?
Prometheus? For a ping script? You're building a monitoring suite for a problem that needs a 30-second fix.
Their API is fine. The real issue is network variance. Picking the "fastest" based on one ping run is like choosing a marriage partner from a lineup.
If you really want to track it, dump JSON to S3 and run Athena queries once a quarter. That's when you'll actually look at it.
Concurrent pings is the obvious choice, sure, but you're still trusting a single ICMP echo from your local machine to decide where your entire CI traffic goes? That's a lot of faith in one packet's journey, which could get lost on the way back from a coffee break.
The real question is why you're even pinging the gateway itself. Your runners aren't talking to the gateway IP, they're talking to whatever resource is behind it. The latency to the gateway's front door is a terrible proxy for the latency your actual workloads will see. You're measuring the lobby, not the elevator ride up to your app.
And I hope you're not running this from your laptop. Where's the script actually living? If it's not on the runner itself, you're measuring a network path you'll never use. The variance between your dev machine and a cloud-based runner could be comical. So you pick the "fastest" gateway for your laptop, then ship all the traffic from a data center in Frankfurt. Solid plan.
🤷