Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit37a0537

Browse files
authored
fix: disable relay if built-in DERP is disabled (#12654)
Fixes#12493
1 parentd3c9aaf commit37a0537

File tree

8 files changed

+225
-60
lines changed

8 files changed

+225
-60
lines changed

‎cli/server_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ import (
3535
"github.com/stretchr/testify/require"
3636
"go.uber.org/goleak"
3737
"gopkg.in/yaml.v3"
38+
"tailscale.com/derp/derphttp"
39+
"tailscale.com/types/key"
3840

3941
"cdr.dev/slog/sloggers/slogtest"
4042

@@ -1830,3 +1832,32 @@ func TestServer_InvalidDERP(t *testing.T) {
18301832
require.Error(t,err)
18311833
require.ErrorContains(t,err,"A valid DERP map is required for networking to work")
18321834
}
1835+
1836+
funcTestServer_DisabledDERP(t*testing.T) {
1837+
t.Parallel()
1838+
1839+
ctx,cancelFunc:=context.WithTimeout(context.Background(),testutil.WaitShort)
1840+
defercancelFunc()
1841+
1842+
// Try to start a server with the built-in DERP server disabled and an
1843+
// external DERP map.
1844+
inv,cfg:=clitest.New(t,
1845+
"server",
1846+
"--in-memory",
1847+
"--http-address",":0",
1848+
"--access-url","http://example.com",
1849+
"--derp-server-enable=false",
1850+
"--derp-config-url","https://controlplane.tailscale.com/derpmap/default",
1851+
)
1852+
clitest.Start(t,inv.WithContext(ctx))
1853+
accessURL:=waitAccessURL(t,cfg)
1854+
derpURL,err:=accessURL.Parse("/derp")
1855+
require.NoError(t,err)
1856+
1857+
c,err:=derphttp.NewClient(key.NewNode(),derpURL.String(),func(formatstring,args...any) {})
1858+
require.NoError(t,err)
1859+
1860+
// DERP should fail to connect
1861+
err=c.Connect(ctx)
1862+
require.Error(t,err)
1863+
}

‎coderd/coderd.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ func New(options *Options) *API {
288288
ifoptions.PrometheusRegistry==nil {
289289
options.PrometheusRegistry=prometheus.NewRegistry()
290290
}
291-
ifoptions.DERPServer==nil {
291+
ifoptions.DERPServer==nil&&options.DeploymentValues.DERP.Server.Enable{
292292
options.DERPServer=derp.NewServer(key.NewNode(),tailnet.Logger(options.Logger.Named("derp")))
293293
}
294294
ifoptions.DERPMapUpdateFrequency==0 {
@@ -577,8 +577,6 @@ func New(options *Options) *API {
577577
// replicas or instances of this middleware.
578578
apiRateLimiter:=httpmw.RateLimit(options.APIRateLimit,time.Minute)
579579

580-
derpHandler:=derphttp.Handler(api.DERPServer)
581-
derpHandler,api.derpCloseFunc=tailnet.WithWebsocketSupport(api.DERPServer,derpHandler)
582580
// Register DERP on expvar HTTP handler, which we serve below in the router, c.f. expvar.Handler()
583581
// These are the metrics the DERP server exposes.
584582
// TODO: export via prometheus
@@ -587,7 +585,9 @@ func New(options *Options) *API {
587585
// register multiple times. In production there is only one Coderd and one DERP server per
588586
// process, but in testing, we create multiple of both, so the Once protects us from
589587
// panicking.
590-
expvar.Publish("derp",api.DERPServer.ExpVar())
588+
ifoptions.DERPServer!=nil {
589+
expvar.Publish("derp",api.DERPServer.ExpVar())
590+
}
591591
})
592592
cors:=httpmw.Cors(options.DeploymentValues.Dangerous.AllowAllCors.Value())
593593
prometheusMW:=httpmw.Prometheus(options.PrometheusRegistry)
@@ -637,13 +637,18 @@ func New(options *Options) *API {
637637
api.workspaceAppServer.Attach(r)
638638
})
639639

640-
r.Route("/derp",func(r chi.Router) {
641-
r.Get("/",derpHandler.ServeHTTP)
642-
// This is used when UDP is blocked, and latency must be checked via HTTP(s).
643-
r.Get("/latency-check",func(w http.ResponseWriter,r*http.Request) {
644-
w.WriteHeader(http.StatusOK)
640+
ifoptions.DERPServer!=nil {
641+
derpHandler:=derphttp.Handler(api.DERPServer)
642+
derpHandler,api.derpCloseFunc=tailnet.WithWebsocketSupport(api.DERPServer,derpHandler)
643+
644+
r.Route("/derp",func(r chi.Router) {
645+
r.Get("/",derpHandler.ServeHTTP)
646+
// This is used when UDP is blocked, and latency must be checked via HTTP(s).
647+
r.Get("/latency-check",func(w http.ResponseWriter,r*http.Request) {
648+
w.WriteHeader(http.StatusOK)
649+
})
645650
})
646-
})
651+
}
647652

648653
// Register callback handlers for each OAuth2 provider.
649654
// We must support gitauth and externalauth for backwards compatibility.
@@ -1067,9 +1072,11 @@ func New(options *Options) *API {
10671072
r.Use(httpmw.ExtractUserParam(options.Database))
10681073
r.Get("/debug-link",api.userDebugOIDC)
10691074
})
1070-
r.Route("/derp",func(r chi.Router) {
1071-
r.Get("/traffic",options.DERPServer.ServeDebugTraffic)
1072-
})
1075+
ifoptions.DERPServer!=nil {
1076+
r.Route("/derp",func(r chi.Router) {
1077+
r.Get("/traffic",options.DERPServer.ServeDebugTraffic)
1078+
})
1079+
}
10731080
r.Method("GET","/expvar",expvar.Handler())// contains DERP metrics as well as cmdline and memstats
10741081
})
10751082
})
@@ -1197,7 +1204,9 @@ type API struct {
11971204
// Close waits for all WebSocket connections to drain before returning.
11981205
func (api*API)Close()error {
11991206
api.cancel()
1200-
api.derpCloseFunc()
1207+
ifapi.derpCloseFunc!=nil {
1208+
api.derpCloseFunc()
1209+
}
12011210

12021211
api.WebsocketWaitMutex.Lock()
12031212
api.WebsocketWaitGroup.Wait()

‎coderd/coderdtest/coderdtest.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,11 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
429429
if!options.DeploymentValues.DERP.Server.Enable.Value() {
430430
region=nil
431431
}
432-
derpMap,err:=tailnet.NewDERPMap(ctx,region,stunAddresses,"","",options.DeploymentValues.DERP.Config.BlockDirect.Value())
432+
derpMap,err:=tailnet.NewDERPMap(ctx,region,stunAddresses,
433+
options.DeploymentValues.DERP.Config.URL.Value(),
434+
options.DeploymentValues.DERP.Config.Path.Value(),
435+
options.DeploymentValues.DERP.Config.BlockDirect.Value(),
436+
)
433437
require.NoError(t,err)
434438

435439
returnfunc(h http.Handler) {

‎enterprise/cli/server.go

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,41 +37,42 @@ func (r *RootCmd) Server(_ func()) *serpent.Command {
3737
}
3838
}
3939

40-
options.DERPServer=derp.NewServer(key.NewNode(),tailnet.Logger(options.Logger.Named("derp")))
41-
42-
varmeshKeystring
43-
err:=options.Database.InTx(func(tx database.Store)error {
44-
// This will block until the lock is acquired, and will be
45-
// automatically released when the transaction ends.
46-
err:=tx.AcquireLock(ctx,database.LockIDEnterpriseDeploymentSetup)
47-
iferr!=nil {
48-
returnxerrors.Errorf("acquire lock: %w",err)
49-
}
40+
ifoptions.DeploymentValues.DERP.Server.Enable {
41+
options.DERPServer=derp.NewServer(key.NewNode(),tailnet.Logger(options.Logger.Named("derp")))
42+
varmeshKeystring
43+
err:=options.Database.InTx(func(tx database.Store)error {
44+
// This will block until the lock is acquired, and will be
45+
// automatically released when the transaction ends.
46+
err:=tx.AcquireLock(ctx,database.LockIDEnterpriseDeploymentSetup)
47+
iferr!=nil {
48+
returnxerrors.Errorf("acquire lock: %w",err)
49+
}
5050

51-
meshKey,err=tx.GetDERPMeshKey(ctx)
52-
iferr==nil {
51+
meshKey,err=tx.GetDERPMeshKey(ctx)
52+
iferr==nil {
53+
returnnil
54+
}
55+
if!errors.Is(err,sql.ErrNoRows) {
56+
returnxerrors.Errorf("get DERP mesh key: %w",err)
57+
}
58+
meshKey,err=cryptorand.String(32)
59+
iferr!=nil {
60+
returnxerrors.Errorf("generate DERP mesh key: %w",err)
61+
}
62+
err=tx.InsertDERPMeshKey(ctx,meshKey)
63+
iferr!=nil {
64+
returnxerrors.Errorf("insert DERP mesh key: %w",err)
65+
}
5366
returnnil
54-
}
55-
if!errors.Is(err,sql.ErrNoRows) {
56-
returnxerrors.Errorf("get DERP mesh key: %w",err)
57-
}
58-
meshKey,err=cryptorand.String(32)
67+
},nil)
5968
iferr!=nil {
60-
returnxerrors.Errorf("generate DERP mesh key: %w",err)
69+
returnnil,nil,err
6170
}
62-
err=tx.InsertDERPMeshKey(ctx,meshKey)
63-
iferr!=nil {
64-
returnxerrors.Errorf("insert DERP mesh key: %w",err)
71+
ifmeshKey=="" {
72+
returnnil,nil,xerrors.New("mesh key is empty")
6573
}
66-
returnnil
67-
},nil)
68-
iferr!=nil {
69-
returnnil,nil,err
70-
}
71-
ifmeshKey=="" {
72-
returnnil,nil,xerrors.New("mesh key is empty")
74+
options.DERPServer.SetMeshKey(meshKey)
7375
}
74-
options.DERPServer.SetMeshKey(meshKey)
7576

7677
options.Auditor=audit.NewAuditor(
7778
options.Database,

‎enterprise/cli/server_test.go

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,43 @@
11
package cli_test
22

33
import (
4-
"fmt"
4+
"context"
55
"io"
66
"net/http"
7+
"net/url"
78
"testing"
89

910
"github.com/stretchr/testify/assert"
1011
"github.com/stretchr/testify/require"
1112

1213
"github.com/coder/coder/v2/cli/clitest"
14+
"github.com/coder/coder/v2/cli/config"
1315
"github.com/coder/coder/v2/enterprise/cli"
1416
"github.com/coder/coder/v2/testutil"
1517
)
1618

1719
// TestServer runs the enterprise server command
1820
// and waits for /healthz to return "OK".
19-
funcTestServer(t*testing.T) {
21+
funcTestServer_Single(t*testing.T) {
2022
t.Parallel()
2123

24+
ctx,cancelFunc:=context.WithTimeout(context.Background(),testutil.WaitLong)
25+
defercancelFunc()
26+
2227
varroot cli.RootCmd
2328
cmd,err:=root.Command(root.EnterpriseSubcommands())
2429
require.NoError(t,err)
25-
port:=testutil.RandomPort(t)
26-
inv,_:=clitest.NewWithCommand(t,cmd,
30+
inv,cfg:=clitest.NewWithCommand(t,cmd,
2731
"server",
2832
"--in-memory",
29-
"--http-address",fmt.Sprintf(":%d",port),
33+
"--http-address",":0",
3034
"--access-url","http://example.com",
3135
)
32-
waiter:=clitest.StartWithWaiter(t,inv)
36+
clitest.Start(t,inv.WithContext(ctx))
37+
accessURL:=waitAccessURL(t,cfg)
3338
require.Eventually(t,func()bool {
3439
reqCtx:=testutil.Context(t,testutil.IntervalMedium)
35-
req,err:=http.NewRequestWithContext(reqCtx,http.MethodGet,fmt.Sprintf("http://localhost:%d/healthz",port),nil)
40+
req,err:=http.NewRequestWithContext(reqCtx,http.MethodGet,accessURL.String()+"/healthz",nil)
3641
iferr!=nil {
3742
panic(err)
3843
}
@@ -48,5 +53,20 @@ func TestServer(t *testing.T) {
4853
}
4954
returnassert.Equal(t,"OK",string(bs))
5055
},testutil.WaitShort,testutil.IntervalMedium)
51-
waiter.Cancel()
56+
}
57+
58+
funcwaitAccessURL(t*testing.T,cfg config.Root)*url.URL {
59+
t.Helper()
60+
61+
varerrerror
62+
varrawURLstring
63+
require.Eventually(t,func()bool {
64+
rawURL,err=cfg.URL().Read()
65+
returnerr==nil&&rawURL!=""
66+
},testutil.WaitLong,testutil.IntervalFast,"failed to get access URL")
67+
68+
accessURL,err:=url.Parse(rawURL)
69+
require.NoError(t,err,"failed to parse access URL")
70+
71+
returnaccessURL
5272
}

‎enterprise/coderd/coderd.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
418418
iferr!=nil {
419419
returnnil,xerrors.Errorf("create DERP mesh TLS config: %w",err)
420420
}
421+
// We always want to run the replica manager even if we don't have DERP
422+
// enabled, since it's used to detect other coder servers for licensing.
421423
api.replicaManager,err=replicasync.New(ctx,options.Logger,options.Database,options.Pubsub,&replicasync.Options{
422424
ID:api.AGPL.ID,
423425
RelayAddress:options.DERPServerRelayAddress,
@@ -428,7 +430,9 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
428430
iferr!=nil {
429431
returnnil,xerrors.Errorf("initialize replica: %w",err)
430432
}
431-
api.derpMesh=derpmesh.New(options.Logger.Named("derpmesh"),api.DERPServer,meshTLSConfig)
433+
ifapi.DERPServer!=nil {
434+
api.derpMesh=derpmesh.New(options.Logger.Named("derpmesh"),api.DERPServer,meshTLSConfig)
435+
}
432436

433437
// Moon feature init. Proxyhealh is a go routine to periodically check
434438
// the health of all workspace proxies.
@@ -666,11 +670,18 @@ func (api *API) updateEntitlements(ctx context.Context) error {
666670
}
667671

668672
api.replicaManager.SetCallback(func() {
669-
addresses:=make([]string,0)
670-
for_,replica:=rangeapi.replicaManager.Regional() {
671-
addresses=append(addresses,replica.RelayAddress)
673+
// Only update DERP mesh if the built-in server is enabled.
674+
ifapi.Options.DeploymentValues.DERP.Server.Enable {
675+
addresses:=make([]string,0)
676+
for_,replica:=rangeapi.replicaManager.Regional() {
677+
// Don't add replicas with an empty relay address.
678+
ifreplica.RelayAddress=="" {
679+
continue
680+
}
681+
addresses=append(addresses,replica.RelayAddress)
682+
}
683+
api.derpMesh.SetAddresses(addresses,false)
672684
}
673-
api.derpMesh.SetAddresses(addresses,false)
674685
_=api.updateEntitlements(ctx)
675686
})
676687
}else {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp