fix: add CODER_AGENT_TAILNET_LISTEN_PORT for specifying a static tailnet port (#6980)

Fixes #5175.
This commit is contained in:
Kyle Carberry
2023-04-03 11:20:19 -05:00
committed by GitHub
parent 4ee01dc95c
commit bc18f6c113
4 changed files with 35 additions and 17 deletions

View File

@ -82,6 +82,7 @@ type Options struct {
Logger slog.Logger Logger slog.Logger
AgentPorts map[int]string AgentPorts map[int]string
SSHMaxTimeout time.Duration SSHMaxTimeout time.Duration
TailnetListenPort uint16
} }
type Client interface { type Client interface {
@ -118,6 +119,7 @@ func New(options Options) io.Closer {
} }
ctx, cancelFunc := context.WithCancel(context.Background()) ctx, cancelFunc := context.WithCancel(context.Background())
a := &agent{ a := &agent{
tailnetListenPort: options.TailnetListenPort,
reconnectingPTYTimeout: options.ReconnectingPTYTimeout, reconnectingPTYTimeout: options.ReconnectingPTYTimeout,
logger: options.Logger, logger: options.Logger,
closeCancel: cancelFunc, closeCancel: cancelFunc,
@ -139,12 +141,13 @@ func New(options Options) io.Closer {
} }
type agent struct { type agent struct {
logger slog.Logger logger slog.Logger
client Client client Client
exchangeToken func(ctx context.Context) (string, error) exchangeToken func(ctx context.Context) (string, error)
filesystem afero.Fs tailnetListenPort uint16
logDir string filesystem afero.Fs
tempDir string logDir string
tempDir string
// ignorePorts tells the api handler which ports to ignore when // ignorePorts tells the api handler which ports to ignore when
// listing all listening ports. This is helpful to hide ports that // listing all listening ports. This is helpful to hide ports that
// are used by the agent, that the user does not care about. // are used by the agent, that the user does not care about.
@ -606,9 +609,10 @@ func (a *agent) trackConnGoroutine(fn func()) error {
func (a *agent) createTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) (_ *tailnet.Conn, err error) { func (a *agent) createTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) (_ *tailnet.Conn, err error) {
network, err := tailnet.NewConn(&tailnet.Options{ network, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(codersdk.WorkspaceAgentIP, 128)}, Addresses: []netip.Prefix{netip.PrefixFrom(codersdk.WorkspaceAgentIP, 128)},
DERPMap: derpMap, DERPMap: derpMap,
Logger: a.logger.Named("tailnet"), Logger: a.logger.Named("tailnet"),
ListenPort: a.tailnetListenPort,
}) })
if err != nil { if err != nil {
return nil, xerrors.Errorf("create tailnet: %w", err) return nil, xerrors.Errorf("create tailnet: %w", err)

View File

@ -30,11 +30,12 @@ import (
func (r *RootCmd) workspaceAgent() *clibase.Cmd { func (r *RootCmd) workspaceAgent() *clibase.Cmd {
var ( var (
auth string auth string
logDir string logDir string
pprofAddress string pprofAddress string
noReap bool noReap bool
sshMaxTimeout time.Duration sshMaxTimeout time.Duration
tailnetListenPort int64
) )
cmd := &clibase.Cmd{ cmd := &clibase.Cmd{
Use: "agent", Use: "agent",
@ -187,9 +188,10 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
} }
closer := agent.New(agent.Options{ closer := agent.New(agent.Options{
Client: client, Client: client,
Logger: logger, Logger: logger,
LogDir: logDir, LogDir: logDir,
TailnetListenPort: uint16(tailnetListenPort),
ExchangeToken: func(ctx context.Context) (string, error) { ExchangeToken: func(ctx context.Context) (string, error) {
if exchangeToken == nil { if exchangeToken == nil {
return client.SDK.SessionToken(), nil return client.SDK.SessionToken(), nil
@ -248,6 +250,13 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
Description: "Specify the max timeout for a SSH connection.", Description: "Specify the max timeout for a SSH connection.",
Value: clibase.DurationOf(&sshMaxTimeout), Value: clibase.DurationOf(&sshMaxTimeout),
}, },
{
Flag: "tailnet-listen-port",
Default: "0",
Env: "CODER_AGENT_TAILNET_LISTEN_PORT",
Description: "Specify a static port for Tailscale to use for listening.",
Value: clibase.Int64Of(&tailnetListenPort),
},
} }
return cmd return cmd

View File

@ -18,5 +18,8 @@ Starts the Coder workspace agent.
--ssh-max-timeout duration, $CODER_AGENT_SSH_MAX_TIMEOUT (default: 0) --ssh-max-timeout duration, $CODER_AGENT_SSH_MAX_TIMEOUT (default: 0)
Specify the max timeout for a SSH connection. Specify the max timeout for a SSH connection.
--tailnet-listen-port int, $CODER_AGENT_TAILNET_LISTEN_PORT (default: 0)
Specify a static port for Tailscale to use for listening.
--- ---
Run `coder --help` for a list of global options. Run `coder --help` for a list of global options.

View File

@ -59,6 +59,7 @@ type Options struct {
// If so, only DERPs can establish connections. // If so, only DERPs can establish connections.
BlockEndpoints bool BlockEndpoints bool
Logger slog.Logger Logger slog.Logger
ListenPort uint16
} }
// NewConn constructs a new Wireguard server that will accept connections from the addresses provided. // NewConn constructs a new Wireguard server that will accept connections from the addresses provided.
@ -137,6 +138,7 @@ func NewConn(options *Options) (conn *Conn, err error) {
wireguardEngine, err := wgengine.NewUserspaceEngine(Logger(options.Logger.Named("wgengine")), wgengine.Config{ wireguardEngine, err := wgengine.NewUserspaceEngine(Logger(options.Logger.Named("wgengine")), wgengine.Config{
LinkMonitor: wireguardMonitor, LinkMonitor: wireguardMonitor,
Dialer: dialer, Dialer: dialer,
ListenPort: options.ListenPort,
}) })
if err != nil { if err != nil {
return nil, xerrors.Errorf("create wgengine: %w", err) return nil, xerrors.Errorf("create wgengine: %w", err)