Am I Mullvad? Or am I Death, destroyer of worlds?

This commit is contained in:
kayos@tcp.direct 2022-10-28 05:25:01 -07:00
parent 3e82ec53ee
commit 17a530eb81
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
4 changed files with 128 additions and 34 deletions

38
api.go
View File

@ -32,21 +32,25 @@ type IPDetails struct {
}
type MullvadServer struct {
Hostname string `json:"hostname"`
CountryCode string `json:"country_code"`
CountryName string `json:"country_name"`
CityCode string `json:"city_code"`
CityName string `json:"city_name"`
Active bool `json:"active"`
Owned bool `json:"owned"`
Provider string `json:"provider"`
Ipv4AddrIn string `json:"ipv4_addr_in"`
Ipv6AddrIn string `json:"ipv6_addr_in"`
NetworkPortSpeed int `json:"network_port_speed"`
Type string `json:"type"`
Pubkey string `json:"pubkey,omitempty"`
MultihopPort int `json:"multihop_port,omitempty"`
SocksName string `json:"socks_name,omitempty"`
SSHFingerprintSHA256 string `json:"ssh_fingerprint_sha256,omitempty"`
SSHFingerprintMD5 string `json:"ssh_fingerprint_md5,omitempty"`
Hostname string `json:"hostname"`
CountryCode string `json:"country_code"`
CountryName string `json:"country_name"`
CityCode string `json:"city_code"`
CityName string `json:"city_name"`
Active bool `json:"active"`
Owned bool `json:"owned"`
Provider string `json:"provider"`
Ipv4AddrIn string `json:"ipv4_addr_in"`
Ipv6AddrIn *string `json:"ipv6_addr_in"`
NetworkPortSpeed int `json:"network_port_speed"`
Stboot bool `json:"stboot"`
Type string `json:"type"`
StatusMessages []interface{} `json:"status_messages"`
Pubkey string `json:"pubkey,omitempty"`
MultihopPort int `json:"multihop_port,omitempty"`
SocksName string `json:"socks_name,omitempty"`
SocksPort int `json:"socks_port,omitempty"`
Ipv4V2Ray *string `json:"ipv4_v2ray,omitempty"`
SshFingerprintSha256 string `json:"ssh_fingerprint_sha256,omitempty"`
SshFingerprintMd5 string `json:"ssh_fingerprint_md5,omitempty"`
}

View File

