Skip to content

feat: add flag to disable all direct connections instance-wide #7936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jun 21, 2023
Prev Previous commit
Next Next commit
rename flag and fields
  • Loading branch information
deansheather committed Jun 21, 2023
commit bd107bc4709906b7feebba4f00b3304ea7f4ad20
8 changes: 4 additions & 4 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ func (a *agent) run(ctx context.Context) error {
network := a.network
a.closeMutex.Unlock()
if network == nil {
network, err = a.createTailnet(ctx, manifest.DERPMap, manifest.AllowDirectConnections)
network, err = a.createTailnet(ctx, manifest.DERPMap, manifest.DisableDirectConnections)
if err != nil {
return xerrors.Errorf("create tailnet: %w", err)
}
Expand All @@ -607,7 +607,7 @@ func (a *agent) run(ctx context.Context) error {
} else {
// Update the DERP map and allow/disallow direct connections.
network.SetDERPMap(manifest.DERPMap)
network.SetBlockEndpoints(!manifest.AllowDirectConnections)
network.SetBlockEndpoints(manifest.DisableDirectConnections)
}

a.logger.Debug(ctx, "running tailnet connection coordinator")
Expand All @@ -632,13 +632,13 @@ func (a *agent) trackConnGoroutine(fn func()) error {
return nil
}

func (a *agent) createTailnet(ctx context.Context, derpMap *tailcfg.DERPMap, allowDirectConnections bool) (_ *tailnet.Conn, err error) {
func (a *agent) createTailnet(ctx context.Context, derpMap *tailcfg.DERPMap, disableDirectConnections bool) (_ *tailnet.Conn, err error) {
network, err := tailnet.NewConn(&tailnet.Options{
Addresses: []netip.Prefix{netip.PrefixFrom(codersdk.WorkspaceAgentIP, 128)},
DERPMap: derpMap,
Logger: a.logger.Named("tailnet"),
ListenPort: a.tailnetListenPort,
BlockEndpoints: !allowDirectConnections,
BlockEndpoints: disableDirectConnections,
})
if err != nil {
return nil, xerrors.Errorf("create tailnet: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion cli/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
derpMap, err := tailnet.NewDERPMap(
ctx, defaultRegion, cfg.DERP.Server.STUNAddresses,
cfg.DERP.Config.URL.String(), cfg.DERP.Config.Path.String(),
cfg.DERP.Config.DisableDirect.Value(),
cfg.DERP.Config.BlockDirect.Value(),
)
if err != nil {
return xerrors.Errorf("create derp map: %w", err)
Expand Down
16 changes: 8 additions & 8 deletions cli/testdata/coder_server_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ between workspaces and users are peer-to-peer. However, when Coder cannot
establish a peer to peer connection, Coder uses a distributed relay network
backed by Tailscale and WireGuard.

--block-direct-connections bool, $CODER_BLOCK_DIRECT
Block peer-to-peer (aka. direct) workspace connections. All workspace
connections from the CLI will be proxied through Coder (or custom
configured DERP servers) and will never be peer-to-peer when enabled.
Workspaces may still reach out to STUN servers to get their address
until they are restarted after this change has been made, but new
connections will still be proxied regardless.

--derp-config-path string, $CODER_DERP_CONFIG_PATH
Path to read a DERP mapping from. See:
https://tailscale.com/kb/1118/custom-derp-servers/.
Expand All @@ -171,14 +179,6 @@ backed by Tailscale and WireGuard.
Addresses for STUN servers to establish P2P connections. Use special
value 'disable' to turn off STUN.

--disable-direct bool, $CODER_DISABLE_DIRECT
Disable peer-to-peer (aka. direct) workspace connections. All
workspace connections from the CLI will be proxied through Coder (or
custom configured DERP servers) and will never be peer-to-peer when
enabled. Workspaces may still reach out to STUN servers to get their
address until they are restarted after this change has been made, but
new connections will still be proxied regardless.

Networking / HTTP Options
--disable-password-auth bool, $CODER_DISABLE_PASSWORD_AUTH
Disable password authentication. This is recommended for security
Expand Down
4 changes: 2 additions & 2 deletions cli/testdata/server-config.yaml.golden
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ networking:
# for high availability.
# (default: <unset>, type: url)
relayURL:
# Disable peer-to-peer (aka. direct) workspace connections. All workspace
# Block peer-to-peer (aka. direct) workspace connections. All workspace
# connections from the CLI will be proxied through Coder (or custom configured
# DERP servers) and will never be peer-to-peer when enabled. Workspaces may still
# reach out to STUN servers to get their address until they are restarted after
# this change has been made, but new connections will still be proxied regardless.
# (default: <unset>, type: bool)
disableDirect: false
blockDirect: false
# URL to fetch a DERP mapping on startup. See:
# https://tailscale.com/kb/1118/custom-derp-servers/.
# (default: <unset>, type: string)
Expand Down
2 changes: 1 addition & 1 deletion coderd/coderdtest/coderdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
if !options.DeploymentValues.DERP.Server.Enable.Value() {
region = nil
}
derpMap, err := tailnet.NewDERPMap(ctx, region, []string{stunAddr.String()}, "", "", !options.DeploymentValues.DERP.Config.DisableDirect.Value())
derpMap, err := tailnet.NewDERPMap(ctx, region, []string{stunAddr.String()}, "", "", options.DeploymentValues.DERP.Config.BlockDirect.Value())
require.NoError(t, err)

return func(h http.Handler) {
Expand Down
32 changes: 16 additions & 16 deletions coderd/workspaceagents.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,19 +161,19 @@ func (api *API) workspaceAgentManifest(rw http.ResponseWriter, r *http.Request)
}

httpapi.Write(ctx, rw, http.StatusOK, agentsdk.Manifest{
Apps: convertApps(dbApps),
DERPMap: api.DERPMap,
GitAuthConfigs: len(api.GitAuthConfigs),
EnvironmentVariables: apiAgent.EnvironmentVariables,
StartupScript: apiAgent.StartupScript,
Directory: apiAgent.Directory,
VSCodePortProxyURI: vscodeProxyURI,
MOTDFile: workspaceAgent.MOTDFile,
StartupScriptTimeout: time.Duration(apiAgent.StartupScriptTimeoutSeconds) * time.Second,
ShutdownScript: apiAgent.ShutdownScript,
ShutdownScriptTimeout: time.Duration(apiAgent.ShutdownScriptTimeoutSeconds) * time.Second,
AllowDirectConnections: !api.DeploymentValues.DERP.Config.DisableDirect.Value(),
Metadata: convertWorkspaceAgentMetadataDesc(metadata),
Apps: convertApps(dbApps),
DERPMap: api.DERPMap,
GitAuthConfigs: len(api.GitAuthConfigs),
EnvironmentVariables: apiAgent.EnvironmentVariables,
StartupScript: apiAgent.StartupScript,
Directory: apiAgent.Directory,
VSCodePortProxyURI: vscodeProxyURI,
MOTDFile: workspaceAgent.MOTDFile,
StartupScriptTimeout: time.Duration(apiAgent.StartupScriptTimeoutSeconds) * time.Second,
ShutdownScript: apiAgent.ShutdownScript,
ShutdownScriptTimeout: time.Duration(apiAgent.ShutdownScriptTimeoutSeconds) * time.Second,
DisableDirectConnections: api.DeploymentValues.DERP.Config.BlockDirect.Value(),
Metadata: convertWorkspaceAgentMetadataDesc(metadata),
})
}

Expand Down Expand Up @@ -667,7 +667,7 @@ func (api *API) dialWorkspaceAgentTailnet(agentID uuid.UUID) (*codersdk.Workspac
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)},
DERPMap: api.DERPMap,
Logger: api.Logger.Named("tailnet"),
BlockEndpoints: api.DeploymentValues.DERP.Config.DisableDirect.Value(),
BlockEndpoints: api.DeploymentValues.DERP.Config.BlockDirect.Value(),
})
if err != nil {
_ = clientConn.Close()
Expand Down Expand Up @@ -735,8 +735,8 @@ func (api *API) workspaceAgentConnection(rw http.ResponseWriter, r *http.Request
ctx := r.Context()

httpapi.Write(ctx, rw, http.StatusOK, codersdk.WorkspaceAgentConnectionInfo{
DERPMap: api.DERPMap,
AllowDirectConnections: !api.DeploymentValues.DERP.Config.DisableDirect.Value(),
DERPMap: api.DERPMap,
DisableDirectConnections: api.DeploymentValues.DERP.Config.BlockDirect.Value(),
})
}

Expand Down
12 changes: 6 additions & 6 deletions coderd/workspaceagents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,9 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) {
t.Parallel()

dv := coderdtest.DeploymentValues(t)
err := dv.DERP.Config.DisableDirect.Set("true")
err := dv.DERP.Config.BlockDirect.Set("true")
require.NoError(t, err)
require.True(t, dv.DERP.Config.DisableDirect.Value())
require.True(t, dv.DERP.Config.BlockDirect.Value())

client, daemonCloser := coderdtest.NewWithProvisionerCloser(t, &coderdtest.Options{
DeploymentValues: dv,
Expand All @@ -471,12 +471,12 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) {

ctx := testutil.Context(t, testutil.WaitLong)

// Verify that the manifest has AllowDirectConnections set to false.
// Verify that the manifest has DisableDirectConnections set to true.
agentClient := agentsdk.New(client.URL)
agentClient.SetSessionToken(authToken)
manifest, err := agentClient.Manifest(ctx)
require.NoError(t, err)
require.False(t, manifest.AllowDirectConnections)
require.True(t, manifest.DisableDirectConnections)

agentCloser := agent.New(agent.Options{
Client: agentClient,
Expand All @@ -487,15 +487,15 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) {
agentID := resources[0].Agents[0].ID

// Verify that the connection data has no STUN ports and
// AllowDirectConnections set to false.
// DisableDirectConnections set to true.
res, err := client.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaceagents/%s/connection", agentID), nil)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusOK, res.StatusCode)
var connInfo codersdk.WorkspaceAgentConnectionInfo
err = json.NewDecoder(res.Body).Decode(&connInfo)
require.NoError(t, err)
require.False(t, connInfo.AllowDirectConnections)
require.True(t, connInfo.DisableDirectConnections)
for _, region := range connInfo.DERPMap.Regions {
t.Logf("region %s (%v)", region.RegionCode, region.EmbeddedRelay)
for _, node := range region.Nodes {
Expand Down
26 changes: 13 additions & 13 deletions codersdk/agentsdk/agentsdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,19 @@ type Manifest struct {
// GitAuthConfigs stores the number of Git configurations
// the Coder deployment has. If this number is >0, we
// set up special configuration in the workspace.
GitAuthConfigs int `json:"git_auth_configs"`
VSCodePortProxyURI string `json:"vscode_port_proxy_uri"`
Apps []codersdk.WorkspaceApp `json:"apps"`
DERPMap *tailcfg.DERPMap `json:"derpmap"`
EnvironmentVariables map[string]string `json:"environment_variables"`
StartupScript string `json:"startup_script"`
StartupScriptTimeout time.Duration `json:"startup_script_timeout"`
Directory string `json:"directory"`
MOTDFile string `json:"motd_file"`
ShutdownScript string `json:"shutdown_script"`
ShutdownScriptTimeout time.Duration `json:"shutdown_script_timeout"`
AllowDirectConnections bool `json:"allow_direct_connections"`
Metadata []codersdk.WorkspaceAgentMetadataDescription `json:"metadata"`
GitAuthConfigs int `json:"git_auth_configs"`
VSCodePortProxyURI string `json:"vscode_port_proxy_uri"`
Apps []codersdk.WorkspaceApp `json:"apps"`
DERPMap *tailcfg.DERPMap `json:"derpmap"`
EnvironmentVariables map[string]string `json:"environment_variables"`
StartupScript string `json:"startup_script"`
StartupScriptTimeout time.Duration `json:"startup_script_timeout"`
Directory string `json:"directory"`
MOTDFile string `json:"motd_file"`
ShutdownScript string `json:"shutdown_script"`
ShutdownScriptTimeout time.Duration `json:"shutdown_script_timeout"`
DisableDirectConnections bool `json:"disable_direct_connections"`
Metadata []codersdk.WorkspaceAgentMetadataDescription `json:"metadata"`
}

// Manifest fetches manifest for the currently authenticated workspace agent.
Expand Down
23 changes: 13 additions & 10 deletions codersdk/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ type DERPServerConfig struct {
}

type DERPConfig struct {
DisableDirect clibase.Bool `json:"disable_direct" typescript:",notnull"`
URL clibase.String `json:"url" typescript:",notnull"`
Path clibase.String `json:"path" typescript:",notnull"`
BlockDirect clibase.Bool `json:"block_direct" typescript:",notnull"`
URL clibase.String `json:"url" typescript:",notnull"`
Path clibase.String `json:"path" typescript:",notnull"`
}

type PrometheusConfig struct {
Expand Down Expand Up @@ -712,13 +712,16 @@ when required by your organization's security policy.`,
YAML: "relayURL",
},
{
Name: "Disable Direct Connections",
Description: "Disable peer-to-peer (aka. direct) workspace connections. All workspace connections from the CLI will be proxied through Coder (or custom configured DERP servers) and will never be peer-to-peer when enabled. Workspaces may still reach out to STUN servers to get their address until they are restarted after this change has been made, but new connections will still be proxied regardless.",
Flag: "disable-direct",
Env: "CODER_DISABLE_DIRECT",
Value: &c.DERP.Config.DisableDirect,
Group: &deploymentGroupNetworkingDERP,
YAML: "disableDirect",
Name: "Block Direct Connections",
Description: "Block peer-to-peer (aka. direct) workspace connections. All workspace connections from the CLI will be proxied through Coder (or custom configured DERP servers) and will never be peer-to-peer when enabled. Workspaces may still reach out to STUN servers to get their address until they are restarted after this change has been made, but new connections will still be proxied regardless.",
// This cannot be called `disable-direct-connections` because that's
// already a global CLI flag for CLI connections. This is a
// deployment-wide flag.
Flag: "block-direct-connections",
Env: "CODER_BLOCK_DIRECT",
Value: &c.DERP.Config.BlockDirect,
Group: &deploymentGroupNetworkingDERP,
YAML: "blockDirect",
},
{
Name: "DERP Config URL",
Expand Down
6 changes: 3 additions & 3 deletions codersdk/workspaceagents.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ type DERPRegion struct {
// a connection with a workspace.
// @typescript-ignore WorkspaceAgentConnectionInfo
type WorkspaceAgentConnectionInfo struct {
DERPMap *tailcfg.DERPMap `json:"derp_map"`
AllowDirectConnections bool `json:"allow_direct_connections"`
DERPMap *tailcfg.DERPMap `json:"derp_map"`
DisableDirectConnections bool `json:"disable_direct_connections"`
}

// @typescript-ignore DialWorkspaceAgentOptions
Expand All @@ -188,7 +188,7 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
if err != nil {
return nil, xerrors.Errorf("decode conn info: %w", err)
}
if !connInfo.AllowDirectConnections {
if connInfo.DisableDirectConnections {
options.BlockEndpoints = true
}

Expand Down
16 changes: 8 additions & 8 deletions enterprise/cli/testdata/coder_server_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ between workspaces and users are peer-to-peer. However, when Coder cannot
establish a peer to peer connection, Coder uses a distributed relay network
backed by Tailscale and WireGuard.

--block-direct-connections bool, $CODER_BLOCK_DIRECT
Block peer-to-peer (aka. direct) workspace connections. All workspace
connections from the CLI will be proxied through Coder (or custom
configured DERP servers) and will never be peer-to-peer when enabled.
Workspaces may still reach out to STUN servers to get their address
until they are restarted after this change has been made, but new
connections will still be proxied regardless.

--derp-config-path string, $CODER_DERP_CONFIG_PATH
Path to read a DERP mapping from. See:
https://tailscale.com/kb/1118/custom-derp-servers/.
Expand All @@ -171,14 +179,6 @@ backed by Tailscale and WireGuard.
Addresses for STUN servers to establish P2P connections. Use special
value 'disable' to turn off STUN.

--disable-direct bool, $CODER_DISABLE_DIRECT
Disable peer-to-peer (aka. direct) workspace connections. All
workspace connections from the CLI will be proxied through Coder (or
custom configured DERP servers) and will never be peer-to-peer when
enabled. Workspaces may still reach out to STUN servers to get their
address until they are restarted after this change has been made, but
new connections will still be proxied regardless.

Networking / HTTP Options
--disable-password-auth bool, $CODER_DISABLE_PASSWORD_AUTH
Disable password authentication. This is recommended for security
Expand Down
6 changes: 3 additions & 3 deletions tailnet/derpmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ import (
// URL to fetch a mapping from e.g. https://controlplane.tailscale.com/derpmap/default.
//
//nolint:revive
func NewDERPMap(ctx context.Context, region *tailcfg.DERPRegion, stunAddrs []string, remoteURL, localPath string, allowSTUN bool) (*tailcfg.DERPMap, error) {
func NewDERPMap(ctx context.Context, region *tailcfg.DERPRegion, stunAddrs []string, remoteURL, localPath string, disableSTUN bool) (*tailcfg.DERPMap, error) {
if remoteURL != "" && localPath != "" {
return nil, xerrors.New("a remote URL or local path must be specified, not both")
}
if !allowSTUN {
if disableSTUN {
stunAddrs = nil
}

Expand Down Expand Up @@ -82,7 +82,7 @@ func NewDERPMap(ctx context.Context, region *tailcfg.DERPRegion, stunAddrs []str
}
// Remove all STUNPorts from DERPy nodes, and fully remove all STUNOnly
// nodes.
if !allowSTUN {
if disableSTUN {
for _, region := range derpMap.Regions {
newNodes := make([]*tailcfg.DERPNode, 0, len(region.Nodes))
for _, node := range region.Nodes {
Expand Down
10 changes: 5 additions & 5 deletions tailnet/derpmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestNewDERPMap(t *testing.T) {
derpMap, err := tailnet.NewDERPMap(context.Background(), &tailcfg.DERPRegion{
RegionID: 1,
Nodes: []*tailcfg.DERPNode{{}},
}, []string{"stun.google.com:2345"}, "", "", true)
}, []string{"stun.google.com:2345"}, "", "", false)
require.NoError(t, err)
require.Len(t, derpMap.Regions[1].Nodes, 2)
})
Expand All @@ -39,7 +39,7 @@ func TestNewDERPMap(t *testing.T) {
t.Cleanup(server.Close)
derpMap, err := tailnet.NewDERPMap(context.Background(), &tailcfg.DERPRegion{
RegionID: 2,
}, []string{}, server.URL, "", true)
}, []string{}, server.URL, "", false)
require.NoError(t, err)
require.Len(t, derpMap.Regions, 2)
})
Expand All @@ -56,7 +56,7 @@ func TestNewDERPMap(t *testing.T) {
t.Cleanup(server.Close)
_, err := tailnet.NewDERPMap(context.Background(), &tailcfg.DERPRegion{
RegionID: 1,
}, []string{}, server.URL, "", true)
}, []string{}, server.URL, "", false)
require.Error(t, err)
})
t.Run("LocalPath", func(t *testing.T) {
Expand All @@ -72,7 +72,7 @@ func TestNewDERPMap(t *testing.T) {
require.NoError(t, err)
derpMap, err := tailnet.NewDERPMap(context.Background(), &tailcfg.DERPRegion{
RegionID: 2,
}, []string{}, "", localPath, true)
}, []string{}, "", localPath, false)
require.NoError(t, err)
require.Len(t, derpMap.Regions, 2)
})
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestNewDERPMap(t *testing.T) {
STUNPort: 1234,
}},
}
derpMap, err := tailnet.NewDERPMap(context.Background(), region, []string{"127.0.0.1:54321"}, "", localPath, false)
derpMap, err := tailnet.NewDERPMap(context.Background(), region, []string{"127.0.0.1:54321"}, "", localPath, true)
require.NoError(t, err)
require.Len(t, derpMap.Regions, 3)

Expand Down