Compare commits

...

6 Commits

Author SHA1 Message Date
7f736db2cc update readme 2024-06-09 09:08:56 -07:00
4dd5e871f8 add readme and license 2024-06-09 08:51:51 -07:00
20d4f1bdc7 add bin/ dir 2024-06-09 07:53:46 -07:00
de48e9ae24 update .gitignore and makefile 2024-06-09 07:53:11 -07:00
2b16955b18 ignore build artifact 2024-06-09 07:43:00 -07:00
001f54c5e0 latest 2024-06-09 07:40:44 -07:00
10 changed files with 247 additions and 11 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
bin

14
LICENSE Normal file
View File

@@ -0,0 +1,14 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

7
Makefile Normal file
View File

@@ -0,0 +1,7 @@
default: build
build:
@go build -o bin/ ./...
run:
sudo go run ./cmd/mullvadclosest/*.go

156
README.md Normal file
View File

@@ -0,0 +1,156 @@
# mullvadclosest
A small golang program that checks your latency to all of the known mullvad
relays.
This will use your local relay database as installed by the mullvad client
if it finds it. Otherwise, it will use a bundled copy which may be a bit
out of date. If that happens, contact me and I'll update it.
This will show you the top 25 lowest latency relays (VPN servers) to you,
and the 5 highest for comparison.
# Errata
The go ICMP ping library I'm using doesn't work on OSX if you're not root, so the
program requires it. Oh well.
# Usage
Make sure you're **disconnected** from the VPN when you run this. It needs
to be able to ping the relays directly, and if you're connected to the VPN
you'll get the latency through the VPN server to which you're connected,
which is not what you want.
Run:
```
GOPROXY=direct go run sneak.berlin/go/mullvadclosest/cmd/mullvadclosest@4dd5e871f830ff62bb30c2290623ad9d8c4d4554
```
The GOPROXY=direct means to download the code directly from my servers, not
the Google-operated golang module proxy. Given that you're running this
program as root from a random place on the internet, downloading it directly
from me avoids the case where Google can serve you arbitrary code that runs
on your machine.
The full git commit hash is provided to ensure that you're running the
specific version of the code that I've tested and that you're expecting to
run. Don't do "git run <whatever>@latest" because it's just granting random
people code exec on your machine. (Same goes for docker images that use
_any_ tag that uses `:` instead of a specific hash identified by `@`.)
# Example output
Run from the southwestern US:
```
root@bastion:~# GOPROXY=direct go run sneak.berlin/go/mullvadclosest/cmd/mullvadclosest@latest
Checking liveness 100% |███████████████████████████████████████████████████████████████████████████████████████████████| (684/684, 78 it/s)
Measuring latency 100% |███████████████████████████████████████████████████████████████████████████████████████████████| (673/673, 7 it/s)
Total relays: 684
Live relays: 673
Dead relays: 11
Min latency: 11.240837ms (Relay(hostname=us-lax-wg-203, ip=169.150.203.28, country=USA))
Max latency: 351.145942ms (Relay(hostname=sg-sin-wg-002, ip=138.199.60.15, country=Singapore))
Median latency: 152.235439ms (Relay(hostname=de-fra-wg-106, ip=146.70.117.34, country=Germany))
Mean latency: 122.094918ms
Stddev latency: 63.354381ms
Country City Hostname Latency
USA Los Angeles, CA us-lax-wg-203 11.240837ms
USA Los Angeles, CA us-lax-wg-303 11.414964ms
USA Los Angeles, CA us-lax-ovpn-201 11.575832ms
USA Los Angeles, CA us-lax-wg-404 12.160305ms
USA Los Angeles, CA us-lax-wg-102 12.189879ms
USA Los Angeles, CA us-lax-ovpn-402 12.37345ms
USA Los Angeles, CA us-lax-wg-403 12.724075ms
USA Los Angeles, CA us-lax-wg-401 12.802629ms
USA Los Angeles, CA us-lax-ovpn-202 13.044014ms
USA Los Angeles, CA us-lax-wg-202 13.129124ms
USA Los Angeles, CA us-lax-wg-406 13.655117ms
USA Los Angeles, CA us-lax-wg-302 13.804244ms
USA Los Angeles, CA us-lax-wg-501 13.854577ms
USA Los Angeles, CA us-lax-wg-502 14.668269ms
USA Los Angeles, CA us-lax-br-401 15.198631ms
USA Los Angeles, CA us-lax-wg-405 15.47022ms
USA Los Angeles, CA us-lax-ovpn-102 15.764457ms
USA Los Angeles, CA us-lax-wg-503 15.918306ms
USA Los Angeles, CA us-lax-ovpn-401 16.264245ms
USA Los Angeles, CA us-lax-wg-103 16.35017ms
USA Los Angeles, CA us-lax-wg-201 16.469779ms
USA Los Angeles, CA us-lax-ovpn-101 16.655777ms
USA Los Angeles, CA us-lax-ovpn-403 17.289434ms
USA Los Angeles, CA us-lax-wg-402 18.19131ms
USA Los Angeles, CA us-lax-wg-101 18.290308ms
South Africa Johannesburg za-jnb-wg-001 288.186466ms
Singapore Singapore sg-sin-wg-001 342.030852ms
Singapore Singapore sg-sin-wg-003 346.614045ms
Singapore Singapore sg-sin-wg-002 351.145942ms
```
Run from an LTE connection in Türkiye:
```
akrotiri:~$ GOPROXY=direct sudo go run sneak.berlin/go/mullvadclosest/cmd/mullvadclosest@latest
Checking liveness 100% |███████████████████████████████████████████████████████████████████████████████████████████| (684/684, 25 it/s)
Measuring latency 100% |███████████████████████████████████████████████████████████████████████████████████████████| (602/602, 5 it/s)
Total relays: 684
Live relays: 602
Dead relays: 82
Min latency: 87.088ms (Relay(hostname=nl-ams-ovpn-003, ip=185.65.134.73, country=Netherlands))
Max latency: 560.733ms (Relay(hostname=th-bkk-wg-001, ip=156.59.50.194, country=Thailand))
Median latency: 155.925ms (Relay(hostname=gr-ath-wg-101, ip=149.102.246.2, country=Greece))
Mean latency: 175.519705ms
Stddev latency: 84.258738ms
Country City Hostname Latency
Netherlands Amsterdam nl-ams-ovpn-003 87.088ms
Netherlands Amsterdam nl-ams-wg-006 87.523ms
Netherlands Amsterdam nl-ams-wg-101 89.472ms
Netherlands Amsterdam nl-ams-wg-201 91.061ms
Netherlands Amsterdam nl-ams-ovpn-005 91.272ms
Netherlands Amsterdam nl-ams-wg-004 91.527ms
Belgium Brussels be-bru-wg-102 92.082ms
Netherlands Amsterdam nl-ams-ovpn-004 93.036ms
Belgium Brussels be-bru-wg-101 93.22ms
Germany Frankfurt de-fra-wg-004 94.146ms
Netherlands Amsterdam nl-ams-ovpn-001 94.465ms
Netherlands Amsterdam nl-ams-wg-007 94.578ms
Germany Frankfurt de-fra-ovpn-003 94.681ms
Germany Dusseldorf de-dus-wg-002 95.224ms
Netherlands Amsterdam nl-ams-wg-001 95.555ms
UK London gb-lon-wg-202 96.297ms
UK London gb-lon-wg-201 96.468ms
Germany Frankfurt de-fra-ovpn-006 96.544ms
Germany Frankfurt de-fra-wg-006 96.58ms
UK London gb-lon-ovpn-002 96.775ms
UK London gb-lon-wg-203 96.822ms
Germany Dusseldorf de-dus-wg-001 96.865ms
Belgium Brussels be-bru-ovpn-101 96.869ms
UK London gb-lon-ovpn-301 96.922ms
UK London gb-lon-ovpn-005 97.231ms
Australia Perth au-per-wg-302 438.455ms
Singapore Singapore sg-sin-ovpn-102 444.711ms
Indonesia Jakarta id-jpu-wg-002 504.1ms
Thailand Bangkok th-bkk-wg-001 560.733ms
```
# Author
sneak &lt;[sneak@sneak.berlin](mailto:sneak@sneak.berlin)&gt;
# License
[WTFPL](./LICENSE)
Do with it what you will. There is no warranty, express or implied,
including but not limited to merchantability or fitness for a particular
purpose. Use at your own risk. Maybe clone it and read the code before
you run random shit from some weirdo from the internet as root.
# Source
https://sneak.berlin/go/mullvadclosest

0
bin/.keep Normal file
View File

View File

@@ -102,11 +102,15 @@ func ParseRelayData() ([]Relay, error) {
}
var fileData []byte
var err error
if filePath == "" {
// use embedded cache if not on filesystem
fileData = mullvadclosest.RelayJSON
fileData, err = mullvadclosest.GetRelays()
if err != nil {
return nil, fmt.Errorf("failed to read embedded file: %v", err)
}
} else {
fileData, err := ioutil.ReadFile(filePath)
fileData, err = ioutil.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("failed to read file: %v", err)
}

16
embed.go Normal file
View File

@@ -0,0 +1,16 @@
package mullvadclosest
import (
"embed"
)
//go:embed relays.2024-06-04.json
var fs embed.FS
func GetEmbeddedFile(name string) ([]byte, error) {
return fs.ReadFile(name)
}
func GetRelays() ([]byte, error) {
return GetEmbeddedFile("relays.2024-06-04.json")
}

View File

@@ -1,9 +0,0 @@
package mullvadclosest
import (
"embed"
)
//go:embed relays.2024-06-04.json
var RelayJSON embed.FS

15
go.mod Normal file
View File

@@ -0,0 +1,15 @@
module sneak.berlin/go/mullvadclosest
go 1.22.3
require (
github.com/go-ping/ping v1.1.0 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/schollz/progressbar/v3 v3.14.3 // indirect
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
)

32
go.sum Normal file
View File

@@ -0,0 +1,32 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/schollz/progressbar/v3 v3.14.3 h1:oOuWW19ka12wxYU1XblR4n16wF/2Y1dBLMarMo6p4xU=
github.com/schollz/progressbar/v3 v3.14.3/go.mod h1:aT3UQ7yGm+2ZjeXPqsjTenwL3ddUiuZ0kfQ/2tHlyNI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005 h1:pDMpM2zh2MT0kHy037cKlSby2nEhD50SYqwQk76Nm40=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=