1
1
package main
2
2
3
3
import (
4
+ "encoding/json"
4
5
"errors"
5
6
"fmt"
6
7
"io"
@@ -19,6 +20,7 @@ import (
19
20
"github.com/coder/wush/tsserver"
20
21
"github.com/schollz/progressbar/v3"
21
22
"tailscale.com/net/netns"
23
+ "tailscale.com/tailcfg"
22
24
"tailscale.com/types/ptr"
23
25
)
24
26
@@ -65,13 +67,10 @@ func initAuth(authFlag *string, ca *overlay.ClientAuth) serpent.MiddlewareFunc {
65
67
}
66
68
}
67
69
68
- func sendOverlayMW (opts * sendOverlayOpts , send * * overlay.Send , logger * slog.Logger , logf * func (str string , args ... any )) serpent.MiddlewareFunc {
70
+ func sendOverlayMW (opts * sendOverlayOpts , send * * overlay.Send , logger * slog.Logger , dm * tailcfg. DERPMap , logf * func (str string , args ... any )) serpent.MiddlewareFunc {
69
71
return func (next serpent.HandlerFunc ) serpent.HandlerFunc {
70
72
return func (i * serpent.Invocation ) error {
71
- dm , err := tsserver .DERPMapTailscale (i .Context ())
72
- if err != nil {
73
- return err
74
- }
73
+ var err error
75
74
76
75
newSend := overlay .NewSendOverlay (logger , dm )
77
76
newSend .Auth = opts .clientAuth
@@ -90,6 +89,30 @@ func sendOverlayMW(opts *sendOverlayOpts, send **overlay.Send, logger *slog.Logg
90
89
}
91
90
}
92
91
92
+ func derpMap (fi * string , dm * tailcfg.DERPMap ) serpent.MiddlewareFunc {
93
+ return func (next serpent.HandlerFunc ) serpent.HandlerFunc {
94
+ return func (i * serpent.Invocation ) error {
95
+ if * fi == "" {
96
+ _dm , err := tsserver .DERPMapTailscale (i .Context ())
97
+ if err != nil {
98
+ return fmt .Errorf ("request derpmap from tailscale: %w" , err )
99
+ }
100
+ * dm = * _dm
101
+ } else {
102
+ data , err := os .ReadFile (* fi )
103
+ if err != nil {
104
+ return fmt .Errorf ("read derp config file: %w" , err )
105
+ }
106
+ if err := json .Unmarshal (data , dm ); err != nil {
107
+ return fmt .Errorf ("unmarshal derp config: %w" , err )
108
+ }
109
+ }
110
+
111
+ return next (i )
112
+ }
113
+ }
114
+ }
115
+
93
116
type sendOverlayOpts struct {
94
117
authKey string
95
118
clientAuth overlay.ClientAuth
@@ -99,10 +122,12 @@ type sendOverlayOpts struct {
99
122
100
123
func cpCmd () * serpent.Command {
101
124
var (
102
- verbose bool
103
- logger = new (slog.Logger )
104
- logf = func (str string , args ... any ) {}
125
+ verbose bool
126
+ derpmapFi string
127
+ logger = new (slog.Logger )
128
+ logf = func (str string , args ... any ) {}
105
129
130
+ dm = new (tailcfg.DERPMap )
106
131
overlayOpts = new (sendOverlayOpts )
107
132
send = new (overlay.Send )
108
133
)
@@ -119,12 +144,13 @@ func cpCmd() *serpent.Command {
119
144
serpent .RequireNArgs (1 ),
120
145
initLogger (& verbose , ptr .To (false ), logger , & logf ),
121
146
initAuth (& overlayOpts .authKey , & overlayOpts .clientAuth ),
122
- sendOverlayMW (overlayOpts , & send , logger , & logf ),
147
+ derpMap (& derpmapFi , dm ),
148
+ sendOverlayMW (overlayOpts , & send , logger , dm , & logf ),
123
149
),
124
150
Handler : func (inv * serpent.Invocation ) error {
125
151
ctx := inv .Context ()
126
152
127
- s , err := tsserver .NewServer (ctx , logger , send )
153
+ s , err := tsserver .NewServer (ctx , logger , send , dm )
128
154
if err != nil {
129
155
return err
130
156
}
@@ -215,6 +241,12 @@ func cpCmd() *serpent.Command {
215
241
Default : "" ,
216
242
Value : serpent .StringOf (& overlayOpts .authKey ),
217
243
},
244
+ {
245
+ Flag : "derp-config-file" ,
246
+ Description :
"File which specifies the DERP config to use. In the structure of https://pkg.go.dev/[email protected] /tailcfg#DERPMap. By default, https://controlplane.tailscale.com/derpmap/default is used." ,
247
+ Default : "" ,
248
+ Value : serpent .StringOf (& derpmapFi ),
249
+ },
218
250
{
219
251
Flag : "stun-ip-override" ,
220
252
Default : "" ,
0 commit comments