server.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  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 ipnserver
  5. import (
  6. "bufio"
  7. "context"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "io/ioutil"
  12. "log"
  13. "net"
  14. "net/http"
  15. "os"
  16. "os/exec"
  17. "os/signal"
  18. "os/user"
  19. "runtime"
  20. "strings"
  21. "sync"
  22. "syscall"
  23. "time"
  24. "inet.af/netaddr"
  25. "tailscale.com/control/controlclient"
  26. "tailscale.com/ipn"
  27. "tailscale.com/log/filelogger"
  28. "tailscale.com/logtail/backoff"
  29. "tailscale.com/net/netstat"
  30. "tailscale.com/safesocket"
  31. "tailscale.com/smallzstd"
  32. "tailscale.com/types/logger"
  33. "tailscale.com/util/pidowner"
  34. "tailscale.com/version"
  35. "tailscale.com/wgengine"
  36. )
  37. // Options is the configuration of the Tailscale node agent.
  38. type Options struct {
  39. // SocketPath, on unix systems, is the unix socket path to listen
  40. // on for frontend connections.
  41. SocketPath string
  42. // Port, on windows, is the localhost TCP port to listen on for
  43. // frontend connections.
  44. Port int
  45. // StatePath is the path to the stored agent state.
  46. StatePath string
  47. // AutostartStateKey, if non-empty, immediately starts the agent
  48. // using the given StateKey. If empty, the agent stays idle and
  49. // waits for a frontend to start it.
  50. AutostartStateKey ipn.StateKey
  51. // LegacyConfigPath optionally specifies the old-style relaynode
  52. // relay.conf location. If both LegacyConfigPath and
  53. // AutostartStateKey are specified and the requested state doesn't
  54. // exist in the backend store, the backend migrates the config
  55. // from LegacyConfigPath.
  56. //
  57. // TODO(danderson): remove some time after the transition to
  58. // tailscaled is done.
  59. LegacyConfigPath string
  60. // SurviveDisconnects specifies how the server reacts to its
  61. // frontend disconnecting. If true, the server keeps running on
  62. // its existing state, and accepts new frontend connections. If
  63. // false, the server dumps its state and becomes idle.
  64. //
  65. // This is effectively whether the platform is in "server
  66. // mode" by default. On Linux, it's true; on Windows, it's
  67. // false. But on some platforms (currently only Windows), the
  68. // "server mode" can be overridden at runtime with a change in
  69. // Prefs.ForceDaemon/WantRunning.
  70. //
  71. // To support CLI connections (notably, "tailscale status"),
  72. // the actual definition of "disconnect" is when the
  73. // connection count transitions from 1 to 0.
  74. SurviveDisconnects bool
  75. // DebugMux, if non-nil, specifies an HTTP ServeMux in which
  76. // to register a debug handler.
  77. DebugMux *http.ServeMux
  78. }
  79. // server is an IPN backend and its set of 0 or more active connections
  80. // talking to an IPN backend.
  81. type server struct {
  82. b *ipn.LocalBackend
  83. logf logger.Logf
  84. // resetOnZero is whether to call bs.Reset on transition from
  85. // 1->0 connections. That is, this is whether the backend is
  86. // being run in "client mode" that requires an active GUI
  87. // connection (such as on Windows by default). Even if this
  88. // is true, the ForceDaemon pref can override this.
  89. resetOnZero bool
  90. bsMu sync.Mutex // lock order: bsMu, then mu
  91. bs *ipn.BackendServer
  92. mu sync.Mutex
  93. serverModeUser *user.User // or nil if not in server mode
  94. lastUserID string // tracks last userid; on change, Reset state for paranoia
  95. allClients map[net.Conn]connIdentity // HTTP or IPN
  96. clients map[net.Conn]bool // subset of allClients; only IPN protocol
  97. disconnectSub map[chan<- struct{}]struct{} // keys are subscribers of disconnects
  98. }
  99. // connIdentity represents the owner of a localhost TCP connection.
  100. type connIdentity struct {
  101. Unknown bool
  102. Pid int
  103. UserID string
  104. User *user.User
  105. }
  106. // getConnIdentity returns the localhost TCP connection's identity information
  107. // (pid, userid, user). If it's not Windows (for now), it returns a nil error
  108. // and a ConnIdentity with Unknown set true. It's only an error if we expected
  109. // to be able to map it and couldn't.
  110. func (s *server) getConnIdentity(c net.Conn) (ci connIdentity, err error) {
  111. if runtime.GOOS != "windows" { // for now; TODO: expand to other OSes
  112. return connIdentity{Unknown: true}, nil
  113. }
  114. la, err := netaddr.ParseIPPort(c.LocalAddr().String())
  115. if err != nil {
  116. return ci, fmt.Errorf("parsing local address: %w", err)
  117. }
  118. ra, err := netaddr.ParseIPPort(c.RemoteAddr().String())
  119. if err != nil {
  120. return ci, fmt.Errorf("parsing local remote: %w", err)
  121. }
  122. if !la.IP.IsLoopback() || !ra.IP.IsLoopback() {
  123. return ci, errors.New("non-loopback connection")
  124. }
  125. tab, err := netstat.Get()
  126. if err != nil {
  127. return ci, fmt.Errorf("failed to get local connection table: %w", err)
  128. }
  129. pid := peerPid(tab.Entries, la, ra)
  130. if pid == 0 {
  131. return ci, errors.New("no local process found matching localhost connection")
  132. }
  133. ci.Pid = pid
  134. uid, err := pidowner.OwnerOfPID(pid)
  135. if err != nil {
  136. var hint string
  137. if runtime.GOOS == "windows" {
  138. hint = " (WSL?)"
  139. }
  140. return ci, fmt.Errorf("failed to map connection's pid to a user%s: %w", hint, err)
  141. }
  142. ci.UserID = uid
  143. u, err := s.lookupUserFromID(uid)
  144. if err != nil {
  145. return ci, fmt.Errorf("failed to look up user from userid: %w", err)
  146. }
  147. ci.User = u
  148. return ci, nil
  149. }
  150. func (s *server) lookupUserFromID(uid string) (*user.User, error) {
  151. u, err := user.LookupId(uid)
  152. if err != nil && runtime.GOOS == "windows" && errors.Is(err, syscall.Errno(0x534)) {
  153. s.logf("[warning] issue 869: os/user.LookupId failed; ignoring")
  154. // Work around https://github.com/tailscale/tailscale/issues/869 for
  155. // now. We don't strictly need the username. It's just a nice-to-have.
  156. // So make up a *user.User if their machine is broken in this way.
  157. return &user.User{
  158. Uid: uid,
  159. Username: "unknown-user-" + uid,
  160. Name: "unknown user " + uid,
  161. }, nil
  162. }
  163. return u, err
  164. }
  165. // blockWhileInUse blocks while until either a Read from conn fails
  166. // (i.e. it's closed) or until the server is able to accept ci as a
  167. // user.
  168. func (s *server) blockWhileInUse(conn io.Reader, ci connIdentity) {
  169. s.logf("blocking client while server in use; connIdentity=%v", ci)
  170. connDone := make(chan struct{})
  171. go func() {
  172. io.Copy(ioutil.Discard, conn)
  173. close(connDone)
  174. }()
  175. ch := make(chan struct{}, 1)
  176. s.registerDisconnectSub(ch, true)
  177. defer s.registerDisconnectSub(ch, false)
  178. for {
  179. select {
  180. case <-connDone:
  181. s.logf("blocked client Read completed; connIdentity=%v", ci)
  182. return
  183. case <-ch:
  184. s.mu.Lock()
  185. err := s.checkConnIdentityLocked(ci)
  186. s.mu.Unlock()
  187. if err == nil {
  188. s.logf("unblocking client, server is free; connIdentity=%v", ci)
  189. // Server is now available again for a new user.
  190. // TODO(bradfitz): keep this connection alive. But for
  191. // now just return and have our caller close the connection
  192. // (which unblocks the io.Copy goroutine we started above)
  193. // and then the client (e.g. Windows) will reconnect and
  194. // discover that it works.
  195. return
  196. }
  197. }
  198. }
  199. }
  200. func (s *server) serveConn(ctx context.Context, c net.Conn, logf logger.Logf) {
  201. // First see if it's an HTTP request.
  202. br := bufio.NewReader(c)
  203. c.SetReadDeadline(time.Now().Add(time.Second))
  204. peek, _ := br.Peek(4)
  205. c.SetReadDeadline(time.Time{})
  206. isHTTPReq := string(peek) == "GET "
  207. ci, err := s.addConn(c, isHTTPReq)
  208. if err != nil {
  209. if isHTTPReq {
  210. fmt.Fprintf(c, "HTTP/1.0 500 Nope\r\nContent-Type: text/plain\r\nX-Content-Type-Options: nosniff\r\n\r\n%s\n", err.Error())
  211. c.Close()
  212. return
  213. }
  214. defer c.Close()
  215. serverToClient := func(b []byte) { ipn.WriteMsg(c, b) }
  216. bs := ipn.NewBackendServer(logf, nil, serverToClient)
  217. _, occupied := err.(inUseOtherUserError)
  218. if occupied {
  219. bs.SendInUseOtherUserErrorMessage(err.Error())
  220. s.blockWhileInUse(c, ci)
  221. } else {
  222. bs.SendErrorMessage(err.Error())
  223. time.Sleep(time.Second)
  224. }
  225. return
  226. }
  227. // Tell the LocalBackend about the identity we're now running as.
  228. s.b.SetCurrentUserID(ci.UserID)
  229. if isHTTPReq {
  230. httpServer := http.Server{
  231. // Localhost connections are cheap; so only do
  232. // keep-alives for a short period of time, as these
  233. // active connections lock the server into only serving
  234. // that user. If the user has this page open, we don't
  235. // want another switching user to be locked out for
  236. // minutes. 5 seconds is enough to let browser hit
  237. // favicon.ico and such.
  238. IdleTimeout: 5 * time.Second,
  239. ErrorLog: logger.StdLogger(logf),
  240. Handler: s.localhostHandler(ci),
  241. }
  242. httpServer.Serve(&oneConnListener{&protoSwitchConn{s: s, br: br, Conn: c}})
  243. return
  244. }
  245. defer s.removeAndCloseConn(c)
  246. logf("incoming control connection")
  247. for ctx.Err() == nil {
  248. msg, err := ipn.ReadMsg(br)
  249. if err != nil {
  250. if ctx.Err() == nil {
  251. logf("ReadMsg: %v", err)
  252. }
  253. return
  254. }
  255. s.bsMu.Lock()
  256. if err := s.bs.GotCommandMsg(msg); err != nil {
  257. logf("GotCommandMsg: %v", err)
  258. }
  259. gotQuit := s.bs.GotQuit
  260. s.bsMu.Unlock()
  261. if gotQuit {
  262. return
  263. }
  264. }
  265. }
  266. // inUseOtherUserError is the error type for when the server is in use
  267. // by a different local user.
  268. type inUseOtherUserError struct{ error }
  269. func (e inUseOtherUserError) Unwrap() error { return e.error }
  270. // checkConnIdentityLocked checks whether the provided identity is
  271. // allowed to connect to the server.
  272. //
  273. // The returned error, when non-nil, will be of type inUseOtherUserError.
  274. //
  275. // s.mu must be held.
  276. func (s *server) checkConnIdentityLocked(ci connIdentity) error {
  277. // If clients are already connected, verify they're the same user.
  278. // This mostly matters on Windows at the moment.
  279. if len(s.allClients) > 0 {
  280. var active connIdentity
  281. for _, active = range s.allClients {
  282. break
  283. }
  284. if ci.UserID != active.UserID {
  285. //lint:ignore ST1005 we want to capitalize Tailscale here
  286. return inUseOtherUserError{fmt.Errorf("Tailscale already in use by %s, pid %d", active.User.Username, active.Pid)}
  287. }
  288. }
  289. if su := s.serverModeUser; su != nil && ci.UserID != su.Uid {
  290. //lint:ignore ST1005 we want to capitalize Tailscale here
  291. return inUseOtherUserError{fmt.Errorf("Tailscale already in use by %s", su.Username)}
  292. }
  293. return nil
  294. }
  295. // registerDisconnectSub adds ch as a subscribe to connection disconnect
  296. // events. If add is false, the subscriber is removed.
  297. func (s *server) registerDisconnectSub(ch chan<- struct{}, add bool) {
  298. s.mu.Lock()
  299. defer s.mu.Unlock()
  300. if add {
  301. if s.disconnectSub == nil {
  302. s.disconnectSub = make(map[chan<- struct{}]struct{})
  303. }
  304. s.disconnectSub[ch] = struct{}{}
  305. } else {
  306. delete(s.disconnectSub, ch)
  307. }
  308. }
  309. // addConn adds c to the server's list of clients.
  310. //
  311. // If the returned error is of type inUseOtherUserError then the
  312. // returned connIdentity is also valid.
  313. func (s *server) addConn(c net.Conn, isHTTP bool) (ci connIdentity, err error) {
  314. ci, err = s.getConnIdentity(c)
  315. if err != nil {
  316. return
  317. }
  318. // If the connected user changes, reset the backend server state to make
  319. // sure node keys don't leak between users.
  320. var doReset bool
  321. defer func() {
  322. if doReset {
  323. s.logf("identity changed; resetting server")
  324. s.bsMu.Lock()
  325. s.bs.Reset()
  326. s.bsMu.Unlock()
  327. }
  328. }()
  329. s.mu.Lock()
  330. defer s.mu.Unlock()
  331. if s.clients == nil {
  332. s.clients = map[net.Conn]bool{}
  333. }
  334. if s.allClients == nil {
  335. s.allClients = map[net.Conn]connIdentity{}
  336. }
  337. if err := s.checkConnIdentityLocked(ci); err != nil {
  338. return ci, err
  339. }
  340. if !isHTTP {
  341. s.clients[c] = true
  342. }
  343. s.allClients[c] = ci
  344. if s.lastUserID != ci.UserID {
  345. if s.lastUserID != "" {
  346. doReset = true
  347. }
  348. s.lastUserID = ci.UserID
  349. }
  350. return ci, nil
  351. }
  352. func (s *server) removeAndCloseConn(c net.Conn) {
  353. s.mu.Lock()
  354. delete(s.clients, c)
  355. delete(s.allClients, c)
  356. remain := len(s.allClients)
  357. for sub := range s.disconnectSub {
  358. select {
  359. case sub <- struct{}{}:
  360. default:
  361. }
  362. }
  363. s.mu.Unlock()
  364. if remain == 0 && s.resetOnZero {
  365. if s.b.InServerMode() {
  366. s.logf("client disconnected; staying alive in server mode")
  367. } else {
  368. s.logf("client disconnected; stopping server")
  369. s.bsMu.Lock()
  370. s.bs.Reset()
  371. s.bsMu.Unlock()
  372. }
  373. }
  374. c.Close()
  375. }
  376. func (s *server) stopAll() {
  377. s.mu.Lock()
  378. defer s.mu.Unlock()
  379. for c := range s.clients {
  380. safesocket.ConnCloseRead(c)
  381. safesocket.ConnCloseWrite(c)
  382. }
  383. s.clients = nil
  384. }
  385. // setServerModeUserLocked is called when we're in server mode but our s.serverModeUser is nil.
  386. //
  387. // s.mu must be held
  388. func (s *server) setServerModeUserLocked() {
  389. var ci connIdentity
  390. var ok bool
  391. for _, ci = range s.allClients {
  392. ok = true
  393. break
  394. }
  395. if !ok {
  396. s.logf("ipnserver: [unexpected] now in server mode, but no connected client")
  397. return
  398. }
  399. if ci.Unknown {
  400. return
  401. }
  402. if ci.User != nil {
  403. s.logf("ipnserver: now in server mode; user=%v", ci.User.Username)
  404. s.serverModeUser = ci.User
  405. } else {
  406. s.logf("ipnserver: [unexpected] now in server mode, but nil User")
  407. }
  408. }
  409. func (s *server) writeToClients(b []byte) {
  410. inServerMode := s.b.InServerMode()
  411. s.mu.Lock()
  412. defer s.mu.Unlock()
  413. if inServerMode {
  414. if s.serverModeUser == nil {
  415. s.setServerModeUserLocked()
  416. }
  417. } else {
  418. if s.serverModeUser != nil {
  419. s.logf("ipnserver: no longer in server mode")
  420. s.serverModeUser = nil
  421. }
  422. }
  423. for c := range s.clients {
  424. ipn.WriteMsg(c, b)
  425. }
  426. }
  427. // Run runs a Tailscale backend service.
  428. // The getEngine func is called repeatedly, once per connection, until it returns an engine successfully.
  429. func Run(ctx context.Context, logf logger.Logf, logid string, getEngine func() (wgengine.Engine, error), opts Options) error {
  430. runDone := make(chan struct{})
  431. defer close(runDone)
  432. listen, _, err := safesocket.Listen(opts.SocketPath, uint16(opts.Port))
  433. if err != nil {
  434. return fmt.Errorf("safesocket.Listen: %v", err)
  435. }
  436. server := &server{
  437. logf: logf,
  438. resetOnZero: !opts.SurviveDisconnects,
  439. }
  440. // When the context is closed or when we return, whichever is first, close our listner
  441. // and all open connections.
  442. go func() {
  443. select {
  444. case <-ctx.Done():
  445. case <-runDone:
  446. }
  447. server.stopAll()
  448. listen.Close()
  449. }()
  450. logf("Listening on %v", listen.Addr())
  451. bo := backoff.NewBackoff("ipnserver", logf, 30*time.Second)
  452. var unservedConn net.Conn // if non-nil, accepted, but hasn't served yet
  453. eng, err := getEngine()
  454. if err != nil {
  455. logf("ipnserver: initial getEngine call: %v", err)
  456. for i := 1; ctx.Err() == nil; i++ {
  457. c, err := listen.Accept()
  458. if err != nil {
  459. logf("%d: Accept: %v", i, err)
  460. bo.BackOff(ctx, err)
  461. continue
  462. }
  463. logf("ipnserver: try%d: trying getEngine again...", i)
  464. eng, err = getEngine()
  465. if err == nil {
  466. logf("%d: GetEngine worked; exiting failure loop", i)
  467. unservedConn = c
  468. break
  469. }
  470. logf("ipnserver%d: getEngine failed again: %v", i, err)
  471. errMsg := err.Error()
  472. go func() {
  473. defer c.Close()
  474. serverToClient := func(b []byte) { ipn.WriteMsg(c, b) }
  475. bs := ipn.NewBackendServer(logf, nil, serverToClient)
  476. bs.SendErrorMessage(errMsg)
  477. time.Sleep(time.Second)
  478. }()
  479. }
  480. if err := ctx.Err(); err != nil {
  481. return err
  482. }
  483. }
  484. var store ipn.StateStore
  485. if opts.StatePath != "" {
  486. store, err = ipn.NewFileStore(opts.StatePath)
  487. if err != nil {
  488. return fmt.Errorf("ipn.NewFileStore(%q): %v", opts.StatePath, err)
  489. }
  490. if opts.AutostartStateKey == "" {
  491. autoStartKey, err := store.ReadState(ipn.ServerModeStartKey)
  492. if err != nil && err != ipn.ErrStateNotExist {
  493. return fmt.Errorf("calling ReadState on %s: %w", opts.StatePath, err)
  494. }
  495. key := string(autoStartKey)
  496. if strings.HasPrefix(key, "user-") {
  497. uid := strings.TrimPrefix(key, "user-")
  498. u, err := server.lookupUserFromID(uid)
  499. if err != nil {
  500. logf("ipnserver: found server mode auto-start key %q; failed to load user: %v", key, err)
  501. } else {
  502. logf("ipnserver: found server mode auto-start key %q (user %s)", key, u.Username)
  503. server.serverModeUser = u
  504. }
  505. opts.AutostartStateKey = ipn.StateKey(key)
  506. }
  507. }
  508. } else {
  509. store = &ipn.MemoryStore{}
  510. }
  511. b, err := ipn.NewLocalBackend(logf, logid, store, eng)
  512. if err != nil {
  513. return fmt.Errorf("NewLocalBackend: %v", err)
  514. }
  515. defer b.Shutdown()
  516. b.SetDecompressor(func() (controlclient.Decompressor, error) {
  517. return smallzstd.NewDecoder(nil)
  518. })
  519. if opts.DebugMux != nil {
  520. opts.DebugMux.HandleFunc("/debug/ipn", func(w http.ResponseWriter, r *http.Request) {
  521. serveHTMLStatus(w, b)
  522. })
  523. }
  524. server.b = b
  525. server.bs = ipn.NewBackendServer(logf, b, server.writeToClients)
  526. if opts.AutostartStateKey != "" {
  527. server.bs.GotCommand(&ipn.Command{
  528. Version: version.Long,
  529. Start: &ipn.StartArgs{
  530. Opts: ipn.Options{
  531. StateKey: opts.AutostartStateKey,
  532. LegacyConfigPath: opts.LegacyConfigPath,
  533. },
  534. },
  535. })
  536. }
  537. for i := 1; ctx.Err() == nil; i++ {
  538. var c net.Conn
  539. var err error
  540. if unservedConn != nil {
  541. c = unservedConn
  542. unservedConn = nil
  543. } else {
  544. c, err = listen.Accept()
  545. }
  546. if err != nil {
  547. if ctx.Err() == nil {
  548. logf("ipnserver: Accept: %v", err)
  549. bo.BackOff(ctx, err)
  550. }
  551. continue
  552. }
  553. go server.serveConn(ctx, c, logger.WithPrefix(logf, fmt.Sprintf("ipnserver: conn%d: ", i)))
  554. }
  555. return ctx.Err()
  556. }
  557. // BabysitProc runs the current executable as a child process with the
  558. // provided args, capturing its output, writing it to files, and
  559. // restarting the process on any crashes.
  560. //
  561. // It's only currently (2020-10-29) used on Windows.
  562. func BabysitProc(ctx context.Context, args []string, logf logger.Logf) {
  563. executable, err := os.Executable()
  564. if err != nil {
  565. panic("cannot determine executable: " + err.Error())
  566. }
  567. if runtime.GOOS == "windows" {
  568. if len(args) != 2 && args[0] != "/subproc" {
  569. panic(fmt.Sprintf("unexpected arguments %q", args))
  570. }
  571. logID := args[1]
  572. logf = filelogger.New("tailscale-service", logID, logf)
  573. }
  574. var proc struct {
  575. mu sync.Mutex
  576. p *os.Process
  577. }
  578. done := make(chan struct{})
  579. go func() {
  580. interrupt := make(chan os.Signal, 1)
  581. signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM)
  582. var sig os.Signal
  583. select {
  584. case sig = <-interrupt:
  585. logf("BabysitProc: got signal: %v", sig)
  586. close(done)
  587. case <-ctx.Done():
  588. logf("BabysitProc: context done")
  589. sig = os.Kill
  590. close(done)
  591. }
  592. proc.mu.Lock()
  593. proc.p.Signal(sig)
  594. proc.mu.Unlock()
  595. }()
  596. bo := backoff.NewBackoff("BabysitProc", logf, 30*time.Second)
  597. for {
  598. startTime := time.Now()
  599. log.Printf("exec: %#v %v", executable, args)
  600. cmd := exec.Command(executable, args...)
  601. // Create a pipe object to use as the subproc's stdin.
  602. // When the writer goes away, the reader gets EOF.
  603. // A subproc can watch its stdin and exit when it gets EOF;
  604. // this is a very reliable way to have a subproc die when
  605. // its parent (us) disappears.
  606. // We never need to actually write to wStdin.
  607. rStdin, wStdin, err := os.Pipe()
  608. if err != nil {
  609. log.Printf("os.Pipe 1: %v", err)
  610. return
  611. }
  612. // Create a pipe object to use as the subproc's stdout/stderr.
  613. // We'll read from this pipe and send it to logf, line by line.
  614. // We can't use os.exec's io.Writer for this because it
  615. // doesn't care about lines, and thus ends up merging multiple
  616. // log lines into one or splitting one line into multiple
  617. // logf() calls. bufio is more appropriate.
  618. rStdout, wStdout, err := os.Pipe()
  619. if err != nil {
  620. log.Printf("os.Pipe 2: %v", err)
  621. }
  622. go func(r *os.File) {
  623. defer r.Close()
  624. rb := bufio.NewReader(r)
  625. for {
  626. s, err := rb.ReadString('\n')
  627. if s != "" {
  628. logf("%s", s)
  629. }
  630. if err != nil {
  631. break
  632. }
  633. }
  634. }(rStdout)
  635. cmd.Stdin = rStdin
  636. cmd.Stdout = wStdout
  637. cmd.Stderr = wStdout
  638. err = cmd.Start()
  639. // Now that the subproc is started, get rid of our copy of the
  640. // pipe reader. Bad things happen on Windows if more than one
  641. // process owns the read side of a pipe.
  642. rStdin.Close()
  643. wStdout.Close()
  644. if err != nil {
  645. log.Printf("starting subprocess failed: %v", err)
  646. } else {
  647. proc.mu.Lock()
  648. proc.p = cmd.Process
  649. proc.mu.Unlock()
  650. err = cmd.Wait()
  651. log.Printf("subprocess exited: %v", err)
  652. }
  653. // If the process finishes, clean up the write side of the
  654. // pipe. We'll make a new one when we restart the subproc.
  655. wStdin.Close()
  656. if time.Since(startTime) < 60*time.Second {
  657. bo.BackOff(ctx, fmt.Errorf("subproc early exit: %v", err))
  658. } else {
  659. // Reset the timeout, since the process ran for a while.
  660. bo.BackOff(ctx, nil)
  661. }
  662. select {
  663. case <-done:
  664. return
  665. default:
  666. }
  667. }
  668. }
  669. // FixedEngine returns a func that returns eng and a nil error.
  670. func FixedEngine(eng wgengine.Engine) func() (wgengine.Engine, error) {
  671. return func() (wgengine.Engine, error) { return eng, nil }
  672. }
  673. type dummyAddr string
  674. type oneConnListener struct {
  675. conn net.Conn
  676. }
  677. func (l *oneConnListener) Accept() (c net.Conn, err error) {
  678. c = l.conn
  679. if c == nil {
  680. err = io.EOF
  681. return
  682. }
  683. err = nil
  684. l.conn = nil
  685. return
  686. }
  687. func (l *oneConnListener) Close() error { return nil }
  688. func (l *oneConnListener) Addr() net.Addr { return dummyAddr("unused-address") }
  689. func (a dummyAddr) Network() string { return string(a) }
  690. func (a dummyAddr) String() string { return string(a) }
  691. // protoSwitchConn is a net.Conn that's we want to speak HTTP to but
  692. // it's already had a few bytes read from it to determine that it's
  693. // HTTP. So we Read from its bufio.Reader. On Close, we we tell the
  694. // server it's closed, so the server can account the who's connected.
  695. type protoSwitchConn struct {
  696. s *server
  697. net.Conn
  698. br *bufio.Reader
  699. closeOnce sync.Once
  700. }
  701. func (psc *protoSwitchConn) Read(p []byte) (int, error) { return psc.br.Read(p) }
  702. func (psc *protoSwitchConn) Close() error {
  703. psc.closeOnce.Do(func() { psc.s.removeAndCloseConn(psc.Conn) })
  704. return nil
  705. }
  706. func (s *server) localhostHandler(ci connIdentity) http.Handler {
  707. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  708. if ci.Unknown {
  709. io.WriteString(w, "<html><title>Tailscale</title><body><h1>Tailscale</h1>This is the local Tailscale daemon.")
  710. return
  711. }
  712. serveHTMLStatus(w, s.b)
  713. })
  714. }
  715. func serveHTMLStatus(w http.ResponseWriter, b *ipn.LocalBackend) {
  716. w.Header().Set("Content-Type", "text/html; charset=utf-8")
  717. st := b.Status()
  718. // TODO(bradfitz): add LogID and opts to st?
  719. st.WriteHTML(w)
  720. }
  721. func peerPid(entries []netstat.Entry, la, ra netaddr.IPPort) int {
  722. for _, e := range entries {
  723. if e.Local == ra && e.Remote == la {
  724. return e.Pid
  725. }
  726. }
  727. return 0
  728. }