mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
tstest/integration/vms: add in-process DERP server (#2108)
Previously this test would reach out to the public DERP servers in order to help machines connect with eachother. This is not ideal given our plans to run these tests completely disconnected from the internet. This patch introduces an in-process DERP server running on its own randomly assigned HTTP port. Updates #1988 Signed-off-by: Christine Dodrill <xe@tailscale.com>
This commit is contained in:
parent
6b234323a0
commit
194d5b8412
@ -9,6 +9,11 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
@ -19,6 +24,13 @@
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"tailscale.com/derp"
|
||||||
|
"tailscale.com/derp/derphttp"
|
||||||
|
"tailscale.com/net/stun/stuntest"
|
||||||
|
"tailscale.com/tailcfg"
|
||||||
|
"tailscale.com/types/key"
|
||||||
|
"tailscale.com/types/logger"
|
||||||
|
"tailscale.com/types/nettype"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -98,3 +110,53 @@ func exe() string {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RunDERPAndSTUN runs a local DERP and STUN server for tests, returning the derpMap
|
||||||
|
// that clients should use. This creates resources that must be cleaned up with the
|
||||||
|
// returned cleanup function.
|
||||||
|
func RunDERPAndSTUN(t testing.TB, logf logger.Logf, ipAddress string) (derpMap *tailcfg.DERPMap) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var serverPrivateKey key.Private
|
||||||
|
if _, err := rand.Read(serverPrivateKey[:]); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
d := derp.NewServer(serverPrivateKey, logf)
|
||||||
|
|
||||||
|
httpsrv := httptest.NewUnstartedServer(derphttp.Handler(d))
|
||||||
|
httpsrv.Config.ErrorLog = logger.StdLogger(logf)
|
||||||
|
httpsrv.Config.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
|
||||||
|
httpsrv.StartTLS()
|
||||||
|
|
||||||
|
stunAddr, stunCleanup := stuntest.ServeWithPacketListener(t, nettype.Std{})
|
||||||
|
|
||||||
|
m := &tailcfg.DERPMap{
|
||||||
|
Regions: map[int]*tailcfg.DERPRegion{
|
||||||
|
1: {
|
||||||
|
RegionID: 1,
|
||||||
|
RegionCode: "test",
|
||||||
|
Nodes: []*tailcfg.DERPNode{
|
||||||
|
{
|
||||||
|
Name: "t1",
|
||||||
|
RegionID: 1,
|
||||||
|
HostName: ipAddress,
|
||||||
|
IPv4: ipAddress,
|
||||||
|
IPv6: "none",
|
||||||
|
STUNPort: stunAddr.Port,
|
||||||
|
DERPTestPort: httpsrv.Listener.Addr().(*net.TCPAddr).Port,
|
||||||
|
STUNTestIP: stunAddr.IP.String(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
httpsrv.CloseClientConnections()
|
||||||
|
httpsrv.Close()
|
||||||
|
d.Close()
|
||||||
|
stunCleanup()
|
||||||
|
})
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
crand "crypto/rand"
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
@ -16,7 +14,6 @@
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
@ -31,18 +28,13 @@
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go4.org/mem"
|
"go4.org/mem"
|
||||||
"tailscale.com/derp"
|
|
||||||
"tailscale.com/derp/derphttp"
|
|
||||||
"tailscale.com/ipn/ipnstate"
|
"tailscale.com/ipn/ipnstate"
|
||||||
"tailscale.com/net/stun/stuntest"
|
|
||||||
"tailscale.com/safesocket"
|
"tailscale.com/safesocket"
|
||||||
"tailscale.com/smallzstd"
|
"tailscale.com/smallzstd"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/tstest"
|
"tailscale.com/tstest"
|
||||||
"tailscale.com/tstest/integration/testcontrol"
|
"tailscale.com/tstest/integration/testcontrol"
|
||||||
"tailscale.com/types/key"
|
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/nettype"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -301,8 +293,6 @@ type testEnv struct {
|
|||||||
|
|
||||||
TrafficTrap *trafficTrap
|
TrafficTrap *trafficTrap
|
||||||
TrafficTrapServer *httptest.Server
|
TrafficTrapServer *httptest.Server
|
||||||
|
|
||||||
derpShutdown func()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type testEnvOpt interface {
|
type testEnvOpt interface {
|
||||||
@ -323,7 +313,7 @@ func newTestEnv(t testing.TB, bins *Binaries, opts ...testEnvOpt) *testEnv {
|
|||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
t.Skip("not tested/working on Windows yet")
|
t.Skip("not tested/working on Windows yet")
|
||||||
}
|
}
|
||||||
derpMap, derpShutdown := runDERPAndStun(t, logger.Discard)
|
derpMap := RunDERPAndSTUN(t, logger.Discard, "127.0.0.1")
|
||||||
logc := new(logCatcher)
|
logc := new(logCatcher)
|
||||||
control := &testcontrol.Server{
|
control := &testcontrol.Server{
|
||||||
DERPMap: derpMap,
|
DERPMap: derpMap,
|
||||||
@ -339,7 +329,6 @@ func newTestEnv(t testing.TB, bins *Binaries, opts ...testEnvOpt) *testEnv {
|
|||||||
ControlServer: control.HTTPTestServer,
|
ControlServer: control.HTTPTestServer,
|
||||||
TrafficTrap: trafficTrap,
|
TrafficTrap: trafficTrap,
|
||||||
TrafficTrapServer: httptest.NewServer(trafficTrap),
|
TrafficTrapServer: httptest.NewServer(trafficTrap),
|
||||||
derpShutdown: derpShutdown,
|
|
||||||
}
|
}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o.modifyTestEnv(e)
|
o.modifyTestEnv(e)
|
||||||
@ -357,7 +346,6 @@ func (e *testEnv) Close() error {
|
|||||||
e.LogCatcherServer.Close()
|
e.LogCatcherServer.Close()
|
||||||
e.TrafficTrapServer.Close()
|
e.TrafficTrapServer.Close()
|
||||||
e.ControlServer.Close()
|
e.ControlServer.Close()
|
||||||
e.derpShutdown()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,51 +608,6 @@ func (tt *trafficTrap) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.WriteHeader(403)
|
w.WriteHeader(403)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDERPAndStun(t testing.TB, logf logger.Logf) (derpMap *tailcfg.DERPMap, cleanup func()) {
|
|
||||||
var serverPrivateKey key.Private
|
|
||||||
if _, err := crand.Read(serverPrivateKey[:]); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
d := derp.NewServer(serverPrivateKey, logf)
|
|
||||||
|
|
||||||
httpsrv := httptest.NewUnstartedServer(derphttp.Handler(d))
|
|
||||||
httpsrv.Config.ErrorLog = logger.StdLogger(logf)
|
|
||||||
httpsrv.Config.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
|
|
||||||
httpsrv.StartTLS()
|
|
||||||
|
|
||||||
stunAddr, stunCleanup := stuntest.ServeWithPacketListener(t, nettype.Std{})
|
|
||||||
|
|
||||||
m := &tailcfg.DERPMap{
|
|
||||||
Regions: map[int]*tailcfg.DERPRegion{
|
|
||||||
1: {
|
|
||||||
RegionID: 1,
|
|
||||||
RegionCode: "test",
|
|
||||||
Nodes: []*tailcfg.DERPNode{
|
|
||||||
{
|
|
||||||
Name: "t1",
|
|
||||||
RegionID: 1,
|
|
||||||
HostName: "127.0.0.1", // to bypass HTTP proxy
|
|
||||||
IPv4: "127.0.0.1",
|
|
||||||
IPv6: "none",
|
|
||||||
STUNPort: stunAddr.Port,
|
|
||||||
DERPTestPort: httpsrv.Listener.Addr().(*net.TCPAddr).Port,
|
|
||||||
STUNTestIP: stunAddr.IP.String(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup = func() {
|
|
||||||
httpsrv.CloseClientConnections()
|
|
||||||
httpsrv.Close()
|
|
||||||
d.Close()
|
|
||||||
stunCleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
return m, cleanup
|
|
||||||
}
|
|
||||||
|
|
||||||
type authURLParserWriter struct {
|
type authURLParserWriter struct {
|
||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
fn func(urlStr string) error
|
fn func(urlStr string) error
|
||||||
|
@ -546,7 +546,8 @@ func TestVMIntegrationEndToEnd(t *testing.T) {
|
|||||||
|
|
||||||
rex := distroRex.Unwrap()
|
rex := distroRex.Unwrap()
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", deriveBindhost(t)+":0")
|
bindHost := deriveBindhost(t)
|
||||||
|
ln, err := net.Listen("tcp", net.JoinHostPort(bindHost, "0"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't make TCP listener: %v", err)
|
t.Fatalf("can't make TCP listener: %v", err)
|
||||||
}
|
}
|
||||||
@ -555,6 +556,9 @@ func TestVMIntegrationEndToEnd(t *testing.T) {
|
|||||||
|
|
||||||
cs := &testcontrol.Server{}
|
cs := &testcontrol.Server{}
|
||||||
|
|
||||||
|
derpMap := integration.RunDERPAndSTUN(t, t.Logf, bindHost)
|
||||||
|
cs.DERPMap = derpMap
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ipMu sync.Mutex
|
ipMu sync.Mutex
|
||||||
ipMap = map[string]ipMapping{}
|
ipMap = map[string]ipMapping{}
|
||||||
|
Loading…
Reference in New Issue
Block a user