direct.go 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  1. // Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package controlclient
  5. import (
  6. "bytes"
  7. "context"
  8. "encoding/binary"
  9. "encoding/json"
  10. "errors"
  11. "flag"
  12. "fmt"
  13. "io"
  14. "io/ioutil"
  15. "log"
  16. "net/http"
  17. "net/url"
  18. "os"
  19. "os/exec"
  20. "reflect"
  21. "runtime"
  22. "strconv"
  23. "strings"
  24. "sync"
  25. "sync/atomic"
  26. "time"
  27. "go4.org/mem"
  28. "inet.af/netaddr"
  29. "tailscale.com/control/controlknobs"
  30. "tailscale.com/health"
  31. "tailscale.com/hostinfo"
  32. "tailscale.com/ipn/ipnstate"
  33. "tailscale.com/log/logheap"
  34. "tailscale.com/net/dnscache"
  35. "tailscale.com/net/dnsfallback"
  36. "tailscale.com/net/interfaces"
  37. "tailscale.com/net/netns"
  38. "tailscale.com/net/tlsdial"
  39. "tailscale.com/net/tshttpproxy"
  40. "tailscale.com/tailcfg"
  41. "tailscale.com/types/key"
  42. "tailscale.com/types/logger"
  43. "tailscale.com/types/netmap"
  44. "tailscale.com/types/opt"
  45. "tailscale.com/types/persist"
  46. "tailscale.com/util/clientmetric"
  47. "tailscale.com/util/systemd"
  48. "tailscale.com/wgengine/monitor"
  49. )
  50. // Direct is the client that connects to a tailcontrol server for a node.
  51. type Direct struct {
  52. httpc *http.Client // HTTP client used to talk to tailcontrol
  53. serverURL string // URL of the tailcontrol server
  54. timeNow func() time.Time
  55. lastPrintMap time.Time
  56. newDecompressor func() (Decompressor, error)
  57. keepAlive bool
  58. logf logger.Logf
  59. linkMon *monitor.Mon // or nil
  60. discoPubKey key.DiscoPublic
  61. getMachinePrivKey func() (key.MachinePrivate, error)
  62. debugFlags []string
  63. keepSharerAndUserSplit bool
  64. skipIPForwardingCheck bool
  65. pinger Pinger
  66. mu sync.Mutex // mutex guards the following fields
  67. serverKey key.MachinePublic
  68. persist persist.Persist
  69. authKey string
  70. tryingNewKey key.NodePrivate
  71. expiry *time.Time
  72. // hostinfo is mutated in-place while mu is held.
  73. hostinfo *tailcfg.Hostinfo // always non-nil
  74. endpoints []tailcfg.Endpoint
  75. everEndpoints bool // whether we've ever had non-empty endpoints
  76. localPort uint16 // or zero to mean auto
  77. lastPingURL string // last PingRequest.URL received, for dup suppression
  78. }
  79. type Options struct {
  80. Persist persist.Persist // initial persistent data
  81. GetMachinePrivateKey func() (key.MachinePrivate, error) // returns the machine key to use
  82. ServerURL string // URL of the tailcontrol server
  83. AuthKey string // optional node auth key for auto registration
  84. TimeNow func() time.Time // time.Now implementation used by Client
  85. Hostinfo *tailcfg.Hostinfo // non-nil passes ownership, nil means to use default using os.Hostname, etc
  86. DiscoPublicKey key.DiscoPublic
  87. NewDecompressor func() (Decompressor, error)
  88. KeepAlive bool
  89. Logf logger.Logf
  90. HTTPTestClient *http.Client // optional HTTP client to use (for tests only)
  91. DebugFlags []string // debug settings to send to control
  92. LinkMonitor *monitor.Mon // optional link monitor
  93. // KeepSharerAndUserSplit controls whether the client
  94. // understands Node.Sharer. If false, the Sharer is mapped to the User.
  95. KeepSharerAndUserSplit bool
  96. // SkipIPForwardingCheck declares that the host's IP
  97. // forwarding works and should not be double-checked by the
  98. // controlclient package.
  99. SkipIPForwardingCheck bool
  100. // Pinger optionally specifies the Pinger to use to satisfy
  101. // MapResponse.PingRequest queries from the control plane.
  102. // If nil, PingRequest queries are not answered.
  103. Pinger Pinger
  104. }
  105. // Pinger is a subset of the wgengine.Engine interface, containing just the Ping method.
  106. type Pinger interface {
  107. // Ping is a request to start a discovery or TSMP ping with the peer handling
  108. // the given IP and then call cb with its ping latency & method.
  109. Ping(ip netaddr.IP, useTSMP bool, cb func(*ipnstate.PingResult))
  110. }
  111. type Decompressor interface {
  112. DecodeAll(input, dst []byte) ([]byte, error)
  113. Close()
  114. }
  115. // NewDirect returns a new Direct client.
  116. func NewDirect(opts Options) (*Direct, error) {
  117. if opts.ServerURL == "" {
  118. return nil, errors.New("controlclient.New: no server URL specified")
  119. }
  120. if opts.GetMachinePrivateKey == nil {
  121. return nil, errors.New("controlclient.New: no GetMachinePrivateKey specified")
  122. }
  123. opts.ServerURL = strings.TrimRight(opts.ServerURL, "/")
  124. serverURL, err := url.Parse(opts.ServerURL)
  125. if err != nil {
  126. return nil, err
  127. }
  128. if opts.TimeNow == nil {
  129. opts.TimeNow = time.Now
  130. }
  131. if opts.Logf == nil {
  132. // TODO(apenwarr): remove this default and fail instead.
  133. // TODO(bradfitz): ... but then it shouldn't be in Options.
  134. opts.Logf = log.Printf
  135. }
  136. httpc := opts.HTTPTestClient
  137. if httpc == nil && runtime.GOOS == "js" {
  138. // In js/wasm, net/http.Transport (as of Go 1.18) will
  139. // only use the browser's Fetch API if you're using
  140. // the DefaultClient (or a client without dial hooks
  141. // etc set).
  142. httpc = http.DefaultClient
  143. }
  144. if httpc == nil {
  145. dnsCache := &dnscache.Resolver{
  146. Forward: dnscache.Get().Forward, // use default cache's forwarder
  147. UseLastGood: true,
  148. LookupIPFallback: dnsfallback.Lookup,
  149. }
  150. dialer := netns.NewDialer(opts.Logf)
  151. tr := http.DefaultTransport.(*http.Transport).Clone()
  152. tr.Proxy = tshttpproxy.ProxyFromEnvironment
  153. tshttpproxy.SetTransportGetProxyConnectHeader(tr)
  154. tr.TLSClientConfig = tlsdial.Config(serverURL.Hostname(), tr.TLSClientConfig)
  155. tr.DialContext = dnscache.Dialer(dialer.DialContext, dnsCache)
  156. tr.DialTLSContext = dnscache.TLSDialer(dialer.DialContext, dnsCache, tr.TLSClientConfig)
  157. tr.ForceAttemptHTTP2 = true
  158. httpc = &http.Client{Transport: tr}
  159. }
  160. c := &Direct{
  161. httpc: httpc,
  162. getMachinePrivKey: opts.GetMachinePrivateKey,
  163. serverURL: opts.ServerURL,
  164. timeNow: opts.TimeNow,
  165. logf: opts.Logf,
  166. newDecompressor: opts.NewDecompressor,
  167. keepAlive: opts.KeepAlive,
  168. persist: opts.Persist,
  169. authKey: opts.AuthKey,
  170. discoPubKey: opts.DiscoPublicKey,
  171. debugFlags: opts.DebugFlags,
  172. keepSharerAndUserSplit: opts.KeepSharerAndUserSplit,
  173. linkMon: opts.LinkMonitor,
  174. skipIPForwardingCheck: opts.SkipIPForwardingCheck,
  175. pinger: opts.Pinger,
  176. }
  177. if opts.Hostinfo == nil {
  178. c.SetHostinfo(hostinfo.New())
  179. } else {
  180. c.SetHostinfo(opts.Hostinfo)
  181. }
  182. return c, nil
  183. }
  184. // SetHostinfo clones the provided Hostinfo and remembers it for the
  185. // next update. It reports whether the Hostinfo has changed.
  186. func (c *Direct) SetHostinfo(hi *tailcfg.Hostinfo) bool {
  187. if hi == nil {
  188. panic("nil Hostinfo")
  189. }
  190. c.mu.Lock()
  191. defer c.mu.Unlock()
  192. if hi.Equal(c.hostinfo) {
  193. return false
  194. }
  195. c.hostinfo = hi.Clone()
  196. j, _ := json.Marshal(c.hostinfo)
  197. c.logf("HostInfo: %s", j)
  198. return true
  199. }
  200. // SetNetInfo clones the provided NetInfo and remembers it for the
  201. // next update. It reports whether the NetInfo has changed.
  202. func (c *Direct) SetNetInfo(ni *tailcfg.NetInfo) bool {
  203. if ni == nil {
  204. panic("nil NetInfo")
  205. }
  206. c.mu.Lock()
  207. defer c.mu.Unlock()
  208. if c.hostinfo == nil {
  209. c.logf("[unexpected] SetNetInfo called with no HostInfo; ignoring NetInfo update: %+v", ni)
  210. return false
  211. }
  212. if reflect.DeepEqual(ni, c.hostinfo.NetInfo) {
  213. return false
  214. }
  215. c.hostinfo.NetInfo = ni.Clone()
  216. return true
  217. }
  218. func (c *Direct) GetPersist() persist.Persist {
  219. c.mu.Lock()
  220. defer c.mu.Unlock()
  221. return c.persist
  222. }
  223. func (c *Direct) TryLogout(ctx context.Context) error {
  224. c.logf("direct.TryLogout()")
  225. mustRegen, newURL, err := c.doLogin(ctx, loginOpt{Logout: true})
  226. c.logf("TryLogout control response: mustRegen=%v, newURL=%v, err=%v", mustRegen, newURL, err)
  227. c.mu.Lock()
  228. c.persist = persist.Persist{}
  229. c.mu.Unlock()
  230. return err
  231. }
  232. func (c *Direct) TryLogin(ctx context.Context, t *tailcfg.Oauth2Token, flags LoginFlags) (url string, err error) {
  233. c.logf("direct.TryLogin(token=%v, flags=%v)", t != nil, flags)
  234. return c.doLoginOrRegen(ctx, loginOpt{Token: t, Flags: flags})
  235. }
  236. // WaitLoginURL sits in a long poll waiting for the user to authenticate at url.
  237. //
  238. // On success, newURL and err will both be nil.
  239. func (c *Direct) WaitLoginURL(ctx context.Context, url string) (newURL string, err error) {
  240. c.logf("direct.WaitLoginURL")
  241. return c.doLoginOrRegen(ctx, loginOpt{URL: url})
  242. }
  243. func (c *Direct) doLoginOrRegen(ctx context.Context, opt loginOpt) (newURL string, err error) {
  244. mustRegen, url, err := c.doLogin(ctx, opt)
  245. if err != nil {
  246. return url, err
  247. }
  248. if mustRegen {
  249. opt.Regen = true
  250. _, url, err = c.doLogin(ctx, opt)
  251. }
  252. return url, err
  253. }
  254. type loginOpt struct {
  255. Token *tailcfg.Oauth2Token
  256. Flags LoginFlags
  257. Regen bool
  258. URL string
  259. Logout bool
  260. }
  261. func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, newURL string, err error) {
  262. c.mu.Lock()
  263. persist := c.persist
  264. tryingNewKey := c.tryingNewKey
  265. serverKey := c.serverKey
  266. authKey := c.authKey
  267. hi := c.hostinfo.Clone()
  268. backendLogID := hi.BackendLogID
  269. expired := c.expiry != nil && !c.expiry.IsZero() && c.expiry.Before(c.timeNow())
  270. c.mu.Unlock()
  271. machinePrivKey, err := c.getMachinePrivKey()
  272. if err != nil {
  273. return false, "", fmt.Errorf("getMachinePrivKey: %w", err)
  274. }
  275. if machinePrivKey.IsZero() {
  276. return false, "", errors.New("getMachinePrivKey returned zero key")
  277. }
  278. regen := opt.Regen
  279. if opt.Logout {
  280. c.logf("logging out...")
  281. } else {
  282. if expired {
  283. c.logf("Old key expired -> regen=true")
  284. systemd.Status("key expired; run 'tailscale up' to authenticate")
  285. regen = true
  286. }
  287. if (opt.Flags & LoginInteractive) != 0 {
  288. c.logf("LoginInteractive -> regen=true")
  289. regen = true
  290. }
  291. }
  292. c.logf("doLogin(regen=%v, hasUrl=%v)", regen, opt.URL != "")
  293. if serverKey.IsZero() {
  294. var err error
  295. serverKey, err = loadServerKey(ctx, c.httpc, c.serverURL)
  296. if err != nil {
  297. return regen, opt.URL, err
  298. }
  299. c.logf("control server key %s from %s", serverKey.ShortString(), c.serverURL)
  300. c.mu.Lock()
  301. c.serverKey = serverKey
  302. c.mu.Unlock()
  303. }
  304. var oldNodeKey key.NodePublic
  305. switch {
  306. case opt.Logout:
  307. tryingNewKey = persist.PrivateNodeKey
  308. case opt.URL != "":
  309. // Nothing.
  310. case regen || persist.PrivateNodeKey.IsZero():
  311. c.logf("Generating a new nodekey.")
  312. persist.OldPrivateNodeKey = persist.PrivateNodeKey
  313. tryingNewKey = key.NewNode()
  314. default:
  315. // Try refreshing the current key first
  316. tryingNewKey = persist.PrivateNodeKey
  317. }
  318. if !persist.OldPrivateNodeKey.IsZero() {
  319. oldNodeKey = persist.OldPrivateNodeKey.Public()
  320. }
  321. if tryingNewKey.IsZero() {
  322. if opt.Logout {
  323. return false, "", errors.New("no nodekey to log out")
  324. }
  325. log.Fatalf("tryingNewKey is empty, give up")
  326. }
  327. if backendLogID == "" {
  328. err = errors.New("hostinfo: BackendLogID missing")
  329. return regen, opt.URL, err
  330. }
  331. now := time.Now().Round(time.Second)
  332. request := tailcfg.RegisterRequest{
  333. Version: 1,
  334. OldNodeKey: oldNodeKey,
  335. NodeKey: tryingNewKey.Public(),
  336. Hostinfo: hi,
  337. Followup: opt.URL,
  338. Timestamp: &now,
  339. Ephemeral: (opt.Flags & LoginEphemeral) != 0,
  340. }
  341. if opt.Logout {
  342. request.Expiry = time.Unix(123, 0) // far in the past
  343. }
  344. c.logf("RegisterReq: onode=%v node=%v fup=%v",
  345. request.OldNodeKey.ShortString(),
  346. request.NodeKey.ShortString(), opt.URL != "")
  347. request.Auth.Oauth2Token = opt.Token
  348. request.Auth.Provider = persist.Provider
  349. request.Auth.LoginName = persist.LoginName
  350. request.Auth.AuthKey = authKey
  351. err = signRegisterRequest(&request, c.serverURL, c.serverKey, machinePrivKey.Public())
  352. if err != nil {
  353. // If signing failed, clear all related fields
  354. request.SignatureType = tailcfg.SignatureNone
  355. request.Timestamp = nil
  356. request.DeviceCert = nil
  357. request.Signature = nil
  358. // Don't log the common error types. Signatures are not usually enabled,
  359. // so these are expected.
  360. if !errors.Is(err, errCertificateNotConfigured) && !errors.Is(err, errNoCertStore) {
  361. c.logf("RegisterReq sign error: %v", err)
  362. }
  363. }
  364. if debugRegister {
  365. j, _ := json.MarshalIndent(request, "", "\t")
  366. c.logf("RegisterRequest: %s", j)
  367. }
  368. bodyData, err := encode(request, serverKey, machinePrivKey)
  369. if err != nil {
  370. return regen, opt.URL, err
  371. }
  372. body := bytes.NewReader(bodyData)
  373. u := fmt.Sprintf("%s/machine/%s", c.serverURL, machinePrivKey.Public().UntypedHexString())
  374. req, err := http.NewRequest("POST", u, body)
  375. if err != nil {
  376. return regen, opt.URL, err
  377. }
  378. req = req.WithContext(ctx)
  379. res, err := c.httpc.Do(req)
  380. if err != nil {
  381. return regen, opt.URL, fmt.Errorf("register request: %v", err)
  382. }
  383. if res.StatusCode != 200 {
  384. msg, _ := ioutil.ReadAll(res.Body)
  385. res.Body.Close()
  386. return regen, opt.URL, fmt.Errorf("register request: http %d: %.200s",
  387. res.StatusCode, strings.TrimSpace(string(msg)))
  388. }
  389. resp := tailcfg.RegisterResponse{}
  390. if err := decode(res, &resp, serverKey, machinePrivKey); err != nil {
  391. c.logf("error decoding RegisterResponse with server key %s and machine key %s: %v", serverKey, machinePrivKey.Public(), err)
  392. return regen, opt.URL, fmt.Errorf("register request: %v", err)
  393. }
  394. if debugRegister {
  395. j, _ := json.MarshalIndent(resp, "", "\t")
  396. c.logf("RegisterResponse: %s", j)
  397. }
  398. // Log without PII:
  399. c.logf("RegisterReq: got response; nodeKeyExpired=%v, machineAuthorized=%v; authURL=%v",
  400. resp.NodeKeyExpired, resp.MachineAuthorized, resp.AuthURL != "")
  401. if resp.Error != "" {
  402. return false, "", UserVisibleError(resp.Error)
  403. }
  404. if resp.NodeKeyExpired {
  405. if regen {
  406. return true, "", fmt.Errorf("weird: regen=true but server says NodeKeyExpired: %v", request.NodeKey)
  407. }
  408. c.logf("server reports new node key %v has expired",
  409. request.NodeKey.ShortString())
  410. return true, "", nil
  411. }
  412. if resp.Login.Provider != "" {
  413. persist.Provider = resp.Login.Provider
  414. }
  415. if resp.Login.LoginName != "" {
  416. persist.LoginName = resp.Login.LoginName
  417. }
  418. // TODO(crawshaw): RegisterResponse should be able to mechanically
  419. // communicate some extra instructions from the server:
  420. // - new node key required
  421. // - machine key no longer supported
  422. // - user is disabled
  423. if resp.AuthURL != "" {
  424. c.logf("AuthURL is %v", resp.AuthURL)
  425. } else {
  426. c.logf("No AuthURL")
  427. }
  428. c.mu.Lock()
  429. if resp.AuthURL == "" {
  430. // key rotation is complete
  431. persist.PrivateNodeKey = tryingNewKey
  432. } else {
  433. // save it for the retry-with-URL
  434. c.tryingNewKey = tryingNewKey
  435. }
  436. c.persist = persist
  437. c.mu.Unlock()
  438. if err != nil {
  439. return regen, "", err
  440. }
  441. if ctx.Err() != nil {
  442. return regen, "", ctx.Err()
  443. }
  444. return false, resp.AuthURL, nil
  445. }
  446. func sameEndpoints(a, b []tailcfg.Endpoint) bool {
  447. if len(a) != len(b) {
  448. return false
  449. }
  450. for i := range a {
  451. if a[i] != b[i] {
  452. return false
  453. }
  454. }
  455. return true
  456. }
  457. // newEndpoints acquires c.mu and sets the local port and endpoints and reports
  458. // whether they've changed.
  459. //
  460. // It does not retain the provided slice.
  461. func (c *Direct) newEndpoints(localPort uint16, endpoints []tailcfg.Endpoint) (changed bool) {
  462. c.mu.Lock()
  463. defer c.mu.Unlock()
  464. // Nothing new?
  465. if c.localPort == localPort && sameEndpoints(c.endpoints, endpoints) {
  466. return false // unchanged
  467. }
  468. var epStrs []string
  469. for _, ep := range endpoints {
  470. epStrs = append(epStrs, ep.Addr.String())
  471. }
  472. c.logf("client.newEndpoints(%v, %v)", localPort, epStrs)
  473. c.localPort = localPort
  474. c.endpoints = append(c.endpoints[:0], endpoints...)
  475. if len(endpoints) > 0 {
  476. c.everEndpoints = true
  477. }
  478. return true // changed
  479. }
  480. // SetEndpoints updates the list of locally advertised endpoints.
  481. // It won't be replicated to the server until a *fresh* call to PollNetMap().
  482. // You don't need to restart PollNetMap if we return changed==false.
  483. func (c *Direct) SetEndpoints(localPort uint16, endpoints []tailcfg.Endpoint) (changed bool) {
  484. // (no log message on function entry, because it clutters the logs
  485. // if endpoints haven't changed. newEndpoints() will log it.)
  486. return c.newEndpoints(localPort, endpoints)
  487. }
  488. func inTest() bool { return flag.Lookup("test.v") != nil }
  489. // PollNetMap makes a /map request to download the network map, calling cb with
  490. // each new netmap.
  491. //
  492. // maxPolls is how many network maps to download; common values are 1
  493. // or -1 (to keep a long-poll query open to the server).
  494. func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*netmap.NetworkMap)) error {
  495. return c.sendMapRequest(ctx, maxPolls, cb)
  496. }
  497. // SendLiteMapUpdate makes a /map request to update the server of our latest state,
  498. // but does not fetch anything. It returns an error if the server did not return a
  499. // successful 200 OK response.
  500. func (c *Direct) SendLiteMapUpdate(ctx context.Context) error {
  501. return c.sendMapRequest(ctx, 1, nil)
  502. }
  503. // If we go more than pollTimeout without hearing from the server,
  504. // end the long poll. We should be receiving a keep alive ping
  505. // every minute.
  506. const pollTimeout = 120 * time.Second
  507. // cb nil means to omit peers.
  508. func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netmap.NetworkMap)) error {
  509. metricMapRequests.Add(1)
  510. metricMapRequestsActive.Add(1)
  511. defer metricMapRequestsActive.Add(-1)
  512. if maxPolls == -1 {
  513. metricMapRequestsPoll.Add(1)
  514. } else {
  515. metricMapRequestsLite.Add(1)
  516. }
  517. c.mu.Lock()
  518. persist := c.persist
  519. serverURL := c.serverURL
  520. serverKey := c.serverKey
  521. hi := c.hostinfo.Clone()
  522. backendLogID := hi.BackendLogID
  523. localPort := c.localPort
  524. var epStrs []string
  525. var epTypes []tailcfg.EndpointType
  526. for _, ep := range c.endpoints {
  527. epStrs = append(epStrs, ep.Addr.String())
  528. epTypes = append(epTypes, ep.Type)
  529. }
  530. everEndpoints := c.everEndpoints
  531. c.mu.Unlock()
  532. machinePrivKey, err := c.getMachinePrivKey()
  533. if err != nil {
  534. return fmt.Errorf("getMachinePrivKey: %w", err)
  535. }
  536. if machinePrivKey.IsZero() {
  537. return errors.New("getMachinePrivKey returned zero key")
  538. }
  539. if persist.PrivateNodeKey.IsZero() {
  540. return errors.New("privateNodeKey is zero")
  541. }
  542. if backendLogID == "" {
  543. return errors.New("hostinfo: BackendLogID missing")
  544. }
  545. allowStream := maxPolls != 1
  546. c.logf("[v1] PollNetMap: stream=%v :%v ep=%v", allowStream, localPort, epStrs)
  547. vlogf := logger.Discard
  548. if Debug.NetMap {
  549. // TODO(bradfitz): update this to use "[v2]" prefix perhaps? but we don't
  550. // want to upload it always.
  551. vlogf = c.logf
  552. }
  553. request := &tailcfg.MapRequest{
  554. Version: tailcfg.CurrentMapRequestVersion,
  555. KeepAlive: c.keepAlive,
  556. NodeKey: persist.PrivateNodeKey.Public(),
  557. DiscoKey: c.discoPubKey,
  558. Endpoints: epStrs,
  559. EndpointTypes: epTypes,
  560. Stream: allowStream,
  561. Hostinfo: hi,
  562. DebugFlags: c.debugFlags,
  563. OmitPeers: cb == nil,
  564. }
  565. var extraDebugFlags []string
  566. if hi != nil && c.linkMon != nil && !c.skipIPForwardingCheck &&
  567. ipForwardingBroken(hi.RoutableIPs, c.linkMon.InterfaceState()) {
  568. extraDebugFlags = append(extraDebugFlags, "warn-ip-forwarding-off")
  569. }
  570. if health.RouterHealth() != nil {
  571. extraDebugFlags = append(extraDebugFlags, "warn-router-unhealthy")
  572. }
  573. if health.NetworkCategoryHealth() != nil {
  574. extraDebugFlags = append(extraDebugFlags, "warn-network-category-unhealthy")
  575. }
  576. if hostinfo.DisabledEtcAptSource() {
  577. extraDebugFlags = append(extraDebugFlags, "warn-etc-apt-source-disabled")
  578. }
  579. if len(extraDebugFlags) > 0 {
  580. old := request.DebugFlags
  581. request.DebugFlags = append(old[:len(old):len(old)], extraDebugFlags...)
  582. }
  583. if c.newDecompressor != nil {
  584. request.Compress = "zstd"
  585. }
  586. // On initial startup before we know our endpoints, set the ReadOnly flag
  587. // to tell the control server not to distribute out our (empty) endpoints to peers.
  588. // Presumably we'll learn our endpoints in a half second and do another post
  589. // with useful results. The first POST just gets us the DERP map which we
  590. // need to do the STUN queries to discover our endpoints.
  591. // TODO(bradfitz): we skip this optimization in tests, though,
  592. // because the e2e tests are currently hyperspecific about the
  593. // ordering of things. The e2e tests need love.
  594. if len(epStrs) == 0 && !everEndpoints && !inTest() {
  595. request.ReadOnly = true
  596. }
  597. bodyData, err := encode(request, serverKey, machinePrivKey)
  598. if err != nil {
  599. vlogf("netmap: encode: %v", err)
  600. return err
  601. }
  602. ctx, cancel := context.WithCancel(ctx)
  603. defer cancel()
  604. machinePubKey := machinePrivKey.Public()
  605. t0 := time.Now()
  606. u := fmt.Sprintf("%s/machine/%s/map", serverURL, machinePubKey.UntypedHexString())
  607. req, err := http.NewRequestWithContext(ctx, "POST", u, bytes.NewReader(bodyData))
  608. if err != nil {
  609. return err
  610. }
  611. res, err := c.httpc.Do(req)
  612. if err != nil {
  613. vlogf("netmap: Do: %v", err)
  614. return err
  615. }
  616. vlogf("netmap: Do = %v after %v", res.StatusCode, time.Since(t0).Round(time.Millisecond))
  617. if res.StatusCode != 200 {
  618. msg, _ := ioutil.ReadAll(res.Body)
  619. res.Body.Close()
  620. return fmt.Errorf("initial fetch failed %d: %.200s",
  621. res.StatusCode, strings.TrimSpace(string(msg)))
  622. }
  623. defer res.Body.Close()
  624. health.NoteMapRequestHeard(request)
  625. if cb == nil {
  626. io.Copy(ioutil.Discard, res.Body)
  627. return nil
  628. }
  629. timeout := time.NewTimer(pollTimeout)
  630. timeoutReset := make(chan struct{})
  631. pollDone := make(chan struct{})
  632. defer close(pollDone)
  633. go func() {
  634. for {
  635. select {
  636. case <-pollDone:
  637. vlogf("netmap: ending timeout goroutine")
  638. return
  639. case <-timeout.C:
  640. c.logf("map response long-poll timed out!")
  641. cancel()
  642. return
  643. case <-timeoutReset:
  644. if !timeout.Stop() {
  645. select {
  646. case <-timeout.C:
  647. case <-pollDone:
  648. vlogf("netmap: ending timeout goroutine")
  649. return
  650. }
  651. }
  652. vlogf("netmap: reset timeout timer")
  653. timeout.Reset(pollTimeout)
  654. }
  655. }
  656. }()
  657. sess := newMapSession(persist.PrivateNodeKey)
  658. sess.logf = c.logf
  659. sess.vlogf = vlogf
  660. sess.machinePubKey = machinePubKey
  661. sess.keepSharerAndUserSplit = c.keepSharerAndUserSplit
  662. // If allowStream, then the server will use an HTTP long poll to
  663. // return incremental results. There is always one response right
  664. // away, followed by a delay, and eventually others.
  665. // If !allowStream, it'll still send the first result in exactly
  666. // the same format before just closing the connection.
  667. // We can use this same read loop either way.
  668. var msg []byte
  669. for i := 0; i < maxPolls || maxPolls < 0; i++ {
  670. vlogf("netmap: starting size read after %v (poll %v)", time.Since(t0).Round(time.Millisecond), i)
  671. var siz [4]byte
  672. if _, err := io.ReadFull(res.Body, siz[:]); err != nil {
  673. vlogf("netmap: size read error after %v: %v", time.Since(t0).Round(time.Millisecond), err)
  674. return err
  675. }
  676. size := binary.LittleEndian.Uint32(siz[:])
  677. vlogf("netmap: read size %v after %v", size, time.Since(t0).Round(time.Millisecond))
  678. msg = append(msg[:0], make([]byte, size)...)
  679. if _, err := io.ReadFull(res.Body, msg); err != nil {
  680. vlogf("netmap: body read error: %v", err)
  681. return err
  682. }
  683. vlogf("netmap: read body after %v", time.Since(t0).Round(time.Millisecond))
  684. var resp tailcfg.MapResponse
  685. if err := c.decodeMsg(msg, &resp, machinePrivKey); err != nil {
  686. vlogf("netmap: decode error: %v")
  687. return err
  688. }
  689. metricMapResponseMessages.Add(1)
  690. if allowStream {
  691. health.GotStreamedMapResponse()
  692. }
  693. if pr := resp.PingRequest; pr != nil && c.isUniquePingRequest(pr) {
  694. metricMapResponsePings.Add(1)
  695. go answerPing(c.logf, c.httpc, pr)
  696. }
  697. if resp.KeepAlive {
  698. vlogf("netmap: got keep-alive")
  699. } else {
  700. vlogf("netmap: got new map")
  701. }
  702. select {
  703. case timeoutReset <- struct{}{}:
  704. vlogf("netmap: sent timer reset")
  705. case <-ctx.Done():
  706. c.logf("[v1] netmap: not resetting timer; context done: %v", ctx.Err())
  707. return ctx.Err()
  708. }
  709. if resp.KeepAlive {
  710. metricMapResponseKeepAlives.Add(1)
  711. continue
  712. }
  713. metricMapResponseMap.Add(1)
  714. if i > 0 {
  715. metricMapResponseMapDelta.Add(1)
  716. }
  717. hasDebug := resp.Debug != nil
  718. // being conservative here, if Debug not present set to False
  719. controlknobs.SetDisableUPnP(hasDebug && resp.Debug.DisableUPnP.EqualBool(true))
  720. if hasDebug {
  721. if code := resp.Debug.Exit; code != nil {
  722. c.logf("exiting process with status %v per controlplane", *code)
  723. os.Exit(*code)
  724. }
  725. if resp.Debug.LogHeapPprof {
  726. go logheap.LogHeap(resp.Debug.LogHeapURL)
  727. }
  728. if resp.Debug.GoroutineDumpURL != "" {
  729. go dumpGoroutinesToURL(c.httpc, resp.Debug.GoroutineDumpURL)
  730. }
  731. setControlAtomic(&controlUseDERPRoute, resp.Debug.DERPRoute)
  732. setControlAtomic(&controlTrimWGConfig, resp.Debug.TrimWGConfig)
  733. if sleep := time.Duration(resp.Debug.SleepSeconds * float64(time.Second)); sleep > 0 {
  734. if err := sleepAsRequested(ctx, c.logf, timeoutReset, sleep); err != nil {
  735. return err
  736. }
  737. }
  738. }
  739. nm := sess.netmapForResponse(&resp)
  740. if nm.SelfNode == nil {
  741. c.logf("MapResponse lacked node")
  742. return errors.New("MapResponse lacked node")
  743. }
  744. if Debug.StripEndpoints {
  745. for _, p := range resp.Peers {
  746. // We need at least one endpoint here for now else
  747. // other code doesn't even create the discoEndpoint.
  748. // TODO(bradfitz): fix that and then just nil this out.
  749. p.Endpoints = []string{"127.9.9.9:456"}
  750. }
  751. }
  752. if Debug.StripCaps {
  753. nm.SelfNode.Capabilities = nil
  754. }
  755. // Get latest localPort. This might've changed if
  756. // a lite map update occurred meanwhile. This only affects
  757. // the end-to-end test.
  758. // TODO(bradfitz): remove the NetworkMap.LocalPort field entirely.
  759. c.mu.Lock()
  760. nm.LocalPort = c.localPort
  761. c.mu.Unlock()
  762. // Occasionally print the netmap header.
  763. // This is handy for debugging, and our logs processing
  764. // pipeline depends on it. (TODO: Remove this dependency.)
  765. // Code elsewhere prints netmap diffs every time they are received.
  766. now := c.timeNow()
  767. if now.Sub(c.lastPrintMap) >= 5*time.Minute {
  768. c.lastPrintMap = now
  769. c.logf("[v1] new network map[%d]:\n%s", i, nm.VeryConcise())
  770. }
  771. c.mu.Lock()
  772. c.expiry = &nm.Expiry
  773. c.mu.Unlock()
  774. cb(nm)
  775. }
  776. if ctx.Err() != nil {
  777. return ctx.Err()
  778. }
  779. return nil
  780. }
  781. func decode(res *http.Response, v interface{}, serverKey key.MachinePublic, mkey key.MachinePrivate) error {
  782. defer res.Body.Close()
  783. msg, err := ioutil.ReadAll(io.LimitReader(res.Body, 1<<20))
  784. if err != nil {
  785. return err
  786. }
  787. if res.StatusCode != 200 {
  788. return fmt.Errorf("%d: %v", res.StatusCode, string(msg))
  789. }
  790. return decodeMsg(msg, v, serverKey, mkey)
  791. }
  792. var (
  793. debugMap, _ = strconv.ParseBool(os.Getenv("TS_DEBUG_MAP"))
  794. debugRegister, _ = strconv.ParseBool(os.Getenv("TS_DEBUG_REGISTER"))
  795. )
  796. var jsonEscapedZero = []byte(`\u0000`)
  797. func (c *Direct) decodeMsg(msg []byte, v interface{}, machinePrivKey key.MachinePrivate) error {
  798. c.mu.Lock()
  799. serverKey := c.serverKey
  800. c.mu.Unlock()
  801. decrypted, ok := machinePrivKey.OpenFrom(serverKey, msg)
  802. if !ok {
  803. return errors.New("cannot decrypt response")
  804. }
  805. var b []byte
  806. if c.newDecompressor == nil {
  807. b = decrypted
  808. } else {
  809. decoder, err := c.newDecompressor()
  810. if err != nil {
  811. return err
  812. }
  813. defer decoder.Close()
  814. b, err = decoder.DecodeAll(decrypted, nil)
  815. if err != nil {
  816. return err
  817. }
  818. }
  819. if debugMap {
  820. var buf bytes.Buffer
  821. json.Indent(&buf, b, "", " ")
  822. log.Printf("MapResponse: %s", buf.Bytes())
  823. }
  824. if bytes.Contains(b, jsonEscapedZero) {
  825. log.Printf("[unexpected] zero byte in controlclient.Direct.decodeMsg into %T: %q", v, b)
  826. }
  827. if err := json.Unmarshal(b, v); err != nil {
  828. return fmt.Errorf("response: %v", err)
  829. }
  830. return nil
  831. }
  832. func decodeMsg(msg []byte, v interface{}, serverKey key.MachinePublic, machinePrivKey key.MachinePrivate) error {
  833. decrypted, ok := machinePrivKey.OpenFrom(serverKey, msg)
  834. if !ok {
  835. return errors.New("cannot decrypt response")
  836. }
  837. if bytes.Contains(decrypted, jsonEscapedZero) {
  838. log.Printf("[unexpected] zero byte in controlclient decodeMsg into %T: %q", v, decrypted)
  839. }
  840. if err := json.Unmarshal(decrypted, v); err != nil {
  841. return fmt.Errorf("response: %v", err)
  842. }
  843. return nil
  844. }
  845. func encode(v interface{}, serverKey key.MachinePublic, mkey key.MachinePrivate) ([]byte, error) {
  846. b, err := json.Marshal(v)
  847. if err != nil {
  848. return nil, err
  849. }
  850. if debugMap {
  851. if _, ok := v.(*tailcfg.MapRequest); ok {
  852. log.Printf("MapRequest: %s", b)
  853. }
  854. }
  855. return mkey.SealTo(serverKey, b), nil
  856. }
  857. func loadServerKey(ctx context.Context, httpc *http.Client, serverURL string) (key.MachinePublic, error) {
  858. req, err := http.NewRequest("GET", serverURL+"/key", nil)
  859. if err != nil {
  860. return key.MachinePublic{}, fmt.Errorf("create control key request: %v", err)
  861. }
  862. req = req.WithContext(ctx)
  863. res, err := httpc.Do(req)
  864. if err != nil {
  865. return key.MachinePublic{}, fmt.Errorf("fetch control key: %v", err)
  866. }
  867. defer res.Body.Close()
  868. b, err := ioutil.ReadAll(io.LimitReader(res.Body, 1<<16))
  869. if err != nil {
  870. return key.MachinePublic{}, fmt.Errorf("fetch control key response: %v", err)
  871. }
  872. if res.StatusCode != 200 {
  873. return key.MachinePublic{}, fmt.Errorf("fetch control key: %d: %s", res.StatusCode, string(b))
  874. }
  875. k, err := key.ParseMachinePublicUntyped(mem.B(b))
  876. if err != nil {
  877. return key.MachinePublic{}, fmt.Errorf("fetch control key: %v", err)
  878. }
  879. return k, nil
  880. }
  881. // Debug contains temporary internal-only debug knobs.
  882. // They're unexported to not draw attention to them.
  883. var Debug = initDebug()
  884. type debug struct {
  885. NetMap bool
  886. ProxyDNS bool
  887. Disco bool
  888. StripEndpoints bool // strip endpoints from control (only use disco messages)
  889. StripCaps bool // strip all local node's control-provided capabilities
  890. }
  891. func initDebug() debug {
  892. return debug{
  893. NetMap: envBool("TS_DEBUG_NETMAP"),
  894. ProxyDNS: envBool("TS_DEBUG_PROXY_DNS"),
  895. StripEndpoints: envBool("TS_DEBUG_STRIP_ENDPOINTS"),
  896. StripCaps: envBool("TS_DEBUG_STRIP_CAPS"),
  897. Disco: os.Getenv("TS_DEBUG_USE_DISCO") == "" || envBool("TS_DEBUG_USE_DISCO"),
  898. }
  899. }
  900. func envBool(k string) bool {
  901. e := os.Getenv(k)
  902. if e == "" {
  903. return false
  904. }
  905. v, err := strconv.ParseBool(e)
  906. if err != nil {
  907. panic(fmt.Sprintf("invalid non-bool %q for env var %q", e, k))
  908. }
  909. return v
  910. }
  911. var clockNow = time.Now
  912. // opt.Bool configs from control.
  913. var (
  914. controlUseDERPRoute atomic.Value
  915. controlTrimWGConfig atomic.Value
  916. )
  917. func setControlAtomic(dst *atomic.Value, v opt.Bool) {
  918. old, ok := dst.Load().(opt.Bool)
  919. if !ok || old != v {
  920. dst.Store(v)
  921. }
  922. }
  923. // DERPRouteFlag reports the last reported value from control for whether
  924. // DERP route optimization (Issue 150) should be enabled.
  925. func DERPRouteFlag() opt.Bool {
  926. v, _ := controlUseDERPRoute.Load().(opt.Bool)
  927. return v
  928. }
  929. // TrimWGConfig reports the last reported value from control for whether
  930. // we should do lazy wireguard configuration.
  931. func TrimWGConfig() opt.Bool {
  932. v, _ := controlTrimWGConfig.Load().(opt.Bool)
  933. return v
  934. }
  935. // ipForwardingBroken reports whether the system's IP forwarding is disabled
  936. // and will definitely not work for the routes provided.
  937. //
  938. // It should not return false positives.
  939. //
  940. // TODO(bradfitz): merge this code into LocalBackend.CheckIPForwarding
  941. // and change controlclient.Options.SkipIPForwardingCheck into a
  942. // func([]netaddr.IPPrefix) error signature instead. Then we only have
  943. // one copy of this code.
  944. func ipForwardingBroken(routes []netaddr.IPPrefix, state *interfaces.State) bool {
  945. if len(routes) == 0 {
  946. // Nothing to route, so no need to warn.
  947. return false
  948. }
  949. if runtime.GOOS != "linux" {
  950. // We only do subnet routing on Linux for now.
  951. // It might work on darwin/macOS when building from source, so
  952. // don't return true for other OSes. We can OS-based warnings
  953. // already in the admin panel.
  954. return false
  955. }
  956. localIPs := map[netaddr.IP]bool{}
  957. for _, addrs := range state.InterfaceIPs {
  958. for _, pfx := range addrs {
  959. localIPs[pfx.IP()] = true
  960. }
  961. }
  962. v4Routes, v6Routes := false, false
  963. for _, r := range routes {
  964. // It's possible to advertise a route to one of the local
  965. // machine's local IPs. IP forwarding isn't required for this
  966. // to work, so we shouldn't warn for such exports.
  967. if r.IsSingleIP() && localIPs[r.IP()] {
  968. continue
  969. }
  970. if r.IP().Is4() {
  971. v4Routes = true
  972. } else {
  973. v6Routes = true
  974. }
  975. }
  976. if v4Routes {
  977. out, err := ioutil.ReadFile("/proc/sys/net/ipv4/ip_forward")
  978. if err != nil {
  979. // Try another way.
  980. out, err = exec.Command("sysctl", "-n", "net.ipv4.ip_forward").Output()
  981. }
  982. if err != nil {
  983. // Oh well, we tried. This is just for debugging.
  984. // We don't want false positives.
  985. // TODO: maybe we want a different warning for inability to check?
  986. return false
  987. }
  988. if strings.TrimSpace(string(out)) == "0" {
  989. return true
  990. }
  991. }
  992. if v6Routes {
  993. // Note: you might be wondering why we check only the state of
  994. // conf.all.forwarding, rather than per-interface forwarding
  995. // configuration. According to kernel documentation, it seems
  996. // that to actually forward packets, you need to enable
  997. // forwarding globally, and the per-interface forwarding
  998. // setting only alters other things such as how router
  999. // advertisements are handled. The kernel itself warns that
  1000. // enabling forwarding per-interface and not globally will
  1001. // probably not work, so I feel okay calling those configs
  1002. // broken until we have proof otherwise.
  1003. out, err := ioutil.ReadFile("/proc/sys/net/ipv6/conf/all/forwarding")
  1004. if err != nil {
  1005. out, err = exec.Command("sysctl", "-n", "net.ipv6.conf.all.forwarding").Output()
  1006. }
  1007. if err != nil {
  1008. // Oh well, we tried. This is just for debugging.
  1009. // We don't want false positives.
  1010. // TODO: maybe we want a different warning for inability to check?
  1011. return false
  1012. }
  1013. if strings.TrimSpace(string(out)) == "0" {
  1014. return true
  1015. }
  1016. }
  1017. return false
  1018. }
  1019. // isUniquePingRequest reports whether pr contains a new PingRequest.URL
  1020. // not already handled, noting its value when returning true.
  1021. func (c *Direct) isUniquePingRequest(pr *tailcfg.PingRequest) bool {
  1022. if pr == nil || pr.URL == "" {
  1023. // Bogus.
  1024. return false
  1025. }
  1026. c.mu.Lock()
  1027. defer c.mu.Unlock()
  1028. if pr.URL == c.lastPingURL {
  1029. return false
  1030. }
  1031. c.lastPingURL = pr.URL
  1032. return true
  1033. }
  1034. func answerPing(logf logger.Logf, c *http.Client, pr *tailcfg.PingRequest) {
  1035. if pr.URL == "" {
  1036. logf("invalid PingRequest with no URL")
  1037. return
  1038. }
  1039. ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
  1040. defer cancel()
  1041. req, err := http.NewRequestWithContext(ctx, "HEAD", pr.URL, nil)
  1042. if err != nil {
  1043. logf("http.NewRequestWithContext(%q): %v", pr.URL, err)
  1044. return
  1045. }
  1046. if pr.Log {
  1047. logf("answerPing: sending ping to %v ...", pr.URL)
  1048. }
  1049. t0 := time.Now()
  1050. _, err = c.Do(req)
  1051. d := time.Since(t0).Round(time.Millisecond)
  1052. if err != nil {
  1053. logf("answerPing error: %v to %v (after %v)", err, pr.URL, d)
  1054. } else if pr.Log {
  1055. logf("answerPing complete to %v (after %v)", pr.URL, d)
  1056. }
  1057. }
  1058. func sleepAsRequested(ctx context.Context, logf logger.Logf, timeoutReset chan<- struct{}, d time.Duration) error {
  1059. const maxSleep = 5 * time.Minute
  1060. if d > maxSleep {
  1061. logf("sleeping for %v, capped from server-requested %v ...", maxSleep, d)
  1062. d = maxSleep
  1063. } else {
  1064. logf("sleeping for server-requested %v ...", d)
  1065. }
  1066. ticker := time.NewTicker(pollTimeout / 2)
  1067. defer ticker.Stop()
  1068. timer := time.NewTimer(d)
  1069. defer timer.Stop()
  1070. for {
  1071. select {
  1072. case <-ctx.Done():
  1073. return ctx.Err()
  1074. case <-timer.C:
  1075. return nil
  1076. case <-ticker.C:
  1077. select {
  1078. case timeoutReset <- struct{}{}:
  1079. case <-timer.C:
  1080. return nil
  1081. case <-ctx.Done():
  1082. return ctx.Err()
  1083. }
  1084. }
  1085. }
  1086. }
  1087. // SetDNS sends the SetDNSRequest request to the control plane server,
  1088. // requesting a DNS record be created or updated.
  1089. func (c *Direct) SetDNS(ctx context.Context, req *tailcfg.SetDNSRequest) (err error) {
  1090. metricSetDNS.Add(1)
  1091. defer func() {
  1092. if err != nil {
  1093. metricSetDNSError.Add(1)
  1094. }
  1095. }()
  1096. c.mu.Lock()
  1097. serverKey := c.serverKey
  1098. c.mu.Unlock()
  1099. if serverKey.IsZero() {
  1100. return errors.New("zero serverKey")
  1101. }
  1102. machinePrivKey, err := c.getMachinePrivKey()
  1103. if err != nil {
  1104. return fmt.Errorf("getMachinePrivKey: %w", err)
  1105. }
  1106. if machinePrivKey.IsZero() {
  1107. return errors.New("getMachinePrivKey returned zero key")
  1108. }
  1109. bodyData, err := encode(req, serverKey, machinePrivKey)
  1110. if err != nil {
  1111. return err
  1112. }
  1113. body := bytes.NewReader(bodyData)
  1114. u := fmt.Sprintf("%s/machine/%s/set-dns", c.serverURL, machinePrivKey.Public().UntypedHexString())
  1115. hreq, err := http.NewRequestWithContext(ctx, "POST", u, body)
  1116. if err != nil {
  1117. return err
  1118. }
  1119. res, err := c.httpc.Do(hreq)
  1120. if err != nil {
  1121. return err
  1122. }
  1123. defer res.Body.Close()
  1124. if res.StatusCode != 200 {
  1125. msg, _ := ioutil.ReadAll(res.Body)
  1126. return fmt.Errorf("set-dns response: %v, %.200s", res.Status, strings.TrimSpace(string(msg)))
  1127. }
  1128. var setDNSRes struct{} // no fields yet
  1129. if err := decode(res, &setDNSRes, serverKey, machinePrivKey); err != nil {
  1130. c.logf("error decoding SetDNSResponse with server key %s and machine key %s: %v", serverKey, machinePrivKey.Public(), err)
  1131. return fmt.Errorf("set-dns-response: %v", err)
  1132. }
  1133. return nil
  1134. }
  1135. // tsmpPing sends a Ping to pr.IP, and sends an http request back to pr.URL
  1136. // with ping response data.
  1137. func tsmpPing(logf logger.Logf, c *http.Client, pr *tailcfg.PingRequest, pinger Pinger) error {
  1138. var err error
  1139. if pr.URL == "" {
  1140. return errors.New("invalid PingRequest with no URL")
  1141. }
  1142. if pr.IP.IsZero() {
  1143. return errors.New("PingRequest without IP")
  1144. }
  1145. if !strings.Contains(pr.Types, "TSMP") {
  1146. return fmt.Errorf("PingRequest with no TSMP in Types, got %q", pr.Types)
  1147. }
  1148. now := time.Now()
  1149. pinger.Ping(pr.IP, true, func(res *ipnstate.PingResult) {
  1150. // Currently does not check for error since we just return if it fails.
  1151. err = postPingResult(now, logf, c, pr, res)
  1152. })
  1153. return err
  1154. }
  1155. func postPingResult(now time.Time, logf logger.Logf, c *http.Client, pr *tailcfg.PingRequest, res *ipnstate.PingResult) error {
  1156. if res.Err != "" {
  1157. return errors.New(res.Err)
  1158. }
  1159. duration := time.Since(now)
  1160. if pr.Log {
  1161. logf("TSMP ping to %v completed in %v seconds. pinger.Ping took %v seconds", pr.IP, res.LatencySeconds, duration.Seconds())
  1162. }
  1163. ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
  1164. defer cancel()
  1165. jsonPingRes, err := json.Marshal(res)
  1166. if err != nil {
  1167. return err
  1168. }
  1169. // Send the results of the Ping, back to control URL.
  1170. req, err := http.NewRequestWithContext(ctx, "POST", pr.URL, bytes.NewBuffer(jsonPingRes))
  1171. if err != nil {
  1172. return fmt.Errorf("http.NewRequestWithContext(%q): %w", pr.URL, err)
  1173. }
  1174. if pr.Log {
  1175. logf("tsmpPing: sending ping results to %v ...", pr.URL)
  1176. }
  1177. t0 := time.Now()
  1178. _, err = c.Do(req)
  1179. d := time.Since(t0).Round(time.Millisecond)
  1180. if err != nil {
  1181. return fmt.Errorf("tsmpPing error: %w to %v (after %v)", err, pr.URL, d)
  1182. } else if pr.Log {
  1183. logf("tsmpPing complete to %v (after %v)", pr.URL, d)
  1184. }
  1185. return nil
  1186. }
  1187. var (
  1188. metricMapRequestsActive = clientmetric.NewGauge("controlclient_map_requests_active")
  1189. metricMapRequests = clientmetric.NewCounter("controlclient_map_requests")
  1190. metricMapRequestsLite = clientmetric.NewCounter("controlclient_map_requests_lite")
  1191. metricMapRequestsPoll = clientmetric.NewCounter("controlclient_map_requests_poll")
  1192. metricMapResponseMessages = clientmetric.NewCounter("controlclient_map_response_message") // any message type
  1193. metricMapResponsePings = clientmetric.NewCounter("controlclient_map_response_ping")
  1194. metricMapResponseKeepAlives = clientmetric.NewCounter("controlclient_map_response_keepalive")
  1195. metricMapResponseMap = clientmetric.NewCounter("controlclient_map_response_map") // any non-keepalive map response
  1196. metricMapResponseMapDelta = clientmetric.NewCounter("controlclient_map_response_map_delta") // 2nd+ non-keepalive map response
  1197. metricSetDNS = clientmetric.NewCounter("controlclient_setdns")
  1198. metricSetDNSError = clientmetric.NewCounter("controlclient_setdns_error")
  1199. )