services.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. /*
  2. * Copyright (c) 2016, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. // Package server implements the core tunnel functionality of a Psiphon server.
  20. // The main function is RunServices, which runs one or all of a Psiphon API web server,
  21. // a tunneling SSH server, and an Obfuscated SSH protocol server. The server configuration
  22. // is created by the GenerateConfig function.
  23. package server
  24. import (
  25. "context"
  26. "fmt"
  27. "math/rand"
  28. "os"
  29. "os/signal"
  30. "runtime"
  31. "runtime/debug"
  32. "sync"
  33. "syscall"
  34. "time"
  35. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/buildinfo"
  37. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/dsl"
  38. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  39. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/osl"
  40. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/packetman"
  41. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tactics"
  42. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tun"
  43. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/server/psinet"
  44. "github.com/shirou/gopsutil/v4/cpu"
  45. )
  46. // RunServices initializes support functions including logging and GeoIP services;
  47. // and then starts the server components and runs them until os.Interrupt or
  48. // os.Kill signals are received. The config determines which components are run.
  49. func RunServices(configJSON []byte) (retErr error) {
  50. loggingInitialized := false
  51. defer func() {
  52. if retErr != nil && loggingInitialized {
  53. log.WithTraceFields(LogFields{"error": retErr}).Error("RunServices failed")
  54. }
  55. }()
  56. rand.Seed(int64(time.Now().Nanosecond()))
  57. config, err := LoadConfig(configJSON)
  58. if err != nil {
  59. return errors.Trace(err)
  60. }
  61. err = InitLogging(config)
  62. if err != nil {
  63. return errors.Trace(err)
  64. }
  65. loggingInitialized = true
  66. if ShouldLogProtobuf() {
  67. defer func() {
  68. ctx, cancel := context.WithTimeout(context.Background(), config.metricWriterShutdownDelay)
  69. defer cancel()
  70. metricSocketWriter.Stop(ctx)
  71. }()
  72. }
  73. err = addHostConfig(config)
  74. if err != nil {
  75. return errors.Trace(err)
  76. }
  77. defer func() {
  78. err := removeHostConfig(config)
  79. if err != nil {
  80. log.WithTraceFields(LogFields{"error": retErr}).Error("removeHostConfig failed")
  81. }
  82. }()
  83. support, err := NewSupportServices(config)
  84. if err != nil {
  85. return errors.Trace(err)
  86. }
  87. startupFields := buildinfo.GetBuildInfo().ToMap()
  88. startupFields["GODEBUG"] = os.Getenv("GODEBUG")
  89. log.WithTraceFields(startupFields).Info("startup")
  90. waitGroup := new(sync.WaitGroup)
  91. shutdownBroadcast := make(chan struct{})
  92. errorChannel := make(chan error, 1)
  93. tunnelServer, err := NewTunnelServer(support, shutdownBroadcast)
  94. if err != nil {
  95. return errors.Trace(err)
  96. }
  97. support.TunnelServer = tunnelServer
  98. if config.RunPacketTunnel {
  99. packetTunnelServer, err := tun.NewServer(&tun.ServerConfig{
  100. Logger: CommonLogger(log),
  101. SudoNetworkConfigCommands: config.PacketTunnelSudoNetworkConfigCommands,
  102. GetDNSResolverIPv4Addresses: support.DNSResolver.GetAllIPv4,
  103. GetDNSResolverIPv6Addresses: support.DNSResolver.GetAllIPv6,
  104. EnableDNSFlowTracking: config.PacketTunnelEnableDNSFlowTracking,
  105. EgressInterface: config.PacketTunnelEgressInterface,
  106. DownstreamPacketQueueSize: config.PacketTunnelDownstreamPacketQueueSize,
  107. SessionIdleExpirySeconds: config.PacketTunnelSessionIdleExpirySeconds,
  108. AllowBogons: config.AllowBogons,
  109. })
  110. if err != nil {
  111. return errors.Trace(err)
  112. }
  113. support.PacketTunnelServer = packetTunnelServer
  114. }
  115. if config.RunPacketManipulator {
  116. packetManipulatorConfig, err := makePacketManipulatorConfig(support)
  117. if err != nil {
  118. return errors.Trace(err)
  119. }
  120. packetManipulator, err := packetman.NewManipulator(packetManipulatorConfig)
  121. if err != nil {
  122. return errors.Trace(err)
  123. }
  124. support.PacketManipulator = packetManipulator
  125. }
  126. if config.DSLRelayServiceAddress != "" {
  127. support.dslRelay, err = dsl.NewRelay(&dsl.RelayConfig{
  128. Logger: CommonLogger(log),
  129. CACertificatesFilename: config.DSLRelayCACertificatesFilename,
  130. HostCertificateFilename: config.DSLRelayHostCertificateFilename,
  131. HostKeyFilename: config.DSLRelayHostKeyFilename,
  132. GetServiceAddress: dslMakeGetServiceAddress(support),
  133. HostID: config.HostID,
  134. APIParameterValidator: getDSLAPIParameterValidator(),
  135. APIParameterLogFieldFormatter: getDSLAPIParameterLogFieldFormatter(),
  136. })
  137. if err != nil {
  138. return errors.Trace(err)
  139. }
  140. err := dslReloadRelayTactics(support)
  141. if err != nil {
  142. return errors.Trace(err)
  143. }
  144. }
  145. support.discovery = makeDiscovery(support)
  146. if config.RunDestBytesLogger() {
  147. support.destBytesLogger = newDestBytesLogger(support)
  148. }
  149. // After this point, errors should be delivered to the errors channel and
  150. // orderly shutdown should flow through to the end of the function to ensure
  151. // all workers are synchronously stopped.
  152. if config.RunPacketTunnel {
  153. support.PacketTunnelServer.Start()
  154. waitGroup.Add(1)
  155. go func() {
  156. defer waitGroup.Done()
  157. <-shutdownBroadcast
  158. support.PacketTunnelServer.Stop()
  159. }()
  160. }
  161. if config.RunPacketManipulator {
  162. err := support.PacketManipulator.Start()
  163. if err != nil {
  164. select {
  165. case errorChannel <- err:
  166. default:
  167. }
  168. } else {
  169. waitGroup.Add(1)
  170. go func() {
  171. defer waitGroup.Done()
  172. <-shutdownBroadcast
  173. support.PacketManipulator.Stop()
  174. }()
  175. }
  176. }
  177. err = support.discovery.Start()
  178. if err != nil {
  179. select {
  180. case errorChannel <- err:
  181. default:
  182. }
  183. } else {
  184. waitGroup.Add(1)
  185. go func() {
  186. defer waitGroup.Done()
  187. <-shutdownBroadcast
  188. support.discovery.Stop()
  189. }()
  190. }
  191. if config.RunLoadMonitor() {
  192. waitGroup.Add(1)
  193. go func() {
  194. defer waitGroup.Done()
  195. ticker := time.NewTicker(time.Duration(config.LoadMonitorPeriodSeconds) * time.Second)
  196. defer ticker.Stop()
  197. logNetworkBytes := true
  198. logCPU := true
  199. previousNetworkBytesReceived, previousNetworkBytesSent, err := getNetworkBytesTransferred()
  200. if err != nil {
  201. log.WithTraceFields(LogFields{"error": errors.Trace(err)}).Error(
  202. "failed to get initial network bytes transferred")
  203. // If getNetworkBytesTransferred fails, stop logging network
  204. // bytes for the lifetime of this process, in case there's a
  205. // persistent issue with /proc/net/dev data.
  206. logNetworkBytes = false
  207. }
  208. // Establish initial previous CPU stats. The previous CPU stats
  209. // are stored internally by gopsutil/cpu.
  210. _, err = getCPUPercent()
  211. if err != nil {
  212. log.WithTraceFields(LogFields{"error": errors.Trace(err)}).Error(
  213. "failed to get initial CPU percent")
  214. logCPU = false
  215. }
  216. for {
  217. select {
  218. case <-shutdownBroadcast:
  219. return
  220. case <-ticker.C:
  221. var networkBytesReceived, networkBytesSent int64
  222. if logNetworkBytes {
  223. currentNetworkBytesReceived, currentNetworkBytesSent, err := getNetworkBytesTransferred()
  224. if err != nil {
  225. log.WithTraceFields(LogFields{"error": errors.Trace(err)}).Error(
  226. "failed to get current network bytes transferred")
  227. logNetworkBytes = false
  228. } else {
  229. networkBytesReceived = currentNetworkBytesReceived - previousNetworkBytesReceived
  230. networkBytesSent = currentNetworkBytesSent - previousNetworkBytesSent
  231. previousNetworkBytesReceived, previousNetworkBytesSent =
  232. currentNetworkBytesReceived, currentNetworkBytesSent
  233. }
  234. }
  235. var CPUPercent float64
  236. if logCPU {
  237. recentCPUPercent, err := getCPUPercent()
  238. if err != nil {
  239. log.WithTraceFields(LogFields{"error": errors.Trace(err)}).Error(
  240. "failed to get recent CPU percent")
  241. logCPU = false
  242. } else {
  243. CPUPercent = recentCPUPercent
  244. }
  245. }
  246. // In the rare case that /proc/net/dev rx or tx counters
  247. // wrap around or are reset, networkBytesReceived or
  248. // networkBytesSent may be < 0. logServerLoad will not
  249. // log these negative values.
  250. logServerLoad(
  251. support, logNetworkBytes, networkBytesReceived, networkBytesSent, logCPU, CPUPercent)
  252. }
  253. }
  254. }()
  255. }
  256. if config.RunPeriodicGarbageCollection() {
  257. waitGroup.Add(1)
  258. go func() {
  259. defer waitGroup.Done()
  260. ticker := time.NewTicker(config.periodicGarbageCollection)
  261. defer ticker.Stop()
  262. for {
  263. select {
  264. case <-shutdownBroadcast:
  265. return
  266. case <-ticker.C:
  267. debug.FreeOSMemory()
  268. }
  269. }
  270. }()
  271. }
  272. if config.RunDestBytesLogger() {
  273. err = support.destBytesLogger.Start()
  274. if err != nil {
  275. select {
  276. case errorChannel <- err:
  277. default:
  278. }
  279. } else {
  280. waitGroup.Add(1)
  281. go func() {
  282. defer waitGroup.Done()
  283. <-shutdownBroadcast
  284. support.destBytesLogger.Stop()
  285. }()
  286. }
  287. }
  288. // The tunnel server is always run; it launches multiple
  289. // listeners, depending on which tunnel protocols are enabled.
  290. waitGroup.Add(1)
  291. go func() {
  292. defer waitGroup.Done()
  293. err := tunnelServer.Run()
  294. select {
  295. case errorChannel <- err:
  296. default:
  297. }
  298. }()
  299. // Shutdown doesn't wait for the outputProcessProfiles goroutine
  300. // to complete, as it may be sleeping while running a "block" or
  301. // CPU profile.
  302. signalProcessProfiles := make(chan struct{}, 1)
  303. go func() {
  304. for {
  305. select {
  306. case <-signalProcessProfiles:
  307. outputProcessProfiles(support.Config, "")
  308. case <-shutdownBroadcast:
  309. return
  310. }
  311. }
  312. }()
  313. // In addition to the actual signal handling here, there is
  314. // a list of signals that need to be passed through panicwrap
  315. // in 'github.com/Psiphon-Labs/psiphon-tunnel-core/Server/main.go'
  316. // where 'panicwrap.Wrap' is called. The handled signals below, and the
  317. // list there must be kept in sync to ensure proper signal handling
  318. // An OS signal triggers an orderly shutdown
  319. systemStopSignal := make(chan os.Signal, 1)
  320. signal.Notify(systemStopSignal, os.Interrupt, syscall.SIGTERM)
  321. // SIGUSR1 triggers a reload of support services
  322. reloadSupportServicesSignal := makeSIGUSR1Channel()
  323. // SIGUSR2 triggers an immediate load log and optional process profile output
  324. logServerLoadSignal := makeSIGUSR2Channel()
  325. // SIGTSTP triggers tunnelServer to stop establishing new tunnels. The
  326. // in-proxy broker, if running, may also stop enqueueing announces or
  327. // offers.
  328. stopEstablishingTunnelsSignal := makeSIGTSTPChannel()
  329. // SIGCONT triggers tunnelServer to resume establishing new tunnels. The
  330. // in-proxy broker, if running, will resume enqueueing all announces and
  331. // offers.
  332. resumeEstablishingTunnelsSignal := makeSIGCONTChannel()
  333. err = nil
  334. loop:
  335. for {
  336. select {
  337. case <-stopEstablishingTunnelsSignal:
  338. tunnelServer.SetEstablishTunnels(false)
  339. // Dump profiles when entering the load limiting state with an
  340. // unexpectedly low established client count, as determined by
  341. // DumpProfilesOnStopEstablishTunnels.
  342. if config.DumpProfilesOnStopEstablishTunnels(
  343. tunnelServer.GetEstablishedClientCount()) {
  344. // Run the profile dump in a goroutine and don't block this loop. Shutdown
  345. // doesn't wait for any running outputProcessProfiles to complete.
  346. go func() {
  347. outputProcessProfiles(support.Config, "stop_establish_tunnels")
  348. }()
  349. }
  350. case <-resumeEstablishingTunnelsSignal:
  351. tunnelServer.SetEstablishTunnels(true)
  352. case <-reloadSupportServicesSignal:
  353. support.Reload()
  354. case <-logServerLoadSignal:
  355. // Signal profiles writes first to ensure some diagnostics are
  356. // available in case logServerLoad hangs (which has happened
  357. // in the past due to a deadlock bug).
  358. select {
  359. case signalProcessProfiles <- struct{}{}:
  360. default:
  361. }
  362. logServerLoad(support, false, 0, 0, false, 0)
  363. case <-systemStopSignal:
  364. log.WithTrace().Info("shutdown by system")
  365. break loop
  366. case err = <-errorChannel:
  367. break loop
  368. }
  369. }
  370. // During any delayed or hung shutdown, periodically dump profiles to help
  371. // diagnose the cause. Shutdown doesn't wait for any running
  372. // outputProcessProfiles to complete.
  373. //
  374. // Wait 10 seconds before the first profile dump, and at least 10
  375. // seconds between profile dumps (longer when
  376. // ProcessCPUProfileDurationSeconds is set).
  377. signalProfileDumperStop := make(chan struct{})
  378. shutdownStartTime := time.Now()
  379. go func() {
  380. for i := 0; i < 3; i++ {
  381. timer := time.NewTimer(10 * time.Second)
  382. select {
  383. case <-signalProfileDumperStop:
  384. timer.Stop()
  385. return
  386. case <-timer.C:
  387. }
  388. filenameSuffix := fmt.Sprintf(
  389. "delayed_shutdown_%ds",
  390. time.Since(shutdownStartTime)/time.Second)
  391. outputProcessProfiles(support.Config, filenameSuffix)
  392. }
  393. }()
  394. close(shutdownBroadcast)
  395. waitGroup.Wait()
  396. close(signalProfileDumperStop)
  397. return err
  398. }
  399. func getRuntimeMetrics() LogFields {
  400. numGoroutine := runtime.NumGoroutine()
  401. var memStats runtime.MemStats
  402. runtime.ReadMemStats(&memStats)
  403. lastGC := ""
  404. if memStats.LastGC > 0 {
  405. lastGC = time.Unix(0, int64(memStats.LastGC)).UTC().Format(time.RFC3339)
  406. }
  407. return LogFields{
  408. "num_goroutine": int64(numGoroutine),
  409. "heap_alloc": int64(memStats.HeapAlloc),
  410. "heap_sys": int64(memStats.HeapSys),
  411. "heap_idle": int64(memStats.HeapIdle),
  412. "heap_inuse": int64(memStats.HeapInuse),
  413. "heap_released": int64(memStats.HeapReleased),
  414. "heap_objects": int64(memStats.HeapObjects),
  415. "num_gc": int64(memStats.NumGC),
  416. "num_forced_gc": int64(memStats.NumForcedGC),
  417. "last_gc": lastGC,
  418. }
  419. }
  420. func outputProcessProfiles(config *Config, filenameSuffix string) {
  421. log.WithTraceFields(getRuntimeMetrics()).Info("runtime_metrics")
  422. if config.ProcessProfileOutputDirectory != "" {
  423. common.WriteRuntimeProfiles(
  424. CommonLogger(log),
  425. config.ProcessProfileOutputDirectory,
  426. filenameSuffix,
  427. config.ProcessBlockProfileDurationSeconds,
  428. config.ProcessCPUProfileDurationSeconds)
  429. }
  430. }
  431. // getCPUPercent returns the overall system CPU percent (not the percent used
  432. // by this process), across all cores.
  433. func getCPUPercent() (float64, error) {
  434. values, err := cpu.Percent(0, false)
  435. if err != nil {
  436. return 0, errors.Trace(err)
  437. }
  438. if len(values) != 1 {
  439. return 0, errors.TraceNew("unexpected cpu.Percent return value")
  440. }
  441. return values[0], nil
  442. }
  443. func logServerLoad(
  444. support *SupportServices,
  445. logNetworkBytes bool,
  446. networkBytesReceived int64,
  447. networkBytesSent int64,
  448. logCPU bool,
  449. CPUPercent float64) {
  450. serverLoad := getRuntimeMetrics()
  451. serverLoad["event_name"] = "server_load"
  452. support.Config.AddServerEntryTag(serverLoad)
  453. if logNetworkBytes {
  454. // Negative values, which may occur due to counter wrap arounds, are
  455. // omitted.
  456. if networkBytesReceived >= 0 {
  457. serverLoad["network_bytes_received"] = networkBytesReceived
  458. }
  459. if networkBytesSent >= 0 {
  460. serverLoad["network_bytes_sent"] = networkBytesSent
  461. }
  462. }
  463. if logCPU {
  464. serverLoad["cpu_percent"] = CPUPercent
  465. }
  466. establishTunnels, establishLimitedCount :=
  467. support.TunnelServer.GetEstablishTunnelsMetrics()
  468. serverLoad["establish_tunnels"] = establishTunnels
  469. serverLoad["establish_tunnels_limited_count"] = establishLimitedCount
  470. serverLoad.Add(support.ReplayCache.GetMetrics())
  471. serverLoad.Add(support.ServerTacticsParametersCache.GetMetrics())
  472. upstreamStats, protocolStats, regionStats :=
  473. support.TunnelServer.GetLoadStats()
  474. for name, value := range upstreamStats {
  475. serverLoad[name] = value
  476. }
  477. for protocol, stats := range protocolStats {
  478. serverLoad[protocol] = stats
  479. }
  480. log.LogRawFieldsWithTimestamp(serverLoad)
  481. for region, regionProtocolStats := range regionStats {
  482. serverLoad := LogFields{
  483. "event_name": "server_load",
  484. "region": region,
  485. }
  486. support.Config.AddServerEntryTag(serverLoad)
  487. for protocol, stats := range regionProtocolStats {
  488. serverLoad[protocol] = stats
  489. }
  490. log.LogRawFieldsWithTimestamp(serverLoad)
  491. }
  492. }
  493. func logIrregularTunnel(
  494. support *SupportServices,
  495. listenerTunnelProtocol string,
  496. listenerPort int,
  497. peerIP string,
  498. tunnelError error,
  499. logFields LogFields) {
  500. if logFields == nil {
  501. logFields = make(LogFields)
  502. }
  503. logFields["event_name"] = "irregular_tunnel"
  504. support.Config.AddServerEntryTag(logFields)
  505. logFields["tunnel_error"] = tunnelError.Error()
  506. if listenerTunnelProtocol != "" {
  507. logFields["listener_protocol"] = listenerTunnelProtocol
  508. logFields["listener_port_number"] = listenerPort
  509. }
  510. if peerIP != "" {
  511. // Note: logging with the "client_" prefix for legacy compatibility; it
  512. // would be more correct to use the prefix "peer_".
  513. support.GeoIPService.Lookup(peerIP).SetClientLogFields(logFields)
  514. }
  515. log.LogRawFieldsWithTimestamp(logFields)
  516. }
  517. // SupportServices carries common and shared data components
  518. // across different server components. SupportServices implements a
  519. // hot reload of traffic rules, psinet database, and geo IP database
  520. // components, which allows these data components to be refreshed
  521. // without restarting the server process.
  522. type SupportServices struct {
  523. // TODO: make all fields non-exported, none are accessed outside
  524. // of this package.
  525. Config *Config
  526. TrafficRulesSet *TrafficRulesSet
  527. OSLConfig *osl.Config
  528. PsinetDatabase *psinet.Database
  529. GeoIPService *GeoIPService
  530. DNSResolver *DNSResolver
  531. TunnelServer *TunnelServer
  532. PacketTunnelServer *tun.Server
  533. TacticsServer *tactics.Server
  534. Blocklist *Blocklist
  535. PacketManipulator *packetman.Manipulator
  536. ReplayCache *ReplayCache
  537. ServerTacticsParametersCache *ServerTacticsParametersCache
  538. dslRelay *dsl.Relay
  539. discovery *Discovery
  540. destBytesLogger *destBytesLogger
  541. }
  542. // NewSupportServices initializes a new SupportServices.
  543. func NewSupportServices(config *Config) (*SupportServices, error) {
  544. trafficRulesSet, err := NewTrafficRulesSet(config.TrafficRulesFilename)
  545. if err != nil {
  546. return nil, errors.Trace(err)
  547. }
  548. oslConfig, err := osl.NewConfig(config.OSLConfigFilename)
  549. if err != nil {
  550. return nil, errors.Trace(err)
  551. }
  552. psinetDatabase, err := psinet.NewDatabase(config.PsinetDatabaseFilename)
  553. if err != nil {
  554. return nil, errors.Trace(err)
  555. }
  556. geoIPService, err := NewGeoIPService(config.GeoIPDatabaseFilenames)
  557. if err != nil {
  558. return nil, errors.Trace(err)
  559. }
  560. dnsResolver, err := NewDNSResolver(config.DNSResolverIPAddress)
  561. if err != nil {
  562. return nil, errors.Trace(err)
  563. }
  564. blocklist, err := NewBlocklist(config.BlocklistFilename)
  565. if err != nil {
  566. return nil, errors.Trace(err)
  567. }
  568. tacticsServer, err := tactics.NewServer(
  569. CommonLogger(log),
  570. getTacticsAPIParameterLogFieldFormatter(),
  571. getTacticsAPIParameterValidator(),
  572. config.TacticsConfigFilename,
  573. config.TacticsRequestPublicKey,
  574. config.TacticsRequestPrivateKey,
  575. config.TacticsRequestObfuscatedKey)
  576. if err != nil {
  577. return nil, errors.Trace(err)
  578. }
  579. support := &SupportServices{
  580. Config: config,
  581. TrafficRulesSet: trafficRulesSet,
  582. OSLConfig: oslConfig,
  583. PsinetDatabase: psinetDatabase,
  584. GeoIPService: geoIPService,
  585. DNSResolver: dnsResolver,
  586. TacticsServer: tacticsServer,
  587. Blocklist: blocklist,
  588. }
  589. support.ReplayCache = NewReplayCache(support)
  590. support.ServerTacticsParametersCache =
  591. NewServerTacticsParametersCache(support)
  592. return support, nil
  593. }
  594. // Reload reinitializes traffic rules, psinet database, and geo IP database
  595. // components. If any component fails to reload, an error is logged and
  596. // Reload proceeds, using the previous state of the component.
  597. func (support *SupportServices) Reload() {
  598. reloaders := append(
  599. []common.Reloader{
  600. support.TrafficRulesSet,
  601. support.OSLConfig,
  602. support.PsinetDatabase,
  603. support.TacticsServer,
  604. support.Blocklist},
  605. support.GeoIPService.Reloaders()...)
  606. if support.dslRelay != nil {
  607. reloaders = append(reloaders, support.dslRelay)
  608. }
  609. reloadDiscovery := func(reloadedTactics bool) {
  610. err := support.discovery.reload(reloadedTactics)
  611. if err != nil {
  612. log.WithTraceFields(
  613. LogFields{"error": errors.Trace(err)}).Warning(
  614. "failed to reload discovery")
  615. return
  616. }
  617. }
  618. // Note: established clients aren't notified when tactics change after a
  619. // reload; new tactics will be obtained on the next client handshake or
  620. // tactics request.
  621. reloadTactics := func() {
  622. // Don't use stale tactics.
  623. support.ReplayCache.Flush()
  624. support.ServerTacticsParametersCache.Flush()
  625. err := support.TunnelServer.ReloadTactics()
  626. if err != nil {
  627. log.WithTraceFields(
  628. LogFields{"error": errors.Trace(err)}).Warning(
  629. "failed to reload tunnel server tactics")
  630. }
  631. if support.Config.RunPacketManipulator {
  632. err := reloadPacketManipulationSpecs(support)
  633. if err != nil {
  634. log.WithTraceFields(
  635. LogFields{"error": errors.Trace(err)}).Warning(
  636. "failed to reload packet manipulation specs")
  637. }
  638. }
  639. reloadDiscovery(true)
  640. if support.dslRelay != nil {
  641. err := dslReloadRelayTactics(support)
  642. if err != nil {
  643. log.WithTraceFields(
  644. LogFields{"error": errors.Trace(err)}).Warning(
  645. "failed to reload DSL relay tactics")
  646. }
  647. }
  648. }
  649. // Take these actions only after the corresponding Reloader has reloaded.
  650. // In both the traffic rules and OSL cases, there is some impact from state
  651. // reset, so the reset should be avoided where possible.
  652. //
  653. // Note: if both tactics and psinet are reloaded at the same time and
  654. // the discovery strategy tactic has changed, then discovery will be reloaded
  655. // twice.
  656. reloadPostActions := map[common.Reloader]func(){
  657. support.TrafficRulesSet: func() { support.TunnelServer.ResetAllClientTrafficRules() },
  658. support.OSLConfig: func() { support.TunnelServer.ResetAllClientOSLConfigs() },
  659. support.TacticsServer: reloadTactics,
  660. support.PsinetDatabase: func() { reloadDiscovery(false) },
  661. }
  662. for _, reloader := range reloaders {
  663. if !reloader.WillReload() {
  664. // Skip logging
  665. continue
  666. }
  667. // "reloaded" flag indicates if file was actually reloaded or ignored
  668. reloaded, err := reloader.Reload()
  669. if reloaded {
  670. if action, ok := reloadPostActions[reloader]; ok {
  671. action()
  672. }
  673. }
  674. if err != nil {
  675. log.WithTraceFields(
  676. LogFields{
  677. "reloader": reloader.ReloadLogDescription(),
  678. "error": err}).Error("reload failed")
  679. // Keep running with previous state
  680. } else {
  681. log.WithTraceFields(
  682. LogFields{
  683. "reloader": reloader.ReloadLogDescription(),
  684. "reloaded": reloaded}).Info("reload success")
  685. }
  686. }
  687. }