@@ -3,52 +3,42 @@ package devtunnel
3
3
import (
4
4
"bytes"
5
5
"context"
6
- "encoding/base64"
7
6
"encoding/hex"
8
7
"encoding/json"
9
8
"fmt"
10
- "io"
11
9
"net"
12
10
"net/http"
13
11
"net/netip"
14
12
"os"
15
13
"path/filepath"
16
14
"time"
17
15
18
- "github.com/google/uuid "
16
+ "github.com/briandowns/spinner "
19
17
"golang.org/x/xerrors"
20
18
"golang.zx2c4.com/wireguard/conn"
21
19
"golang.zx2c4.com/wireguard/device"
22
20
"golang.zx2c4.com/wireguard/tun/netstack"
23
21
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
24
22
25
23
"cdr.dev/slog"
24
+ "github.com/coder/coder/cli/cliui"
26
25
"github.com/coder/coder/cryptorand"
27
26
)
28
27
29
- var (
30
- v0EndpointHTTPS = "wg-tunnel.coder.app"
31
-
32
- v0ServerPublicKey = "+KNSMwed/IlqoesvTMSBNsHFaKVLrmmaCkn0bxIhUg0="
33
- v0ServerIP = netip .AddrFrom16 (uuid .MustParse ("fcad0000-0000-4000-8000-000000000001" ))
34
- )
35
-
36
28
type Tunnel struct {
37
29
URL string
38
30
Listener net.Listener
39
31
}
40
32
41
33
type Config struct {
42
34
Version int `json:"version"`
43
- ID uuid.UUID `json:"id"`
44
35
PrivateKey device.NoisePrivateKey `json:"private_key"`
45
36
PublicKey device.NoisePublicKey `json:"public_key"`
46
37
47
38
Tunnel Node `json:"tunnel"`
48
39
}
49
40
type configExt struct {
50
41
Version int `json:"-"`
51
- ID uuid.UUID `json:"id"`
52
42
PrivateKey device.NoisePrivateKey `json:"-"`
53
43
PublicKey device.NoisePublicKey `json:"public_key"`
54
44
@@ -146,7 +136,7 @@ func startUpdateRoutine(ctx context.Context, logger slog.Logger, cfg Config) (Se
146
136
endCh := make (chan struct {})
147
137
go func () {
148
138
defer close (endCh )
149
- ticker := time .NewTicker (30 * time .Second )
139
+ ticker := time .NewTicker (10 * time .Second )
150
140
defer ticker .Stop ()
151
141
152
142
for {
@@ -179,22 +169,9 @@ func sendConfigToServer(ctx context.Context, cfg Config) (ServerResponse, error)
179
169
return ServerResponse {}, xerrors .Errorf ("marshal config: %w" , err )
180
170
}
181
171
182
- var req * http.Request
183
- switch cfg .Version {
184
- case 0 :
185
- req , err = http .NewRequestWithContext (ctx , "POST" , "https://" + v0EndpointHTTPS + "/tun" , bytes .NewReader (raw ))
186
- if err != nil {
187
- return ServerResponse {}, xerrors .Errorf ("new request: %w" , err )
188
- }
189
-
190
- case 1 :
191
- req , err = http .NewRequestWithContext (ctx , "POST" , "https://" + cfg .Tunnel .HostnameHTTPS + "/tun" , bytes .NewReader (raw ))
192
- if err != nil {
193
- return ServerResponse {}, xerrors .Errorf ("new request: %w" , err )
194
- }
195
-
196
- default :
197
- return ServerResponse {}, xerrors .Errorf ("unknown config version: %d" , cfg .Version )
172
+ req , err := http .NewRequestWithContext (ctx , "POST" , "https://" + cfg .Tunnel .HostnameHTTPS + "/tun" , bytes .NewReader (raw ))
173
+ if err != nil {
174
+ return ServerResponse {}, xerrors .Errorf ("new request: %w" , err )
198
175
}
199
176
200
177
res , err := http .DefaultClient .Do (req )
@@ -204,23 +181,9 @@ func sendConfigToServer(ctx context.Context, cfg Config) (ServerResponse, error)
204
181
defer res .Body .Close ()
205
182
206
183
var resp ServerResponse
207
- switch cfg .Version {
208
- case 0 :
209
- _ , _ = io .Copy (io .Discard , res .Body )
210
- resp .Hostname = fmt .Sprintf ("%s.%s" , cfg .ID , v0EndpointHTTPS )
211
- resp .ServerIP = v0ServerIP
212
- resp .ServerPublicKey = encodeBase64ToHex (v0ServerPublicKey )
213
- resp .ClientIP = netip .AddrFrom16 (cfg .ID )
214
-
215
- case 1 :
216
- err := json .NewDecoder (res .Body ).Decode (& resp )
217
- if err != nil {
218
- return ServerResponse {}, xerrors .Errorf ("decode response: %w" , err )
219
- }
220
-
221
- default :
222
- _ , _ = io .Copy (io .Discard , res .Body )
223
- return ServerResponse {}, xerrors .Errorf ("unknown config version: %d" , cfg .Version )
184
+ err = json .NewDecoder (res .Body ).Decode (& resp )
185
+ if err != nil {
186
+ return ServerResponse {}, xerrors .Errorf ("decode response: %w" , err )
224
187
}
225
188
226
189
return resp , nil
@@ -273,12 +236,22 @@ func readOrGenerateConfig() (Config, error) {
273
236
}
274
237
275
238
if cfg .Version == 0 {
276
- cfg .Tunnel = Node {
277
- ID : 0 ,
278
- HostnameHTTPS : "wg-tunnel.coder.app" ,
279
- HostnameWireguard : "wg-tunnel-udp.coder.app" ,
280
- WireguardPort : 55555 ,
239
+ _ , _ = fmt .Println ()
240
+ _ , _ = fmt .Println (cliui .Styles .Error .Render ("You're running a deprecated tunnel version!" ))
241
+ _ , _ = fmt .Println (cliui .Styles .Error .Render ("Upgrading you to the new version now. You will need to rebuild running workspaces." ))
242
+ _ , _ = fmt .Println ()
243
+
244
+ cfg , err := GenerateConfig ()
245
+ if err != nil {
246
+ return Config {}, xerrors .Errorf ("generate config: %w" , err )
247
+ }
248
+
249
+ err = writeConfig (cfg )
250
+ if err != nil {
251
+ return Config {}, xerrors .Errorf ("write config: %w" , err )
281
252
}
253
+
254
+ return cfg , nil
282
255
}
283
256
284
257
return cfg , nil
@@ -291,15 +264,27 @@ func GenerateConfig() (Config, error) {
291
264
}
292
265
pub := priv .PublicKey ()
293
266
267
+ spin := spinner .New (spinner .CharSets [39 ], 350 * time .Millisecond )
268
+ spin .Suffix = " Finding the closest tunnel region..."
269
+ spin .Start ()
270
+
294
271
node , err := FindClosestNode ()
295
272
if err != nil {
273
+ // If we fail to find the closest node, default to US East.
296
274
region := Regions [0 ]
297
275
n , _ := cryptorand .Intn (len (region .Nodes ))
298
276
node = region .Nodes [n ]
277
+ spin .Stop ()
299
278
_ , _ = fmt .Println ("Error picking closest dev tunnel:" , err )
300
279
_ , _ = fmt .Println ("Defaulting to" , Regions [0 ].LocationName )
301
280
}
302
281
282
+ spin .Stop ()
283
+ _ , _ = fmt .Printf ("Using tunnel in %s with latency %s.\n " ,
284
+ cliui .Styles .Keyword .Render (Regions [node .RegionID ].LocationName ),
285
+ cliui .Styles .Code .Render (node .AvgLatency .String ()),
286
+ )
287
+
303
288
return Config {
304
289
Version : 1 ,
305
290
PrivateKey : device .NoisePrivateKey (priv ),
@@ -326,16 +311,3 @@ func writeConfig(cfg Config) error {
326
311
327
312
return nil
328
313
}
329
-
330
- func encodeBase64ToHex (key string ) string {
331
- decoded , err := base64 .StdEncoding .DecodeString (key )
332
- if err != nil {
333
- panic (err )
334
- }
335
-
336
- if len (decoded ) != 32 {
337
- panic ((xerrors .New ("key should be 32 bytes: " + key )))
338
- }
339
-
340
- return hex .EncodeToString (decoded )
341
- }
0 commit comments