config.go 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263
  1. /*
  2. * Copyright (c) 2015, 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 psiphon
  20. import (
  21. "crypto/md5"
  22. "encoding/base64"
  23. "encoding/binary"
  24. "encoding/json"
  25. "fmt"
  26. "io/ioutil"
  27. "net/http"
  28. "os"
  29. "path/filepath"
  30. "regexp"
  31. "strconv"
  32. "strings"
  33. "sync"
  34. "unicode"
  35. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  37. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
  38. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
  39. )
  40. const (
  41. TUNNEL_POOL_SIZE = 1
  42. MAX_TUNNEL_POOL_SIZE = 32
  43. // Psiphon data directory name, relative to config.DataRootDirectory.
  44. // See config.GetPsiphonDataDirectory().
  45. PsiphonDataDirectoryName = "ca.psiphon.PsiphonTunnel.tunnel-core"
  46. // Filename constants, all relative to config.GetPsiphonDataDirectory().
  47. HomepageFilename = "homepage"
  48. NoticesFilename = "notices"
  49. OldNoticesFilename = "notices.1"
  50. UpgradeDownloadFilename = "upgrade"
  51. )
  52. // Config is the Psiphon configuration specified by the application. This
  53. // configuration controls the behavior of the core tunnel functionality.
  54. //
  55. // To distinguish omitted timeout params from explicit 0 value timeout params,
  56. // corresponding fields are int pointers. nil means no value was supplied and
  57. // to use the default; a non-nil pointer to 0 means no timeout.
  58. type Config struct {
  59. // DataRootDirectory is the directory in which to store persistent files,
  60. // which contain information such as server entries. By default, current
  61. // working directory.
  62. //
  63. // Psiphon will assume full control of files under this directory. They may
  64. // be deleted, moved or overwritten.
  65. DataRootDirectory string
  66. // UseNoticeFiles configures notice files for writing. If set, homepages
  67. // will be written to a file created at config.GetHomePageFilename()
  68. // and notices will be written to a file created at
  69. // config.GetNoticesFilename().
  70. //
  71. // The homepage file may be read after the Tunnels notice with count of 1.
  72. //
  73. // The value of UseNoticeFiles sets the size and frequency at which the
  74. // notices file, config.GetNoticesFilename(), will be rotated. See the
  75. // comment for UseNoticeFiles for more details. One rotated older file,
  76. // config.GetOldNoticesFilename(), is retained.
  77. //
  78. // The notice files may be may be read at any time; and should be opened
  79. // read-only for reading. Diagnostic notices are omitted from the notice
  80. // files.
  81. //
  82. // See comment for setNoticeFiles in notice.go for further details.
  83. UseNoticeFiles *UseNoticeFiles
  84. // PropagationChannelId is a string identifier which indicates how the
  85. // Psiphon client was distributed. This parameter is required. This value
  86. // is supplied by and depends on the Psiphon Network, and is typically
  87. // embedded in the client binary.
  88. PropagationChannelId string
  89. // SponsorId is a string identifier which indicates who is sponsoring this
  90. // Psiphon client. One purpose of this value is to determine the home
  91. // pages for display. This parameter is required. This value is supplied
  92. // by and depends on the Psiphon Network, and is typically embedded in the
  93. // client binary.
  94. SponsorId string
  95. // ClientVersion is the client version number that the client reports to
  96. // the server. The version number refers to the host client application,
  97. // not the core tunnel library. One purpose of this value is to enable
  98. // automatic updates. This value is supplied by and depends on the Psiphon
  99. // Network, and is typically embedded in the client binary.
  100. //
  101. // Note that sending a ClientPlatform string which includes "windows"
  102. // (case insensitive) and a ClientVersion of <= 44 will cause an error in
  103. // processing the response to DoConnectedRequest calls.
  104. ClientVersion string
  105. // ClientPlatform is the client platform ("Windows", "Android", etc.) that
  106. // the client reports to the server.
  107. ClientPlatform string
  108. // ClientFeatures is a list of feature names denoting enabled application
  109. // features. Clients report enabled features to the server for stats
  110. // purposes.
  111. ClientFeatures []string
  112. // EgressRegion is a ISO 3166-1 alpha-2 country code which indicates which
  113. // country to egress from. For the default, "", the best performing server
  114. // in any country is selected.
  115. EgressRegion string
  116. // EnableSplitTunnel toggles split tunnel mode. When enabled, TCP port
  117. // forward destinations that resolve to the same GeoIP country as the client
  118. // are connected to directly, untunneled.
  119. EnableSplitTunnel bool
  120. // ListenInterface specifies which interface to listen on. If no
  121. // interface is provided then listen on 127.0.0.1. If 'any' is provided
  122. // then use 0.0.0.0. If there are multiple IP addresses on an interface
  123. // use the first IPv4 address.
  124. ListenInterface string
  125. // DisableLocalSocksProxy disables running the local SOCKS proxy.
  126. DisableLocalSocksProxy bool
  127. // LocalSocksProxyPort specifies a port number for the local SOCKS proxy
  128. // running at 127.0.0.1. For the default value, 0, the system selects a
  129. // free port (a notice reporting the selected port is emitted).
  130. LocalSocksProxyPort int
  131. // LocalHttpProxyPort specifies a port number for the local HTTP proxy
  132. // running at 127.0.0.1. For the default value, 0, the system selects a
  133. // free port (a notice reporting the selected port is emitted).
  134. LocalHttpProxyPort int
  135. // DisableLocalHTTPProxy disables running the local HTTP proxy.
  136. DisableLocalHTTPProxy bool
  137. // NetworkLatencyMultiplier is a multiplier that is to be applied to
  138. // default network event timeouts. Set this to tune performance for
  139. // slow networks.
  140. // When set, must be >= 1.0.
  141. NetworkLatencyMultiplier float64
  142. // LimitTunnelProtocols indicates which protocols to use. Valid values
  143. // include: "SSH", "OSSH", "UNFRONTED-MEEK-OSSH",
  144. // "UNFRONTED-MEEK-HTTPS-OSSH", "UNFRONTED-MEEK-SESSION-TICKET-OSSH",
  145. // "FRONTED-MEEK-OSSH", "FRONTED-MEEK-HTTP-OSSH", "QUIC-OSSH",
  146. // "FRONTED-MEEK-QUIC-OSSH", "MARIONETTE-OSSH", "TAPDANCE-OSSH", and
  147. // "CONJURE-OSSH".
  148. // For the default, an empty list, all protocols are used.
  149. LimitTunnelProtocols []string
  150. // InitialLimitTunnelProtocols is an optional initial phase of limited
  151. // protocols for the first InitialLimitTunnelProtocolsCandidateCount
  152. // candidates; after these candidates, LimitTunnelProtocols applies.
  153. //
  154. // For the default, an empty list, InitialLimitTunnelProtocols is off.
  155. InitialLimitTunnelProtocols []string
  156. // InitialLimitTunnelProtocolsCandidateCount is the number of candidates
  157. // to which InitialLimitTunnelProtocols is applied instead of
  158. // LimitTunnelProtocols.
  159. //
  160. // For the default, 0, InitialLimitTunnelProtocols is off.
  161. InitialLimitTunnelProtocolsCandidateCount int
  162. // LimitTLSProfiles indicates which TLS profiles to select from. Valid
  163. // values are listed in protocols.SupportedTLSProfiles.
  164. // For the default, an empty list, all profiles are candidates for
  165. // selection.
  166. LimitTLSProfiles []string
  167. // LimitQUICVersions indicates which QUIC versions to select from. Valid
  168. // values are listed in protocols.SupportedQUICVersions.
  169. // For the default, an empty list, all versions are candidates for
  170. // selection.
  171. LimitQUICVersions []string
  172. // EstablishTunnelTimeoutSeconds specifies a time limit after which to
  173. // halt the core tunnel controller if no tunnel has been established. The
  174. // default is parameters.EstablishTunnelTimeout.
  175. EstablishTunnelTimeoutSeconds *int
  176. // EstablishTunnelPausePeriodSeconds specifies the delay between attempts
  177. // to establish tunnels. Briefly pausing allows for network conditions to
  178. // improve and for asynchronous operations such as fetch remote server
  179. // list to complete. If omitted, a default value is used. This value is
  180. // typical overridden for testing.
  181. EstablishTunnelPausePeriodSeconds *int
  182. // EstablishTunnelPausePeriodSeconds specifies the grace period, or head
  183. // start, provided to the affinity server candidate when establishing. The
  184. // affinity server is the server used for the last established tunnel.
  185. EstablishTunnelServerAffinityGracePeriodMilliseconds *int
  186. // ConnectionWorkerPoolSize specifies how many connection attempts to
  187. // attempt in parallel. If omitted of when 0, a default is used; this is
  188. // recommended.
  189. ConnectionWorkerPoolSize int
  190. // TunnelPoolSize specifies how many tunnels to run in parallel. Port
  191. // forwards are multiplexed over multiple tunnels. If omitted or when 0,
  192. // the default is TUNNEL_POOL_SIZE, which is recommended. Any value over
  193. // MAX_TUNNEL_POOL_SIZE is treated as MAX_TUNNEL_POOL_SIZE.
  194. TunnelPoolSize int
  195. // StaggerConnectionWorkersMilliseconds adds a specified delay before
  196. // making each server candidate available to connection workers. This
  197. // option is enabled when StaggerConnectionWorkersMilliseconds > 0.
  198. StaggerConnectionWorkersMilliseconds int
  199. // LimitIntensiveConnectionWorkers limits the number of concurrent
  200. // connection workers attempting connections with resource intensive
  201. // protocols. This option is enabled when LimitIntensiveConnectionWorkers
  202. // > 0.
  203. LimitIntensiveConnectionWorkers int
  204. // LimitMeekBufferSizes selects smaller buffers for meek protocols.
  205. LimitMeekBufferSizes bool
  206. // IgnoreHandshakeStatsRegexps skips compiling and using stats regexes.
  207. IgnoreHandshakeStatsRegexps bool
  208. // UpstreamProxyURL is a URL specifying an upstream proxy to use for all
  209. // outbound connections. The URL should include proxy type and
  210. // authentication information, as required. See example URLs here:
  211. // https://github.com/Psiphon-Labs/psiphon-tunnel-core/tree/master/psiphon/upstreamproxy
  212. UpstreamProxyURL string
  213. // CustomHeaders is a set of additional arbitrary HTTP headers that are
  214. // added to all plaintext HTTP requests and requests made through an HTTP
  215. // upstream proxy when specified by UpstreamProxyURL.
  216. CustomHeaders http.Header
  217. // NetworkConnectivityChecker is an interface that enables tunnel-core to
  218. // call into the host application to check for network connectivity. See:
  219. // NetworkConnectivityChecker doc.
  220. NetworkConnectivityChecker NetworkConnectivityChecker
  221. // DeviceBinder is an interface that enables tunnel-core to call into the
  222. // host application to bind sockets to specific devices. See: DeviceBinder
  223. // doc.
  224. //
  225. // When DeviceBinder is set, the "VPN" feature name is automatically added
  226. // when reporting ClientFeatures.
  227. DeviceBinder DeviceBinder
  228. // IPv6Synthesizer is an interface that allows tunnel-core to call into
  229. // the host application to synthesize IPv6 addresses. See: IPv6Synthesizer
  230. // doc.
  231. IPv6Synthesizer IPv6Synthesizer
  232. // DnsServerGetter is an interface that enables tunnel-core to call into
  233. // the host application to discover the native network DNS server
  234. // settings. See: DnsServerGetter doc.
  235. DnsServerGetter DnsServerGetter
  236. // NetworkIDGetter in an interface that enables tunnel-core to call into
  237. // the host application to get an identifier for the host's current active
  238. // network. See: NetworkIDGetter doc.
  239. NetworkIDGetter NetworkIDGetter
  240. // NetworkID, when not blank, is used as the identifier for the host's
  241. // current active network.
  242. // NetworkID is ignored when NetworkIDGetter is set.
  243. NetworkID string
  244. // DisableTactics disables tactics operations including requests, payload
  245. // handling, and application of parameters.
  246. DisableTactics bool
  247. // DisableReplay causes any persisted dial parameters to be ignored when
  248. // they would otherwise be used for replay.
  249. DisableReplay bool
  250. // TargetServerEntry is an encoded server entry. When specified, this
  251. // server entry is used exclusively and all other known servers are
  252. // ignored; also, when set, ConnectionWorkerPoolSize is ignored and
  253. // the pool size is 1.
  254. TargetServerEntry string
  255. // DisableApi disables Psiphon server API calls including handshake,
  256. // connected, status, etc. This is used for special case temporary tunnels
  257. // (Windows VPN mode).
  258. DisableApi bool
  259. // TargetApiProtocol specifies whether to force use of "ssh" or "web" API
  260. // protocol. When blank, the default, the optimal API protocol is used.
  261. // Note that this capability check is not applied before the
  262. // "CandidateServers" count is emitted.
  263. //
  264. // This parameter is intended for testing and debugging only. Not all
  265. // parameters are supported in the legacy "web" API protocol, including
  266. // speed test samples.
  267. TargetApiProtocol string
  268. // RemoteServerListURLs is list of URLs which specify locations to fetch
  269. // out-of-band server entries. This facility is used when a tunnel cannot
  270. // be established to known servers. This value is supplied by and depends
  271. // on the Psiphon Network, and is typically embedded in the client binary.
  272. // All URLs must point to the same entity with the same ETag. At least one
  273. // TransferURL must have OnlyAfterAttempts = 0.
  274. RemoteServerListURLs parameters.TransferURLs
  275. // RemoteServerListSignaturePublicKey specifies a public key that's used
  276. // to authenticate the remote server list payload. This value is supplied
  277. // by and depends on the Psiphon Network, and is typically embedded in the
  278. // client binary.
  279. RemoteServerListSignaturePublicKey string
  280. // DisableRemoteServerListFetcher disables fetching remote server lists.
  281. // This is used for special case temporary tunnels.
  282. DisableRemoteServerListFetcher bool
  283. // FetchRemoteServerListRetryPeriodMilliseconds specifies the delay before
  284. // resuming a remote server list download after a failure. If omitted, a
  285. // default value is used. This value is typical overridden for testing.
  286. FetchRemoteServerListRetryPeriodMilliseconds *int
  287. // ObfuscatedServerListRootURLs is a list of URLs which specify root
  288. // locations from which to fetch obfuscated server list files. This value
  289. // is supplied by and depends on the Psiphon Network, and is typically
  290. // embedded in the client binary. All URLs must point to the same entity
  291. // with the same ETag. At least one DownloadURL must have
  292. // OnlyAfterAttempts = 0.
  293. ObfuscatedServerListRootURLs parameters.TransferURLs
  294. // UpgradeDownloadURLs is list of URLs which specify locations from which
  295. // to download a host client upgrade file, when one is available. The core
  296. // tunnel controller provides a resumable download facility which
  297. // downloads this resource and emits a notice when complete. This value is
  298. // supplied by and depends on the Psiphon Network, and is typically
  299. // embedded in the client binary. All URLs must point to the same entity
  300. // with the same ETag. At least one DownloadURL must have
  301. // OnlyAfterAttempts = 0.
  302. UpgradeDownloadURLs parameters.TransferURLs
  303. // UpgradeDownloadClientVersionHeader specifies the HTTP header name for
  304. // the entity at UpgradeDownloadURLs which specifies the client version
  305. // (an integer value). A HEAD request may be made to check the version
  306. // number available at UpgradeDownloadURLs.
  307. // UpgradeDownloadClientVersionHeader is required when UpgradeDownloadURLs
  308. // is specified.
  309. UpgradeDownloadClientVersionHeader string
  310. // FetchUpgradeRetryPeriodMilliseconds specifies the delay before resuming
  311. // a client upgrade download after a failure. If omitted, a default value
  312. // is used. This value is typical overridden for testing.
  313. FetchUpgradeRetryPeriodMilliseconds *int
  314. // FeedbackUploadURLs is a list of SecureTransferURLs which specify
  315. // locations where feedback data can be uploaded, pairing with each
  316. // location a public key with which to encrypt the feedback data. This
  317. // value is supplied by and depends on the Psiphon Network, and is
  318. // typically embedded in the client binary. At least one TransferURL must
  319. // have OnlyAfterAttempts = 0.
  320. FeedbackUploadURLs parameters.TransferURLs
  321. // FeedbackEncryptionPublicKey is a default base64-encoded, RSA public key
  322. // value used to encrypt feedback data. Used when uploading feedback with a
  323. // TransferURL which has no public key value configured, i.e.
  324. // B64EncodedPublicKey = "".
  325. FeedbackEncryptionPublicKey string
  326. // TrustedCACertificatesFilename specifies a file containing trusted CA
  327. // certs. When set, this toggles use of the trusted CA certs, specified in
  328. // TrustedCACertificatesFilename, for tunneled TLS connections that expect
  329. // server certificates signed with public certificate authorities
  330. // (currently, only upgrade downloads). This option is used with stock Go
  331. // TLS in cases where Go may fail to obtain a list of root CAs from the
  332. // operating system.
  333. TrustedCACertificatesFilename string
  334. // DisablePeriodicSshKeepAlive indicates whether to send an SSH keepalive
  335. // every 1-2 minutes, when the tunnel is idle. If the SSH keepalive times
  336. // out, the tunnel is considered to have failed.
  337. DisablePeriodicSshKeepAlive bool
  338. // DeviceRegion is the optional, reported region the host device is
  339. // running in. This input value should be a ISO 3166-1 alpha-2 country
  340. // code. The device region is reported to the server in the connected
  341. // request and recorded for Psiphon stats.
  342. //
  343. // When provided, this value may be used, pre-connection, to select
  344. // performance or circumvention optimization strategies for the given
  345. // region.
  346. DeviceRegion string
  347. // EmitDiagnosticNotices indicates whether to output notices containing
  348. // detailed information about the Psiphon session. As these notices may
  349. // contain sensitive information, they should not be insecurely distributed
  350. // or displayed to users. Default is off.
  351. EmitDiagnosticNotices bool
  352. // EmitDiagnosticNetworkParameters indicates whether to include network
  353. // parameters in diagnostic notices. As these parameters are sensitive
  354. // circumvention network information, they should not be insecurely
  355. // distributed or displayed to users. Default is off.
  356. EmitDiagnosticNetworkParameters bool
  357. // EmitBytesTransferred indicates whether to emit periodic notices showing
  358. // bytes sent and received.
  359. EmitBytesTransferred bool
  360. // EmitSLOKs indicates whether to emit notices for each seeded SLOK. As
  361. // this could reveal user browsing activity, it's intended for debugging
  362. // and testing only.
  363. EmitSLOKs bool
  364. // EmitRefractionNetworkingLogs indicates whether to emit gotapdance log
  365. // messages to stdout. Note that gotapdance log messages do not conform to
  366. // the Notice format standard. Default is off.
  367. EmitRefractionNetworkingLogs bool
  368. // EmitServerAlerts indicates whether to emit notices for server alerts.
  369. EmitServerAlerts bool
  370. // EmitClientAddress indicates whether to emit the client's public network
  371. // address, IP and port, as seen by the server.
  372. EmitClientAddress bool
  373. // RateLimits specify throttling configuration for the tunnel.
  374. RateLimits common.RateLimits
  375. // PacketTunnelTunDeviceFileDescriptor specifies a tun device file
  376. // descriptor to use for running a packet tunnel. When this value is > 0,
  377. // a packet tunnel is established through the server and packets are
  378. // relayed via the tun device file descriptor. The file descriptor is
  379. // duped in NewController. When PacketTunnelTunDeviceFileDescriptor is
  380. // set, TunnelPoolSize must be 1.
  381. PacketTunnelTunFileDescriptor int
  382. // SessionID specifies a client session ID to use in the Psiphon API. The
  383. // session ID should be a randomly generated value that is used only for a
  384. // single session, which is defined as the period between a user starting
  385. // a Psiphon client and stopping the client.
  386. //
  387. // A session ID must be 32 hex digits (lower case). When blank, a random
  388. // session ID is automatically generated. Supply a session ID when a
  389. // single client session will cross multiple Controller instances.
  390. SessionID string
  391. // Authorizations is a list of encoded, signed access control
  392. // authorizations that the client has obtained and will present to the
  393. // server.
  394. Authorizations []string
  395. // ServerEntrySignaturePublicKey is a base64-encoded, ed25519 public
  396. // key value used to verify individual server entry signatures. This value
  397. // is supplied by and depends on the Psiphon Network, and is typically
  398. // embedded in the client binary.
  399. ServerEntrySignaturePublicKey string
  400. // ExchangeObfuscationKey is a base64-encoded, NaCl secretbox key used to
  401. // obfuscate server info exchanges between clients.
  402. // Required for the exchange functionality.
  403. ExchangeObfuscationKey string
  404. // MigrateHomepageNoticesFilename migrates a homepage file from the path
  405. // previously configured with setNoticeFiles to the new path for homepage
  406. // files under the data root directory. The file specified by this config
  407. // value will be moved to config.GetHomePageFilename().
  408. //
  409. // Note: see comment for config.Commit() for a description of how file
  410. // migrations are performed.
  411. //
  412. // If not set, no migration operation will be performed.
  413. MigrateHomepageNoticesFilename string
  414. // MigrateRotatingNoticesFilename migrates notice files from the path
  415. // previously configured with setNoticeFiles to the new path for notice
  416. // files under the data root directory.
  417. //
  418. // MigrateRotatingNoticesFilename will be moved to
  419. // config.GetNoticesFilename().
  420. //
  421. // MigrateRotatingNoticesFilename.1 will be moved to
  422. // config.GetOldNoticesFilename().
  423. //
  424. // Note: see comment for config.Commit() for a description of how file
  425. // migrations are performed.
  426. //
  427. // If not set, no migration operation will be performed.
  428. MigrateRotatingNoticesFilename string
  429. // MigrateDataStoreDirectory indicates the location of the datastore
  430. // directory, as previously configured with the deprecated
  431. // DataStoreDirectory config field. Datastore files found in the specified
  432. // directory will be moved under the data root directory.
  433. //
  434. // Note: see comment for config.Commit() for a description of how file
  435. // migrations are performed.
  436. MigrateDataStoreDirectory string
  437. // MigrateRemoteServerListDownloadFilename indicates the location of
  438. // remote server list download files. The remote server list files found at
  439. // the specified path will be moved under the data root directory.
  440. //
  441. // Note: see comment for config.Commit() for a description of how file
  442. // migrations are performed.
  443. MigrateRemoteServerListDownloadFilename string
  444. // MigrateObfuscatedServerListDownloadDirectory indicates the location of
  445. // the obfuscated server list downloads directory, as previously configured
  446. // with ObfuscatedServerListDownloadDirectory. Obfuscated server list
  447. // download files found in the specified directory will be moved under the
  448. // data root directory.
  449. //
  450. // Warning: if the directory is empty after obfuscated server
  451. // list files are moved, then it will be deleted.
  452. //
  453. // Note: see comment for config.Commit() for a description of how file
  454. // migrations are performed.
  455. MigrateObfuscatedServerListDownloadDirectory string
  456. // MigrateUpgradeDownloadFilename indicates the location of downloaded
  457. // application upgrade files. Downloaded upgrade files found at the
  458. // specified path will be moved under the data root directory.
  459. //
  460. // Note: see comment for config.Commit() for a description of how file
  461. // migrations are performed.
  462. MigrateUpgradeDownloadFilename string
  463. //
  464. // The following parameters are deprecated.
  465. //
  466. // DataStoreDirectory is the directory in which to store the persistent
  467. // database, which contains information such as server entries. By
  468. // default, current working directory.
  469. //
  470. // Deprecated:
  471. // Use MigrateDataStoreDirectory. When MigrateDataStoreDirectory
  472. // is set, this parameter is ignored.
  473. //
  474. // DataStoreDirectory has been subsumed by the new data root directory,
  475. // which is configured with DataRootDirectory. If set, datastore files
  476. // found in the specified directory will be moved under the data root
  477. // directory.
  478. DataStoreDirectory string
  479. // RemoteServerListDownloadFilename specifies a target filename for
  480. // storing the remote server list download. Data is stored in co-located
  481. // files (RemoteServerListDownloadFilename.part*) to allow for resumable
  482. // downloading.
  483. //
  484. // Deprecated:
  485. // Use MigrateRemoteServerListDownloadFilename. When
  486. // MigrateRemoteServerListDownloadFilename is set, this parameter is
  487. // ignored.
  488. //
  489. // If set, remote server list download files found at the specified path
  490. // will be moved under the data root directory.
  491. RemoteServerListDownloadFilename string
  492. // ObfuscatedServerListDownloadDirectory specifies a target directory for
  493. // storing the obfuscated remote server list downloads. Data is stored in
  494. // co-located files (<OSL filename>.part*) to allow for resumable
  495. // downloading.
  496. //
  497. // Deprecated:
  498. // Use MigrateObfuscatedServerListDownloadDirectory. When
  499. // MigrateObfuscatedServerListDownloadDirectory is set, this parameter is
  500. // ignored.
  501. //
  502. // If set, obfuscated server list download files found at the specified path
  503. // will be moved under the data root directory.
  504. ObfuscatedServerListDownloadDirectory string
  505. // UpgradeDownloadFilename is the local target filename for an upgrade
  506. // download. This parameter is required when UpgradeDownloadURLs (or
  507. // UpgradeDownloadUrl) is specified. Data is stored in co-located files
  508. // (UpgradeDownloadFilename.part*) to allow for resumable downloading.
  509. //
  510. // Deprecated:
  511. // Use MigrateUpgradeDownloadFilename. When MigrateUpgradeDownloadFilename
  512. // is set, this parameter is ignored.
  513. //
  514. // If set, upgrade download files found at the specified path will be moved
  515. // under the data root directory.
  516. UpgradeDownloadFilename string
  517. // TunnelProtocol indicates which protocol to use. For the default, "",
  518. // all protocols are used.
  519. //
  520. // Deprecated: Use LimitTunnelProtocols. When LimitTunnelProtocols is not
  521. // nil, this parameter is ignored.
  522. TunnelProtocol string
  523. // Deprecated: Use CustomHeaders. When CustomHeaders is not nil, this
  524. // parameter is ignored.
  525. UpstreamProxyCustomHeaders http.Header
  526. // RemoteServerListUrl is a URL which specifies a location to fetch out-
  527. // of-band server entries. This facility is used when a tunnel cannot be
  528. // established to known servers. This value is supplied by and depends on
  529. // the Psiphon Network, and is typically embedded in the client binary.
  530. //
  531. // Deprecated: Use RemoteServerListURLs. When RemoteServerListURLs is not
  532. // nil, this parameter is ignored.
  533. RemoteServerListUrl string
  534. // ObfuscatedServerListRootURL is a URL which specifies the root location
  535. // from which to fetch obfuscated server list files. This value is
  536. // supplied by and depends on the Psiphon Network, and is typically
  537. // embedded in the client binary.
  538. //
  539. // Deprecated: Use ObfuscatedServerListRootURLs. When
  540. // ObfuscatedServerListRootURLs is not nil, this parameter is ignored.
  541. ObfuscatedServerListRootURL string
  542. // UpgradeDownloadUrl specifies a URL from which to download a host client
  543. // upgrade file, when one is available. The core tunnel controller
  544. // provides a resumable download facility which downloads this resource
  545. // and emits a notice when complete. This value is supplied by and depends
  546. // on the Psiphon Network, and is typically embedded in the client binary.
  547. //
  548. // Deprecated: Use UpgradeDownloadURLs. When UpgradeDownloadURLs is not
  549. // nil, this parameter is ignored.
  550. UpgradeDownloadUrl string
  551. //
  552. // The following parameters are for testing purposes.
  553. //
  554. // TransformHostNameProbability is for testing purposes.
  555. TransformHostNameProbability *float64
  556. // FragmentorProbability and associated Fragmentor fields are for testing
  557. // purposes.
  558. FragmentorProbability *float64
  559. FragmentorLimitProtocols []string
  560. FragmentorMinTotalBytes *int
  561. FragmentorMaxTotalBytes *int
  562. FragmentorMinWriteBytes *int
  563. FragmentorMaxWriteBytes *int
  564. FragmentorMinDelayMicroseconds *int
  565. FragmentorMaxDelayMicroseconds *int
  566. // MeekTrafficShapingProbability and associated fields are for testing
  567. // purposes.
  568. MeekTrafficShapingProbability *float64
  569. MeekTrafficShapingLimitProtocols []string
  570. MeekMinTLSPadding *int
  571. MeekMaxTLSPadding *int
  572. MeekMinLimitRequestPayloadLength *int
  573. MeekMaxLimitRequestPayloadLength *int
  574. MeekRedialTLSProbability *float64
  575. // ObfuscatedSSHAlgorithms and associated ObfuscatedSSH fields are for
  576. // testing purposes. If specified, ObfuscatedSSHAlgorithms must have 4 SSH
  577. // KEX elements in order: the kex algorithm, cipher, MAC, and server host
  578. // key algorithm.
  579. ObfuscatedSSHAlgorithms []string
  580. ObfuscatedSSHMinPadding *int
  581. ObfuscatedSSHMaxPadding *int
  582. // LivenessTestMinUpstreamBytes and other LivenessTest fields are for
  583. // testing purposes.
  584. LivenessTestMinUpstreamBytes *int
  585. LivenessTestMaxUpstreamBytes *int
  586. LivenessTestMinDownstreamBytes *int
  587. LivenessTestMaxDownstreamBytes *int
  588. // ReplayCandidateCount and other Replay fields are for testing purposes.
  589. ReplayCandidateCount *int
  590. ReplayDialParametersTTLSeconds *int
  591. ReplayTargetUpstreamBytes *int
  592. ReplayTargetDownstreamBytes *int
  593. ReplayTargetTunnelDurationSeconds *int
  594. ReplayLaterRoundMoveToFrontProbability *float64
  595. ReplayRetainFailedProbability *float64
  596. // NetworkLatencyMultiplierMin and other NetworkLatencyMultiplier fields are
  597. // for testing purposes.
  598. NetworkLatencyMultiplierMin float64
  599. NetworkLatencyMultiplierMax float64
  600. NetworkLatencyMultiplierLambda float64
  601. // UseOnlyCustomTLSProfiles and other TLS configuration fields are for
  602. // testing purposes.
  603. UseOnlyCustomTLSProfiles *bool
  604. CustomTLSProfiles protocol.CustomTLSProfiles
  605. SelectRandomizedTLSProfileProbability *float64
  606. NoDefaultTLSSessionIDProbability *float64
  607. DisableFrontingProviderTLSProfiles protocol.LabeledTLSProfiles
  608. // ClientBurstUpstreamTargetBytes and other burst metric fields are for
  609. // testing purposes.
  610. ClientBurstUpstreamTargetBytes *int
  611. ClientBurstUpstreamDeadlineMilliseconds *int
  612. ClientBurstDownstreamTargetBytes *int
  613. ClientBurstDownstreamDeadlineMilliseconds *int
  614. // ApplicationParameters is for testing purposes.
  615. ApplicationParameters parameters.KeyValues
  616. // CustomHostNameRegexes and other custom host name fields are for testing
  617. // purposes.
  618. CustomHostNameRegexes []string
  619. CustomHostNameProbability *float64
  620. CustomHostNameLimitProtocols []string
  621. // ConjureCachedRegistrationTTLSeconds and other Conjure fields are for
  622. // testing purposes.
  623. ConjureCachedRegistrationTTLSeconds *int
  624. ConjureAPIRegistrarURL string
  625. ConjureAPIRegistrarFrontingSpecs parameters.FrontingSpecs
  626. ConjureAPIRegistrarMinDelayMilliseconds *int
  627. ConjureAPIRegistrarMaxDelayMilliseconds *int
  628. ConjureDecoyRegistrarProbability *float64
  629. ConjureDecoyRegistrarWidth *int
  630. ConjureDecoyRegistrarMinDelayMilliseconds *int
  631. ConjureDecoyRegistrarMaxDelayMilliseconds *int
  632. // HoldOffTunnelMinDurationMilliseconds and other HoldOffTunnel fields are
  633. // for testing purposes.
  634. HoldOffTunnelMinDurationMilliseconds *int
  635. HoldOffTunnelMaxDurationMilliseconds *int
  636. HoldOffTunnelProtocols []string
  637. HoldOffTunnelFrontingProviderIDs []string
  638. HoldOffTunnelProbability *float64
  639. // RestrictFrontingProviderIDs and other RestrictFrontingProviderIDs fields
  640. // are for testing purposes.
  641. RestrictFrontingProviderIDs []string
  642. RestrictFrontingProviderIDsClientProbability *float64
  643. // UpstreamProxyAllowAllServerEntrySources is for testing purposes.
  644. UpstreamProxyAllowAllServerEntrySources *bool
  645. // params is the active parameters.Parameters with defaults, config values,
  646. // and, optionally, tactics applied.
  647. //
  648. // New tactics must be applied by calling Config.SetParameters; calling
  649. // params.Set directly will fail to add config values.
  650. params *parameters.Parameters
  651. dialParametersHash []byte
  652. dynamicConfigMutex sync.Mutex
  653. sponsorID string
  654. authorizations []string
  655. deviceBinder DeviceBinder
  656. networkIDGetter NetworkIDGetter
  657. clientFeatures []string
  658. committed bool
  659. loadTimestamp string
  660. }
  661. // Config field which specifies if notice files should be used and at which
  662. // frequency and size they should be rotated.
  663. //
  664. // If either RotatingFileSize or RotatingSyncFrequency are <= 0, default values
  665. // are used.
  666. //
  667. // See comment for setNoticeFiles in notice.go for further details.
  668. type UseNoticeFiles struct {
  669. RotatingFileSize int
  670. RotatingSyncFrequency int
  671. }
  672. // LoadConfig parses a JSON format Psiphon config JSON string and returns a
  673. // Config struct populated with config values.
  674. //
  675. // The Config struct may then be programmatically populated with additional
  676. // values, including callbacks such as DeviceBinder.
  677. //
  678. // Before using the Config, Commit must be called, which will perform further
  679. // validation and initialize internal data structures.
  680. func LoadConfig(configJson []byte) (*Config, error) {
  681. var config Config
  682. err := json.Unmarshal(configJson, &config)
  683. if err != nil {
  684. return nil, errors.Trace(err)
  685. }
  686. config.loadTimestamp = common.TruncateTimestampToHour(
  687. common.GetCurrentTimestamp())
  688. return &config, nil
  689. }
  690. // IsCommitted checks if Commit was called.
  691. func (config *Config) IsCommitted() bool {
  692. return config.committed
  693. }
  694. // Commit validates Config fields finalizes initialization.
  695. //
  696. // Config fields should not be set after calling Config, as any changes may
  697. // not be reflected in internal data structures.
  698. //
  699. // If migrateFromLegacyFields is set to true, then an attempt to migrate from
  700. // legacy fields is made.
  701. //
  702. // Migration from legacy fields:
  703. // Config fields of the naming Migrate* (e.g. MigrateDataStoreDirectory) specify
  704. // a file migration operation which should be performed. These fields correspond
  705. // to deprecated fields, which previously could be used to specify where Psiphon
  706. // stored different sets of persistent files (e.g. MigrateDataStoreDirectory
  707. // corresponds to the deprecated field DataStoreDirectory).
  708. //
  709. // Psiphon now stores all persistent data under the configurable
  710. // DataRootDirectory (see Config.DataRootDirectory). The deprecated fields, and
  711. // corresponding Migrate* fields, are now used to specify the file or directory
  712. // path where, or under which, persistent files and directories created by
  713. // previous versions of Psiphon exist, so they can be moved under the
  714. // DataRootDirectory.
  715. //
  716. // For each migration operation:
  717. // - In the case of directories that could have defaulted to the current working
  718. // directory, persistent files and directories created by Psiphon are
  719. // precisely targeted to avoid moving files which were not created by Psiphon.
  720. // - If no file is found at the specified path, or an error is encountered while
  721. // migrating the file, then an error is logged and execution continues
  722. // normally.
  723. //
  724. // A sentinel file which signals that file migration has been completed, and
  725. // should not be attempted again, is created under DataRootDirectory after one
  726. // full pass through Commit(), regardless of whether file migration succeeds or
  727. // fails. It is better to not endlessly retry file migrations on each Commit()
  728. // because file system errors are expected to be rare and persistent files will
  729. // be re-populated over time.
  730. func (config *Config) Commit(migrateFromLegacyFields bool) error {
  731. // Do SetEmitDiagnosticNotices first, to ensure config file errors are
  732. // emitted.
  733. if config.EmitDiagnosticNotices {
  734. SetEmitDiagnosticNotices(
  735. true, config.EmitDiagnosticNetworkParameters)
  736. }
  737. // Migrate and set notice files before any operations that may emit an
  738. // error. This is to ensure config file errors are written to file when
  739. // notice files are configured with config.UseNoticeFiles.
  740. //
  741. // Note:
  742. // Errors encountered while configuring the data directory cannot be written
  743. // to notice files. This is because notices files are created within the
  744. // data directory.
  745. if config.DataRootDirectory == "" {
  746. wd, err := os.Getwd()
  747. if err != nil {
  748. return errors.Trace(StripFilePathsError(err))
  749. }
  750. config.DataRootDirectory = wd
  751. }
  752. // Create root directory
  753. dataDirectoryPath := config.GetPsiphonDataDirectory()
  754. if !common.FileExists(dataDirectoryPath) {
  755. err := os.Mkdir(dataDirectoryPath, os.ModePerm)
  756. if err != nil {
  757. return errors.Tracef("failed to create datastore directory with error: %s", StripFilePathsError(err, dataDirectoryPath))
  758. }
  759. }
  760. // Check if the migration from legacy config fields has already been
  761. // completed. See the Migrate* config fields for more details.
  762. migrationCompleteFilePath := filepath.Join(config.GetPsiphonDataDirectory(), "migration_complete")
  763. needMigration := !common.FileExists(migrationCompleteFilePath)
  764. // Collect notices to emit them after notice files are set
  765. var noticeMigrationAlertMsgs []string
  766. var noticeMigrationInfoMsgs []string
  767. // Migrate notices first to ensure notice files are used for notices if
  768. // UseNoticeFiles is set.
  769. homepageFilePath := config.GetHomePageFilename()
  770. noticesFilePath := config.GetNoticesFilename()
  771. if migrateFromLegacyFields {
  772. if needMigration {
  773. // Move notice files that exist at legacy file paths under the data root
  774. // directory.
  775. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, "Config migration: need migration")
  776. noticeMigrations := migrationsFromLegacyNoticeFilePaths(config)
  777. successfulMigrations := 0
  778. for _, migration := range noticeMigrations {
  779. err := DoFileMigration(migration)
  780. if err != nil {
  781. alertMsg := fmt.Sprintf("Config migration: %s", errors.Trace(err))
  782. noticeMigrationAlertMsgs = append(noticeMigrationAlertMsgs, alertMsg)
  783. } else {
  784. successfulMigrations += 1
  785. }
  786. }
  787. infoMsg := fmt.Sprintf("Config migration: %d/%d notice files successfully migrated", successfulMigrations, len(noticeMigrations))
  788. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, infoMsg)
  789. } else {
  790. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, "Config migration: migration already completed")
  791. }
  792. }
  793. if config.UseNoticeFiles != nil {
  794. setNoticeFiles(
  795. homepageFilePath,
  796. noticesFilePath,
  797. config.UseNoticeFiles.RotatingFileSize,
  798. config.UseNoticeFiles.RotatingSyncFrequency)
  799. }
  800. // Emit notices now that notice files are set if configured
  801. for _, msg := range noticeMigrationAlertMsgs {
  802. NoticeWarning(msg)
  803. }
  804. for _, msg := range noticeMigrationInfoMsgs {
  805. NoticeInfo(msg)
  806. }
  807. // Promote legacy fields.
  808. if config.CustomHeaders == nil {
  809. config.CustomHeaders = config.UpstreamProxyCustomHeaders
  810. config.UpstreamProxyCustomHeaders = nil
  811. }
  812. if config.RemoteServerListUrl != "" && config.RemoteServerListURLs == nil {
  813. config.RemoteServerListURLs = promoteLegacyTransferURL(config.RemoteServerListUrl)
  814. }
  815. if config.ObfuscatedServerListRootURL != "" && config.ObfuscatedServerListRootURLs == nil {
  816. config.ObfuscatedServerListRootURLs = promoteLegacyTransferURL(config.ObfuscatedServerListRootURL)
  817. }
  818. if config.UpgradeDownloadUrl != "" && config.UpgradeDownloadURLs == nil {
  819. config.UpgradeDownloadURLs = promoteLegacyTransferURL(config.UpgradeDownloadUrl)
  820. }
  821. if config.TunnelProtocol != "" && len(config.LimitTunnelProtocols) == 0 {
  822. config.LimitTunnelProtocols = []string{config.TunnelProtocol}
  823. }
  824. if config.DataStoreDirectory != "" && config.MigrateDataStoreDirectory == "" {
  825. config.MigrateDataStoreDirectory = config.DataStoreDirectory
  826. }
  827. if config.RemoteServerListDownloadFilename != "" && config.MigrateRemoteServerListDownloadFilename == "" {
  828. config.MigrateRemoteServerListDownloadFilename = config.RemoteServerListDownloadFilename
  829. }
  830. if config.ObfuscatedServerListDownloadDirectory != "" && config.MigrateObfuscatedServerListDownloadDirectory == "" {
  831. config.MigrateObfuscatedServerListDownloadDirectory = config.ObfuscatedServerListDownloadDirectory
  832. }
  833. if config.UpgradeDownloadFilename != "" && config.MigrateUpgradeDownloadFilename == "" {
  834. config.MigrateUpgradeDownloadFilename = config.UpgradeDownloadFilename
  835. }
  836. // Supply default values.
  837. // Create datastore directory.
  838. dataStoreDirectoryPath := config.GetDataStoreDirectory()
  839. if !common.FileExists(dataStoreDirectoryPath) {
  840. err := os.Mkdir(dataStoreDirectoryPath, os.ModePerm)
  841. if err != nil {
  842. return errors.Tracef("failed to create datastore directory with error: %s", StripFilePathsError(err, dataStoreDirectoryPath))
  843. }
  844. }
  845. // Create OSL directory.
  846. oslDirectoryPath := config.GetObfuscatedServerListDownloadDirectory()
  847. if !common.FileExists(oslDirectoryPath) {
  848. err := os.Mkdir(oslDirectoryPath, os.ModePerm)
  849. if err != nil {
  850. return errors.Tracef("failed to create osl directory with error: %s", StripFilePathsError(err, oslDirectoryPath))
  851. }
  852. }
  853. if config.ClientVersion == "" {
  854. config.ClientVersion = "0"
  855. }
  856. if config.TunnelPoolSize == 0 {
  857. config.TunnelPoolSize = TUNNEL_POOL_SIZE
  858. }
  859. // Validate config fields.
  860. if !common.FileExists(config.DataRootDirectory) {
  861. return errors.TraceNew("DataRootDirectory does not exist")
  862. }
  863. if config.PropagationChannelId == "" {
  864. return errors.TraceNew("propagation channel ID is missing from the configuration file")
  865. }
  866. if config.SponsorId == "" {
  867. return errors.TraceNew("sponsor ID is missing from the configuration file")
  868. }
  869. _, err := strconv.Atoi(config.ClientVersion)
  870. if err != nil {
  871. return errors.Tracef("invalid client version: %s", err)
  872. }
  873. if !common.Contains(
  874. []string{"", protocol.PSIPHON_SSH_API_PROTOCOL, protocol.PSIPHON_WEB_API_PROTOCOL},
  875. config.TargetApiProtocol) {
  876. return errors.TraceNew("invalid TargetApiProtocol")
  877. }
  878. if !config.DisableRemoteServerListFetcher {
  879. if config.RemoteServerListURLs != nil {
  880. if config.RemoteServerListSignaturePublicKey == "" {
  881. return errors.TraceNew("missing RemoteServerListSignaturePublicKey")
  882. }
  883. }
  884. if config.ObfuscatedServerListRootURLs != nil {
  885. if config.RemoteServerListSignaturePublicKey == "" {
  886. return errors.TraceNew("missing RemoteServerListSignaturePublicKey")
  887. }
  888. }
  889. }
  890. if config.UpgradeDownloadURLs != nil {
  891. if config.UpgradeDownloadClientVersionHeader == "" {
  892. return errors.TraceNew("missing UpgradeDownloadClientVersionHeader")
  893. }
  894. }
  895. if config.FeedbackUploadURLs != nil {
  896. if config.FeedbackEncryptionPublicKey == "" {
  897. return errors.TraceNew("missing FeedbackEncryptionPublicKey")
  898. }
  899. }
  900. // This constraint is expected by logic in Controller.runTunnels().
  901. if config.PacketTunnelTunFileDescriptor > 0 && config.TunnelPoolSize != 1 {
  902. return errors.TraceNew("packet tunnel mode requires TunnelPoolSize to be 1")
  903. }
  904. // SessionID must be PSIPHON_API_CLIENT_SESSION_ID_LENGTH lowercase hex-encoded bytes.
  905. if config.SessionID == "" {
  906. sessionID, err := MakeSessionId()
  907. if err != nil {
  908. return errors.Trace(err)
  909. }
  910. config.SessionID = sessionID
  911. }
  912. if len(config.SessionID) != 2*protocol.PSIPHON_API_CLIENT_SESSION_ID_LENGTH ||
  913. -1 != strings.IndexFunc(config.SessionID, func(c rune) bool {
  914. return !unicode.Is(unicode.ASCII_Hex_Digit, c) || unicode.IsUpper(c)
  915. }) {
  916. return errors.TraceNew("invalid SessionID")
  917. }
  918. config.params, err = parameters.NewParameters(
  919. func(err error) {
  920. NoticeWarning("Parameters getValue failed: %s", err)
  921. })
  922. if err != nil {
  923. return errors.Trace(err)
  924. }
  925. if config.ObfuscatedSSHAlgorithms != nil &&
  926. len(config.ObfuscatedSSHAlgorithms) != 4 {
  927. // TODO: validate each algorithm?
  928. return errors.TraceNew("invalid ObfuscatedSSHAlgorithms")
  929. }
  930. // parametersParameters.Set will validate the config fields applied to
  931. // parametersParameters.
  932. err = config.SetParameters("", false, nil)
  933. if err != nil {
  934. return errors.Trace(err)
  935. }
  936. // Calculate and set the dial parameters hash. After this point, related
  937. // config fields must not change.
  938. config.setDialParametersHash()
  939. // Set defaults for dynamic config fields.
  940. config.SetDynamicConfig(config.SponsorId, config.Authorizations)
  941. // Initialize config.deviceBinder and config.config.networkIDGetter. These
  942. // wrap config.DeviceBinder and config.NetworkIDGetter/NetworkID with
  943. // loggers.
  944. //
  945. // New variables are set to avoid mutating input config fields.
  946. // Internally, code must use config.deviceBinder and
  947. // config.networkIDGetter and not the input/exported fields.
  948. if config.DeviceBinder != nil {
  949. config.deviceBinder = newLoggingDeviceBinder(config.DeviceBinder)
  950. }
  951. networkIDGetter := config.NetworkIDGetter
  952. if networkIDGetter == nil {
  953. // Limitation: unlike NetworkIDGetter, which calls back to platform APIs
  954. // this method of network identification is not dynamic and will not reflect
  955. // network changes that occur while running.
  956. if config.NetworkID != "" {
  957. networkIDGetter = newStaticNetworkGetter(config.NetworkID)
  958. } else {
  959. networkIDGetter = newStaticNetworkGetter("UNKNOWN")
  960. }
  961. }
  962. config.networkIDGetter = newLoggingNetworkIDGetter(networkIDGetter)
  963. // Initialize config.clientFeatures, which adds feature names on top of
  964. // those specified by the host application in config.ClientFeatures.
  965. config.clientFeatures = config.ClientFeatures
  966. feature := "VPN"
  967. if config.DeviceBinder != nil && !common.Contains(config.clientFeatures, feature) {
  968. config.clientFeatures = append(config.clientFeatures, feature)
  969. }
  970. // Migrate from old config fields. This results in files being moved under
  971. // a config specified data root directory.
  972. if migrateFromLegacyFields && needMigration {
  973. // If unset, set MigrateDataStoreDirectory to the previous default value for
  974. // DataStoreDirectory to ensure that datastore files are migrated.
  975. if config.MigrateDataStoreDirectory == "" {
  976. wd, err := os.Getwd()
  977. if err != nil {
  978. return errors.Trace(err)
  979. }
  980. NoticeInfo("MigrateDataStoreDirectory unset, using working directory")
  981. config.MigrateDataStoreDirectory = wd
  982. }
  983. // Move files that exist at legacy file paths under the data root
  984. // directory.
  985. migrations, err := migrationsFromLegacyFilePaths(config)
  986. if err != nil {
  987. return errors.Trace(err)
  988. }
  989. // Do migrations
  990. successfulMigrations := 0
  991. for _, migration := range migrations {
  992. err := DoFileMigration(migration)
  993. if err != nil {
  994. NoticeWarning("Config migration: %s", errors.Trace(err))
  995. } else {
  996. successfulMigrations += 1
  997. }
  998. }
  999. NoticeInfo(fmt.Sprintf("Config migration: %d/%d legacy files successfully migrated", successfulMigrations, len(migrations)))
  1000. // Remove OSL directory if empty
  1001. if config.MigrateObfuscatedServerListDownloadDirectory != "" {
  1002. files, err := ioutil.ReadDir(config.MigrateObfuscatedServerListDownloadDirectory)
  1003. if err != nil {
  1004. NoticeWarning("Error reading OSL directory: %s", errors.Trace(StripFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory)))
  1005. } else if len(files) == 0 {
  1006. err := os.Remove(config.MigrateObfuscatedServerListDownloadDirectory)
  1007. if err != nil {
  1008. NoticeWarning("Error deleting empty OSL directory: %s", errors.Trace(StripFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory)))
  1009. }
  1010. }
  1011. }
  1012. f, err := os.Create(migrationCompleteFilePath)
  1013. if err != nil {
  1014. NoticeWarning("Config migration: failed to create migration completed file with error %s", errors.Trace(StripFilePathsError(err, migrationCompleteFilePath)))
  1015. } else {
  1016. NoticeInfo("Config migration: completed")
  1017. f.Close()
  1018. }
  1019. }
  1020. config.committed = true
  1021. return nil
  1022. }
  1023. // GetParameters returns the current parameters.Parameters.
  1024. func (config *Config) GetParameters() *parameters.Parameters {
  1025. return config.params
  1026. }
  1027. // SetParameters resets the parameters.Parameters to the default values,
  1028. // applies any config file values, and then applies the input parameters (from
  1029. // tactics, etc.)
  1030. //
  1031. // Set skipOnError to false when initially applying only config values, as
  1032. // this will validate the values and should fail. Set skipOnError to true when
  1033. // applying tactics to ignore invalid or unknown parameter values from tactics.
  1034. //
  1035. // In the case of applying tactics, do not call Config.parameters.Set
  1036. // directly as this will not first apply config values.
  1037. //
  1038. // If there is an error, the existing Config.parameters are left
  1039. // entirely unmodified.
  1040. func (config *Config) SetParameters(tag string, skipOnError bool, applyParameters map[string]interface{}) error {
  1041. setParameters := []map[string]interface{}{config.makeConfigParameters()}
  1042. if applyParameters != nil {
  1043. setParameters = append(setParameters, applyParameters)
  1044. }
  1045. counts, err := config.params.Set(tag, skipOnError, setParameters...)
  1046. if err != nil {
  1047. return errors.Trace(err)
  1048. }
  1049. NoticeInfo("applied %v parameters with tag '%s'", counts, tag)
  1050. // Emit certain individual parameter values for quick reference in diagnostics.
  1051. p := config.params.Get()
  1052. NoticeInfo(
  1053. "NetworkLatencyMultiplier Min/Max/Lambda: %f/%f/%f",
  1054. p.Float(parameters.NetworkLatencyMultiplierMin),
  1055. p.Float(parameters.NetworkLatencyMultiplierMax),
  1056. p.Float(parameters.NetworkLatencyMultiplierLambda))
  1057. // Application Parameters are feature flags/config info, delivered as Client
  1058. // Parameters via tactics/etc., to be communicated to the outer application.
  1059. // Emit these now, as notices.
  1060. if p.WeightedCoinFlip(parameters.ApplicationParametersProbability) {
  1061. NoticeApplicationParameters(p.KeyValues(parameters.ApplicationParameters))
  1062. }
  1063. return nil
  1064. }
  1065. // SetDynamicConfig sets the current client sponsor ID and authorizations.
  1066. // Invalid values for sponsor ID are ignored. The caller must not modify the
  1067. // input authorizations slice.
  1068. func (config *Config) SetDynamicConfig(sponsorID string, authorizations []string) {
  1069. config.dynamicConfigMutex.Lock()
  1070. defer config.dynamicConfigMutex.Unlock()
  1071. if sponsorID != "" {
  1072. config.sponsorID = sponsorID
  1073. }
  1074. config.authorizations = authorizations
  1075. }
  1076. // GetSponsorID returns the current client sponsor ID.
  1077. func (config *Config) GetSponsorID() string {
  1078. config.dynamicConfigMutex.Lock()
  1079. defer config.dynamicConfigMutex.Unlock()
  1080. return config.sponsorID
  1081. }
  1082. // GetAuthorizations returns the current client authorizations.
  1083. // The caller must not modify the returned slice.
  1084. func (config *Config) GetAuthorizations() []string {
  1085. config.dynamicConfigMutex.Lock()
  1086. defer config.dynamicConfigMutex.Unlock()
  1087. return config.authorizations
  1088. }
  1089. // GetPsiphonDataDirectory returns the directory under which all persistent
  1090. // files should be stored. This directory is created under
  1091. // config.DataRootDirectory. The motivation for an additional directory is that
  1092. // config.DataRootDirectory defaults to the current working directory, which may
  1093. // include non-tunnel-core files that should be excluded from directory-spanning
  1094. // operations (e.g. excluding all tunnel-core files from backup).
  1095. func (config *Config) GetPsiphonDataDirectory() string {
  1096. return filepath.Join(config.DataRootDirectory, PsiphonDataDirectoryName)
  1097. }
  1098. // GetHomePageFilename the path where the homepage notices file will be created.
  1099. func (config *Config) GetHomePageFilename() string {
  1100. return filepath.Join(config.GetPsiphonDataDirectory(), HomepageFilename)
  1101. }
  1102. // GetNoticesFilename returns the path where the notices file will be created.
  1103. // When the file is rotated it will be moved to config.GetOldNoticesFilename().
  1104. func (config *Config) GetNoticesFilename() string {
  1105. return filepath.Join(config.GetPsiphonDataDirectory(), NoticesFilename)
  1106. }
  1107. // GetOldNoticeFilename returns the path where the rotated notices file will be
  1108. // created.
  1109. func (config *Config) GetOldNoticesFilename() string {
  1110. return filepath.Join(config.GetPsiphonDataDirectory(), OldNoticesFilename)
  1111. }
  1112. // GetDataStoreDirectory returns the directory in which the persistent database
  1113. // will be stored. Created in Config.Commit(). The persistent database contains
  1114. // information such as server entries.
  1115. func (config *Config) GetDataStoreDirectory() string {
  1116. return filepath.Join(config.GetPsiphonDataDirectory(), "datastore")
  1117. }
  1118. // GetObfuscatedServerListDownloadDirectory returns the directory in which
  1119. // obfuscated remote server list downloads will be stored. Created in
  1120. // Config.Commit().
  1121. func (config *Config) GetObfuscatedServerListDownloadDirectory() string {
  1122. return filepath.Join(config.GetPsiphonDataDirectory(), "osl")
  1123. }
  1124. // GetRemoteServerListDownloadFilename returns the filename where the remote
  1125. // server list download will be stored. Data is stored in co-located files
  1126. // (RemoteServerListDownloadFilename.part*) to allow for resumable downloading.
  1127. func (config *Config) GetRemoteServerListDownloadFilename() string {
  1128. return filepath.Join(config.GetPsiphonDataDirectory(), "remote_server_list")
  1129. }
  1130. // GetUpgradeDownloadFilename specifies the filename where upgrade downloads
  1131. // will be stored. This filename is valid when UpgradeDownloadURLs
  1132. // (or UpgradeDownloadUrl) is specified. Data is stored in co-located files
  1133. // (UpgradeDownloadFilename.part*) to allow for resumable downloading.
  1134. func (config *Config) GetUpgradeDownloadFilename() string {
  1135. return filepath.Join(config.GetPsiphonDataDirectory(), UpgradeDownloadFilename)
  1136. }
  1137. // UseUpstreamProxy indicates if an upstream proxy has been
  1138. // configured.
  1139. func (config *Config) UseUpstreamProxy() bool {
  1140. return config.UpstreamProxyURL != ""
  1141. }
  1142. // GetNetworkID returns the current network ID. When NetworkIDGetter
  1143. // is set, this calls into the host application; otherwise, a default
  1144. // value is returned.
  1145. func (config *Config) GetNetworkID() string {
  1146. return config.networkIDGetter.GetNetworkID()
  1147. }
  1148. func (config *Config) makeConfigParameters() map[string]interface{} {
  1149. // Build set of config values to apply to parameters.
  1150. //
  1151. // Note: names of some config fields such as
  1152. // StaggerConnectionWorkersMilliseconds and LimitMeekBufferSizes have
  1153. // changed in the parameters. The existing config fields are retained for
  1154. // backwards compatibility.
  1155. applyParameters := make(map[string]interface{})
  1156. // To support platform clients that configure NetworkLatencyMultiplier, set
  1157. // the NetworkLatencyMultiplierMin/NetworkLatencyMultiplierMax range to the
  1158. // specified value. Also set the older NetworkLatencyMultiplier tactic, since
  1159. // that will be used in the case of replaying with dial parameters persisted
  1160. // by an older client version.
  1161. if config.NetworkLatencyMultiplier > 0.0 {
  1162. applyParameters[parameters.NetworkLatencyMultiplier] = config.NetworkLatencyMultiplier
  1163. applyParameters[parameters.NetworkLatencyMultiplierMin] = config.NetworkLatencyMultiplier
  1164. applyParameters[parameters.NetworkLatencyMultiplierMax] = config.NetworkLatencyMultiplier
  1165. }
  1166. if config.NetworkLatencyMultiplierMin > 0.0 {
  1167. applyParameters[parameters.NetworkLatencyMultiplierMin] = config.NetworkLatencyMultiplierMin
  1168. }
  1169. if config.NetworkLatencyMultiplierMax > 0.0 {
  1170. applyParameters[parameters.NetworkLatencyMultiplierMax] = config.NetworkLatencyMultiplierMax
  1171. }
  1172. if config.NetworkLatencyMultiplierLambda > 0.0 {
  1173. applyParameters[parameters.NetworkLatencyMultiplierLambda] = config.NetworkLatencyMultiplierLambda
  1174. }
  1175. if len(config.LimitTunnelProtocols) > 0 {
  1176. applyParameters[parameters.LimitTunnelProtocols] = protocol.TunnelProtocols(config.LimitTunnelProtocols)
  1177. }
  1178. if len(config.InitialLimitTunnelProtocols) > 0 && config.InitialLimitTunnelProtocolsCandidateCount > 0 {
  1179. applyParameters[parameters.InitialLimitTunnelProtocols] = protocol.TunnelProtocols(config.InitialLimitTunnelProtocols)
  1180. applyParameters[parameters.InitialLimitTunnelProtocolsCandidateCount] = config.InitialLimitTunnelProtocolsCandidateCount
  1181. }
  1182. if len(config.LimitTLSProfiles) > 0 {
  1183. applyParameters[parameters.LimitTLSProfiles] = protocol.TunnelProtocols(config.LimitTLSProfiles)
  1184. }
  1185. if len(config.LimitQUICVersions) > 0 {
  1186. applyParameters[parameters.LimitQUICVersions] = protocol.QUICVersions(config.LimitQUICVersions)
  1187. }
  1188. if config.EstablishTunnelTimeoutSeconds != nil {
  1189. applyParameters[parameters.EstablishTunnelTimeout] = fmt.Sprintf("%ds", *config.EstablishTunnelTimeoutSeconds)
  1190. }
  1191. if config.EstablishTunnelServerAffinityGracePeriodMilliseconds != nil {
  1192. applyParameters[parameters.EstablishTunnelServerAffinityGracePeriod] = fmt.Sprintf("%dms", *config.EstablishTunnelServerAffinityGracePeriodMilliseconds)
  1193. }
  1194. if config.EstablishTunnelPausePeriodSeconds != nil {
  1195. applyParameters[parameters.EstablishTunnelPausePeriod] = fmt.Sprintf("%ds", *config.EstablishTunnelPausePeriodSeconds)
  1196. }
  1197. if config.ConnectionWorkerPoolSize != 0 {
  1198. applyParameters[parameters.ConnectionWorkerPoolSize] = config.ConnectionWorkerPoolSize
  1199. }
  1200. if config.TunnelPoolSize != 0 {
  1201. applyParameters[parameters.TunnelPoolSize] = config.TunnelPoolSize
  1202. }
  1203. if config.StaggerConnectionWorkersMilliseconds > 0 {
  1204. applyParameters[parameters.StaggerConnectionWorkersPeriod] = fmt.Sprintf("%dms", config.StaggerConnectionWorkersMilliseconds)
  1205. }
  1206. if config.LimitIntensiveConnectionWorkers > 0 {
  1207. applyParameters[parameters.LimitIntensiveConnectionWorkers] = config.LimitIntensiveConnectionWorkers
  1208. }
  1209. applyParameters[parameters.MeekLimitBufferSizes] = config.LimitMeekBufferSizes
  1210. applyParameters[parameters.IgnoreHandshakeStatsRegexps] = config.IgnoreHandshakeStatsRegexps
  1211. if config.EstablishTunnelTimeoutSeconds != nil {
  1212. applyParameters[parameters.EstablishTunnelTimeout] = fmt.Sprintf("%ds", *config.EstablishTunnelTimeoutSeconds)
  1213. }
  1214. if config.FetchRemoteServerListRetryPeriodMilliseconds != nil {
  1215. applyParameters[parameters.FetchRemoteServerListRetryPeriod] = fmt.Sprintf("%dms", *config.FetchRemoteServerListRetryPeriodMilliseconds)
  1216. }
  1217. if config.FetchUpgradeRetryPeriodMilliseconds != nil {
  1218. applyParameters[parameters.FetchUpgradeRetryPeriod] = fmt.Sprintf("%dms", *config.FetchUpgradeRetryPeriodMilliseconds)
  1219. }
  1220. if !config.DisableRemoteServerListFetcher {
  1221. if config.RemoteServerListURLs != nil {
  1222. applyParameters[parameters.RemoteServerListSignaturePublicKey] = config.RemoteServerListSignaturePublicKey
  1223. applyParameters[parameters.RemoteServerListURLs] = config.RemoteServerListURLs
  1224. }
  1225. if config.ObfuscatedServerListRootURLs != nil {
  1226. applyParameters[parameters.RemoteServerListSignaturePublicKey] = config.RemoteServerListSignaturePublicKey
  1227. applyParameters[parameters.ObfuscatedServerListRootURLs] = config.ObfuscatedServerListRootURLs
  1228. }
  1229. }
  1230. if config.UpgradeDownloadURLs != nil {
  1231. applyParameters[parameters.UpgradeDownloadClientVersionHeader] = config.UpgradeDownloadClientVersionHeader
  1232. applyParameters[parameters.UpgradeDownloadURLs] = config.UpgradeDownloadURLs
  1233. }
  1234. if len(config.FeedbackUploadURLs) > 0 {
  1235. applyParameters[parameters.FeedbackUploadURLs] = config.FeedbackUploadURLs
  1236. }
  1237. if config.FeedbackEncryptionPublicKey != "" {
  1238. applyParameters[parameters.FeedbackEncryptionPublicKey] = config.FeedbackEncryptionPublicKey
  1239. }
  1240. applyParameters[parameters.TunnelRateLimits] = config.RateLimits
  1241. if config.TransformHostNameProbability != nil {
  1242. applyParameters[parameters.TransformHostNameProbability] = *config.TransformHostNameProbability
  1243. }
  1244. if config.FragmentorProbability != nil {
  1245. applyParameters[parameters.FragmentorProbability] = *config.FragmentorProbability
  1246. }
  1247. if len(config.FragmentorLimitProtocols) > 0 {
  1248. applyParameters[parameters.FragmentorLimitProtocols] = protocol.TunnelProtocols(config.FragmentorLimitProtocols)
  1249. }
  1250. if config.FragmentorMinTotalBytes != nil {
  1251. applyParameters[parameters.FragmentorMinTotalBytes] = *config.FragmentorMinTotalBytes
  1252. }
  1253. if config.FragmentorMaxTotalBytes != nil {
  1254. applyParameters[parameters.FragmentorMaxTotalBytes] = *config.FragmentorMaxTotalBytes
  1255. }
  1256. if config.FragmentorMinWriteBytes != nil {
  1257. applyParameters[parameters.FragmentorMinWriteBytes] = *config.FragmentorMinWriteBytes
  1258. }
  1259. if config.FragmentorMaxWriteBytes != nil {
  1260. applyParameters[parameters.FragmentorMaxWriteBytes] = *config.FragmentorMaxWriteBytes
  1261. }
  1262. if config.FragmentorMinDelayMicroseconds != nil {
  1263. applyParameters[parameters.FragmentorMinDelay] = fmt.Sprintf("%dus", *config.FragmentorMinDelayMicroseconds)
  1264. }
  1265. if config.FragmentorMaxDelayMicroseconds != nil {
  1266. applyParameters[parameters.FragmentorMaxDelay] = fmt.Sprintf("%dus", *config.FragmentorMaxDelayMicroseconds)
  1267. }
  1268. if config.MeekTrafficShapingProbability != nil {
  1269. applyParameters[parameters.MeekTrafficShapingProbability] = *config.MeekTrafficShapingProbability
  1270. }
  1271. if len(config.MeekTrafficShapingLimitProtocols) > 0 {
  1272. applyParameters[parameters.MeekTrafficShapingLimitProtocols] = protocol.TunnelProtocols(config.MeekTrafficShapingLimitProtocols)
  1273. }
  1274. if config.MeekMinTLSPadding != nil {
  1275. applyParameters[parameters.MeekMinTLSPadding] = *config.MeekMinTLSPadding
  1276. }
  1277. if config.MeekMaxTLSPadding != nil {
  1278. applyParameters[parameters.MeekMaxTLSPadding] = *config.MeekMaxTLSPadding
  1279. }
  1280. if config.MeekMinLimitRequestPayloadLength != nil {
  1281. applyParameters[parameters.MeekMinLimitRequestPayloadLength] = *config.MeekMinLimitRequestPayloadLength
  1282. }
  1283. if config.MeekMaxLimitRequestPayloadLength != nil {
  1284. applyParameters[parameters.MeekMaxLimitRequestPayloadLength] = *config.MeekMaxLimitRequestPayloadLength
  1285. }
  1286. if config.MeekRedialTLSProbability != nil {
  1287. applyParameters[parameters.MeekRedialTLSProbability] = *config.MeekRedialTLSProbability
  1288. }
  1289. if config.ObfuscatedSSHMinPadding != nil {
  1290. applyParameters[parameters.ObfuscatedSSHMinPadding] = *config.ObfuscatedSSHMinPadding
  1291. }
  1292. if config.ObfuscatedSSHMaxPadding != nil {
  1293. applyParameters[parameters.ObfuscatedSSHMaxPadding] = *config.ObfuscatedSSHMaxPadding
  1294. }
  1295. if config.LivenessTestMinUpstreamBytes != nil {
  1296. applyParameters[parameters.LivenessTestMinUpstreamBytes] = *config.LivenessTestMinUpstreamBytes
  1297. }
  1298. if config.LivenessTestMaxUpstreamBytes != nil {
  1299. applyParameters[parameters.LivenessTestMaxUpstreamBytes] = *config.LivenessTestMaxUpstreamBytes
  1300. }
  1301. if config.LivenessTestMinDownstreamBytes != nil {
  1302. applyParameters[parameters.LivenessTestMinDownstreamBytes] = *config.LivenessTestMinDownstreamBytes
  1303. }
  1304. if config.LivenessTestMaxDownstreamBytes != nil {
  1305. applyParameters[parameters.LivenessTestMaxDownstreamBytes] = *config.LivenessTestMaxDownstreamBytes
  1306. }
  1307. if config.ReplayCandidateCount != nil {
  1308. applyParameters[parameters.ReplayCandidateCount] = *config.ReplayCandidateCount
  1309. }
  1310. if config.ReplayDialParametersTTLSeconds != nil {
  1311. applyParameters[parameters.ReplayDialParametersTTL] = fmt.Sprintf("%ds", *config.ReplayDialParametersTTLSeconds)
  1312. }
  1313. if config.ReplayTargetUpstreamBytes != nil {
  1314. applyParameters[parameters.ReplayTargetUpstreamBytes] = *config.ReplayTargetUpstreamBytes
  1315. }
  1316. if config.ReplayTargetDownstreamBytes != nil {
  1317. applyParameters[parameters.ReplayTargetDownstreamBytes] = *config.ReplayTargetDownstreamBytes
  1318. }
  1319. if config.ReplayTargetTunnelDurationSeconds != nil {
  1320. applyParameters[parameters.ReplayTargetTunnelDuration] = fmt.Sprintf("%ds", *config.ReplayTargetTunnelDurationSeconds)
  1321. }
  1322. if config.ReplayLaterRoundMoveToFrontProbability != nil {
  1323. applyParameters[parameters.ReplayLaterRoundMoveToFrontProbability] = *config.ReplayLaterRoundMoveToFrontProbability
  1324. }
  1325. if config.ReplayRetainFailedProbability != nil {
  1326. applyParameters[parameters.ReplayRetainFailedProbability] = *config.ReplayRetainFailedProbability
  1327. }
  1328. if config.UseOnlyCustomTLSProfiles != nil {
  1329. applyParameters[parameters.UseOnlyCustomTLSProfiles] = *config.UseOnlyCustomTLSProfiles
  1330. }
  1331. if config.CustomTLSProfiles != nil {
  1332. applyParameters[parameters.CustomTLSProfiles] = config.CustomTLSProfiles
  1333. }
  1334. if config.SelectRandomizedTLSProfileProbability != nil {
  1335. applyParameters[parameters.SelectRandomizedTLSProfileProbability] = *config.SelectRandomizedTLSProfileProbability
  1336. }
  1337. if config.NoDefaultTLSSessionIDProbability != nil {
  1338. applyParameters[parameters.NoDefaultTLSSessionIDProbability] = *config.NoDefaultTLSSessionIDProbability
  1339. }
  1340. if config.DisableFrontingProviderTLSProfiles != nil {
  1341. applyParameters[parameters.DisableFrontingProviderTLSProfiles] = config.DisableFrontingProviderTLSProfiles
  1342. }
  1343. if config.ClientBurstUpstreamTargetBytes != nil {
  1344. applyParameters[parameters.ClientBurstUpstreamTargetBytes] = *config.ClientBurstUpstreamTargetBytes
  1345. }
  1346. if config.ClientBurstUpstreamDeadlineMilliseconds != nil {
  1347. applyParameters[parameters.ClientBurstUpstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstUpstreamDeadlineMilliseconds)
  1348. }
  1349. if config.ClientBurstDownstreamTargetBytes != nil {
  1350. applyParameters[parameters.ClientBurstDownstreamTargetBytes] = *config.ClientBurstDownstreamTargetBytes
  1351. }
  1352. if config.ClientBurstDownstreamDeadlineMilliseconds != nil {
  1353. applyParameters[parameters.ClientBurstDownstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstDownstreamDeadlineMilliseconds)
  1354. }
  1355. if config.ApplicationParameters != nil {
  1356. applyParameters[parameters.ApplicationParameters] = config.ApplicationParameters
  1357. }
  1358. if config.CustomHostNameRegexes != nil {
  1359. applyParameters[parameters.CustomHostNameRegexes] = parameters.RegexStrings(config.CustomHostNameRegexes)
  1360. }
  1361. if config.CustomHostNameProbability != nil {
  1362. applyParameters[parameters.CustomHostNameProbability] = *config.CustomHostNameProbability
  1363. }
  1364. if config.CustomHostNameLimitProtocols != nil {
  1365. applyParameters[parameters.CustomHostNameLimitProtocols] = protocol.TunnelProtocols(config.CustomHostNameLimitProtocols)
  1366. }
  1367. if config.ConjureCachedRegistrationTTLSeconds != nil {
  1368. applyParameters[parameters.ConjureCachedRegistrationTTL] = fmt.Sprintf("%ds", *config.ConjureCachedRegistrationTTLSeconds)
  1369. }
  1370. if config.ConjureAPIRegistrarURL != "" {
  1371. applyParameters[parameters.ConjureAPIRegistrarURL] = config.ConjureAPIRegistrarURL
  1372. }
  1373. if config.ConjureAPIRegistrarFrontingSpecs != nil {
  1374. applyParameters[parameters.ConjureAPIRegistrarFrontingSpecs] = config.ConjureAPIRegistrarFrontingSpecs
  1375. }
  1376. if config.ConjureAPIRegistrarMinDelayMilliseconds != nil {
  1377. applyParameters[parameters.ConjureAPIRegistrarMinDelay] = fmt.Sprintf("%dms", *config.ConjureAPIRegistrarMinDelayMilliseconds)
  1378. }
  1379. if config.ConjureAPIRegistrarMaxDelayMilliseconds != nil {
  1380. applyParameters[parameters.ConjureAPIRegistrarMaxDelay] = fmt.Sprintf("%dms", *config.ConjureAPIRegistrarMaxDelayMilliseconds)
  1381. }
  1382. if config.ConjureDecoyRegistrarProbability != nil {
  1383. applyParameters[parameters.ConjureDecoyRegistrarProbability] = *config.ConjureDecoyRegistrarProbability
  1384. }
  1385. if config.ConjureDecoyRegistrarWidth != nil {
  1386. applyParameters[parameters.ConjureDecoyRegistrarWidth] = *config.ConjureDecoyRegistrarWidth
  1387. }
  1388. if config.ConjureDecoyRegistrarMinDelayMilliseconds != nil {
  1389. applyParameters[parameters.ConjureDecoyRegistrarMinDelay] = fmt.Sprintf("%dms", *config.ConjureDecoyRegistrarMinDelayMilliseconds)
  1390. }
  1391. if config.ConjureDecoyRegistrarMaxDelayMilliseconds != nil {
  1392. applyParameters[parameters.ConjureDecoyRegistrarMaxDelay] = fmt.Sprintf("%dms", *config.ConjureDecoyRegistrarMaxDelayMilliseconds)
  1393. }
  1394. if config.HoldOffTunnelMinDurationMilliseconds != nil {
  1395. applyParameters[parameters.HoldOffTunnelMinDuration] = fmt.Sprintf("%dms", *config.HoldOffTunnelMinDurationMilliseconds)
  1396. }
  1397. if config.HoldOffTunnelMaxDurationMilliseconds != nil {
  1398. applyParameters[parameters.HoldOffTunnelMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffTunnelMaxDurationMilliseconds)
  1399. }
  1400. if len(config.HoldOffTunnelProtocols) > 0 {
  1401. applyParameters[parameters.HoldOffTunnelProtocols] = protocol.TunnelProtocols(config.HoldOffTunnelProtocols)
  1402. }
  1403. if len(config.HoldOffTunnelFrontingProviderIDs) > 0 {
  1404. applyParameters[parameters.HoldOffTunnelFrontingProviderIDs] = config.HoldOffTunnelFrontingProviderIDs
  1405. }
  1406. if config.HoldOffTunnelProbability != nil {
  1407. applyParameters[parameters.HoldOffTunnelProbability] = *config.HoldOffTunnelProbability
  1408. }
  1409. if len(config.RestrictFrontingProviderIDs) > 0 {
  1410. applyParameters[parameters.RestrictFrontingProviderIDs] = config.RestrictFrontingProviderIDs
  1411. }
  1412. if config.RestrictFrontingProviderIDsClientProbability != nil {
  1413. applyParameters[parameters.RestrictFrontingProviderIDsClientProbability] = *config.RestrictFrontingProviderIDsClientProbability
  1414. }
  1415. if config.UpstreamProxyAllowAllServerEntrySources != nil {
  1416. applyParameters[parameters.UpstreamProxyAllowAllServerEntrySources] = *config.UpstreamProxyAllowAllServerEntrySources
  1417. }
  1418. // When adding new config dial parameters that may override tactics, also
  1419. // update setDialParametersHash.
  1420. return applyParameters
  1421. }
  1422. func (config *Config) setDialParametersHash() {
  1423. // Calculate and store a hash of the config values that may impact
  1424. // dial parameters. This hash is used as part of the dial parameters
  1425. // replay mechanism to detect when persisted dial parameters should
  1426. // be discarded due to conflicting config changes.
  1427. //
  1428. // With a couple of minor exceptions, configuring dial parameters via the
  1429. // config is intended for testing only, and so these parameters are expected
  1430. // to be present in test runs only. It remains an important case to discard
  1431. // replay dial parameters when test config parameters are varied.
  1432. //
  1433. //
  1434. // Hashing the parameter names detects some ambiguous hash cases, such as two
  1435. // consecutive int64 parameters, one omitted and one not, that are flipped.
  1436. // The serialization is not completely unambiguous, and the format is
  1437. // currently limited by legacy cases (not invalidating replay dial parameters
  1438. // for production clients is more important than invalidating for test runs).
  1439. // We cannot hash the entire config JSON as it contains non-dial parameter
  1440. // fields which may frequently change across runs.
  1441. //
  1442. // MD5 hash is used solely as a data checksum and not for any security
  1443. // purpose.
  1444. hash := md5.New()
  1445. if len(config.LimitTunnelProtocols) > 0 {
  1446. hash.Write([]byte("LimitTunnelProtocols"))
  1447. for _, protocol := range config.LimitTunnelProtocols {
  1448. hash.Write([]byte(protocol))
  1449. }
  1450. }
  1451. if len(config.InitialLimitTunnelProtocols) > 0 && config.InitialLimitTunnelProtocolsCandidateCount > 0 {
  1452. hash.Write([]byte("InitialLimitTunnelProtocols"))
  1453. for _, protocol := range config.InitialLimitTunnelProtocols {
  1454. hash.Write([]byte(protocol))
  1455. }
  1456. binary.Write(hash, binary.LittleEndian, int64(config.InitialLimitTunnelProtocolsCandidateCount))
  1457. }
  1458. if len(config.LimitTLSProfiles) > 0 {
  1459. hash.Write([]byte("LimitTLSProfiles"))
  1460. for _, profile := range config.LimitTLSProfiles {
  1461. hash.Write([]byte(profile))
  1462. }
  1463. }
  1464. if len(config.LimitQUICVersions) > 0 {
  1465. hash.Write([]byte("LimitQUICVersions"))
  1466. for _, version := range config.LimitQUICVersions {
  1467. hash.Write([]byte(version))
  1468. }
  1469. }
  1470. // Whether a custom User-Agent is specified is a binary flag: when not set,
  1471. // the replay dial parameters value applies. When set, external
  1472. // considerations apply.
  1473. if _, ok := config.CustomHeaders["User-Agent"]; ok {
  1474. hash.Write([]byte("CustomHeaders User-Agent"))
  1475. hash.Write([]byte{1})
  1476. }
  1477. if config.UpstreamProxyURL != "" {
  1478. hash.Write([]byte("UpstreamProxyURL"))
  1479. hash.Write([]byte(config.UpstreamProxyURL))
  1480. }
  1481. if config.TransformHostNameProbability != nil {
  1482. hash.Write([]byte("TransformHostNameProbability"))
  1483. binary.Write(hash, binary.LittleEndian, *config.TransformHostNameProbability)
  1484. }
  1485. if config.FragmentorProbability != nil {
  1486. hash.Write([]byte("FragmentorProbability"))
  1487. binary.Write(hash, binary.LittleEndian, *config.FragmentorProbability)
  1488. }
  1489. if len(config.FragmentorLimitProtocols) > 0 {
  1490. hash.Write([]byte("FragmentorLimitProtocols"))
  1491. for _, protocol := range config.FragmentorLimitProtocols {
  1492. hash.Write([]byte(protocol))
  1493. }
  1494. }
  1495. if config.FragmentorMinTotalBytes != nil {
  1496. hash.Write([]byte("FragmentorMinTotalBytes"))
  1497. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinTotalBytes))
  1498. }
  1499. if config.FragmentorMaxTotalBytes != nil {
  1500. hash.Write([]byte("FragmentorMaxTotalBytes"))
  1501. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxTotalBytes))
  1502. }
  1503. if config.FragmentorMinWriteBytes != nil {
  1504. hash.Write([]byte("FragmentorMinWriteBytes"))
  1505. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinWriteBytes))
  1506. }
  1507. if config.FragmentorMaxWriteBytes != nil {
  1508. hash.Write([]byte("FragmentorMaxWriteBytes"))
  1509. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxWriteBytes))
  1510. }
  1511. if config.FragmentorMinDelayMicroseconds != nil {
  1512. hash.Write([]byte("FragmentorMinDelayMicroseconds"))
  1513. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinDelayMicroseconds))
  1514. }
  1515. if config.FragmentorMaxDelayMicroseconds != nil {
  1516. hash.Write([]byte("FragmentorMaxDelayMicroseconds"))
  1517. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxDelayMicroseconds))
  1518. }
  1519. if config.MeekTrafficShapingProbability != nil {
  1520. hash.Write([]byte("MeekTrafficShapingProbability"))
  1521. binary.Write(hash, binary.LittleEndian, int64(*config.MeekTrafficShapingProbability))
  1522. }
  1523. if len(config.MeekTrafficShapingLimitProtocols) > 0 {
  1524. hash.Write([]byte("MeekTrafficShapingLimitProtocols"))
  1525. for _, protocol := range config.MeekTrafficShapingLimitProtocols {
  1526. hash.Write([]byte(protocol))
  1527. }
  1528. }
  1529. if config.MeekMinLimitRequestPayloadLength != nil {
  1530. hash.Write([]byte("MeekMinLimitRequestPayloadLength"))
  1531. binary.Write(hash, binary.LittleEndian, int64(*config.MeekMinLimitRequestPayloadLength))
  1532. }
  1533. if config.MeekMaxLimitRequestPayloadLength != nil {
  1534. hash.Write([]byte("MeekMaxLimitRequestPayloadLength"))
  1535. binary.Write(hash, binary.LittleEndian, int64(*config.MeekMaxLimitRequestPayloadLength))
  1536. }
  1537. if config.MeekRedialTLSProbability != nil {
  1538. hash.Write([]byte("MeekRedialTLSProbability"))
  1539. binary.Write(hash, binary.LittleEndian, *config.MeekRedialTLSProbability)
  1540. }
  1541. if config.ObfuscatedSSHMinPadding != nil {
  1542. hash.Write([]byte("ObfuscatedSSHMinPadding"))
  1543. binary.Write(hash, binary.LittleEndian, int64(*config.ObfuscatedSSHMinPadding))
  1544. }
  1545. if config.ObfuscatedSSHMaxPadding != nil {
  1546. hash.Write([]byte("ObfuscatedSSHMaxPadding"))
  1547. binary.Write(hash, binary.LittleEndian, int64(*config.ObfuscatedSSHMaxPadding))
  1548. }
  1549. if config.LivenessTestMinUpstreamBytes != nil {
  1550. hash.Write([]byte("LivenessTestMinUpstreamBytes"))
  1551. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMinUpstreamBytes))
  1552. }
  1553. if config.LivenessTestMaxUpstreamBytes != nil {
  1554. hash.Write([]byte("LivenessTestMaxUpstreamBytes"))
  1555. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMaxUpstreamBytes))
  1556. }
  1557. if config.LivenessTestMinDownstreamBytes != nil {
  1558. hash.Write([]byte("LivenessTestMinDownstreamBytes"))
  1559. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMinDownstreamBytes))
  1560. }
  1561. if config.LivenessTestMaxDownstreamBytes != nil {
  1562. hash.Write([]byte("LivenessTestMaxDownstreamBytes"))
  1563. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMaxDownstreamBytes))
  1564. }
  1565. // Legacy case: these parameters are included in the hash unconditionally,
  1566. // and so will impact almost all production clients. These parameter names
  1567. // are not hashed since that would invalidate all replay dial parameters for
  1568. // existing clients whose hashes predate the inclusion of parameter names.
  1569. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierMin)
  1570. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierMax)
  1571. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierLambda)
  1572. if config.UseOnlyCustomTLSProfiles != nil {
  1573. hash.Write([]byte("UseOnlyCustomTLSProfiles"))
  1574. binary.Write(hash, binary.LittleEndian, *config.UseOnlyCustomTLSProfiles)
  1575. }
  1576. if len(config.CustomTLSProfiles) > 0 {
  1577. hash.Write([]byte("CustomTLSProfiles"))
  1578. for _, customTLSProfile := range config.CustomTLSProfiles {
  1579. encodedCustomTLSProofile, _ := json.Marshal(customTLSProfile)
  1580. hash.Write(encodedCustomTLSProofile)
  1581. }
  1582. }
  1583. if config.SelectRandomizedTLSProfileProbability != nil {
  1584. hash.Write([]byte("SelectRandomizedTLSProfileProbability"))
  1585. binary.Write(hash, binary.LittleEndian, *config.SelectRandomizedTLSProfileProbability)
  1586. }
  1587. if config.NoDefaultTLSSessionIDProbability != nil {
  1588. hash.Write([]byte("NoDefaultTLSSessionIDProbability"))
  1589. binary.Write(hash, binary.LittleEndian, *config.NoDefaultTLSSessionIDProbability)
  1590. }
  1591. if config.DisableFrontingProviderTLSProfiles != nil {
  1592. hash.Write([]byte("DisableFrontingProviderTLSProfiles"))
  1593. encodedDisableFrontingProviderTLSProfiles, _ :=
  1594. json.Marshal(config.DisableFrontingProviderTLSProfiles)
  1595. hash.Write(encodedDisableFrontingProviderTLSProfiles)
  1596. }
  1597. if len(config.CustomHostNameRegexes) > 0 {
  1598. hash.Write([]byte("CustomHostNameRegexes"))
  1599. for _, customHostNameRegex := range config.CustomHostNameRegexes {
  1600. hash.Write([]byte(customHostNameRegex))
  1601. }
  1602. }
  1603. if config.CustomHostNameProbability != nil {
  1604. hash.Write([]byte("CustomHostNameProbability"))
  1605. binary.Write(hash, binary.LittleEndian, *config.CustomHostNameProbability)
  1606. }
  1607. if len(config.CustomHostNameLimitProtocols) > 0 {
  1608. hash.Write([]byte("CustomHostNameLimitProtocols"))
  1609. for _, protocol := range config.CustomHostNameLimitProtocols {
  1610. hash.Write([]byte(protocol))
  1611. }
  1612. }
  1613. if config.ConjureCachedRegistrationTTLSeconds != nil {
  1614. hash.Write([]byte("ConjureCachedRegistrationTTLSeconds"))
  1615. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureCachedRegistrationTTLSeconds))
  1616. }
  1617. if config.ConjureAPIRegistrarURL != "" {
  1618. hash.Write([]byte("ConjureAPIRegistrarURL"))
  1619. hash.Write([]byte(config.ConjureAPIRegistrarURL))
  1620. }
  1621. if len(config.ConjureAPIRegistrarFrontingSpecs) > 0 {
  1622. hash.Write([]byte("ConjureAPIRegistrarFrontingSpecs"))
  1623. for _, frontingSpec := range config.ConjureAPIRegistrarFrontingSpecs {
  1624. encodedFrontSpec, _ := json.Marshal(frontingSpec)
  1625. hash.Write(encodedFrontSpec)
  1626. }
  1627. }
  1628. if config.ConjureAPIRegistrarMinDelayMilliseconds != nil {
  1629. hash.Write([]byte("ConjureAPIRegistrarMinDelayMilliseconds"))
  1630. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureAPIRegistrarMinDelayMilliseconds))
  1631. }
  1632. if config.ConjureAPIRegistrarMaxDelayMilliseconds != nil {
  1633. hash.Write([]byte("ConjureAPIRegistrarMaxDelayMilliseconds"))
  1634. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureAPIRegistrarMaxDelayMilliseconds))
  1635. }
  1636. if config.ConjureDecoyRegistrarWidth != nil {
  1637. hash.Write([]byte("ConjureDecoyRegistrarWidth"))
  1638. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarWidth))
  1639. }
  1640. if config.ConjureDecoyRegistrarMinDelayMilliseconds != nil {
  1641. hash.Write([]byte("ConjureDecoyRegistrarMinDelayMilliseconds"))
  1642. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarMinDelayMilliseconds))
  1643. }
  1644. if config.ConjureDecoyRegistrarMaxDelayMilliseconds != nil {
  1645. hash.Write([]byte("ConjureDecoyRegistrarMaxDelayMilliseconds"))
  1646. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarMaxDelayMilliseconds))
  1647. }
  1648. if config.HoldOffTunnelMinDurationMilliseconds != nil {
  1649. hash.Write([]byte("HoldOffTunnelMinDurationMilliseconds"))
  1650. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffTunnelMinDurationMilliseconds))
  1651. }
  1652. if config.HoldOffTunnelMaxDurationMilliseconds != nil {
  1653. hash.Write([]byte("HoldOffTunnelMaxDurationMilliseconds"))
  1654. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffTunnelMaxDurationMilliseconds))
  1655. }
  1656. if len(config.HoldOffTunnelProtocols) > 0 {
  1657. hash.Write([]byte("HoldOffTunnelProtocols"))
  1658. for _, protocol := range config.HoldOffTunnelProtocols {
  1659. hash.Write([]byte(protocol))
  1660. }
  1661. }
  1662. if len(config.HoldOffTunnelFrontingProviderIDs) > 0 {
  1663. hash.Write([]byte("HoldOffTunnelFrontingProviderIDs"))
  1664. for _, providerID := range config.HoldOffTunnelFrontingProviderIDs {
  1665. hash.Write([]byte(providerID))
  1666. }
  1667. }
  1668. if config.HoldOffTunnelProbability != nil {
  1669. hash.Write([]byte("HoldOffTunnelProbability"))
  1670. binary.Write(hash, binary.LittleEndian, *config.HoldOffTunnelProbability)
  1671. }
  1672. if len(config.RestrictFrontingProviderIDs) > 0 {
  1673. hash.Write([]byte("RestrictFrontingProviderIDs"))
  1674. for _, providerID := range config.RestrictFrontingProviderIDs {
  1675. hash.Write([]byte(providerID))
  1676. }
  1677. }
  1678. if config.RestrictFrontingProviderIDsClientProbability != nil {
  1679. hash.Write([]byte("RestrictFrontingProviderIDsClientProbability"))
  1680. binary.Write(hash, binary.LittleEndian, *config.RestrictFrontingProviderIDsClientProbability)
  1681. }
  1682. if config.UpstreamProxyAllowAllServerEntrySources != nil {
  1683. hash.Write([]byte("UpstreamProxyAllowAllServerEntrySources"))
  1684. binary.Write(hash, binary.LittleEndian, *config.UpstreamProxyAllowAllServerEntrySources)
  1685. }
  1686. config.dialParametersHash = hash.Sum(nil)
  1687. }
  1688. func promoteLegacyTransferURL(URL string) parameters.TransferURLs {
  1689. transferURLs := make(parameters.TransferURLs, 1)
  1690. transferURLs[0] = &parameters.TransferURL{
  1691. URL: base64.StdEncoding.EncodeToString([]byte(URL)),
  1692. SkipVerify: false,
  1693. OnlyAfterAttempts: 0,
  1694. }
  1695. return transferURLs
  1696. }
  1697. type loggingDeviceBinder struct {
  1698. d DeviceBinder
  1699. }
  1700. func newLoggingDeviceBinder(d DeviceBinder) *loggingDeviceBinder {
  1701. return &loggingDeviceBinder{d: d}
  1702. }
  1703. func (d *loggingDeviceBinder) BindToDevice(fileDescriptor int) (string, error) {
  1704. deviceInfo, err := d.d.BindToDevice(fileDescriptor)
  1705. if err == nil && deviceInfo != "" {
  1706. NoticeBindToDevice(deviceInfo)
  1707. }
  1708. return deviceInfo, err
  1709. }
  1710. type staticNetworkGetter struct {
  1711. networkID string
  1712. }
  1713. func newStaticNetworkGetter(networkID string) *staticNetworkGetter {
  1714. return &staticNetworkGetter{networkID: networkID}
  1715. }
  1716. func (n *staticNetworkGetter) GetNetworkID() string {
  1717. return n.networkID
  1718. }
  1719. type loggingNetworkIDGetter struct {
  1720. n NetworkIDGetter
  1721. }
  1722. func newLoggingNetworkIDGetter(n NetworkIDGetter) *loggingNetworkIDGetter {
  1723. return &loggingNetworkIDGetter{n: n}
  1724. }
  1725. func (n *loggingNetworkIDGetter) GetNetworkID() string {
  1726. networkID := n.n.GetNetworkID()
  1727. // All PII must appear after the initial "-"
  1728. // See: https://godoc.org/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon#NetworkIDGetter
  1729. logNetworkID := networkID
  1730. index := strings.Index(logNetworkID, "-")
  1731. if index != -1 {
  1732. logNetworkID = logNetworkID[:index]
  1733. }
  1734. if len(logNetworkID)+1 < len(networkID) {
  1735. // Indicate when additional network info was present after the first "-".
  1736. logNetworkID += "+[redacted]"
  1737. }
  1738. NoticeNetworkID(logNetworkID)
  1739. return networkID
  1740. }
  1741. // migrationsFromLegacyNoticeFilePaths returns the file migrations which must be
  1742. // performed to move notice files from legacy file paths, which were configured
  1743. // with the legacy config fields HomepageNoticesFilename and
  1744. // RotatingNoticesFilename, to the new file paths used by Psiphon which exist
  1745. // under the data root directory.
  1746. func migrationsFromLegacyNoticeFilePaths(config *Config) []FileMigration {
  1747. var noticeMigrations []FileMigration
  1748. if config.MigrateHomepageNoticesFilename != "" {
  1749. noticeMigrations = append(noticeMigrations, FileMigration{
  1750. Name: "hompage",
  1751. OldPath: config.MigrateHomepageNoticesFilename,
  1752. NewPath: config.GetHomePageFilename(),
  1753. })
  1754. }
  1755. if config.MigrateRotatingNoticesFilename != "" {
  1756. migrations := []FileMigration{
  1757. {
  1758. Name: "notices",
  1759. OldPath: config.MigrateRotatingNoticesFilename,
  1760. NewPath: config.GetNoticesFilename(),
  1761. IsDir: false,
  1762. },
  1763. {
  1764. Name: "notices.1",
  1765. OldPath: config.MigrateRotatingNoticesFilename + ".1",
  1766. NewPath: config.GetNoticesFilename() + ".1",
  1767. },
  1768. }
  1769. noticeMigrations = append(noticeMigrations, migrations...)
  1770. }
  1771. return noticeMigrations
  1772. }
  1773. // migrationsFromLegacyFilePaths returns the file migrations which must be
  1774. // performed to move files from legacy file paths, which were configured with
  1775. // legacy config fields, to the new file paths used by Psiphon which exist
  1776. // under the data root directory.
  1777. // Note: an attempt is made to redact any file paths from the returned error.
  1778. func migrationsFromLegacyFilePaths(config *Config) ([]FileMigration, error) {
  1779. migrations := []FileMigration{
  1780. {
  1781. Name: "psiphon.boltdb",
  1782. OldPath: filepath.Join(config.MigrateDataStoreDirectory, "psiphon.boltdb"),
  1783. NewPath: filepath.Join(config.GetDataStoreDirectory(), "psiphon.boltdb"),
  1784. },
  1785. {
  1786. Name: "psiphon.boltdb.lock",
  1787. OldPath: filepath.Join(config.MigrateDataStoreDirectory, "psiphon.boltdb.lock"),
  1788. NewPath: filepath.Join(config.GetDataStoreDirectory(), "psiphon.boltdb.lock"),
  1789. },
  1790. }
  1791. if config.MigrateRemoteServerListDownloadFilename != "" {
  1792. // Migrate remote server list files
  1793. rslMigrations := []FileMigration{
  1794. {
  1795. Name: "remote_server_list",
  1796. OldPath: config.MigrateRemoteServerListDownloadFilename,
  1797. NewPath: config.GetRemoteServerListDownloadFilename(),
  1798. },
  1799. {
  1800. Name: "remote_server_list.part",
  1801. OldPath: config.MigrateRemoteServerListDownloadFilename + ".part",
  1802. NewPath: config.GetRemoteServerListDownloadFilename() + ".part",
  1803. },
  1804. {
  1805. Name: "remote_server_list.part.etag",
  1806. OldPath: config.MigrateRemoteServerListDownloadFilename + ".part.etag",
  1807. NewPath: config.GetRemoteServerListDownloadFilename() + ".part.etag",
  1808. },
  1809. }
  1810. migrations = append(migrations, rslMigrations...)
  1811. }
  1812. if config.MigrateObfuscatedServerListDownloadDirectory != "" {
  1813. // Migrate OSL registry file and downloads
  1814. oslFileRegex, err := regexp.Compile(`^osl-.+$`)
  1815. if err != nil {
  1816. return nil, errors.TraceMsg(err, "failed to compile regex for osl files")
  1817. }
  1818. files, err := ioutil.ReadDir(config.MigrateObfuscatedServerListDownloadDirectory)
  1819. if err != nil {
  1820. NoticeWarning("Migration: failed to read OSL download directory with error %s", StripFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory))
  1821. } else {
  1822. for _, file := range files {
  1823. if oslFileRegex.MatchString(file.Name()) {
  1824. fileMigration := FileMigration{
  1825. Name: "osl",
  1826. OldPath: filepath.Join(config.MigrateObfuscatedServerListDownloadDirectory, file.Name()),
  1827. NewPath: filepath.Join(config.GetObfuscatedServerListDownloadDirectory(), file.Name()),
  1828. }
  1829. migrations = append(migrations, fileMigration)
  1830. }
  1831. }
  1832. }
  1833. }
  1834. if config.MigrateUpgradeDownloadFilename != "" {
  1835. // Migrate downloaded upgrade files
  1836. oldUpgradeDownloadFilename := filepath.Base(config.MigrateUpgradeDownloadFilename)
  1837. // Create regex for:
  1838. // <old_upgrade_download_filename>
  1839. // <old_upgrade_download_filename>.<client_version_number>
  1840. // <old_upgrade_download_filename>.<client_version_number>.part
  1841. // <old_upgrade_download_filename>.<client_version_number>.part.etag
  1842. upgradeDownloadFileRegex, err := regexp.Compile(`^` + oldUpgradeDownloadFilename + `(\.\d+(\.part(\.etag)?)?)?$`)
  1843. if err != nil {
  1844. return nil, errors.TraceMsg(err, "failed to compile regex for upgrade files")
  1845. }
  1846. upgradeDownloadDir := filepath.Dir(config.MigrateUpgradeDownloadFilename)
  1847. files, err := ioutil.ReadDir(upgradeDownloadDir)
  1848. if err != nil {
  1849. NoticeWarning("Migration: failed to read upgrade download directory with error %s", StripFilePathsError(err, upgradeDownloadDir))
  1850. } else {
  1851. for _, file := range files {
  1852. if upgradeDownloadFileRegex.MatchString(file.Name()) {
  1853. oldFileSuffix := strings.TrimPrefix(file.Name(), oldUpgradeDownloadFilename)
  1854. fileMigration := FileMigration{
  1855. Name: "upgrade",
  1856. OldPath: filepath.Join(upgradeDownloadDir, file.Name()),
  1857. NewPath: config.GetUpgradeDownloadFilename() + oldFileSuffix,
  1858. }
  1859. migrations = append(migrations, fileMigration)
  1860. }
  1861. }
  1862. }
  1863. }
  1864. return migrations, nil
  1865. }