config.go 95 KB

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