tsnet_test.go 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package tsnet
  4. import (
  5. "bufio"
  6. "bytes"
  7. "context"
  8. "crypto/ecdsa"
  9. "crypto/elliptic"
  10. "crypto/rand"
  11. "crypto/tls"
  12. "crypto/x509"
  13. "crypto/x509/pkix"
  14. "encoding/json"
  15. "encoding/pem"
  16. "errors"
  17. "flag"
  18. "fmt"
  19. "io"
  20. "log"
  21. "math/big"
  22. "net"
  23. "net/http"
  24. "net/http/httptest"
  25. "net/netip"
  26. "os"
  27. "path/filepath"
  28. "reflect"
  29. "runtime"
  30. "slices"
  31. "strings"
  32. "sync"
  33. "sync/atomic"
  34. "testing"
  35. "time"
  36. "github.com/google/go-cmp/cmp"
  37. dto "github.com/prometheus/client_model/go"
  38. "github.com/prometheus/common/expfmt"
  39. "golang.org/x/net/proxy"
  40. "tailscale.com/client/local"
  41. "tailscale.com/cmd/testwrapper/flakytest"
  42. "tailscale.com/internal/client/tailscale"
  43. "tailscale.com/ipn"
  44. "tailscale.com/ipn/ipnlocal"
  45. "tailscale.com/ipn/store/mem"
  46. "tailscale.com/net/netns"
  47. "tailscale.com/tailcfg"
  48. "tailscale.com/tstest"
  49. "tailscale.com/tstest/deptest"
  50. "tailscale.com/tstest/integration"
  51. "tailscale.com/tstest/integration/testcontrol"
  52. "tailscale.com/types/key"
  53. "tailscale.com/types/logger"
  54. "tailscale.com/types/views"
  55. "tailscale.com/util/mak"
  56. "tailscale.com/util/must"
  57. )
  58. // TestListener_Server ensures that the listener type always keeps the Server
  59. // method, which is used by some external applications to identify a tsnet.Listener
  60. // from other net.Listeners, as well as access the underlying Server.
  61. func TestListener_Server(t *testing.T) {
  62. s := &Server{}
  63. ln := listener{s: s}
  64. if ln.Server() != s {
  65. t.Errorf("listener.Server() returned %v, want %v", ln.Server(), s)
  66. }
  67. }
  68. func TestListenerPort(t *testing.T) {
  69. errNone := errors.New("sentinel start error")
  70. tests := []struct {
  71. network string
  72. addr string
  73. wantErr bool
  74. }{
  75. {"tcp", ":80", false},
  76. {"foo", ":80", true},
  77. {"tcp", ":http", false}, // built-in name to Go; doesn't require cgo, /etc/services
  78. {"tcp", ":https", false}, // built-in name to Go; doesn't require cgo, /etc/services
  79. {"tcp", ":gibberishsdlkfj", true},
  80. {"tcp", ":%!d(string=80)", true}, // issue 6201
  81. {"udp", ":80", false},
  82. {"udp", "100.102.104.108:80", false},
  83. {"udp", "not-an-ip:80", true},
  84. {"udp4", ":80", false},
  85. {"udp4", "100.102.104.108:80", false},
  86. {"udp4", "not-an-ip:80", true},
  87. // Verify network type matches IP
  88. {"tcp4", "1.2.3.4:80", false},
  89. {"tcp6", "1.2.3.4:80", true},
  90. {"tcp4", "[12::34]:80", true},
  91. {"tcp6", "[12::34]:80", false},
  92. }
  93. for _, tt := range tests {
  94. s := &Server{}
  95. s.initOnce.Do(func() { s.initErr = errNone })
  96. _, err := s.Listen(tt.network, tt.addr)
  97. gotErr := err != nil && err != errNone
  98. if gotErr != tt.wantErr {
  99. t.Errorf("Listen(%q, %q) error = %v, want %v", tt.network, tt.addr, gotErr, tt.wantErr)
  100. }
  101. }
  102. }
  103. var verboseDERP = flag.Bool("verbose-derp", false, "if set, print DERP and STUN logs")
  104. var verboseNodes = flag.Bool("verbose-nodes", false, "if set, print tsnet.Server logs")
  105. func startControl(t *testing.T) (controlURL string, control *testcontrol.Server) {
  106. // Corp#4520: don't use netns for tests.
  107. netns.SetEnabled(false)
  108. t.Cleanup(func() {
  109. netns.SetEnabled(true)
  110. })
  111. derpLogf := logger.Discard
  112. if *verboseDERP {
  113. derpLogf = t.Logf
  114. }
  115. derpMap := integration.RunDERPAndSTUN(t, derpLogf, "127.0.0.1")
  116. control = &testcontrol.Server{
  117. DERPMap: derpMap,
  118. DNSConfig: &tailcfg.DNSConfig{
  119. Proxied: true,
  120. },
  121. MagicDNSDomain: "tail-scale.ts.net",
  122. Logf: t.Logf,
  123. }
  124. control.HTTPTestServer = httptest.NewUnstartedServer(control)
  125. control.HTTPTestServer.Start()
  126. t.Cleanup(control.HTTPTestServer.Close)
  127. controlURL = control.HTTPTestServer.URL
  128. t.Logf("testcontrol listening on %s", controlURL)
  129. return controlURL, control
  130. }
  131. type testCertIssuer struct {
  132. mu sync.Mutex
  133. certs map[string]ipnlocal.TLSCertKeyPair // keyed by hostname
  134. root *x509.Certificate
  135. rootKey *ecdsa.PrivateKey
  136. }
  137. func newCertIssuer() *testCertIssuer {
  138. rootKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  139. if err != nil {
  140. panic(err)
  141. }
  142. t := &x509.Certificate{
  143. SerialNumber: big.NewInt(1),
  144. Subject: pkix.Name{
  145. CommonName: "root",
  146. },
  147. NotBefore: time.Now(),
  148. NotAfter: time.Now().Add(time.Hour),
  149. IsCA: true,
  150. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  151. KeyUsage: x509.KeyUsageCertSign,
  152. BasicConstraintsValid: true,
  153. }
  154. rootDER, err := x509.CreateCertificate(rand.Reader, t, t, &rootKey.PublicKey, rootKey)
  155. if err != nil {
  156. panic(err)
  157. }
  158. rootCA, err := x509.ParseCertificate(rootDER)
  159. if err != nil {
  160. panic(err)
  161. }
  162. return &testCertIssuer{
  163. root: rootCA,
  164. rootKey: rootKey,
  165. certs: map[string]ipnlocal.TLSCertKeyPair{},
  166. }
  167. }
  168. func (tci *testCertIssuer) getCert(hostname string) (*ipnlocal.TLSCertKeyPair, error) {
  169. tci.mu.Lock()
  170. defer tci.mu.Unlock()
  171. cert, ok := tci.certs[hostname]
  172. if ok {
  173. return &cert, nil
  174. }
  175. certPrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  176. if err != nil {
  177. return nil, err
  178. }
  179. certTmpl := &x509.Certificate{
  180. SerialNumber: big.NewInt(1),
  181. DNSNames: []string{hostname},
  182. NotBefore: time.Now(),
  183. NotAfter: time.Now().Add(time.Hour),
  184. }
  185. certDER, err := x509.CreateCertificate(rand.Reader, certTmpl, tci.root, &certPrivKey.PublicKey, tci.rootKey)
  186. if err != nil {
  187. return nil, err
  188. }
  189. keyDER, err := x509.MarshalPKCS8PrivateKey(certPrivKey)
  190. if err != nil {
  191. return nil, err
  192. }
  193. cert = ipnlocal.TLSCertKeyPair{
  194. CertPEM: pem.EncodeToMemory(&pem.Block{
  195. Type: "CERTIFICATE",
  196. Bytes: certDER,
  197. }),
  198. KeyPEM: pem.EncodeToMemory(&pem.Block{
  199. Type: "PRIVATE KEY",
  200. Bytes: keyDER,
  201. }),
  202. }
  203. tci.certs[hostname] = cert
  204. return &cert, nil
  205. }
  206. func (tci *testCertIssuer) Pool() *x509.CertPool {
  207. p := x509.NewCertPool()
  208. p.AddCert(tci.root)
  209. return p
  210. }
  211. var testCertRoot = newCertIssuer()
  212. func startServer(t *testing.T, ctx context.Context, controlURL, hostname string) (*Server, netip.Addr, key.NodePublic) {
  213. t.Helper()
  214. tmp := filepath.Join(t.TempDir(), hostname)
  215. os.MkdirAll(tmp, 0755)
  216. s := &Server{
  217. Dir: tmp,
  218. ControlURL: controlURL,
  219. Hostname: hostname,
  220. Store: new(mem.Store),
  221. Ephemeral: true,
  222. }
  223. if *verboseNodes {
  224. s.Logf = t.Logf
  225. }
  226. t.Cleanup(func() { s.Close() })
  227. status, err := s.Up(ctx)
  228. if err != nil {
  229. t.Fatal(err)
  230. }
  231. s.lb.ConfigureCertsForTest(testCertRoot.getCert)
  232. return s, status.TailscaleIPs[0], status.Self.PublicKey
  233. }
  234. func TestDialBlocks(t *testing.T) {
  235. tstest.Shard(t)
  236. tstest.ResourceCheck(t)
  237. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  238. defer cancel()
  239. controlURL, _ := startControl(t)
  240. // Make one tsnet that blocks until it's up.
  241. s1, _, _ := startServer(t, ctx, controlURL, "s1")
  242. ln, err := s1.Listen("tcp", ":8080")
  243. if err != nil {
  244. t.Fatal(err)
  245. }
  246. defer ln.Close()
  247. // Then make another tsnet node that will only be woken up
  248. // upon the first dial.
  249. tmp := filepath.Join(t.TempDir(), "s2")
  250. os.MkdirAll(tmp, 0755)
  251. s2 := &Server{
  252. Dir: tmp,
  253. ControlURL: controlURL,
  254. Hostname: "s2",
  255. Store: new(mem.Store),
  256. Ephemeral: true,
  257. }
  258. if *verboseNodes {
  259. s2.Logf = log.Printf
  260. }
  261. t.Cleanup(func() { s2.Close() })
  262. c, err := s2.Dial(ctx, "tcp", "s1:8080")
  263. if err != nil {
  264. t.Fatal(err)
  265. }
  266. defer c.Close()
  267. }
  268. // TestConn tests basic TCP connections between two tsnet Servers, s1 and s2:
  269. //
  270. // - s1, a subnet router, first listens on its TCP :8081.
  271. // - s2 can connect to s1:8081
  272. // - s2 cannot connect to s1:8082 (no listener)
  273. // - s2 can dial through the subnet router functionality (getting a synthetic RST
  274. // that we verify we generated & saw)
  275. func TestConn(t *testing.T) {
  276. tstest.Shard(t)
  277. tstest.ResourceCheck(t)
  278. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  279. defer cancel()
  280. controlURL, c := startControl(t)
  281. s1, s1ip, s1PubKey := startServer(t, ctx, controlURL, "s1")
  282. // Track whether we saw an attempted dial to 192.0.2.1:8081.
  283. var saw192DocNetDial atomic.Bool
  284. s1.RegisterFallbackTCPHandler(func(src, dst netip.AddrPort) (handler func(net.Conn), intercept bool) {
  285. t.Logf("s1: fallback TCP handler called for %v -> %v", src, dst)
  286. if dst.String() == "192.0.2.1:8081" {
  287. saw192DocNetDial.Store(true)
  288. }
  289. return nil, true // nil handler but intercept=true means to send RST
  290. })
  291. lc1 := must.Get(s1.LocalClient())
  292. must.Get(lc1.EditPrefs(ctx, &ipn.MaskedPrefs{
  293. Prefs: ipn.Prefs{
  294. AdvertiseRoutes: []netip.Prefix{netip.MustParsePrefix("192.0.2.0/24")},
  295. },
  296. AdvertiseRoutesSet: true,
  297. }))
  298. c.SetSubnetRoutes(s1PubKey, []netip.Prefix{netip.MustParsePrefix("192.0.2.0/24")})
  299. // Start s2 after s1 is fully set up, including advertising its routes,
  300. // otherwise the test is flaky if the test starts dialing through s2 before
  301. // our test control server has told s2 about s1's routes.
  302. s2, _, _ := startServer(t, ctx, controlURL, "s2")
  303. lc2 := must.Get(s2.LocalClient())
  304. must.Get(lc2.EditPrefs(ctx, &ipn.MaskedPrefs{
  305. Prefs: ipn.Prefs{
  306. RouteAll: true,
  307. },
  308. RouteAllSet: true,
  309. }))
  310. // ping to make sure the connection is up.
  311. res, err := lc2.Ping(ctx, s1ip, tailcfg.PingTSMP)
  312. if err != nil {
  313. t.Fatal(err)
  314. }
  315. t.Logf("ping success: %#+v", res)
  316. // pass some data through TCP.
  317. ln, err := s1.Listen("tcp", ":8081")
  318. if err != nil {
  319. t.Fatal(err)
  320. }
  321. defer ln.Close()
  322. s1Conns := make(chan net.Conn)
  323. go func() {
  324. for {
  325. c, err := ln.Accept()
  326. if err != nil {
  327. if ctx.Err() != nil {
  328. return
  329. }
  330. t.Errorf("s1.Accept: %v", err)
  331. return
  332. }
  333. select {
  334. case s1Conns <- c:
  335. case <-ctx.Done():
  336. c.Close()
  337. }
  338. }
  339. }()
  340. w, err := s2.Dial(ctx, "tcp", fmt.Sprintf("%s:8081", s1ip))
  341. if err != nil {
  342. t.Fatal(err)
  343. }
  344. want := "hello"
  345. if _, err := io.WriteString(w, want); err != nil {
  346. t.Fatal(err)
  347. }
  348. select {
  349. case <-time.After(5 * time.Second):
  350. t.Fatal("timeout waiting for connection")
  351. case r := <-s1Conns:
  352. got := make([]byte, len(want))
  353. _, err := io.ReadAtLeast(r, got, len(got))
  354. r.Close()
  355. if err != nil {
  356. t.Fatal(err)
  357. }
  358. t.Logf("got: %q", got)
  359. if string(got) != want {
  360. t.Errorf("got %q, want %q", got, want)
  361. }
  362. }
  363. // Dial a non-existent port on s1 and expect it to fail.
  364. _, err = s2.Dial(ctx, "tcp", fmt.Sprintf("%s:8082", s1ip)) // some random port
  365. if err == nil {
  366. t.Fatalf("unexpected success; should have seen a connection refused error")
  367. }
  368. t.Logf("got expected failure: %v", err)
  369. // s1 is a subnet router for TEST-NET-1 (192.0.2.0/24). Let's dial to that
  370. // subnet from s2 to ensure a listener without an IP address (i.e. our
  371. // ":8081" listen above) only matches destination IPs corresponding to the
  372. // s1 node's IP addresses, and not to any random IP of a subnet it's routing.
  373. //
  374. // The RegisterFallbackTCPHandler on s1 above handles sending a RST when the
  375. // TCP SYN arrives from s2. But we bound it to 5 seconds lest a regression
  376. // like tailscale/tailscale#17805 recur.
  377. s2dialer := s2.Sys().Dialer.Get()
  378. s2dialer.SetSystemDialerForTest(func(ctx context.Context, netw, addr string) (net.Conn, error) {
  379. t.Logf("s2: unexpected system dial called for %s %s", netw, addr)
  380. return nil, fmt.Errorf("system dialer called unexpectedly for %s %s", netw, addr)
  381. })
  382. docCtx, docCancel := context.WithTimeout(ctx, 5*time.Second)
  383. defer docCancel()
  384. _, err = s2.Dial(docCtx, "tcp", "192.0.2.1:8081")
  385. if err == nil {
  386. t.Fatalf("unexpected success; should have seen a connection refused error")
  387. }
  388. if !saw192DocNetDial.Load() {
  389. t.Errorf("expected s1's fallback TCP handler to have been called for 192.0.2.1:8081")
  390. }
  391. }
  392. func TestLoopbackLocalAPI(t *testing.T) {
  393. flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/8557")
  394. tstest.Shard(t)
  395. tstest.ResourceCheck(t)
  396. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  397. defer cancel()
  398. controlURL, _ := startControl(t)
  399. s1, _, _ := startServer(t, ctx, controlURL, "s1")
  400. addr, proxyCred, localAPICred, err := s1.Loopback()
  401. if err != nil {
  402. t.Fatal(err)
  403. }
  404. if proxyCred == localAPICred {
  405. t.Fatal("proxy password matches local API password, they should be different")
  406. }
  407. url := "http://" + addr + "/localapi/v0/status"
  408. req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
  409. if err != nil {
  410. t.Fatal(err)
  411. }
  412. res, err := http.DefaultClient.Do(req)
  413. if err != nil {
  414. t.Fatal(err)
  415. }
  416. res.Body.Close()
  417. if res.StatusCode != 403 {
  418. t.Errorf("GET %s returned %d, want 403 without Sec- header", url, res.StatusCode)
  419. }
  420. req, err = http.NewRequestWithContext(ctx, "GET", url, nil)
  421. if err != nil {
  422. t.Fatal(err)
  423. }
  424. req.Header.Set("Sec-Tailscale", "localapi")
  425. res, err = http.DefaultClient.Do(req)
  426. if err != nil {
  427. t.Fatal(err)
  428. }
  429. res.Body.Close()
  430. if res.StatusCode != 401 {
  431. t.Errorf("GET %s returned %d, want 401 without basic auth", url, res.StatusCode)
  432. }
  433. req, err = http.NewRequestWithContext(ctx, "GET", url, nil)
  434. if err != nil {
  435. t.Fatal(err)
  436. }
  437. req.SetBasicAuth("", localAPICred)
  438. res, err = http.DefaultClient.Do(req)
  439. if err != nil {
  440. t.Fatal(err)
  441. }
  442. res.Body.Close()
  443. if res.StatusCode != 403 {
  444. t.Errorf("GET %s returned %d, want 403 without Sec- header", url, res.StatusCode)
  445. }
  446. req, err = http.NewRequestWithContext(ctx, "GET", url, nil)
  447. if err != nil {
  448. t.Fatal(err)
  449. }
  450. req.Header.Set("Sec-Tailscale", "localapi")
  451. req.SetBasicAuth("", localAPICred)
  452. res, err = http.DefaultClient.Do(req)
  453. if err != nil {
  454. t.Fatal(err)
  455. }
  456. res.Body.Close()
  457. if res.StatusCode != 200 {
  458. t.Errorf("GET /status returned %d, want 200", res.StatusCode)
  459. }
  460. }
  461. func TestLoopbackSOCKS5(t *testing.T) {
  462. flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/8198")
  463. tstest.Shard(t)
  464. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  465. defer cancel()
  466. controlURL, _ := startControl(t)
  467. s1, s1ip, _ := startServer(t, ctx, controlURL, "s1")
  468. s2, _, _ := startServer(t, ctx, controlURL, "s2")
  469. addr, proxyCred, _, err := s2.Loopback()
  470. if err != nil {
  471. t.Fatal(err)
  472. }
  473. ln, err := s1.Listen("tcp", ":8081")
  474. if err != nil {
  475. t.Fatal(err)
  476. }
  477. defer ln.Close()
  478. auth := &proxy.Auth{User: "tsnet", Password: proxyCred}
  479. socksDialer, err := proxy.SOCKS5("tcp", addr, auth, proxy.Direct)
  480. if err != nil {
  481. t.Fatal(err)
  482. }
  483. w, err := socksDialer.Dial("tcp", fmt.Sprintf("%s:8081", s1ip))
  484. if err != nil {
  485. t.Fatal(err)
  486. }
  487. r, err := ln.Accept()
  488. if err != nil {
  489. t.Fatal(err)
  490. }
  491. want := "hello"
  492. if _, err := io.WriteString(w, want); err != nil {
  493. t.Fatal(err)
  494. }
  495. got := make([]byte, len(want))
  496. if _, err := io.ReadAtLeast(r, got, len(got)); err != nil {
  497. t.Fatal(err)
  498. }
  499. t.Logf("got: %q", got)
  500. if string(got) != want {
  501. t.Errorf("got %q, want %q", got, want)
  502. }
  503. }
  504. func TestTailscaleIPs(t *testing.T) {
  505. tstest.Shard(t)
  506. controlURL, _ := startControl(t)
  507. tmp := t.TempDir()
  508. tmps1 := filepath.Join(tmp, "s1")
  509. os.MkdirAll(tmps1, 0755)
  510. s1 := &Server{
  511. Dir: tmps1,
  512. ControlURL: controlURL,
  513. Hostname: "s1",
  514. Store: new(mem.Store),
  515. Ephemeral: true,
  516. }
  517. defer s1.Close()
  518. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  519. defer cancel()
  520. s1status, err := s1.Up(ctx)
  521. if err != nil {
  522. t.Fatal(err)
  523. }
  524. var upIp4, upIp6 netip.Addr
  525. for _, ip := range s1status.TailscaleIPs {
  526. if ip.Is6() {
  527. upIp6 = ip
  528. }
  529. if ip.Is4() {
  530. upIp4 = ip
  531. }
  532. }
  533. sIp4, sIp6 := s1.TailscaleIPs()
  534. if !(upIp4 == sIp4 && upIp6 == sIp6) {
  535. t.Errorf("s1.TailscaleIPs returned a different result than S1.Up, (%s, %s) != (%s, %s)",
  536. sIp4, upIp4, sIp6, upIp6)
  537. }
  538. }
  539. // TestListenerCleanup is a regression test to verify that s.Close doesn't
  540. // deadlock if a listener is still open.
  541. func TestListenerCleanup(t *testing.T) {
  542. tstest.Shard(t)
  543. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  544. defer cancel()
  545. controlURL, _ := startControl(t)
  546. s1, _, _ := startServer(t, ctx, controlURL, "s1")
  547. ln, err := s1.Listen("tcp", ":8081")
  548. if err != nil {
  549. t.Fatal(err)
  550. }
  551. if err := s1.Close(); err != nil {
  552. t.Fatal(err)
  553. }
  554. if err := ln.Close(); !errors.Is(err, net.ErrClosed) {
  555. t.Fatalf("second ln.Close error: %v, want net.ErrClosed", err)
  556. }
  557. // Verify that handling a connection from gVisor (from a packet arriving)
  558. // after a listener closed doesn't panic (previously: sending on a closed
  559. // channel) or hang.
  560. c := &closeTrackConn{}
  561. ln.(*listener).handle(c)
  562. if !c.closed {
  563. t.Errorf("c.closed = false, want true")
  564. }
  565. }
  566. type closeTrackConn struct {
  567. net.Conn
  568. closed bool
  569. }
  570. func (wc *closeTrackConn) Close() error {
  571. wc.closed = true
  572. return nil
  573. }
  574. // tests https://github.com/tailscale/tailscale/issues/6973 -- that we can start a tsnet server,
  575. // stop it, and restart it, even on Windows.
  576. func TestStartStopStartGetsSameIP(t *testing.T) {
  577. tstest.Shard(t)
  578. controlURL, _ := startControl(t)
  579. tmp := t.TempDir()
  580. tmps1 := filepath.Join(tmp, "s1")
  581. os.MkdirAll(tmps1, 0755)
  582. newServer := func() *Server {
  583. return &Server{
  584. Dir: tmps1,
  585. ControlURL: controlURL,
  586. Hostname: "s1",
  587. Logf: tstest.WhileTestRunningLogger(t),
  588. }
  589. }
  590. s1 := newServer()
  591. defer s1.Close()
  592. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  593. defer cancel()
  594. s1status, err := s1.Up(ctx)
  595. if err != nil {
  596. t.Fatal(err)
  597. }
  598. firstIPs := s1status.TailscaleIPs
  599. t.Logf("IPs: %v", firstIPs)
  600. if err := s1.Close(); err != nil {
  601. t.Fatalf("Close: %v", err)
  602. }
  603. s2 := newServer()
  604. defer s2.Close()
  605. s2status, err := s2.Up(ctx)
  606. if err != nil {
  607. t.Fatalf("second Up: %v", err)
  608. }
  609. secondIPs := s2status.TailscaleIPs
  610. t.Logf("IPs: %v", secondIPs)
  611. if !reflect.DeepEqual(firstIPs, secondIPs) {
  612. t.Fatalf("got %v but later %v", firstIPs, secondIPs)
  613. }
  614. }
  615. func TestFunnel(t *testing.T) {
  616. tstest.Shard(t)
  617. ctx, dialCancel := context.WithTimeout(context.Background(), 30*time.Second)
  618. defer dialCancel()
  619. controlURL, _ := startControl(t)
  620. s1, _, _ := startServer(t, ctx, controlURL, "s1")
  621. s2, _, _ := startServer(t, ctx, controlURL, "s2")
  622. ln := must.Get(s1.ListenFunnel("tcp", ":443"))
  623. defer ln.Close()
  624. wantSrcAddrPort := netip.MustParseAddrPort("127.0.0.1:1234")
  625. wantTarget := ipn.HostPort("s1.tail-scale.ts.net:443")
  626. srv := &http.Server{
  627. ConnContext: func(ctx context.Context, c net.Conn) context.Context {
  628. tc, ok := c.(*tls.Conn)
  629. if !ok {
  630. t.Errorf("ConnContext called with non-TLS conn: %T", c)
  631. }
  632. if fc, ok := tc.NetConn().(*ipn.FunnelConn); !ok {
  633. t.Errorf("ConnContext called with non-FunnelConn: %T", c)
  634. } else if fc.Src != wantSrcAddrPort {
  635. t.Errorf("ConnContext called with wrong SrcAddrPort; got %v, want %v", fc.Src, wantSrcAddrPort)
  636. } else if fc.Target != wantTarget {
  637. t.Errorf("ConnContext called with wrong Target; got %q, want %q", fc.Target, wantTarget)
  638. }
  639. return ctx
  640. },
  641. Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  642. fmt.Fprintf(w, "hello")
  643. }),
  644. }
  645. go srv.Serve(ln)
  646. c := &http.Client{
  647. Transport: &http.Transport{
  648. DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
  649. return dialIngressConn(s2, s1, addr)
  650. },
  651. TLSClientConfig: &tls.Config{
  652. RootCAs: testCertRoot.Pool(),
  653. },
  654. },
  655. }
  656. resp, err := c.Get("https://s1.tail-scale.ts.net:443")
  657. if err != nil {
  658. t.Fatal(err)
  659. }
  660. defer resp.Body.Close()
  661. if resp.StatusCode != 200 {
  662. t.Errorf("unexpected status code: %v", resp.StatusCode)
  663. return
  664. }
  665. body, err := io.ReadAll(resp.Body)
  666. if err != nil {
  667. t.Fatal(err)
  668. }
  669. if string(body) != "hello" {
  670. t.Errorf("unexpected body: %q", body)
  671. }
  672. }
  673. // TestFunnelClose ensures that the listener returned by ListenFunnel cleans up
  674. // after itself when closed. Specifically, changes made to the serve config
  675. // should be cleared.
  676. func TestFunnelClose(t *testing.T) {
  677. marshalServeConfig := func(t *testing.T, sc ipn.ServeConfigView) string {
  678. t.Helper()
  679. return string(must.Get(json.MarshalIndent(sc, "", "\t")))
  680. }
  681. t.Run("simple", func(t *testing.T) {
  682. controlURL, _ := startControl(t)
  683. s, _, _ := startServer(t, t.Context(), controlURL, "s")
  684. before := s.lb.ServeConfig()
  685. ln := must.Get(s.ListenFunnel("tcp", ":443"))
  686. ln.Close()
  687. after := s.lb.ServeConfig()
  688. if diff := cmp.Diff(marshalServeConfig(t, after), marshalServeConfig(t, before)); diff != "" {
  689. t.Fatalf("expected serve config to be unchanged after close (-got, +want):\n%s", diff)
  690. }
  691. })
  692. // Closing the listener shouldn't clear out config that predates it.
  693. t.Run("no_clobbering", func(t *testing.T) {
  694. controlURL, _ := startControl(t)
  695. s, _, _ := startServer(t, t.Context(), controlURL, "s")
  696. // To obtain config the listener might want to clobber, we:
  697. // - run a listener
  698. // - grab the config
  699. // - close the listener (clearing config)
  700. ln := must.Get(s.ListenFunnel("tcp", ":443"))
  701. before := s.lb.ServeConfig()
  702. ln.Close()
  703. // Now we manually write the config to the local backend (it should have
  704. // been cleared), run the listener again, and close it again.
  705. must.Do(s.lb.SetServeConfig(before.AsStruct(), ""))
  706. ln = must.Get(s.ListenFunnel("tcp", ":443"))
  707. ln.Close()
  708. // The config should not have been cleared this time since it predated
  709. // the most recent run.
  710. after := s.lb.ServeConfig()
  711. if diff := cmp.Diff(marshalServeConfig(t, after), marshalServeConfig(t, before)); diff != "" {
  712. t.Fatalf("expected existing config to remain intact (-got, +want):\n%s", diff)
  713. }
  714. })
  715. // Closing one listener shouldn't affect config for another listener.
  716. t.Run("two_listeners", func(t *testing.T) {
  717. controlURL, _ := startControl(t)
  718. s, _, _ := startServer(t, t.Context(), controlURL, "s1")
  719. // Start a listener on 443.
  720. ln1 := must.Get(s.ListenFunnel("tcp", ":443"))
  721. defer ln1.Close()
  722. // Save the serve config for this original listener.
  723. before := s.lb.ServeConfig()
  724. // Now start and close a new listener on a different port.
  725. ln2 := must.Get(s.ListenFunnel("tcp", ":8080"))
  726. ln2.Close()
  727. // The serve config for the original listener should be intact.
  728. after := s.lb.ServeConfig()
  729. if diff := cmp.Diff(marshalServeConfig(t, after), marshalServeConfig(t, before)); diff != "" {
  730. t.Fatalf("expected existing config to remain intact (-got, +want):\n%s", diff)
  731. }
  732. })
  733. // It should be possible to close a listener and free system resources even
  734. // when the Server has been closed (or the listener should be automatically
  735. // closed).
  736. t.Run("after_server_close", func(t *testing.T) {
  737. controlURL, _ := startControl(t)
  738. s, _, _ := startServer(t, t.Context(), controlURL, "s")
  739. ln := must.Get(s.ListenFunnel("tcp", ":443"))
  740. // Close the server, then close the listener.
  741. must.Do(s.Close())
  742. // We don't care whether we get an error from the listener closing.
  743. ln.Close()
  744. // The listener should immediately return an error indicating closure.
  745. _, err := ln.Accept()
  746. // Looking for a string in the error sucks, but it's supposed to stay
  747. // consistent:
  748. // https://github.com/golang/go/blob/108b333d510c1f60877ac917375d7931791acfe6/src/internal/poll/fd.go#L20-L24
  749. if err == nil || !strings.Contains(err.Error(), "use of closed network connection") {
  750. t.Fatal("expected listener to be closed, got:", err)
  751. }
  752. })
  753. }
  754. func TestListenService(t *testing.T) {
  755. // First test an error case which doesn't require all of the fancy setup.
  756. t.Run("untagged_node_error", func(t *testing.T) {
  757. ctx := t.Context()
  758. controlURL, _ := startControl(t)
  759. serviceHost, _, _ := startServer(t, ctx, controlURL, "service-host")
  760. ln, err := serviceHost.ListenService("svc:foo", ServiceModeTCP{Port: 8080})
  761. if ln != nil {
  762. ln.Close()
  763. }
  764. if !errors.Is(err, ErrUntaggedServiceHost) {
  765. t.Fatalf("expected %v, got %v", ErrUntaggedServiceHost, err)
  766. }
  767. })
  768. // Now on to the fancier tests.
  769. type dialFn func(context.Context, string, string) (net.Conn, error)
  770. // TCP helpers
  771. acceptAndEcho := func(t *testing.T, ln net.Listener) {
  772. t.Helper()
  773. conn, err := ln.Accept()
  774. if err != nil {
  775. t.Error("accept error:", err)
  776. return
  777. }
  778. defer conn.Close()
  779. if _, err := io.Copy(conn, conn); err != nil {
  780. t.Error("copy error:", err)
  781. }
  782. }
  783. assertEcho := func(t *testing.T, conn net.Conn) {
  784. t.Helper()
  785. msg := "echo"
  786. buf := make([]byte, 1024)
  787. if _, err := conn.Write([]byte(msg)); err != nil {
  788. t.Fatal("write failed:", err)
  789. }
  790. n, err := conn.Read(buf)
  791. if err != nil {
  792. t.Fatal("read failed:", err)
  793. }
  794. got := string(buf[:n])
  795. if got != msg {
  796. t.Fatalf("unexpected response:\n\twant: %s\n\tgot: %s", msg, got)
  797. }
  798. }
  799. // HTTP helpers
  800. checkAndEcho := func(t *testing.T, ln net.Listener, check func(r *http.Request)) {
  801. t.Helper()
  802. if check == nil {
  803. check = func(*http.Request) {}
  804. }
  805. http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  806. defer r.Body.Close()
  807. check(r)
  808. if _, err := io.Copy(w, r.Body); err != nil {
  809. t.Error("copy error:", err)
  810. w.WriteHeader(http.StatusInternalServerError)
  811. }
  812. }))
  813. }
  814. assertEchoHTTP := func(t *testing.T, hostname, path string, dial dialFn) {
  815. t.Helper()
  816. c := http.Client{
  817. Transport: &http.Transport{
  818. DialContext: dial,
  819. },
  820. }
  821. msg := "echo"
  822. resp, err := c.Post("http://"+hostname+path, "text/plain", strings.NewReader(msg))
  823. if err != nil {
  824. t.Fatal("posting request:", err)
  825. }
  826. defer resp.Body.Close()
  827. b, err := io.ReadAll(resp.Body)
  828. if err != nil {
  829. t.Fatal("reading body:", err)
  830. }
  831. got := string(b)
  832. if got != msg {
  833. t.Fatalf("unexpected response:\n\twant: %s\n\tgot: %s", msg, got)
  834. }
  835. }
  836. tests := []struct {
  837. name string
  838. // modes is used as input to [Server.ListenService].
  839. //
  840. // If this slice has multiple modes, then ListenService will be invoked
  841. // multiple times. The number of listeners provided to the run function
  842. // (below) will always match the number of elements in this slice.
  843. modes []ServiceMode
  844. extraSetup func(t *testing.T, control *testcontrol.Server)
  845. // run executes the test. This function does not need to close any of
  846. // the input resources, but it should close any new resources it opens.
  847. // listeners[i] corresponds to inputs[i].
  848. run func(t *testing.T, listeners []*ServiceListener, peer *Server)
  849. }{
  850. {
  851. name: "basic_TCP",
  852. modes: []ServiceMode{
  853. ServiceModeTCP{Port: 99},
  854. },
  855. run: func(t *testing.T, listeners []*ServiceListener, peer *Server) {
  856. go acceptAndEcho(t, listeners[0])
  857. target := fmt.Sprintf("%s:%d", listeners[0].FQDN, 99)
  858. conn := must.Get(peer.Dial(t.Context(), "tcp", target))
  859. defer conn.Close()
  860. assertEcho(t, conn)
  861. },
  862. },
  863. {
  864. name: "TLS_terminated_TCP",
  865. modes: []ServiceMode{
  866. ServiceModeTCP{
  867. TerminateTLS: true,
  868. Port: 443,
  869. },
  870. },
  871. run: func(t *testing.T, listeners []*ServiceListener, peer *Server) {
  872. go acceptAndEcho(t, listeners[0])
  873. target := fmt.Sprintf("%s:%d", listeners[0].FQDN, 443)
  874. conn := must.Get(peer.Dial(t.Context(), "tcp", target))
  875. defer conn.Close()
  876. assertEcho(t, tls.Client(conn, &tls.Config{
  877. ServerName: listeners[0].FQDN,
  878. RootCAs: testCertRoot.Pool(),
  879. }))
  880. },
  881. },
  882. {
  883. name: "identity_headers",
  884. modes: []ServiceMode{
  885. ServiceModeHTTP{
  886. Port: 80,
  887. },
  888. },
  889. run: func(t *testing.T, listeners []*ServiceListener, peer *Server) {
  890. expectHeader := "Tailscale-User-Name"
  891. go checkAndEcho(t, listeners[0], func(r *http.Request) {
  892. if _, ok := r.Header[expectHeader]; !ok {
  893. t.Error("did not see expected header:", expectHeader)
  894. }
  895. })
  896. assertEchoHTTP(t, listeners[0].FQDN, "", peer.Dial)
  897. },
  898. },
  899. {
  900. name: "identity_headers_TLS",
  901. modes: []ServiceMode{
  902. ServiceModeHTTP{
  903. HTTPS: true,
  904. Port: 80,
  905. },
  906. },
  907. run: func(t *testing.T, listeners []*ServiceListener, peer *Server) {
  908. expectHeader := "Tailscale-User-Name"
  909. go checkAndEcho(t, listeners[0], func(r *http.Request) {
  910. if _, ok := r.Header[expectHeader]; !ok {
  911. t.Error("did not see expected header:", expectHeader)
  912. }
  913. })
  914. dial := func(ctx context.Context, network, addr string) (net.Conn, error) {
  915. tcpConn, err := peer.Dial(ctx, network, addr)
  916. if err != nil {
  917. return nil, err
  918. }
  919. return tls.Client(tcpConn, &tls.Config{
  920. ServerName: listeners[0].FQDN,
  921. RootCAs: testCertRoot.Pool(),
  922. }), nil
  923. }
  924. assertEchoHTTP(t, listeners[0].FQDN, "", dial)
  925. },
  926. },
  927. {
  928. name: "app_capabilities",
  929. modes: []ServiceMode{
  930. ServiceModeHTTP{
  931. Port: 80,
  932. AcceptAppCaps: map[string][]string{
  933. "/": {"example.com/cap/all-paths"},
  934. "/foo": {"example.com/cap/all-paths", "example.com/cap/foo"},
  935. },
  936. },
  937. },
  938. extraSetup: func(t *testing.T, control *testcontrol.Server) {
  939. control.SetGlobalAppCaps(tailcfg.PeerCapMap{
  940. "example.com/cap/all-paths": []tailcfg.RawMessage{`true`},
  941. "example.com/cap/foo": []tailcfg.RawMessage{`true`},
  942. })
  943. },
  944. run: func(t *testing.T, listeners []*ServiceListener, peer *Server) {
  945. allPathsCap := "example.com/cap/all-paths"
  946. fooCap := "example.com/cap/foo"
  947. checkCaps := func(r *http.Request) {
  948. rawCaps, ok := r.Header["Tailscale-App-Capabilities"]
  949. if !ok {
  950. t.Error("no app capabilities header")
  951. return
  952. }
  953. if len(rawCaps) != 1 {
  954. t.Error("expected one app capabilities header value, got", len(rawCaps))
  955. return
  956. }
  957. var caps map[string][]any
  958. if err := json.Unmarshal([]byte(rawCaps[0]), &caps); err != nil {
  959. t.Error("error unmarshaling app caps:", err)
  960. return
  961. }
  962. if _, ok := caps[allPathsCap]; !ok {
  963. t.Errorf("got app caps, but %v is not present; saw:\n%v", allPathsCap, caps)
  964. }
  965. if strings.HasPrefix(r.URL.Path, "/foo") {
  966. if _, ok := caps[fooCap]; !ok {
  967. t.Errorf("%v should be present for /foo request; saw:\n%v", fooCap, caps)
  968. }
  969. } else {
  970. if _, ok := caps[fooCap]; ok {
  971. t.Errorf("%v should not be present for non-/foo request; saw:\n%v", fooCap, caps)
  972. }
  973. }
  974. }
  975. go checkAndEcho(t, listeners[0], checkCaps)
  976. assertEchoHTTP(t, listeners[0].FQDN, "", peer.Dial)
  977. assertEchoHTTP(t, listeners[0].FQDN, "/foo", peer.Dial)
  978. assertEchoHTTP(t, listeners[0].FQDN, "/foo/bar", peer.Dial)
  979. },
  980. },
  981. {
  982. name: "multiple_ports",
  983. modes: []ServiceMode{
  984. ServiceModeTCP{
  985. Port: 99,
  986. },
  987. ServiceModeHTTP{
  988. Port: 80,
  989. },
  990. },
  991. run: func(t *testing.T, listeners []*ServiceListener, peer *Server) {
  992. go acceptAndEcho(t, listeners[0])
  993. target := fmt.Sprintf("%s:%d", listeners[0].FQDN, 99)
  994. conn := must.Get(peer.Dial(t.Context(), "tcp", target))
  995. defer conn.Close()
  996. assertEcho(t, conn)
  997. go checkAndEcho(t, listeners[1], nil)
  998. assertEchoHTTP(t, listeners[1].FQDN, "", peer.Dial)
  999. },
  1000. },
  1001. }
  1002. for _, tt := range tests {
  1003. // Overview:
  1004. // - start test control
  1005. // - start 2 tsnet nodes:
  1006. // one to act as Service host and a second to act as a peer client
  1007. // - configure necessary state on control mock
  1008. // - start a Service listener from the host
  1009. // - call tt.run with our test bed
  1010. //
  1011. // This ends up also testing the Service forwarding logic in
  1012. // LocalBackend, but that's useful too.
  1013. t.Run(tt.name, func(t *testing.T) {
  1014. ctx := t.Context()
  1015. controlURL, control := startControl(t)
  1016. serviceHost, _, _ := startServer(t, ctx, controlURL, "service-host")
  1017. serviceClient, _, _ := startServer(t, ctx, controlURL, "service-client")
  1018. const serviceName = tailcfg.ServiceName("svc:foo")
  1019. const serviceVIP = "100.11.22.33"
  1020. // == Set up necessary state in our mock ==
  1021. // The Service host must have the 'service-host' capability, which
  1022. // is a mapping from the Service name to the Service VIP.
  1023. var serviceHostCaps map[tailcfg.ServiceName]views.Slice[netip.Addr]
  1024. mak.Set(&serviceHostCaps, serviceName, views.SliceOf([]netip.Addr{netip.MustParseAddr(serviceVIP)}))
  1025. j := must.Get(json.Marshal(serviceHostCaps))
  1026. cm := serviceHost.lb.NetMap().SelfNode.CapMap().AsMap()
  1027. mak.Set(&cm, tailcfg.NodeAttrServiceHost, []tailcfg.RawMessage{tailcfg.RawMessage(j)})
  1028. control.SetNodeCapMap(serviceHost.lb.NodeKey(), cm)
  1029. // The Service host must be allowed to advertise the Service VIP.
  1030. control.SetSubnetRoutes(serviceHost.lb.NodeKey(), []netip.Prefix{
  1031. netip.MustParsePrefix(serviceVIP + `/32`),
  1032. })
  1033. // The Service host must be a tagged node (any tag will do).
  1034. serviceHostNode := control.Node(serviceHost.lb.NodeKey())
  1035. serviceHostNode.Tags = append(serviceHostNode.Tags, "some-tag")
  1036. control.UpdateNode(serviceHostNode)
  1037. // The service client must accept routes advertised by other nodes
  1038. // (RouteAll is equivalent to --accept-routes).
  1039. must.Get(serviceClient.localClient.EditPrefs(ctx, &ipn.MaskedPrefs{
  1040. RouteAllSet: true,
  1041. Prefs: ipn.Prefs{
  1042. RouteAll: true,
  1043. },
  1044. }))
  1045. // Set up DNS for our Service.
  1046. control.AddDNSRecords(tailcfg.DNSRecord{
  1047. Name: serviceName.WithoutPrefix() + "." + control.MagicDNSDomain,
  1048. Value: serviceVIP,
  1049. })
  1050. if tt.extraSetup != nil {
  1051. tt.extraSetup(t, control)
  1052. }
  1053. // Force netmap updates to avoid race conditions. The nodes need to
  1054. // see our control updates before we can start the test.
  1055. must.Do(control.ForceNetmapUpdate(ctx, serviceHost.lb.NodeKey()))
  1056. must.Do(control.ForceNetmapUpdate(ctx, serviceClient.lb.NodeKey()))
  1057. netmapUpToDate := func(s *Server) bool {
  1058. nm := s.lb.NetMap()
  1059. return slices.ContainsFunc(nm.DNS.ExtraRecords, func(r tailcfg.DNSRecord) bool {
  1060. return r.Value == serviceVIP
  1061. })
  1062. }
  1063. for !netmapUpToDate(serviceClient) {
  1064. time.Sleep(10 * time.Millisecond)
  1065. }
  1066. for !netmapUpToDate(serviceHost) {
  1067. time.Sleep(10 * time.Millisecond)
  1068. }
  1069. // == Done setting up mock state ==
  1070. // Start the Service listeners.
  1071. listeners := make([]*ServiceListener, 0, len(tt.modes))
  1072. for _, input := range tt.modes {
  1073. ln := must.Get(serviceHost.ListenService(serviceName.String(), input))
  1074. defer ln.Close()
  1075. listeners = append(listeners, ln)
  1076. }
  1077. tt.run(t, listeners, serviceClient)
  1078. })
  1079. }
  1080. }
  1081. func TestListenerClose(t *testing.T) {
  1082. tstest.Shard(t)
  1083. ctx := context.Background()
  1084. controlURL, _ := startControl(t)
  1085. s1, _, _ := startServer(t, ctx, controlURL, "s1")
  1086. ln, err := s1.Listen("tcp", ":8080")
  1087. if err != nil {
  1088. t.Fatal(err)
  1089. }
  1090. errc := make(chan error, 1)
  1091. go func() {
  1092. c, err := ln.Accept()
  1093. if c != nil {
  1094. c.Close()
  1095. }
  1096. errc <- err
  1097. }()
  1098. ln.Close()
  1099. select {
  1100. case err := <-errc:
  1101. if !errors.Is(err, net.ErrClosed) {
  1102. t.Errorf("unexpected error: %v", err)
  1103. }
  1104. case <-time.After(10 * time.Second):
  1105. t.Fatal("timeout waiting for Accept to return")
  1106. }
  1107. }
  1108. func dialIngressConn(from, to *Server, target string) (net.Conn, error) {
  1109. toLC := must.Get(to.LocalClient())
  1110. toStatus := must.Get(toLC.StatusWithoutPeers(context.Background()))
  1111. peer6 := toStatus.Self.PeerAPIURL[1] // IPv6
  1112. toPeerAPI, ok := strings.CutPrefix(peer6, "http://")
  1113. if !ok {
  1114. return nil, fmt.Errorf("unexpected PeerAPIURL %q", peer6)
  1115. }
  1116. dialCtx, dialCancel := context.WithTimeout(context.Background(), 30*time.Second)
  1117. outConn, err := from.Dial(dialCtx, "tcp", toPeerAPI)
  1118. dialCancel()
  1119. if err != nil {
  1120. return nil, err
  1121. }
  1122. req, err := http.NewRequest("POST", "/v0/ingress", nil)
  1123. if err != nil {
  1124. return nil, err
  1125. }
  1126. req.Host = toPeerAPI
  1127. req.Header.Set("Tailscale-Ingress-Src", "127.0.0.1:1234")
  1128. req.Header.Set("Tailscale-Ingress-Target", target)
  1129. if err := req.Write(outConn); err != nil {
  1130. return nil, err
  1131. }
  1132. br := bufio.NewReader(outConn)
  1133. res, err := http.ReadResponse(br, req)
  1134. if err != nil {
  1135. return nil, err
  1136. }
  1137. defer res.Body.Close() // just to appease vet
  1138. if res.StatusCode != 101 {
  1139. return nil, fmt.Errorf("unexpected status code: %v", res.StatusCode)
  1140. }
  1141. return &bufferedConn{outConn, br}, nil
  1142. }
  1143. type bufferedConn struct {
  1144. net.Conn
  1145. reader *bufio.Reader
  1146. }
  1147. func (c *bufferedConn) Read(b []byte) (int, error) {
  1148. return c.reader.Read(b)
  1149. }
  1150. func TestFallbackTCPHandler(t *testing.T) {
  1151. tstest.Shard(t)
  1152. tstest.ResourceCheck(t)
  1153. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  1154. defer cancel()
  1155. controlURL, _ := startControl(t)
  1156. s1, s1ip, _ := startServer(t, ctx, controlURL, "s1")
  1157. s2, _, _ := startServer(t, ctx, controlURL, "s2")
  1158. lc2, err := s2.LocalClient()
  1159. if err != nil {
  1160. t.Fatal(err)
  1161. }
  1162. // ping to make sure the connection is up.
  1163. res, err := lc2.Ping(ctx, s1ip, tailcfg.PingICMP)
  1164. if err != nil {
  1165. t.Fatal(err)
  1166. }
  1167. t.Logf("ping success: %#+v", res)
  1168. var s1TcpConnCount atomic.Int32
  1169. deregister := s1.RegisterFallbackTCPHandler(func(src, dst netip.AddrPort) (handler func(net.Conn), intercept bool) {
  1170. s1TcpConnCount.Add(1)
  1171. return nil, false
  1172. })
  1173. if _, err := s2.Dial(ctx, "tcp", fmt.Sprintf("%s:8081", s1ip)); err == nil {
  1174. t.Fatal("Expected dial error because fallback handler did not intercept")
  1175. }
  1176. if got := s1TcpConnCount.Load(); got != 1 {
  1177. t.Errorf("s1TcpConnCount = %d, want %d", got, 1)
  1178. }
  1179. deregister()
  1180. if _, err := s2.Dial(ctx, "tcp", fmt.Sprintf("%s:8081", s1ip)); err == nil {
  1181. t.Fatal("Expected dial error because nothing would intercept")
  1182. }
  1183. if got := s1TcpConnCount.Load(); got != 1 {
  1184. t.Errorf("s1TcpConnCount = %d, want %d", got, 1)
  1185. }
  1186. }
  1187. func TestCapturePcap(t *testing.T) {
  1188. tstest.Shard(t)
  1189. const timeLimit = 120
  1190. ctx, cancel := context.WithTimeout(context.Background(), timeLimit*time.Second)
  1191. defer cancel()
  1192. dir := t.TempDir()
  1193. s1Pcap := filepath.Join(dir, "s1.pcap")
  1194. s2Pcap := filepath.Join(dir, "s2.pcap")
  1195. controlURL, _ := startControl(t)
  1196. s1, s1ip, _ := startServer(t, ctx, controlURL, "s1")
  1197. s2, _, _ := startServer(t, ctx, controlURL, "s2")
  1198. s1.CapturePcap(ctx, s1Pcap)
  1199. s2.CapturePcap(ctx, s2Pcap)
  1200. lc2, err := s2.LocalClient()
  1201. if err != nil {
  1202. t.Fatal(err)
  1203. }
  1204. // send a packet which both nodes will capture
  1205. res, err := lc2.Ping(ctx, s1ip, tailcfg.PingICMP)
  1206. if err != nil {
  1207. t.Fatal(err)
  1208. }
  1209. t.Logf("ping success: %#+v", res)
  1210. fileSize := func(name string) int64 {
  1211. fi, err := os.Stat(name)
  1212. if err != nil {
  1213. return 0
  1214. }
  1215. return fi.Size()
  1216. }
  1217. const pcapHeaderSize = 24
  1218. // there is a lag before the io.Copy writes a packet to the pcap files
  1219. for range timeLimit * 10 {
  1220. time.Sleep(100 * time.Millisecond)
  1221. if (fileSize(s1Pcap) > pcapHeaderSize) && (fileSize(s2Pcap) > pcapHeaderSize) {
  1222. break
  1223. }
  1224. }
  1225. if got := fileSize(s1Pcap); got <= pcapHeaderSize {
  1226. t.Errorf("s1 pcap file size = %d, want > pcapHeaderSize(%d)", got, pcapHeaderSize)
  1227. }
  1228. if got := fileSize(s2Pcap); got <= pcapHeaderSize {
  1229. t.Errorf("s2 pcap file size = %d, want > pcapHeaderSize(%d)", got, pcapHeaderSize)
  1230. }
  1231. }
  1232. func TestUDPConn(t *testing.T) {
  1233. tstest.Shard(t)
  1234. tstest.ResourceCheck(t)
  1235. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  1236. defer cancel()
  1237. controlURL, _ := startControl(t)
  1238. s1, s1ip, _ := startServer(t, ctx, controlURL, "s1")
  1239. s2, s2ip, _ := startServer(t, ctx, controlURL, "s2")
  1240. lc2, err := s2.LocalClient()
  1241. if err != nil {
  1242. t.Fatal(err)
  1243. }
  1244. // ping to make sure the connection is up.
  1245. res, err := lc2.Ping(ctx, s1ip, tailcfg.PingICMP)
  1246. if err != nil {
  1247. t.Fatal(err)
  1248. }
  1249. t.Logf("ping success: %#+v", res)
  1250. pc := must.Get(s1.ListenPacket("udp", fmt.Sprintf("%s:8081", s1ip)))
  1251. defer pc.Close()
  1252. // Dial to s1 from s2
  1253. w, err := s2.Dial(ctx, "udp", fmt.Sprintf("%s:8081", s1ip))
  1254. if err != nil {
  1255. t.Fatal(err)
  1256. }
  1257. defer w.Close()
  1258. // Send a packet from s2 to s1
  1259. want := "hello"
  1260. if _, err := io.WriteString(w, want); err != nil {
  1261. t.Fatal(err)
  1262. }
  1263. // Receive the packet on s1
  1264. got := make([]byte, 1024)
  1265. n, from, err := pc.ReadFrom(got)
  1266. if err != nil {
  1267. t.Fatal(err)
  1268. }
  1269. got = got[:n]
  1270. t.Logf("got: %q", got)
  1271. if string(got) != want {
  1272. t.Errorf("got %q, want %q", got, want)
  1273. }
  1274. if from.(*net.UDPAddr).AddrPort().Addr() != s2ip {
  1275. t.Errorf("got from %v, want %v", from, s2ip)
  1276. }
  1277. // Write a response back to s2
  1278. if _, err := pc.WriteTo([]byte("world"), from); err != nil {
  1279. t.Fatal(err)
  1280. }
  1281. // Receive the response on s2
  1282. got = make([]byte, 1024)
  1283. n, err = w.Read(got)
  1284. if err != nil {
  1285. t.Fatal(err)
  1286. }
  1287. got = got[:n]
  1288. t.Logf("got: %q", got)
  1289. if string(got) != "world" {
  1290. t.Errorf("got %q, want world", got)
  1291. }
  1292. }
  1293. func parseMetrics(m []byte) (map[string]float64, error) {
  1294. metrics := make(map[string]float64)
  1295. var parser expfmt.TextParser
  1296. mf, err := parser.TextToMetricFamilies(bytes.NewReader(m))
  1297. if err != nil {
  1298. return nil, err
  1299. }
  1300. for _, f := range mf {
  1301. for _, ff := range f.Metric {
  1302. val := float64(0)
  1303. switch f.GetType() {
  1304. case dto.MetricType_COUNTER:
  1305. val = ff.GetCounter().GetValue()
  1306. case dto.MetricType_GAUGE:
  1307. val = ff.GetGauge().GetValue()
  1308. }
  1309. metrics[f.GetName()+promMetricLabelsStr(ff.GetLabel())] = val
  1310. }
  1311. }
  1312. return metrics, nil
  1313. }
  1314. func promMetricLabelsStr(labels []*dto.LabelPair) string {
  1315. if len(labels) == 0 {
  1316. return ""
  1317. }
  1318. var b strings.Builder
  1319. b.WriteString("{")
  1320. for i, lb := range labels {
  1321. if i > 0 {
  1322. b.WriteString(",")
  1323. }
  1324. b.WriteString(fmt.Sprintf("%s=%q", lb.GetName(), lb.GetValue()))
  1325. }
  1326. b.WriteString("}")
  1327. return b.String()
  1328. }
  1329. // sendData sends a given amount of bytes from s1 to s2.
  1330. func sendData(logf func(format string, args ...any), ctx context.Context, bytesCount int, s1, s2 *Server, s1ip, s2ip netip.Addr) error {
  1331. lb := must.Get(s1.Listen("tcp", fmt.Sprintf("%s:8081", s1ip)))
  1332. defer lb.Close()
  1333. // Dial to s1 from s2
  1334. w, err := s2.Dial(ctx, "tcp", fmt.Sprintf("%s:8081", s1ip))
  1335. if err != nil {
  1336. return err
  1337. }
  1338. defer w.Close()
  1339. stopReceive := make(chan struct{})
  1340. defer close(stopReceive)
  1341. allReceived := make(chan error)
  1342. defer close(allReceived)
  1343. go func() {
  1344. conn, err := lb.Accept()
  1345. if err != nil {
  1346. allReceived <- err
  1347. return
  1348. }
  1349. conn.SetWriteDeadline(time.Now().Add(30 * time.Second))
  1350. total := 0
  1351. recvStart := time.Now()
  1352. for {
  1353. got := make([]byte, bytesCount)
  1354. n, err := conn.Read(got)
  1355. if err != nil {
  1356. allReceived <- fmt.Errorf("failed reading packet, %s", err)
  1357. return
  1358. }
  1359. got = got[:n]
  1360. select {
  1361. case <-stopReceive:
  1362. return
  1363. default:
  1364. }
  1365. total += n
  1366. logf("received %d/%d bytes, %.2f %%", total, bytesCount, (float64(total) / (float64(bytesCount)) * 100))
  1367. // Validate the received bytes to be the same as the sent bytes.
  1368. for _, b := range string(got) {
  1369. if b != 'A' {
  1370. allReceived <- fmt.Errorf("received unexpected byte: %c", b)
  1371. return
  1372. }
  1373. }
  1374. if total == bytesCount {
  1375. break
  1376. }
  1377. }
  1378. logf("all received, took: %s", time.Since(recvStart).String())
  1379. allReceived <- nil
  1380. }()
  1381. sendStart := time.Now()
  1382. w.SetWriteDeadline(time.Now().Add(30 * time.Second))
  1383. if _, err := w.Write(bytes.Repeat([]byte("A"), bytesCount)); err != nil {
  1384. stopReceive <- struct{}{}
  1385. return err
  1386. }
  1387. logf("all sent (%s), waiting for all packets (%d) to be received", time.Since(sendStart).String(), bytesCount)
  1388. err, _ = <-allReceived
  1389. if err != nil {
  1390. return err
  1391. }
  1392. return nil
  1393. }
  1394. func TestUserMetricsByteCounters(t *testing.T) {
  1395. tstest.Shard(t)
  1396. ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
  1397. defer cancel()
  1398. controlURL, _ := startControl(t)
  1399. s1, s1ip, _ := startServer(t, ctx, controlURL, "s1")
  1400. defer s1.Close()
  1401. s2, s2ip, _ := startServer(t, ctx, controlURL, "s2")
  1402. defer s2.Close()
  1403. lc1, err := s1.LocalClient()
  1404. if err != nil {
  1405. t.Fatal(err)
  1406. }
  1407. lc2, err := s2.LocalClient()
  1408. if err != nil {
  1409. t.Fatal(err)
  1410. }
  1411. // Force an update to the netmap to ensure that the metrics are up-to-date.
  1412. s1.lb.DebugForceNetmapUpdate()
  1413. s2.lb.DebugForceNetmapUpdate()
  1414. // Wait for both nodes to have a peer in their netmap.
  1415. waitForCondition(t, "waiting for netmaps to contain peer", 90*time.Second, func() bool {
  1416. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  1417. defer cancel()
  1418. status1, err := lc1.Status(ctx)
  1419. if err != nil {
  1420. t.Logf("getting status: %s", err)
  1421. return false
  1422. }
  1423. status2, err := lc2.Status(ctx)
  1424. if err != nil {
  1425. t.Logf("getting status: %s", err)
  1426. return false
  1427. }
  1428. return len(status1.Peers()) > 0 && len(status2.Peers()) > 0
  1429. })
  1430. // ping to make sure the connection is up.
  1431. res, err := lc2.Ping(ctx, s1ip, tailcfg.PingICMP)
  1432. if err != nil {
  1433. t.Fatalf("pinging: %s", err)
  1434. }
  1435. t.Logf("ping success: %#+v", res)
  1436. mustDirect(t, t.Logf, lc1, lc2)
  1437. // 1 megabytes
  1438. bytesToSend := 1 * 1024 * 1024
  1439. // This asserts generates some traffic, it is factored out
  1440. // of TestUDPConn.
  1441. start := time.Now()
  1442. err = sendData(t.Logf, ctx, bytesToSend, s1, s2, s1ip, s2ip)
  1443. if err != nil {
  1444. t.Fatalf("Failed to send packets: %v", err)
  1445. }
  1446. t.Logf("Sent %d bytes from s1 to s2 in %s", bytesToSend, time.Since(start).String())
  1447. ctxLc, cancelLc := context.WithTimeout(context.Background(), 5*time.Second)
  1448. defer cancelLc()
  1449. metrics1, err := lc1.UserMetrics(ctxLc)
  1450. if err != nil {
  1451. t.Fatal(err)
  1452. }
  1453. parsedMetrics1, err := parseMetrics(metrics1)
  1454. if err != nil {
  1455. t.Fatal(err)
  1456. }
  1457. // Allow the metrics for the bytes sent to be off by 15%.
  1458. bytesSentTolerance := 1.15
  1459. t.Logf("Metrics1:\n%s\n", metrics1)
  1460. // Verify that the amount of data recorded in bytes is higher or equal to the data sent
  1461. inboundBytes1 := parsedMetrics1[`tailscaled_inbound_bytes_total{path="direct_ipv4"}`]
  1462. if inboundBytes1 < float64(bytesToSend) {
  1463. t.Errorf(`metrics1, tailscaled_inbound_bytes_total{path="direct_ipv4"}: expected higher (or equal) than %d, got: %f`, bytesToSend, inboundBytes1)
  1464. }
  1465. // But ensure that it is not too much higher than the data sent.
  1466. if inboundBytes1 > float64(bytesToSend)*bytesSentTolerance {
  1467. t.Errorf(`metrics1, tailscaled_inbound_bytes_total{path="direct_ipv4"}: expected lower than %f, got: %f`, float64(bytesToSend)*bytesSentTolerance, inboundBytes1)
  1468. }
  1469. metrics2, err := lc2.UserMetrics(ctx)
  1470. if err != nil {
  1471. t.Fatal(err)
  1472. }
  1473. parsedMetrics2, err := parseMetrics(metrics2)
  1474. if err != nil {
  1475. t.Fatal(err)
  1476. }
  1477. t.Logf("Metrics2:\n%s\n", metrics2)
  1478. // Verify that the amount of data recorded in bytes is higher or equal than the data sent.
  1479. outboundBytes2 := parsedMetrics2[`tailscaled_outbound_bytes_total{path="direct_ipv4"}`]
  1480. if outboundBytes2 < float64(bytesToSend) {
  1481. t.Errorf(`metrics2, tailscaled_outbound_bytes_total{path="direct_ipv4"}: expected higher (or equal) than %d, got: %f`, bytesToSend, outboundBytes2)
  1482. }
  1483. // But ensure that it is not too much higher than the data sent.
  1484. if outboundBytes2 > float64(bytesToSend)*bytesSentTolerance {
  1485. t.Errorf(`metrics2, tailscaled_outbound_bytes_total{path="direct_ipv4"}: expected lower than %f, got: %f`, float64(bytesToSend)*bytesSentTolerance, outboundBytes2)
  1486. }
  1487. }
  1488. func TestUserMetricsRouteGauges(t *testing.T) {
  1489. tstest.Shard(t)
  1490. // Windows does not seem to support or report back routes when running in
  1491. // userspace via tsnet. So, we skip this check on Windows.
  1492. // TODO(kradalby): Figure out if this is correct.
  1493. if runtime.GOOS == "windows" {
  1494. t.Skipf("skipping on windows")
  1495. }
  1496. ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
  1497. defer cancel()
  1498. controlURL, c := startControl(t)
  1499. s1, _, s1PubKey := startServer(t, ctx, controlURL, "s1")
  1500. defer s1.Close()
  1501. s2, _, _ := startServer(t, ctx, controlURL, "s2")
  1502. defer s2.Close()
  1503. s1.lb.EditPrefs(&ipn.MaskedPrefs{
  1504. Prefs: ipn.Prefs{
  1505. AdvertiseRoutes: []netip.Prefix{
  1506. netip.MustParsePrefix("192.0.2.0/24"),
  1507. netip.MustParsePrefix("192.0.3.0/24"),
  1508. netip.MustParsePrefix("192.0.5.1/32"),
  1509. netip.MustParsePrefix("0.0.0.0/0"),
  1510. },
  1511. },
  1512. AdvertiseRoutesSet: true,
  1513. })
  1514. c.SetSubnetRoutes(s1PubKey, []netip.Prefix{
  1515. netip.MustParsePrefix("192.0.2.0/24"),
  1516. netip.MustParsePrefix("192.0.5.1/32"),
  1517. netip.MustParsePrefix("0.0.0.0/0"),
  1518. })
  1519. lc1, err := s1.LocalClient()
  1520. if err != nil {
  1521. t.Fatal(err)
  1522. }
  1523. lc2, err := s2.LocalClient()
  1524. if err != nil {
  1525. t.Fatal(err)
  1526. }
  1527. // Force an update to the netmap to ensure that the metrics are up-to-date.
  1528. s1.lb.DebugForceNetmapUpdate()
  1529. s2.lb.DebugForceNetmapUpdate()
  1530. wantRoutes := float64(2)
  1531. // Wait for the routes to be propagated to node 1 to ensure
  1532. // that the metrics are up-to-date.
  1533. waitForCondition(t, "primary routes available for node1", 90*time.Second, func() bool {
  1534. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  1535. defer cancel()
  1536. status1, err := lc1.Status(ctx)
  1537. if err != nil {
  1538. t.Logf("getting status: %s", err)
  1539. return false
  1540. }
  1541. // Wait for the primary routes to reach our desired routes, which is wantRoutes + 1, because
  1542. // the PrimaryRoutes list will contain a exit node route, which the metric does not count.
  1543. return status1.Self.PrimaryRoutes != nil && status1.Self.PrimaryRoutes.Len() == int(wantRoutes)+1
  1544. })
  1545. ctxLc, cancelLc := context.WithTimeout(context.Background(), 5*time.Second)
  1546. defer cancelLc()
  1547. metrics1, err := lc1.UserMetrics(ctxLc)
  1548. if err != nil {
  1549. t.Fatal(err)
  1550. }
  1551. parsedMetrics1, err := parseMetrics(metrics1)
  1552. if err != nil {
  1553. t.Fatal(err)
  1554. }
  1555. t.Logf("Metrics1:\n%s\n", metrics1)
  1556. // The node is advertising 4 routes:
  1557. // - 192.0.2.0/24
  1558. // - 192.0.3.0/24
  1559. // - 192.0.5.1/32
  1560. if got, want := parsedMetrics1["tailscaled_advertised_routes"], 3.0; got != want {
  1561. t.Errorf("metrics1, tailscaled_advertised_routes: got %v, want %v", got, want)
  1562. }
  1563. // The control has approved 2 routes:
  1564. // - 192.0.2.0/24
  1565. // - 192.0.5.1/32
  1566. if got, want := parsedMetrics1["tailscaled_approved_routes"], wantRoutes; got != want {
  1567. t.Errorf("metrics1, tailscaled_approved_routes: got %v, want %v", got, want)
  1568. }
  1569. metrics2, err := lc2.UserMetrics(ctx)
  1570. if err != nil {
  1571. t.Fatal(err)
  1572. }
  1573. parsedMetrics2, err := parseMetrics(metrics2)
  1574. if err != nil {
  1575. t.Fatal(err)
  1576. }
  1577. t.Logf("Metrics2:\n%s\n", metrics2)
  1578. // The node is advertising 0 routes
  1579. if got, want := parsedMetrics2["tailscaled_advertised_routes"], 0.0; got != want {
  1580. t.Errorf("metrics2, tailscaled_advertised_routes: got %v, want %v", got, want)
  1581. }
  1582. // The control has approved 0 routes
  1583. if got, want := parsedMetrics2["tailscaled_approved_routes"], 0.0; got != want {
  1584. t.Errorf("metrics2, tailscaled_approved_routes: got %v, want %v", got, want)
  1585. }
  1586. }
  1587. func waitForCondition(t *testing.T, msg string, waitTime time.Duration, f func() bool) {
  1588. t.Helper()
  1589. for deadline := time.Now().Add(waitTime); time.Now().Before(deadline); time.Sleep(1 * time.Second) {
  1590. if f() {
  1591. return
  1592. }
  1593. }
  1594. t.Fatalf("waiting for condition: %s", msg)
  1595. }
  1596. // mustDirect ensures there is a direct connection between LocalClient 1 and 2
  1597. func mustDirect(t *testing.T, logf logger.Logf, lc1, lc2 *local.Client) {
  1598. t.Helper()
  1599. lastLog := time.Now().Add(-time.Minute)
  1600. // See https://github.com/tailscale/tailscale/issues/654
  1601. // and https://github.com/tailscale/tailscale/issues/3247 for discussions of this deadline.
  1602. for deadline := time.Now().Add(30 * time.Second); time.Now().Before(deadline); time.Sleep(10 * time.Millisecond) {
  1603. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  1604. defer cancel()
  1605. status1, err := lc1.Status(ctx)
  1606. if err != nil {
  1607. continue
  1608. }
  1609. status2, err := lc2.Status(ctx)
  1610. if err != nil {
  1611. continue
  1612. }
  1613. pst := status1.Peer[status2.Self.PublicKey]
  1614. if pst.CurAddr != "" {
  1615. logf("direct link %s->%s found with addr %s", status1.Self.HostName, status2.Self.HostName, pst.CurAddr)
  1616. return
  1617. }
  1618. if now := time.Now(); now.Sub(lastLog) > time.Second {
  1619. logf("no direct path %s->%s yet, addrs %v", status1.Self.HostName, status2.Self.HostName, pst.Addrs)
  1620. lastLog = now
  1621. }
  1622. }
  1623. t.Error("magicsock did not find a direct path from lc1 to lc2")
  1624. }
  1625. func TestDeps(t *testing.T) {
  1626. tstest.Shard(t)
  1627. deptest.DepChecker{
  1628. GOOS: "linux",
  1629. GOARCH: "amd64",
  1630. OnDep: func(dep string) {
  1631. if strings.Contains(dep, "portlist") {
  1632. t.Errorf("unexpected dep: %q", dep)
  1633. }
  1634. },
  1635. }.Check(t)
  1636. }
  1637. func TestResolveAuthKey(t *testing.T) {
  1638. tests := []struct {
  1639. name string
  1640. authKey string
  1641. clientSecret string
  1642. clientID string
  1643. idToken string
  1644. audience string
  1645. oauthAvailable bool
  1646. wifAvailable bool
  1647. resolveViaOAuth func(ctx context.Context, clientSecret string, tags []string) (string, error)
  1648. resolveViaWIF func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error)
  1649. wantAuthKey string
  1650. wantErr bool
  1651. wantErrContains string
  1652. }{
  1653. {
  1654. name: "successful resolution via OAuth client secret",
  1655. clientSecret: "tskey-client-secret-123",
  1656. oauthAvailable: true,
  1657. resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
  1658. if clientSecret != "tskey-client-secret-123" {
  1659. return "", fmt.Errorf("unexpected client secret: %s", clientSecret)
  1660. }
  1661. return "tskey-auth-via-oauth", nil
  1662. },
  1663. wantAuthKey: "tskey-auth-via-oauth",
  1664. wantErrContains: "",
  1665. },
  1666. {
  1667. name: "failing resolution via OAuth client secret",
  1668. clientSecret: "tskey-client-secret-123",
  1669. oauthAvailable: true,
  1670. resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
  1671. return "", fmt.Errorf("resolution failed")
  1672. },
  1673. wantErrContains: "resolution failed",
  1674. },
  1675. {
  1676. name: "successful resolution via federated ID token",
  1677. clientID: "client-id-123",
  1678. idToken: "id-token-456",
  1679. wifAvailable: true,
  1680. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1681. if clientID != "client-id-123" {
  1682. return "", fmt.Errorf("unexpected client ID: %s", clientID)
  1683. }
  1684. if idToken != "id-token-456" {
  1685. return "", fmt.Errorf("unexpected ID token: %s", idToken)
  1686. }
  1687. return "tskey-auth-via-wif", nil
  1688. },
  1689. wantAuthKey: "tskey-auth-via-wif",
  1690. wantErrContains: "",
  1691. },
  1692. {
  1693. name: "successful resolution via federated audience",
  1694. clientID: "client-id-123",
  1695. audience: "api.tailscale.com",
  1696. wifAvailable: true,
  1697. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1698. if clientID != "client-id-123" {
  1699. return "", fmt.Errorf("unexpected client ID: %s", clientID)
  1700. }
  1701. if audience != "api.tailscale.com" {
  1702. return "", fmt.Errorf("unexpected ID token: %s", idToken)
  1703. }
  1704. return "tskey-auth-via-wif", nil
  1705. },
  1706. wantAuthKey: "tskey-auth-via-wif",
  1707. wantErrContains: "",
  1708. },
  1709. {
  1710. name: "failing resolution via federated ID token",
  1711. clientID: "client-id-123",
  1712. idToken: "id-token-456",
  1713. wifAvailable: true,
  1714. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1715. return "", fmt.Errorf("resolution failed")
  1716. },
  1717. wantErrContains: "resolution failed",
  1718. },
  1719. {
  1720. name: "empty client ID with ID token",
  1721. clientID: "",
  1722. idToken: "id-token-456",
  1723. wifAvailable: true,
  1724. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1725. return "", fmt.Errorf("should not be called")
  1726. },
  1727. wantErrContains: "empty",
  1728. },
  1729. {
  1730. name: "empty client ID with audience",
  1731. clientID: "",
  1732. audience: "api.tailscale.com",
  1733. wifAvailable: true,
  1734. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1735. return "", fmt.Errorf("should not be called")
  1736. },
  1737. wantErrContains: "empty",
  1738. },
  1739. {
  1740. name: "empty ID token",
  1741. clientID: "client-id-123",
  1742. idToken: "",
  1743. wifAvailable: true,
  1744. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1745. return "", fmt.Errorf("should not be called")
  1746. },
  1747. wantErrContains: "empty",
  1748. },
  1749. {
  1750. name: "audience with ID token",
  1751. clientID: "client-id-123",
  1752. idToken: "id-token-456",
  1753. audience: "api.tailscale.com",
  1754. wifAvailable: true,
  1755. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1756. return "", fmt.Errorf("should not be called")
  1757. },
  1758. wantErrContains: "only one of ID token and audience",
  1759. },
  1760. {
  1761. name: "workload identity resolution skipped if resolution via OAuth token succeeds",
  1762. clientSecret: "tskey-client-secret-123",
  1763. oauthAvailable: true,
  1764. resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
  1765. if clientSecret != "tskey-client-secret-123" {
  1766. return "", fmt.Errorf("unexpected client secret: %s", clientSecret)
  1767. }
  1768. return "tskey-auth-via-oauth", nil
  1769. },
  1770. wifAvailable: true,
  1771. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1772. return "", fmt.Errorf("should not be called")
  1773. },
  1774. wantAuthKey: "tskey-auth-via-oauth",
  1775. wantErrContains: "",
  1776. },
  1777. {
  1778. name: "workload identity resolution skipped if resolution via OAuth token fails",
  1779. clientID: "tskey-client-id-123",
  1780. idToken: "",
  1781. oauthAvailable: true,
  1782. resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
  1783. return "", fmt.Errorf("resolution failed")
  1784. },
  1785. wifAvailable: true,
  1786. resolveViaWIF: func(ctx context.Context, baseURL, clientID, idToken, audience string, tags []string) (string, error) {
  1787. return "", fmt.Errorf("should not be called")
  1788. },
  1789. wantErrContains: "failed",
  1790. },
  1791. {
  1792. name: "authkey set and no resolution available",
  1793. authKey: "tskey-auth-123",
  1794. oauthAvailable: false,
  1795. wifAvailable: false,
  1796. wantAuthKey: "tskey-auth-123",
  1797. wantErrContains: "",
  1798. },
  1799. {
  1800. name: "no authkey set and no resolution available",
  1801. oauthAvailable: false,
  1802. wifAvailable: false,
  1803. wantAuthKey: "",
  1804. wantErrContains: "",
  1805. },
  1806. {
  1807. name: "authkey is client secret and resolution via OAuth client secret succeeds",
  1808. authKey: "tskey-client-secret-123",
  1809. oauthAvailable: true,
  1810. resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
  1811. if clientSecret != "tskey-client-secret-123" {
  1812. return "", fmt.Errorf("unexpected client secret: %s", clientSecret)
  1813. }
  1814. return "tskey-auth-via-oauth", nil
  1815. },
  1816. wantAuthKey: "tskey-auth-via-oauth",
  1817. wantErrContains: "",
  1818. },
  1819. {
  1820. name: "authkey is client secret but resolution via OAuth client secret fails",
  1821. authKey: "tskey-client-secret-123",
  1822. oauthAvailable: true,
  1823. resolveViaOAuth: func(ctx context.Context, clientSecret string, tags []string) (string, error) {
  1824. return "", fmt.Errorf("resolution failed")
  1825. },
  1826. wantErrContains: "resolution failed",
  1827. },
  1828. }
  1829. for _, tt := range tests {
  1830. t.Run(tt.name, func(t *testing.T) {
  1831. if tt.oauthAvailable {
  1832. t.Cleanup(tailscale.HookResolveAuthKey.SetForTest(tt.resolveViaOAuth))
  1833. }
  1834. if tt.wifAvailable {
  1835. t.Cleanup(tailscale.HookResolveAuthKeyViaWIF.SetForTest(tt.resolveViaWIF))
  1836. }
  1837. s := &Server{
  1838. AuthKey: tt.authKey,
  1839. ClientSecret: tt.clientSecret,
  1840. ClientID: tt.clientID,
  1841. IDToken: tt.idToken,
  1842. Audience: tt.audience,
  1843. ControlURL: "https://control.example.com",
  1844. }
  1845. s.shutdownCtx = context.Background()
  1846. gotAuthKey, err := s.resolveAuthKey()
  1847. if tt.wantErrContains != "" {
  1848. if err == nil {
  1849. t.Errorf("expected error but got none")
  1850. return
  1851. }
  1852. if !strings.Contains(err.Error(), tt.wantErrContains) {
  1853. t.Errorf("expected error containing %q but got error: %v", tt.wantErrContains, err)
  1854. }
  1855. return
  1856. }
  1857. if err != nil {
  1858. t.Errorf("resolveAuthKey expected no error but got error: %v", err)
  1859. return
  1860. }
  1861. if gotAuthKey != tt.wantAuthKey {
  1862. t.Errorf("resolveAuthKey() = %q, want %q", gotAuthKey, tt.wantAuthKey)
  1863. }
  1864. })
  1865. }
  1866. }