Skip to content

Commit

Permalink
Extend Peer metadata with cloud detection (#1552)
Browse files Browse the repository at this point in the history
* add cloud detection + test binary

* test windows exe

* Collect IPv6 addresses

* Change the IP to IP + net

* switch to forked cloud detect lib

* new test builds

* new GCE build

* discontinue using library but local copy instead

* fix imports

* remove openstack check

* add hierarchy to cloud check

* merge IBM and SoftLayer

* close resp bodies and use os lib for file reading

* close more resp bodies

* fix error check logic

* parallelize IBM checks

* fix response value

* go mod tidy

* include context + change kubernetes detection

* add context in info functions

* extract platform into separate field

* fix imports

* add missing wmi import

---------

Co-authored-by: Zoltan Papp <zoltan.pmail@gmail.com>
  • Loading branch information
pascal-fischer and pappz authored Feb 20, 2024
1 parent 5b6cb49 commit 06e9fed
Show file tree
Hide file tree
Showing 20 changed files with 512 additions and 1 deletion.
Binary file added client/netbird
Binary file not shown.
Binary file added client/netbird.exe
Binary file not shown.
24 changes: 24 additions & 0 deletions client/system/detect_cloud/alibabacloud.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectAlibabaCloud(ctx context.Context) string {
req, err := http.NewRequestWithContext(ctx, "GET", "http://100.100.100.200/latest/", nil)
if err != nil {
return ""
}

resp, err := hc.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
return "Alibaba Cloud"
}
return ""
}
57 changes: 57 additions & 0 deletions client/system/detect_cloud/aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectAWS(ctx context.Context) string {
v1ResultChan := make(chan bool, 1)
v2ResultChan := make(chan bool, 1)

go func() {
v1ResultChan <- detectAWSIDMSv1(ctx)
}()

go func() {
v2ResultChan <- detectAWSIDMSv2(ctx)
}()

v1Result, v2Result := <-v1ResultChan, <-v2ResultChan

if v1Result || v2Result {
return "Amazon Web Services"
}
return ""
}

func detectAWSIDMSv1(ctx context.Context) bool {
req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/latest/", nil)
if err != nil {
return false
}

resp, err := hc.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()

return resp.StatusCode == http.StatusOK
}

func detectAWSIDMSv2(ctx context.Context) bool {
req, err := http.NewRequestWithContext(ctx, "PUT", "http://169.254.169.254/latest/api/token", nil)
if err != nil {
return false
}
req.Header.Set("X-aws-ec2-metadata-token-ttl-seconds", "21600")

resp, err := hc.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()

return resp.StatusCode == http.StatusOK
}
25 changes: 25 additions & 0 deletions client/system/detect_cloud/azure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectAzure(ctx context.Context) string {
req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/metadata/instance?api-version=2021-02-01", nil)
if err != nil {
return ""
}
req.Header.Set("Metadata", "true")

resp, err := hc.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
return "Microsoft Azure"
}
return ""
}
65 changes: 65 additions & 0 deletions client/system/detect_cloud/detect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package detect_cloud

import (
"context"
"net/http"
"sync"
"time"
)

/*
This packages is inspired by the work of the original author (https://github.com/perlogix), but it has been modified to fit the needs of the project.
Original project: https://github.com/perlogix/libdetectcloud
*/

var hc = &http.Client{Timeout: 300 * time.Millisecond}

func Detect(ctx context.Context) string {
subCtx, cancel := context.WithCancel(context.Background())
defer cancel()

funcs := []func(context.Context) string{
detectAlibabaCloud,
detectAWS,
detectAzure,
detectDigitalOcean,
detectGCP,
detectOracle,
detectIBMCloud,
detectSoftlayer,
detectVultr,
}

results := make(chan string, len(funcs))

var wg sync.WaitGroup

for _, fn := range funcs {
wg.Add(1)
go func(f func(context.Context) string) {
defer wg.Done()
select {
case <-subCtx.Done():
return
default:
if result := f(ctx); result != "" {
results <- result
cancel()
}
}
}(fn)
}

go func() {
wg.Wait()
close(results)
}()

for result := range results {
if result != "" {
return result
}
}

return ""
}
24 changes: 24 additions & 0 deletions client/system/detect_cloud/digitalocean.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectDigitalOcean(ctx context.Context) string {
req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/metadata/v1/", nil)
if err != nil {
return ""
}

resp, err := hc.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
return "Digital Ocean"
}
return ""
}
25 changes: 25 additions & 0 deletions client/system/detect_cloud/gcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectGCP(ctx context.Context) string {
req, err := http.NewRequestWithContext(ctx, "GET", "http://metadata.google.internal", nil)
if err != nil {
return ""
}
req.Header.Add("Metadata-Flavor", "Google")

resp, err := hc.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
return "Google Cloud Platform"
}
return ""
}
54 changes: 54 additions & 0 deletions client/system/detect_cloud/ibmcloud.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectIBMCloud(ctx context.Context) string {
v1ResultChan := make(chan bool, 1)
v2ResultChan := make(chan bool, 1)

go func() {
v1ResultChan <- detectIBMSecure(ctx)
}()

go func() {
v2ResultChan <- detectIBM(ctx)
}()

v1Result, v2Result := <-v1ResultChan, <-v2ResultChan

if v1Result || v2Result {
return "IBM Cloud"
}
return ""
}

func detectIBMSecure(ctx context.Context) bool {
req, err := http.NewRequestWithContext(ctx, "PUT", "https://api.metadata.cloud.ibm.com/instance_identity/v1/token", nil)
if err != nil {
return false
}

resp, err := hc.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK
}

func detectIBM(ctx context.Context) bool {
req, err := http.NewRequestWithContext(ctx, "PUT", "http://api.metadata.cloud.ibm.com/instance_identity/v1/token", nil)
if err != nil {
return false
}

resp, err := hc.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK
}
56 changes: 56 additions & 0 deletions client/system/detect_cloud/oracle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectOracle(ctx context.Context) string {
v1ResultChan := make(chan bool, 1)
v2ResultChan := make(chan bool, 1)

go func() {
v1ResultChan <- detectOracleIDMSv1(ctx)
}()

go func() {
v2ResultChan <- detectOracleIDMSv2(ctx)
}()

v1Result, v2Result := <-v1ResultChan, <-v2ResultChan

if v1Result || v2Result {
return "Oracle"
}
return ""
}

func detectOracleIDMSv1(ctx context.Context) bool {
req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/opc/v1/instance/", nil)
if err != nil {
return false
}
req.Header.Add("Authorization", "Bearer Oracle")

resp, err := hc.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK
}

func detectOracleIDMSv2(ctx context.Context) bool {
req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/opc/v2/instance/", nil)
if err != nil {
return false
}
req.Header.Add("Authorization", "Bearer Oracle")

resp, err := hc.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK
}
25 changes: 25 additions & 0 deletions client/system/detect_cloud/softlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectSoftlayer(ctx context.Context) string {
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.service.softlayer.com/rest/v3/SoftLayer_Resource_Metadata/UserMetadata.txt", nil)
if err != nil {
return ""
}

resp, err := hc.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
// Since SoftLayer was acquired by IBM, we should return "IBM Cloud"
return "IBM Cloud"
}
return ""
}
24 changes: 24 additions & 0 deletions client/system/detect_cloud/vultr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package detect_cloud

import (
"context"
"net/http"
)

func detectVultr(ctx context.Context) string {
req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/v1.json", nil)
if err != nil {
return ""
}

resp, err := hc.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
return "Vultr"
}
return ""
}
Loading

0 comments on commit 06e9fed

Please sign in to comment.