@ -2,6 +2,7 @@ package mullsox
import (
"context"
"errors"
"fmt"
"io"
"net/http"
@ -123,10 +124,41 @@ func checkIP(ctx context.Context, h *http.Client, ipv6 bool) (details *IPDetails
// AmIMullvad checks if you are currently connecting through a Mullvad relay.
// Returns the mullvad server you are connected to if any, and any error that occured
func AmIMullvad(ctx context.Context) (*MullvadServer, error) {
// v4, v6, err := CheckIP(ctx, http.DefaultClient)
// m
// if err != nil {
// }
return nil, nil
//
//goland:noinspection GoNilness
func AmIMullvad(ctx context.Context, client *http.Client) (MullvadServer, error) {
me, err := CheckIP(ctx, client)
if me == nil || me.V4 == nil && me.V6 == nil {
return MullvadServer{}, err
}
if me.V4 != nil && !me.V4.MullvadExitIP {
return MullvadServer{}, err
}
if me.V6 != nil && !me.V6.MullvadExitIP {
return MullvadServer{}, err
}
relays, err := GetMullvadServers()
if err != nil {
return MullvadServer{}, err
}
isMullvad := false
if me.V4 != nil && me.V4.MullvadExitIP {
isMullvad = true
if relays.Has(me.V4.MullvadExitIPHostname) {
return relays.Get(me.V4.MullvadExitIPHostname), nil
}
}
if me.V6 != nil && me.V6.MullvadExitIP {
isMullvad = true
if relays.Has(me.V6.MullvadExitIPHostname) {
return relays.Get(me.V6.MullvadExitIPHostname), nil
}
}
if isMullvad {
return MullvadServer{},
errors.New("could not find mullvad server in relay list, but you are connected to a mullvad exit ip")
}
return MullvadServer{}, nil
}

View File

@ -10,7 +10,7 @@ import (
)
func TestCheckIP4(t *testing.T) {
ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(15*time.Second))
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(15*time.Second))
v4, err := CheckIP4(ctx, http.DefaultClient)
if err != nil {
t.Fatalf("%s", err.Error())
@ -20,10 +20,11 @@ func TestCheckIP4(t *testing.T) {
t.Fatalf("%s", err4j.Error())
}
t.Logf(string(v4j))
cancel()
}
func TestCheckIP6(t *testing.T) {
ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(15*time.Second))
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(15*time.Second))
v6, err := CheckIP6(ctx, http.DefaultClient)
if err != nil {
t.Fatalf("%s", err.Error())
@ -33,10 +34,11 @@ func TestCheckIP6(t *testing.T) {
t.Fatalf("%s", err6j.Error())
}
t.Logf(string(v6j))
cancel()
}
func TestCheckIPConcurrent(t *testing.T) {
ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(15*time.Second))
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(15*time.Second))
me, err := CheckIP(ctx, http.DefaultClient)
if err != nil {
t.Fatalf("%s", err.Error())
@ -53,15 +55,30 @@ func TestCheckIPConcurrent(t *testing.T) {
unv4 := &IPDetails{}
unv6 := &IPDetails{}
if err := json.Unmarshal(v4j, unv4); err != nil {
if err = json.Unmarshal(v4j, unv4); err != nil {
t.Fatalf("%s", err.Error())
}
if err := json.Unmarshal(v6j, unv6); err != nil {
if err = json.Unmarshal(v6j, unv6); err != nil {
t.Fatalf("%s", err.Error())
}
unmarshaled.V4 = unv4
unmarshaled.V6 = unv6
t.Logf(spew.Sdump(unmarshaled.V4))
t.Logf(spew.Sdump(unmarshaled.V6))
cancel()
}
func TestAmIMullvad(t *testing.T) {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(15*time.Second))
am, err := AmIMullvad(ctx, http.DefaultClient)
if err != nil {
t.Fatalf("%s", err.Error())
}
indented, err := json.MarshalIndent(am, "", " ")
if err != nil {
t.Fatalf("%s", err.Error())
}
t.Logf(string(indented))
cancel()
}

View File

@ -2,9 +2,9 @@ package mullsox
import (
"net/http"
"sync"
jsoniter "github.com/json-iterator/go"
// "github.com/json-iterator/go"
"github.com/valyala/fasthttp"
)
@ -14,14 +14,52 @@ func (mvs MullvadServer) String() string {
return mvs.Hostname
}
type Relays []MullvadServer
type Relays struct {
m map[string]MullvadServer
size int
*sync.RWMutex
}
func NewRelays() *Relays {
r := &Relays{
m: make(map[string]MullvadServer),
RWMutex: &sync.RWMutex{},
}
return r
}
func (r *Relays) Slice() []MullvadServer {
return *r
r.RLock()
defer r.RUnlock()
var servers []MullvadServer
for _, server := range r.m {
servers = append(servers, server)
}
return servers
}
func (r *Relays) Has(hostname string) bool {
r.RLock()
_, ok := r.m[hostname]
r.RUnlock()
return ok
}
func (r *Relays) Add(server MullvadServer) {
r.Lock()
r.m[server.Hostname] = server
r.Unlock()
}
func (r *Relays) Get(hostname string) MullvadServer {
r.RLock()
defer r.RUnlock()
return r.m[hostname]
}
func GetMullvadServers() (*Relays, error) {
var servers = new(Relays)
var servers = NewRelays()
var serverSlice []MullvadServer
req := fasthttp.AcquireRequest()
res := fasthttp.AcquireResponse()
defer func() {
@ -35,8 +73,11 @@ func GetMullvadServers() (*Relays, error) {
if err := fasthttp.Do(req, res); err != nil {
return nil, err
}
if err := json.Unmarshal(res.Body(), servers); err != nil {
if err := json.Unmarshal(res.Body(), &serverSlice); err != nil {
return nil, err
}
for _, server := range serverSlice {
servers.Add(server)
}
return servers, nil
}