Skip to content

Commit 36655f0

Browse files
committed
Add listening
1 parent 844071d commit 36655f0

16 files changed

+316
-312
lines changed

.vscode/settings.json

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"cronstrue",
1414
"DERP",
1515
"derphttp",
16+
"derpmap",
1617
"devel",
1718
"drpc",
1819
"drpcconn",

cli/ssh.go

+53-58
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,13 @@ import (
1818
gosshagent "golang.org/x/crypto/ssh/agent"
1919
"golang.org/x/term"
2020
"golang.org/x/xerrors"
21-
"inet.af/netaddr"
22-
tslogger "tailscale.com/types/logger"
2321

24-
"cdr.dev/slog"
25-
"cdr.dev/slog/sloggers/sloghuman"
2622
"github.com/coder/coder/cli/cliflag"
2723
"github.com/coder/coder/cli/cliui"
2824
"github.com/coder/coder/coderd/autobuild/notify"
2925
"github.com/coder/coder/coderd/util/ptr"
3026
"github.com/coder/coder/codersdk"
3127
"github.com/coder/coder/cryptorand"
32-
"github.com/coder/coder/peer/peerwg"
3328
)
3429

3530
var workspacePollInterval = time.Minute
@@ -122,59 +117,59 @@ func ssh() *cobra.Command {
122117
}
123118
} else {
124119
// TODO: more granual control of Tailscale logging.
125-
peerwg.Logf = tslogger.Discard
126-
127-
ipv6 := peerwg.UUIDToNetaddr(uuid.New())
128-
wgn, err := peerwg.New(
129-
slog.Make(sloghuman.Sink(os.Stderr)),
130-
[]netaddr.IPPrefix{netaddr.IPPrefixFrom(ipv6, 128)},
131-
)
132-
if err != nil {
133-
return xerrors.Errorf("create wireguard network: %w", err)
134-
}
135-
136-
err = client.PostWireguardPeer(cmd.Context(), workspace.ID, peerwg.Handshake{
137-
Recipient: workspaceAgent.ID,
138-
NodePublicKey: wgn.NodePrivateKey.Public(),
139-
DiscoPublicKey: wgn.DiscoPublicKey,
140-
IPv6: ipv6,
141-
})
142-
if err != nil {
143-
return xerrors.Errorf("post wireguard peer: %w", err)
144-
}
145-
146-
err = wgn.AddPeer(peerwg.Handshake{
147-
Recipient: workspaceAgent.ID,
148-
DiscoPublicKey: workspaceAgent.DiscoPublicKey,
149-
NodePublicKey: workspaceAgent.WireguardPublicKey,
150-
IPv6: workspaceAgent.IPv6.IP(),
151-
})
152-
if err != nil {
153-
return xerrors.Errorf("add workspace agent as peer: %w", err)
154-
}
155-
156-
if stdio {
157-
rawSSH, err := wgn.SSH(cmd.Context(), workspaceAgent.IPv6.IP())
158-
if err != nil {
159-
return err
160-
}
161-
162-
go func() {
163-
_, _ = io.Copy(cmd.OutOrStdout(), rawSSH)
164-
}()
165-
_, _ = io.Copy(rawSSH, cmd.InOrStdin())
166-
return nil
167-
}
168-
169-
sshClient, err = wgn.SSHClient(cmd.Context(), workspaceAgent.IPv6.IP())
170-
if err != nil {
171-
return err
172-
}
173-
174-
sshSession, err = sshClient.NewSession()
175-
if err != nil {
176-
return err
177-
}
120+
// peerwg.Logf = tslogger.Discard
121+
122+
// ipv6 := peerwg.UUIDToNetaddr(uuid.New())
123+
// wgn, err := peerwg.New(
124+
// slog.Make(sloghuman.Sink(os.Stderr)),
125+
// []netaddr.IPPrefix{netaddr.IPPrefixFrom(ipv6, 128)},
126+
// )
127+
// if err != nil {
128+
// return xerrors.Errorf("create wireguard network: %w", err)
129+
// }
130+
131+
// err = client.PostWireguardPeer(cmd.Context(), workspace.ID, peerwg.Handshake{
132+
// Recipient: workspaceAgent.ID,
133+
// NodePublicKey: wgn.NodePrivateKey.Public(),
134+
// DiscoPublicKey: wgn.DiscoPublicKey,
135+
// IPv6: ipv6,
136+
// })
137+
// if err != nil {
138+
// return xerrors.Errorf("post wireguard peer: %w", err)
139+
// }
140+
141+
// err = wgn.AddPeer(peerwg.Handshake{
142+
// Recipient: workspaceAgent.ID,
143+
// DiscoPublicKey: workspaceAgent.DiscoPublicKey,
144+
// NodePublicKey: workspaceAgent.WireguardPublicKey,
145+
// IPv6: workspaceAgent.IPv6.IP(),
146+
// })
147+
// if err != nil {
148+
// return xerrors.Errorf("add workspace agent as peer: %w", err)
149+
// }
150+
151+
// if stdio {
152+
// rawSSH, err := wgn.SSH(cmd.Context(), workspaceAgent.IPv6.IP())
153+
// if err != nil {
154+
// return err
155+
// }
156+
157+
// go func() {
158+
// _, _ = io.Copy(cmd.OutOrStdout(), rawSSH)
159+
// }()
160+
// _, _ = io.Copy(rawSSH, cmd.InOrStdin())
161+
// return nil
162+
// }
163+
164+
// sshClient, err = wgn.SSHClient(cmd.Context(), workspaceAgent.IPv6.IP())
165+
// if err != nil {
166+
// return err
167+
// }
168+
169+
// sshSession, err = sshClient.NewSession()
170+
// if err != nil {
171+
// return err
172+
// }
178173
}
179174

