-
Notifications
You must be signed in to change notification settings - Fork 221
/
wireguard.go
140 lines (111 loc) · 3.86 KB
/
wireguard.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package doctor
import (
"bufio"
"context"
"fmt"
"net"
"net/http"
"time"
fly "github.com/superfly/fly-go"
"github.com/superfly/flyctl/agent"
"github.com/superfly/flyctl/internal/command/dig"
"github.com/superfly/flyctl/internal/command/ping"
)
func runPersonalOrgPing(ctx context.Context, orgSlug string) (err error) {
client := fly.ClientFromContext(ctx)
ac, err := agent.DefaultClient(ctx)
if err != nil {
// shouldn't happen, already tested agent
return fmt.Errorf("wireguard ping gateway: can't establish agent client: %w", err)
}
org, err := client.GetOrganizationBySlug(ctx, orgSlug)
if err != nil {
// shouldn't happen, already verified auth token
return fmt.Errorf("wireguard ping gateway: can't get org %s: %w", orgSlug, err)
}
pinger, err := ac.Pinger(ctx, orgSlug, "")
if err != nil {
return fmt.Errorf("wireguard ping gateway: %w", err)
}
defer pinger.Close()
_, ns, err := dig.ResolverForOrg(ctx, ac, org.Slug)
if err != nil {
return fmt.Errorf("wireguard ping gateway: %w", err)
}
replyBuf := make([]byte, 1000)
for i := 0; i < 30; i++ {
_, err = pinger.WriteTo(ping.EchoRequest(0, i, time.Now(), 12), &net.IPAddr{IP: net.ParseIP(ns)})
pinger.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
_, _, err := pinger.ReadFrom(replyBuf)
if err != nil {
continue
}
return nil
}
return fmt.Errorf("ping gateway: no response from gateway received")
}
func runPersonalOrgCheckDns(ctx context.Context, orgSlug string) error {
client := fly.ClientFromContext(ctx)
ac, err := agent.DefaultClient(ctx)
if err != nil {
// shouldn't happen, already tested agent
return fmt.Errorf("wireguard dialer: can't establish agent client: %w", err)
}
org, err := client.GetOrganizationBySlug(ctx, orgSlug)
if err != nil {
// shouldn't happen, already verified auth token
return fmt.Errorf("wireguard dialer: can't get org %s: %w", orgSlug, err)
}
_, err = ac.Resolve(ctx, org.Slug, "_api.internal", "")
if err != nil {
return fmt.Errorf("wireguard dialer: failed to lookup _api.internal: %w", err)
}
return nil
}
func runPersonalOrgCheckFlaps(ctx context.Context, orgSlug string) error {
apiClient := fly.ClientFromContext(ctx)
// Set up the agent connection
ac, err := agent.DefaultClient(ctx)
if err != nil {
// shouldn't happen, already tested agent
return fmt.Errorf("wireguard dialer: can't establish agent client: %w", err)
}
// Connect to the personal org via WireGuard
org, err := apiClient.GetOrganizationBySlug(ctx, orgSlug)
if err != nil {
// shouldn't happen, already verified auth token
return fmt.Errorf("wireguard dialer: can't get org %s: %w", orgSlug, err)
}
wgDialer, err := ac.ConnectToTunnel(ctx, org.Slug, "", true)
if err != nil {
return fmt.Errorf("wireguard dialer: %w", err)
}
// Resolve the IP address of _api.internal
ip, err := ac.Resolve(ctx, org.Slug, "_api.internal:4280", "")
if err != nil {
return fmt.Errorf("wireguard dialer: failed to resolve _api.internal: %w", err)
}
// Dial the IP address of _api.internal
conn, err := wgDialer.DialContext(ctx, "tcp", ip)
if err != nil {
return fmt.Errorf("wireguard dialer: failed to dial _api.internal: %w", err)
}
// Make an HTTP request to _api.internal:4280. This should return a 404.
req, err := http.NewRequest("GET", "http://_api.internal:4280", http.NoBody) // skipcq: GO-S1028
if err != nil {
return fmt.Errorf("wireguard dialer: failed to create HTTP request: %w", err)
}
// Send the HTTP request
if err = req.Write(conn); err != nil {
return fmt.Errorf("wireguard dialer: failed to write HTTP request: %w", err)
}
// Read the HTTP response
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
if err != nil {
return fmt.Errorf("wireguard dialer: failed to read HTTP response: %w", err)
}
if resp.StatusCode != 404 {
return fmt.Errorf("wireguard dialer: expected 404, got %d", resp.StatusCode)
}
return nil
}