180175
if identityAgent == "" {

cli/wireguardtunnel.go

+76-81
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,14 @@ import (
44
"context"
55
"fmt"
66
"net"
7-
"os"
8-
"os/signal"
97
"strconv"
108
"sync"
11-
"syscall"
129

13-
"github.com/google/uuid"
1410
"github.com/pion/udp"
1511
"github.com/spf13/cobra"
1612
"golang.org/x/xerrors"
1713
"inet.af/netaddr"
1814

19-
"cdr.dev/slog"
20-
"cdr.dev/slog/sloggers/sloghuman"
2115
coderagent "github.com/coder/coder/agent"
2216
"github.com/coder/coder/cli/cliui"
2317
"github.com/coder/coder/codersdk"
@@ -94,81 +88,82 @@ func wireguardPortForward() *cobra.Command {
9488
return xerrors.Errorf("await agent: %w", err)
9589
}
9690

97-
ipv6 := peerwg.UUIDToNetaddr(uuid.New())
98-
wgn, err := peerwg.New(
99-
slog.Make(sloghuman.Sink(os.Stderr)),
100-
[]netaddr.IPPrefix{netaddr.IPPrefixFrom(ipv6, 128)},
101-
)
102-
if err != nil {
103-
return xerrors.Errorf("create wireguard network: %w", err)
104-
}
105-
106-
err = client.PostWireguardPeer(cmd.Context(), workspace.ID, peerwg.Handshake{
107-
Recipient: workspaceAgent.ID,
108-
NodePublicKey: wgn.NodePrivateKey.Public(),
109-
DiscoPublicKey: wgn.DiscoPublicKey,
110-
IPv6: ipv6,
111-
})
112-
if err != nil {
113-
return xerrors.Errorf("post wireguard peer: %w", err)
114-
}
115-
116-
err = wgn.AddPeer(peerwg.Handshake{
117-
Recipient: workspaceAgent.ID,
118-
DiscoPublicKey: workspaceAgent.DiscoPublicKey,
119-
NodePublicKey: workspaceAgent.WireguardPublicKey,
120-
IPv6: workspaceAgent.IPv6.IP(),
121-
})
122-
if err != nil {
123-
return xerrors.Errorf("add workspace agent as peer: %w", err)
124-
}
125-
126-
// Start all listeners.
127-
var (
128-
ctx, cancel = context.WithCancel(cmd.Context())
129-
wg = new(sync.WaitGroup)
130-
listeners = make([]net.Listener, len(specs))
131-
closeAllListeners = func() {
132-
for _, l := range listeners {
133-
if l == nil {
134-
continue
135-
}
136-
_ = l.Close()
137-
}
138-
}
139-
)
140-
defer cancel()
141-
for i, spec := range specs {
142-
l, err := listenAndPortForwardWireguard(ctx, cmd, wgn, wg, spec, workspaceAgent.IPv6.IP())
143-
if err != nil {
144-
closeAllListeners()
145-
return err
146-
}
147-
listeners[i] = l
148-
}
149-
150-
// Wait for the context to be canceled or for a signal and close
151-
// all listeners.
152-
var closeErr error
153-
go func() {
154-
sigs := make(chan os.Signal, 1)
155-
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
156-
157-
select {
158-
case <-ctx.Done():
159-
closeErr = ctx.Err()
160-
case <-sigs:
161-
_, _ = fmt.Fprintln(cmd.OutOrStderr(), "Received signal, closing all listeners and active connections")
162-
closeErr = xerrors.New("signal received")
163-
}
164-
165-
cancel()
166-
closeAllListeners()
167-
}()
168-
169-
_, _ = fmt.Fprintln(cmd.OutOrStderr(), "Ready!")
170-
wg.Wait()
171-
return closeErr
91+
// ipv6 := peerwg.UUIDToNetaddr(uuid.New())
92+
// wgn, err := peerwg.New(
93+
// slog.Make(sloghuman.Sink(os.Stderr)),
94+
// []netaddr.IPPrefix{netaddr.IPPrefixFrom(ipv6, 128)},
95+
// )
96+
// if err != nil {
97+
// return xerrors.Errorf("create wireguard network: %w", err)
98+
// }
99+
100+
// err = client.PostWireguardPeer(cmd.Context(), workspace.ID, peerwg.Handshake{
101+
// Recipient: workspaceAgent.ID,
102+
// NodePublicKey: wgn.NodePrivateKey.Public(),
103+
// DiscoPublicKey: wgn.DiscoPublicKey,
104+
// IPv6: ipv6,
105+
// })
106+
// if err != nil {
107+
// return xerrors.Errorf("post wireguard peer: %w", err)
108+
// }
109+
110+
// err = wgn.AddPeer(peerwg.Handshake{
111+
// Recipient: workspaceAgent.ID,
112+
// DiscoPublicKey: workspaceAgent.DiscoPublicKey,
113+
// NodePublicKey: workspaceAgent.WireguardPublicKey,
114+
// IPv6: workspaceAgent.IPv6.IP(),
115+
// })
116+
// if err != nil {
117+
// return xerrors.Errorf("add workspace agent as peer: %w", err)
118+
// }
119+
120+
// // Start all listeners.
121+
// var (
122+
// ctx, cancel = context.WithCancel(cmd.Context())
123+
// wg = new(sync.WaitGroup)
124+
// listeners = make([]net.Listener, len(specs))
125+
// closeAllListeners = func() {
126+
// for _, l := range listeners {
127+
// if l == nil {
128+
// continue
129+
// }
130+
// _ = l.Close()
131+
// }
132+
// }
133+
// )
134+
// defer cancel()
135+
// for i, spec := range specs {
136+
// l, err := listenAndPortForwardWireguard(ctx, cmd, wgn, wg, spec, workspaceAgent.IPv6.IP())
137+
// if err != nil {
138+
// closeAllListeners()
139+
// return err
140+
// }
141+
// listeners[i] = l
142+
// }
143+
144+
// // Wait for the context to be canceled or for a signal and close
145+
// // all listeners.
146+
// var closeErr error
147+
// go func() {
148+
// sigs := make(chan os.Signal, 1)
149+
// signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
150+
151+
// select {
152+
// case <-ctx.Done():
153+
// closeErr = ctx.Err()
154+
// case <-sigs:
155+
// _, _ = fmt.Fprintln(cmd.OutOrStderr(), "Received signal, closing all listeners and active connections")
156+
// closeErr = xerrors.New("signal received")
157+
// }
158+
159+
// cancel()
160+
// closeAllListeners()
161+
// }()
162+
163+
// _, _ = fmt.Fprintln(cmd.OutOrStderr(), "Ready!")
164+
// wg.Wait()
165+
// return closeErr
166+
return nil
172167
},
173168
}
174169

coderd/coderd.go

+5-11
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,10 @@ func New(options *Options) *API {
322322
r.Get("/gitsshkey", api.agentGitSSHKey)
323323
r.Get("/turn", api.workspaceAgentTurn)
324324
r.Get("/iceservers", api.workspaceAgentICEServers)
325-
r.Get("/derp", api.derpMap)
326325

327-
// Posting map under "me" sets the agents node map.
328-
329-
// On the agent side, "map" is a WebSocket that sends
330-
// updates via marshalled JSON and recieves networking
331-
// messages on the other end.
332-
r.Get("/netmap", api.workspaceAgentSelfNetmap)
326+
// Everything below this is Tailnet.
327+
r.Get("/node", api.workspaceAgentNode)
328+
r.Get("/derpmap", api.derpMap)
333329
})
334330
r.Route("/{workspaceagent}", func(r chi.Router) {
335331
r.Use(
@@ -342,11 +338,9 @@ func New(options *Options) *API {
342338
r.Get("/turn", api.workspaceAgentTurn)
343339
r.Get("/pty", api.workspaceAgentPTY)
344340
r.Get("/iceservers", api.workspaceAgentICEServers)
345-
r.Get("/derp", api.derpMap)
346341

347-
// Specific to Tailscale networking:
348-
r.Post("/netmap")
349-
r.Get("/tail-dial", api.workspaceAgentTailnetDial)
342+
r.Get("/derpmap", api.derpMap)
343+
r.Post("/node", api.postWorkspaceAgentNode)
350344
})
351345
})
352346
r.Route("/workspaceresources/{workspaceresource}", func(r chi.Router) {

coderd/database/databasefake/databasefake.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1925,7 +1925,7 @@ func (q *fakeQuerier) UpdateWorkspaceAgentNetworkByID(_ context.Context, arg dat
19251925

19261926
agent.DiscoPublicKey = arg.DiscoPublicKey
19271927
agent.NodePublicKey = arg.NodePublicKey
1928-
agent.DERP = arg.DERP
1928+
agent.PreferredDERP = arg.PreferredDERP
19291929
agent.DERPLatency = arg.DERPLatency
19301930
agent.UpdatedAt = database.Now()
19311931
q.provisionerJobAgents[index] = agent

coderd/database/dump.sql

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/migrations/000029_tailnet.up.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ ALTER TABLE workspace_agents DROP COLUMN wireguard_node_ipv6;
22
ALTER TABLE workspace_agents ADD COLUMN ip_addresses inet[] NOT NULL DEFAULT array[]::inet[];
33
ALTER TABLE workspace_agents RENAME COLUMN wireguard_node_public_key TO node_public_key;
44
ALTER TABLE workspace_agents RENAME COLUMN wireguard_disco_public_key TO disco_public_key;
5-
ALTER TABLE workspace_agents ADD COLUMN derp varchar(128) NOT NULL DEFAULT '127.3.3.40:0';
5+
ALTER TABLE workspace_agents ADD COLUMN preferred_derp integer NOT NULL DEFAULT 0;
66
ALTER TABLE workspace_agents ADD COLUMN derp_latency jsonb NOT NULL DEFAULT '{}';

coderd/database/models.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)