config.go 103 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681
  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. // TransferURLsAlwaysSkipVerify, when true, forces TransferURL.SkipVerify
  356. // to true for all remote server list downloads, upgrade downloads, and
  357. // feedback uploads. Each of these transfers has additional security at
  358. // the payload level. Verifying TLS certificates is preferred, as an
  359. // additional security and circumvention layer; set
  360. // TransferURLsAlwaysSkipVerify only in cases where system root CAs
  361. // cannot be loaded; for example, if unsupported (iOS < 12) or
  362. // insufficient memory (VPN extension on iOS < 15).
  363. TransferURLsAlwaysSkipVerify bool
  364. // DisablePeriodicSshKeepAlive indicates whether to send an SSH keepalive
  365. // every 1-2 minutes, when the tunnel is idle. If the SSH keepalive times
  366. // out, the tunnel is considered to have failed.
  367. DisablePeriodicSshKeepAlive bool
  368. // DeviceRegion is the optional, reported region the host device is
  369. // running in. This input value should be a ISO 3166-1 alpha-2 country
  370. // code. The device region is reported to the server in the connected
  371. // request and recorded for Psiphon stats.
  372. //
  373. // When provided, this value may be used, pre-connection, to select
  374. // performance or circumvention optimization strategies for the given
  375. // region.
  376. DeviceRegion string
  377. // EmitDiagnosticNotices indicates whether to output notices containing
  378. // detailed information about the Psiphon session. As these notices may
  379. // contain sensitive information, they should not be insecurely distributed
  380. // or displayed to users. Default is off.
  381. EmitDiagnosticNotices bool
  382. // EmitDiagnosticNetworkParameters indicates whether to include network
  383. // parameters in diagnostic notices. As these parameters are sensitive
  384. // circumvention network information, they should not be insecurely
  385. // distributed or displayed to users. Default is off.
  386. EmitDiagnosticNetworkParameters bool
  387. // EmitBytesTransferred indicates whether to emit periodic notices showing
  388. // bytes sent and received.
  389. EmitBytesTransferred bool
  390. // EmitSLOKs indicates whether to emit notices for each seeded SLOK. As
  391. // this could reveal user browsing activity, it's intended for debugging
  392. // and testing only.
  393. EmitSLOKs bool
  394. // EmitRefractionNetworkingLogs indicates whether to emit gotapdance log
  395. // messages to stdout. Note that gotapdance log messages do not conform to
  396. // the Notice format standard. Default is off.
  397. EmitRefractionNetworkingLogs bool
  398. // EmitServerAlerts indicates whether to emit notices for server alerts.
  399. EmitServerAlerts bool
  400. // EmitClientAddress indicates whether to emit the client's public network
  401. // address, IP and port, as seen by the server.
  402. EmitClientAddress bool
  403. // RateLimits specify throttling configuration for the tunnel.
  404. RateLimits common.RateLimits
  405. // PacketTunnelTunDeviceFileDescriptor specifies a tun device file
  406. // descriptor to use for running a packet tunnel. When this value is > 0,
  407. // a packet tunnel is established through the server and packets are
  408. // relayed via the tun device file descriptor. The file descriptor is
  409. // duped in NewController. When PacketTunnelTunDeviceFileDescriptor is
  410. // set, TunnelPoolSize must be 1.
  411. PacketTunnelTunFileDescriptor int
  412. // PacketTunnelTransparentDNSIPv4Address is the IPv4 address of the DNS
  413. // server configured by a VPN using a packet tunnel. All DNS packets
  414. // destined to this DNS server are transparently redirected to the
  415. // Psiphon server DNS.
  416. PacketTunnelTransparentDNSIPv4Address string
  417. // PacketTunnelTransparentDNSIPv6Address is the IPv6 address of the DNS
  418. // server configured by a VPN using a packet tunnel. All DNS packets
  419. // destined to this DNS server are transparently redirected to the
  420. // Psiphon server DNS.
  421. PacketTunnelTransparentDNSIPv6Address string
  422. // SessionID specifies a client session ID to use in the Psiphon API. The
  423. // session ID should be a randomly generated value that is used only for a
  424. // single session, which is defined as the period between a user starting
  425. // a Psiphon client and stopping the client.
  426. //
  427. // A session ID must be 32 hex digits (lower case). When blank, a random
  428. // session ID is automatically generated. Supply a session ID when a
  429. // single client session will cross multiple Controller instances.
  430. SessionID string
  431. // Authorizations is a list of encoded, signed access control
  432. // authorizations that the client has obtained and will present to the
  433. // server.
  434. Authorizations []string
  435. // ServerEntrySignaturePublicKey is a base64-encoded, ed25519 public
  436. // key value used to verify individual server entry signatures. This value
  437. // is supplied by and depends on the Psiphon Network, and is typically
  438. // embedded in the client binary.
  439. ServerEntrySignaturePublicKey string
  440. // ExchangeObfuscationKey is a base64-encoded, NaCl secretbox key used to
  441. // obfuscate server info exchanges between clients.
  442. // Required for the exchange functionality.
  443. ExchangeObfuscationKey string
  444. // MigrateHomepageNoticesFilename migrates a homepage file from the path
  445. // previously configured with setNoticeFiles to the new path for homepage
  446. // files under the data root directory. The file specified by this config
  447. // value will be moved to config.GetHomePageFilename().
  448. //
  449. // Note: see comment for config.Commit() for a description of how file
  450. // migrations are performed.
  451. //
  452. // If not set, no migration operation will be performed.
  453. MigrateHomepageNoticesFilename string
  454. // MigrateRotatingNoticesFilename migrates notice files from the path
  455. // previously configured with setNoticeFiles to the new path for notice
  456. // files under the data root directory.
  457. //
  458. // MigrateRotatingNoticesFilename will be moved to
  459. // config.GetNoticesFilename().
  460. //
  461. // MigrateRotatingNoticesFilename.1 will be moved to
  462. // config.GetOldNoticesFilename().
  463. //
  464. // Note: see comment for config.Commit() for a description of how file
  465. // migrations are performed.
  466. //
  467. // If not set, no migration operation will be performed.
  468. MigrateRotatingNoticesFilename string
  469. // MigrateDataStoreDirectory indicates the location of the datastore
  470. // directory, as previously configured with the deprecated
  471. // DataStoreDirectory config field. Datastore files found in the specified
  472. // directory will be moved under the data root directory.
  473. //
  474. // Note: see comment for config.Commit() for a description of how file
  475. // migrations are performed.
  476. MigrateDataStoreDirectory string
  477. // MigrateRemoteServerListDownloadFilename indicates the location of
  478. // remote server list download files. The remote server list files found at
  479. // the 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. MigrateRemoteServerListDownloadFilename string
  484. // MigrateObfuscatedServerListDownloadDirectory indicates the location of
  485. // the obfuscated server list downloads directory, as previously configured
  486. // with ObfuscatedServerListDownloadDirectory. Obfuscated server list
  487. // download files found in the specified directory will be moved under the
  488. // data root directory.
  489. //
  490. // Warning: if the directory is empty after obfuscated server
  491. // list files are moved, then it will be deleted.
  492. //
  493. // Note: see comment for config.Commit() for a description of how file
  494. // migrations are performed.
  495. MigrateObfuscatedServerListDownloadDirectory string
  496. // MigrateUpgradeDownloadFilename indicates the location of downloaded
  497. // application upgrade files. Downloaded upgrade files found at the
  498. // specified path will be moved under the data root directory.
  499. //
  500. // Note: see comment for config.Commit() for a description of how file
  501. // migrations are performed.
  502. MigrateUpgradeDownloadFilename string
  503. //
  504. // The following parameters are deprecated.
  505. //
  506. // DataStoreDirectory is the directory in which to store the persistent
  507. // database, which contains information such as server entries. By
  508. // default, current working directory.
  509. //
  510. // Deprecated:
  511. // Use MigrateDataStoreDirectory. When MigrateDataStoreDirectory
  512. // is set, this parameter is ignored.
  513. //
  514. // DataStoreDirectory has been subsumed by the new data root directory,
  515. // which is configured with DataRootDirectory. If set, datastore files
  516. // found in the specified directory will be moved under the data root
  517. // directory.
  518. DataStoreDirectory string
  519. // RemoteServerListDownloadFilename specifies a target filename for
  520. // storing the remote server list download. Data is stored in co-located
  521. // files (RemoteServerListDownloadFilename.part*) to allow for resumable
  522. // downloading.
  523. //
  524. // Deprecated:
  525. // Use MigrateRemoteServerListDownloadFilename. When
  526. // MigrateRemoteServerListDownloadFilename is set, this parameter is
  527. // ignored.
  528. //
  529. // If set, remote server list download files found at the specified path
  530. // will be moved under the data root directory.
  531. RemoteServerListDownloadFilename string
  532. // ObfuscatedServerListDownloadDirectory specifies a target directory for
  533. // storing the obfuscated remote server list downloads. Data is stored in
  534. // co-located files (<OSL filename>.part*) to allow for resumable
  535. // downloading.
  536. //
  537. // Deprecated:
  538. // Use MigrateObfuscatedServerListDownloadDirectory. When
  539. // MigrateObfuscatedServerListDownloadDirectory is set, this parameter is
  540. // ignored.
  541. //
  542. // If set, obfuscated server list download files found at the specified path
  543. // will be moved under the data root directory.
  544. ObfuscatedServerListDownloadDirectory string
  545. // UpgradeDownloadFilename is the local target filename for an upgrade
  546. // download. This parameter is required when UpgradeDownloadURLs (or
  547. // UpgradeDownloadUrl) is specified. Data is stored in co-located files
  548. // (UpgradeDownloadFilename.part*) to allow for resumable downloading.
  549. //
  550. // Deprecated:
  551. // Use MigrateUpgradeDownloadFilename. When MigrateUpgradeDownloadFilename
  552. // is set, this parameter is ignored.
  553. //
  554. // If set, upgrade download files found at the specified path will be moved
  555. // under the data root directory.
  556. UpgradeDownloadFilename string
  557. // TunnelProtocol indicates which protocol to use. For the default, "",
  558. // all protocols are used.
  559. //
  560. // Deprecated: Use LimitTunnelProtocols. When LimitTunnelProtocols is not
  561. // nil, this parameter is ignored.
  562. TunnelProtocol string
  563. // Deprecated: Use CustomHeaders. When CustomHeaders is not nil, this
  564. // parameter is ignored.
  565. UpstreamProxyCustomHeaders http.Header
  566. // RemoteServerListUrl is a URL which specifies a location to fetch out-
  567. // of-band server entries. This facility is used when a tunnel cannot be
  568. // established to known servers. This value is supplied by and depends on
  569. // the Psiphon Network, and is typically embedded in the client binary.
  570. //
  571. // Deprecated: Use RemoteServerListURLs. When RemoteServerListURLs is not
  572. // nil, this parameter is ignored.
  573. RemoteServerListUrl string
  574. // ObfuscatedServerListRootURL is a URL which specifies the root location
  575. // from which to fetch obfuscated server list files. This value is
  576. // supplied by and depends on the Psiphon Network, and is typically
  577. // embedded in the client binary.
  578. //
  579. // Deprecated: Use ObfuscatedServerListRootURLs. When
  580. // ObfuscatedServerListRootURLs is not nil, this parameter is ignored.
  581. ObfuscatedServerListRootURL string
  582. // UpgradeDownloadUrl specifies a URL from which to download a host client
  583. // upgrade file, when one is available. The core tunnel controller
  584. // provides a resumable download facility which downloads this resource
  585. // and emits a notice when complete. This value is supplied by and depends
  586. // on the Psiphon Network, and is typically embedded in the client binary.
  587. //
  588. // Deprecated: Use UpgradeDownloadURLs. When UpgradeDownloadURLs is not
  589. // nil, this parameter is ignored.
  590. UpgradeDownloadUrl string
  591. //
  592. // The following parameters are for testing purposes.
  593. //
  594. // TransformHostNameProbability is for testing purposes.
  595. TransformHostNameProbability *float64
  596. // FragmentorProbability and associated Fragmentor fields are for testing
  597. // purposes.
  598. FragmentorProbability *float64
  599. FragmentorLimitProtocols []string
  600. FragmentorMinTotalBytes *int
  601. FragmentorMaxTotalBytes *int
  602. FragmentorMinWriteBytes *int
  603. FragmentorMaxWriteBytes *int
  604. FragmentorMinDelayMicroseconds *int
  605. FragmentorMaxDelayMicroseconds *int
  606. // MeekTrafficShapingProbability and associated fields are for testing
  607. // purposes.
  608. MeekTrafficShapingProbability *float64
  609. MeekTrafficShapingLimitProtocols []string
  610. MeekMinTLSPadding *int
  611. MeekMaxTLSPadding *int
  612. MeekMinLimitRequestPayloadLength *int
  613. MeekMaxLimitRequestPayloadLength *int
  614. MeekRedialTLSProbability *float64
  615. MeekAlternateCookieNameProbability *float64
  616. MeekAlternateContentTypeProbability *float64
  617. // ObfuscatedSSHAlgorithms and associated ObfuscatedSSH fields are for
  618. // testing purposes. If specified, ObfuscatedSSHAlgorithms must have 4 SSH
  619. // KEX elements in order: the kex algorithm, cipher, MAC, and server host
  620. // key algorithm.
  621. ObfuscatedSSHAlgorithms []string
  622. ObfuscatedSSHMinPadding *int
  623. ObfuscatedSSHMaxPadding *int
  624. // LivenessTestMinUpstreamBytes and other LivenessTest fields are for
  625. // testing purposes.
  626. LivenessTestMinUpstreamBytes *int
  627. LivenessTestMaxUpstreamBytes *int
  628. LivenessTestMinDownstreamBytes *int
  629. LivenessTestMaxDownstreamBytes *int
  630. // ReplayCandidateCount and other Replay fields are for testing purposes.
  631. ReplayCandidateCount *int
  632. ReplayDialParametersTTLSeconds *int
  633. ReplayTargetUpstreamBytes *int
  634. ReplayTargetDownstreamBytes *int
  635. ReplayTargetTunnelDurationSeconds *int
  636. ReplayLaterRoundMoveToFrontProbability *float64
  637. ReplayRetainFailedProbability *float64
  638. ReplayIgnoreChangedConfigState *bool
  639. // NetworkLatencyMultiplierMin and other NetworkLatencyMultiplier fields are
  640. // for testing purposes.
  641. NetworkLatencyMultiplierMin float64
  642. NetworkLatencyMultiplierMax float64
  643. NetworkLatencyMultiplierLambda float64
  644. // UseOnlyCustomTLSProfiles and other TLS configuration fields are for
  645. // testing purposes.
  646. UseOnlyCustomTLSProfiles *bool
  647. CustomTLSProfiles protocol.CustomTLSProfiles
  648. SelectRandomizedTLSProfileProbability *float64
  649. NoDefaultTLSSessionIDProbability *float64
  650. DisableFrontingProviderTLSProfiles protocol.LabeledTLSProfiles
  651. // ClientBurstUpstreamTargetBytes and other burst metric fields are for
  652. // testing purposes.
  653. ClientBurstUpstreamTargetBytes *int
  654. ClientBurstUpstreamDeadlineMilliseconds *int
  655. ClientBurstDownstreamTargetBytes *int
  656. ClientBurstDownstreamDeadlineMilliseconds *int
  657. // ApplicationParameters is for testing purposes.
  658. ApplicationParameters parameters.KeyValues
  659. // CustomHostNameRegexes and other custom host name fields are for testing
  660. // purposes.
  661. CustomHostNameRegexes []string
  662. CustomHostNameProbability *float64
  663. CustomHostNameLimitProtocols []string
  664. // ConjureCachedRegistrationTTLSeconds and other Conjure fields are for
  665. // testing purposes.
  666. ConjureCachedRegistrationTTLSeconds *int
  667. ConjureAPIRegistrarBidirectionalURL string
  668. ConjureAPIRegistrarFrontingSpecs parameters.FrontingSpecs
  669. ConjureAPIRegistrarMinDelayMilliseconds *int
  670. ConjureAPIRegistrarMaxDelayMilliseconds *int
  671. ConjureDecoyRegistrarProbability *float64
  672. ConjureDecoyRegistrarWidth *int
  673. ConjureDecoyRegistrarMinDelayMilliseconds *int
  674. ConjureDecoyRegistrarMaxDelayMilliseconds *int
  675. // HoldOffTunnelMinDurationMilliseconds and other HoldOffTunnel fields are
  676. // for testing purposes.
  677. HoldOffTunnelMinDurationMilliseconds *int
  678. HoldOffTunnelMaxDurationMilliseconds *int
  679. HoldOffTunnelProtocols []string
  680. HoldOffTunnelFrontingProviderIDs []string
  681. HoldOffTunnelProbability *float64
  682. // RestrictFrontingProviderIDs and other RestrictFrontingProviderIDs fields
  683. // are for testing purposes.
  684. RestrictFrontingProviderIDs []string
  685. RestrictFrontingProviderIDsClientProbability *float64
  686. // UpstreamProxyAllowAllServerEntrySources is for testing purposes.
  687. UpstreamProxyAllowAllServerEntrySources *bool
  688. // LimitTunnelDialPortNumbers is for testing purposes.
  689. LimitTunnelDialPortNumbers parameters.TunnelProtocolPortLists
  690. // QUICDisablePathMTUDiscoveryProbability is for testing purposes.
  691. QUICDisablePathMTUDiscoveryProbability *float64
  692. // DNSResolverAttemptsPerServer and other DNSResolver fields are for
  693. // testing purposes.
  694. DNSResolverAttemptsPerServer *int
  695. DNSResolverAttemptsPerPreferredServer *int
  696. DNSResolverRequestTimeoutMilliseconds *int
  697. DNSResolverAwaitTimeoutMilliseconds *int
  698. DNSResolverPreresolvedIPAddressCIDRs parameters.LabeledCIDRs
  699. DNSResolverPreresolvedIPAddressProbability *float64
  700. DNSResolverAlternateServers []string
  701. DNSResolverPreferredAlternateServers []string
  702. DNSResolverPreferAlternateServerProbability *float64
  703. DNSResolverProtocolTransformSpecs transforms.Specs
  704. DNSResolverProtocolTransformScopedSpecNames transforms.ScopedSpecNames
  705. DNSResolverProtocolTransformProbability *float64
  706. DNSResolverIncludeEDNS0Probability *float64
  707. DNSResolverCacheExtensionInitialTTLMilliseconds *int
  708. DNSResolverCacheExtensionVerifiedTTLMilliseconds *int
  709. DirectHTTPProtocolTransformSpecs transforms.Specs
  710. DirectHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames
  711. DirectHTTPProtocolTransformProbability *float64
  712. FrontedHTTPProtocolTransformSpecs transforms.Specs
  713. FrontedHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames
  714. FrontedHTTPProtocolTransformProbability *float64
  715. OSSHObfuscatorSeedTransformSpecs transforms.Specs
  716. OSSHObfuscatorSeedTransformScopedSpecNames transforms.ScopedSpecNames
  717. OSSHObfuscatorSeedTransformProbability *float64
  718. ObfuscatedQUICNonceTransformSpecs transforms.Specs
  719. ObfuscatedQUICNonceTransformScopedSpecNames transforms.ScopedSpecNames
  720. ObfuscatedQUICNonceTransformProbability *float64
  721. // params is the active parameters.Parameters with defaults, config values,
  722. // and, optionally, tactics applied.
  723. //
  724. // New tactics must be applied by calling Config.SetParameters; calling
  725. // params.Set directly will fail to add config values.
  726. params *parameters.Parameters
  727. dialParametersHash []byte
  728. dynamicConfigMutex sync.Mutex
  729. sponsorID string
  730. authorizations []string
  731. deviceBinder DeviceBinder
  732. networkIDGetter NetworkIDGetter
  733. clientFeatures []string
  734. resolverMutex sync.Mutex
  735. resolver *resolver.Resolver
  736. committed bool
  737. loadTimestamp string
  738. }
  739. // Config field which specifies if notice files should be used and at which
  740. // frequency and size they should be rotated.
  741. //
  742. // If either RotatingFileSize or RotatingSyncFrequency are <= 0, default values
  743. // are used.
  744. //
  745. // See comment for setNoticeFiles in notice.go for further details.
  746. type UseNoticeFiles struct {
  747. RotatingFileSize int
  748. RotatingSyncFrequency int
  749. }
  750. // LoadConfig parses a JSON format Psiphon config JSON string and returns a
  751. // Config struct populated with config values.
  752. //
  753. // The Config struct may then be programmatically populated with additional
  754. // values, including callbacks such as DeviceBinder.
  755. //
  756. // Before using the Config, Commit must be called, which will perform further
  757. // validation and initialize internal data structures.
  758. func LoadConfig(configJson []byte) (*Config, error) {
  759. var config Config
  760. err := json.Unmarshal(configJson, &config)
  761. if err != nil {
  762. return nil, errors.Trace(err)
  763. }
  764. config.loadTimestamp = common.TruncateTimestampToHour(
  765. common.GetCurrentTimestamp())
  766. return &config, nil
  767. }
  768. // IsCommitted checks if Commit was called.
  769. func (config *Config) IsCommitted() bool {
  770. return config.committed
  771. }
  772. // Commit validates Config fields finalizes initialization.
  773. //
  774. // Config fields should not be set after calling Config, as any changes may
  775. // not be reflected in internal data structures.
  776. //
  777. // If migrateFromLegacyFields is set to true, then an attempt to migrate from
  778. // legacy fields is made.
  779. //
  780. // Migration from legacy fields:
  781. // Config fields of the naming Migrate* (e.g. MigrateDataStoreDirectory) specify
  782. // a file migration operation which should be performed. These fields correspond
  783. // to deprecated fields, which previously could be used to specify where Psiphon
  784. // stored different sets of persistent files (e.g. MigrateDataStoreDirectory
  785. // corresponds to the deprecated field DataStoreDirectory).
  786. //
  787. // Psiphon now stores all persistent data under the configurable
  788. // DataRootDirectory (see Config.DataRootDirectory). The deprecated fields, and
  789. // corresponding Migrate* fields, are now used to specify the file or directory
  790. // path where, or under which, persistent files and directories created by
  791. // previous versions of Psiphon exist, so they can be moved under the
  792. // DataRootDirectory.
  793. //
  794. // For each migration operation:
  795. // - In the case of directories that could have defaulted to the current working
  796. // directory, persistent files and directories created by Psiphon are
  797. // precisely targeted to avoid moving files which were not created by Psiphon.
  798. // - If no file is found at the specified path, or an error is encountered while
  799. // migrating the file, then an error is logged and execution continues
  800. // normally.
  801. //
  802. // A sentinel file which signals that file migration has been completed, and
  803. // should not be attempted again, is created under DataRootDirectory after one
  804. // full pass through Commit(), regardless of whether file migration succeeds or
  805. // fails. It is better to not endlessly retry file migrations on each Commit()
  806. // because file system errors are expected to be rare and persistent files will
  807. // be re-populated over time.
  808. func (config *Config) Commit(migrateFromLegacyFields bool) error {
  809. // Do SetEmitDiagnosticNotices first, to ensure config file errors are
  810. // emitted.
  811. if config.EmitDiagnosticNotices {
  812. SetEmitDiagnosticNotices(
  813. true, config.EmitDiagnosticNetworkParameters)
  814. }
  815. // Migrate and set notice files before any operations that may emit an
  816. // error. This is to ensure config file errors are written to file when
  817. // notice files are configured with config.UseNoticeFiles.
  818. //
  819. // Note:
  820. // Errors encountered while configuring the data directory cannot be written
  821. // to notice files. This is because notices files are created within the
  822. // data directory.
  823. if config.DataRootDirectory == "" {
  824. wd, err := os.Getwd()
  825. if err != nil {
  826. return errors.Trace(common.RedactFilePathsError(err))
  827. }
  828. config.DataRootDirectory = wd
  829. }
  830. // Create root directory
  831. dataDirectoryPath := config.GetPsiphonDataDirectory()
  832. if !common.FileExists(dataDirectoryPath) {
  833. err := os.Mkdir(dataDirectoryPath, os.ModePerm)
  834. if err != nil {
  835. return errors.Tracef(
  836. "failed to create datastore directory with error: %s",
  837. common.RedactFilePathsError(err, dataDirectoryPath))
  838. }
  839. }
  840. // Check if the migration from legacy config fields has already been
  841. // completed. See the Migrate* config fields for more details.
  842. migrationCompleteFilePath := filepath.Join(config.GetPsiphonDataDirectory(), "migration_complete")
  843. needMigration := !common.FileExists(migrationCompleteFilePath)
  844. // Collect notices to emit them after notice files are set
  845. var noticeMigrationAlertMsgs []string
  846. var noticeMigrationInfoMsgs []string
  847. // Migrate notices first to ensure notice files are used for notices if
  848. // UseNoticeFiles is set.
  849. homepageFilePath := config.GetHomePageFilename()
  850. noticesFilePath := config.GetNoticesFilename()
  851. if migrateFromLegacyFields {
  852. if needMigration {
  853. // Move notice files that exist at legacy file paths under the data root
  854. // directory.
  855. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, "Config migration: need migration")
  856. noticeMigrations := migrationsFromLegacyNoticeFilePaths(config)
  857. successfulMigrations := 0
  858. for _, migration := range noticeMigrations {
  859. err := DoFileMigration(migration)
  860. if err != nil {
  861. alertMsg := fmt.Sprintf("Config migration: %s", errors.Trace(err))
  862. noticeMigrationAlertMsgs = append(noticeMigrationAlertMsgs, alertMsg)
  863. } else {
  864. successfulMigrations += 1
  865. }
  866. }
  867. infoMsg := fmt.Sprintf("Config migration: %d/%d notice files successfully migrated", successfulMigrations, len(noticeMigrations))
  868. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, infoMsg)
  869. } else {
  870. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, "Config migration: migration already completed")
  871. }
  872. }
  873. if config.UseNoticeFiles != nil {
  874. setNoticeFiles(
  875. homepageFilePath,
  876. noticesFilePath,
  877. config.UseNoticeFiles.RotatingFileSize,
  878. config.UseNoticeFiles.RotatingSyncFrequency)
  879. }
  880. // Emit notices now that notice files are set if configured
  881. for _, msg := range noticeMigrationAlertMsgs {
  882. NoticeWarning(msg)
  883. }
  884. for _, msg := range noticeMigrationInfoMsgs {
  885. NoticeInfo(msg)
  886. }
  887. // Promote legacy fields.
  888. if config.CustomHeaders == nil {
  889. config.CustomHeaders = config.UpstreamProxyCustomHeaders
  890. config.UpstreamProxyCustomHeaders = nil
  891. }
  892. if config.RemoteServerListUrl != "" && config.RemoteServerListURLs == nil {
  893. config.RemoteServerListURLs = promoteLegacyTransferURL(config.RemoteServerListUrl)
  894. }
  895. if config.ObfuscatedServerListRootURL != "" && config.ObfuscatedServerListRootURLs == nil {
  896. config.ObfuscatedServerListRootURLs = promoteLegacyTransferURL(config.ObfuscatedServerListRootURL)
  897. }
  898. if config.UpgradeDownloadUrl != "" && config.UpgradeDownloadURLs == nil {
  899. config.UpgradeDownloadURLs = promoteLegacyTransferURL(config.UpgradeDownloadUrl)
  900. }
  901. if config.TunnelProtocol != "" && len(config.LimitTunnelProtocols) == 0 {
  902. config.LimitTunnelProtocols = []string{config.TunnelProtocol}
  903. }
  904. if config.DataStoreDirectory != "" && config.MigrateDataStoreDirectory == "" {
  905. config.MigrateDataStoreDirectory = config.DataStoreDirectory
  906. }
  907. if config.RemoteServerListDownloadFilename != "" && config.MigrateRemoteServerListDownloadFilename == "" {
  908. config.MigrateRemoteServerListDownloadFilename = config.RemoteServerListDownloadFilename
  909. }
  910. if config.ObfuscatedServerListDownloadDirectory != "" && config.MigrateObfuscatedServerListDownloadDirectory == "" {
  911. config.MigrateObfuscatedServerListDownloadDirectory = config.ObfuscatedServerListDownloadDirectory
  912. }
  913. if config.UpgradeDownloadFilename != "" && config.MigrateUpgradeDownloadFilename == "" {
  914. config.MigrateUpgradeDownloadFilename = config.UpgradeDownloadFilename
  915. }
  916. // Supply default values.
  917. // Create datastore directory.
  918. dataStoreDirectoryPath := config.GetDataStoreDirectory()
  919. if !common.FileExists(dataStoreDirectoryPath) {
  920. err := os.Mkdir(dataStoreDirectoryPath, os.ModePerm)
  921. if err != nil {
  922. return errors.Tracef(
  923. "failed to create datastore directory with error: %s",
  924. common.RedactFilePathsError(err, dataStoreDirectoryPath))
  925. }
  926. }
  927. // Create OSL directory.
  928. oslDirectoryPath := config.GetObfuscatedServerListDownloadDirectory()
  929. if !common.FileExists(oslDirectoryPath) {
  930. err := os.Mkdir(oslDirectoryPath, os.ModePerm)
  931. if err != nil {
  932. return errors.Tracef(
  933. "failed to create osl directory with error: %s",
  934. common.RedactFilePathsError(err, oslDirectoryPath))
  935. }
  936. }
  937. if config.ClientVersion == "" {
  938. config.ClientVersion = "0"
  939. }
  940. if config.TunnelPoolSize == 0 {
  941. config.TunnelPoolSize = TUNNEL_POOL_SIZE
  942. }
  943. // Validate config fields.
  944. if !common.FileExists(config.DataRootDirectory) {
  945. return errors.TraceNew("DataRootDirectory does not exist")
  946. }
  947. if config.PropagationChannelId == "" {
  948. return errors.TraceNew("propagation channel ID is missing from the configuration file")
  949. }
  950. if config.SponsorId == "" {
  951. return errors.TraceNew("sponsor ID is missing from the configuration file")
  952. }
  953. _, err := strconv.Atoi(config.ClientVersion)
  954. if err != nil {
  955. return errors.Tracef("invalid client version: %s", err)
  956. }
  957. if !common.Contains(
  958. []string{"", protocol.PSIPHON_SSH_API_PROTOCOL, protocol.PSIPHON_WEB_API_PROTOCOL},
  959. config.TargetApiProtocol) {
  960. return errors.TraceNew("invalid TargetApiProtocol")
  961. }
  962. if !config.DisableRemoteServerListFetcher {
  963. if config.RemoteServerListURLs != nil {
  964. if config.RemoteServerListSignaturePublicKey == "" {
  965. return errors.TraceNew("missing RemoteServerListSignaturePublicKey")
  966. }
  967. }
  968. if config.ObfuscatedServerListRootURLs != nil {
  969. if config.RemoteServerListSignaturePublicKey == "" {
  970. return errors.TraceNew("missing RemoteServerListSignaturePublicKey")
  971. }
  972. }
  973. }
  974. if config.UpgradeDownloadURLs != nil {
  975. if config.UpgradeDownloadClientVersionHeader == "" {
  976. return errors.TraceNew("missing UpgradeDownloadClientVersionHeader")
  977. }
  978. }
  979. if config.FeedbackUploadURLs != nil {
  980. if config.FeedbackEncryptionPublicKey == "" {
  981. return errors.TraceNew("missing FeedbackEncryptionPublicKey")
  982. }
  983. }
  984. // This constraint is expected by logic in Controller.runTunnels().
  985. if config.PacketTunnelTunFileDescriptor > 0 && config.TunnelPoolSize != 1 {
  986. return errors.TraceNew("packet tunnel mode requires TunnelPoolSize to be 1")
  987. }
  988. // SessionID must be PSIPHON_API_CLIENT_SESSION_ID_LENGTH lowercase hex-encoded bytes.
  989. if config.SessionID == "" {
  990. sessionID, err := MakeSessionId()
  991. if err != nil {
  992. return errors.Trace(err)
  993. }
  994. config.SessionID = sessionID
  995. }
  996. if len(config.SessionID) != 2*protocol.PSIPHON_API_CLIENT_SESSION_ID_LENGTH ||
  997. -1 != strings.IndexFunc(config.SessionID, func(c rune) bool {
  998. return !unicode.Is(unicode.ASCII_Hex_Digit, c) || unicode.IsUpper(c)
  999. }) {
  1000. return errors.TraceNew("invalid SessionID")
  1001. }
  1002. config.params, err = parameters.NewParameters(
  1003. func(err error) {
  1004. NoticeWarning("Parameters getValue failed: %s", err)
  1005. })
  1006. if err != nil {
  1007. return errors.Trace(err)
  1008. }
  1009. if config.ObfuscatedSSHAlgorithms != nil &&
  1010. len(config.ObfuscatedSSHAlgorithms) != 4 {
  1011. // TODO: validate each algorithm?
  1012. return errors.TraceNew("invalid ObfuscatedSSHAlgorithms")
  1013. }
  1014. // parametersParameters.Set will validate the config fields applied to
  1015. // parametersParameters.
  1016. err = config.SetParameters("", false, nil)
  1017. if err != nil {
  1018. return errors.Trace(err)
  1019. }
  1020. // Calculate and set the dial parameters hash. After this point, related
  1021. // config fields must not change.
  1022. config.setDialParametersHash()
  1023. // Set defaults for dynamic config fields.
  1024. config.SetDynamicConfig(config.SponsorId, config.Authorizations)
  1025. // Initialize config.deviceBinder and config.config.networkIDGetter. These
  1026. // wrap config.DeviceBinder and config.NetworkIDGetter/NetworkID with
  1027. // loggers.
  1028. //
  1029. // New variables are set to avoid mutating input config fields.
  1030. // Internally, code must use config.deviceBinder and
  1031. // config.networkIDGetter and not the input/exported fields.
  1032. if config.DeviceBinder != nil {
  1033. config.deviceBinder = newLoggingDeviceBinder(config.DeviceBinder)
  1034. }
  1035. networkIDGetter := config.NetworkIDGetter
  1036. if networkIDGetter == nil {
  1037. // Limitation: unlike NetworkIDGetter, which calls back to platform APIs
  1038. // this method of network identification is not dynamic and will not reflect
  1039. // network changes that occur while running.
  1040. if config.NetworkID != "" {
  1041. networkIDGetter = newStaticNetworkGetter(config.NetworkID)
  1042. } else {
  1043. networkIDGetter = newStaticNetworkGetter("UNKNOWN")
  1044. }
  1045. }
  1046. config.networkIDGetter = newLoggingNetworkIDGetter(networkIDGetter)
  1047. // Initialize config.clientFeatures, which adds feature names on top of
  1048. // those specified by the host application in config.ClientFeatures.
  1049. config.clientFeatures = config.ClientFeatures
  1050. feature := "VPN"
  1051. if config.DeviceBinder != nil && !common.Contains(config.clientFeatures, feature) {
  1052. config.clientFeatures = append(config.clientFeatures, feature)
  1053. }
  1054. // Migrate from old config fields. This results in files being moved under
  1055. // a config specified data root directory.
  1056. if migrateFromLegacyFields && needMigration {
  1057. // If unset, set MigrateDataStoreDirectory to the previous default value for
  1058. // DataStoreDirectory to ensure that datastore files are migrated.
  1059. if config.MigrateDataStoreDirectory == "" {
  1060. wd, err := os.Getwd()
  1061. if err != nil {
  1062. return errors.Trace(err)
  1063. }
  1064. NoticeInfo("MigrateDataStoreDirectory unset, using working directory")
  1065. config.MigrateDataStoreDirectory = wd
  1066. }
  1067. // Move files that exist at legacy file paths under the data root
  1068. // directory.
  1069. migrations, err := migrationsFromLegacyFilePaths(config)
  1070. if err != nil {
  1071. return errors.Trace(err)
  1072. }
  1073. // Do migrations
  1074. successfulMigrations := 0
  1075. for _, migration := range migrations {
  1076. err := DoFileMigration(migration)
  1077. if err != nil {
  1078. NoticeWarning("Config migration: %s", errors.Trace(err))
  1079. } else {
  1080. successfulMigrations += 1
  1081. }
  1082. }
  1083. NoticeInfo(fmt.Sprintf(
  1084. "Config migration: %d/%d legacy files successfully migrated",
  1085. successfulMigrations, len(migrations)))
  1086. // Remove OSL directory if empty
  1087. if config.MigrateObfuscatedServerListDownloadDirectory != "" {
  1088. files, err := ioutil.ReadDir(config.MigrateObfuscatedServerListDownloadDirectory)
  1089. if err != nil {
  1090. NoticeWarning(
  1091. "Error reading OSL directory: %s",
  1092. errors.Trace(common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory)))
  1093. } else if len(files) == 0 {
  1094. err := os.Remove(config.MigrateObfuscatedServerListDownloadDirectory)
  1095. if err != nil {
  1096. NoticeWarning(
  1097. "Error deleting empty OSL directory: %s",
  1098. errors.Trace(common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory)))
  1099. }
  1100. }
  1101. }
  1102. f, err := os.Create(migrationCompleteFilePath)
  1103. if err != nil {
  1104. NoticeWarning(
  1105. "Config migration: failed to create migration completed file with error %s",
  1106. errors.Trace(common.RedactFilePathsError(err, migrationCompleteFilePath)))
  1107. } else {
  1108. NoticeInfo("Config migration: completed")
  1109. f.Close()
  1110. }
  1111. }
  1112. config.committed = true
  1113. return nil
  1114. }
  1115. // GetParameters returns the current parameters.Parameters.
  1116. func (config *Config) GetParameters() *parameters.Parameters {
  1117. return config.params
  1118. }
  1119. // SetParameters resets the parameters.Parameters to the default values,
  1120. // applies any config file values, and then applies the input parameters (from
  1121. // tactics, etc.)
  1122. //
  1123. // Set skipOnError to false when initially applying only config values, as
  1124. // this will validate the values and should fail. Set skipOnError to true when
  1125. // applying tactics to ignore invalid or unknown parameter values from tactics.
  1126. //
  1127. // In the case of applying tactics, do not call Config.parameters.Set
  1128. // directly as this will not first apply config values.
  1129. //
  1130. // If there is an error, the existing Config.parameters are left
  1131. // entirely unmodified.
  1132. func (config *Config) SetParameters(tag string, skipOnError bool, applyParameters map[string]interface{}) error {
  1133. setParameters := []map[string]interface{}{config.makeConfigParameters()}
  1134. if applyParameters != nil {
  1135. setParameters = append(setParameters, applyParameters)
  1136. }
  1137. counts, err := config.params.Set(tag, skipOnError, setParameters...)
  1138. if err != nil {
  1139. return errors.Trace(err)
  1140. }
  1141. NoticeInfo("applied %v parameters with tag '%s'", counts, tag)
  1142. // Emit certain individual parameter values for quick reference in diagnostics.
  1143. p := config.params.Get()
  1144. NoticeInfo(
  1145. "NetworkLatencyMultiplier Min/Max/Lambda: %f/%f/%f",
  1146. p.Float(parameters.NetworkLatencyMultiplierMin),
  1147. p.Float(parameters.NetworkLatencyMultiplierMax),
  1148. p.Float(parameters.NetworkLatencyMultiplierLambda))
  1149. // Application Parameters are feature flags/config info, delivered as Client
  1150. // Parameters via tactics/etc., to be communicated to the outer application.
  1151. // Emit these now, as notices.
  1152. if p.WeightedCoinFlip(parameters.ApplicationParametersProbability) {
  1153. NoticeApplicationParameters(p.KeyValues(parameters.ApplicationParameters))
  1154. }
  1155. return nil
  1156. }
  1157. // SetResolver sets the current resolver.
  1158. func (config *Config) SetResolver(resolver *resolver.Resolver) {
  1159. config.resolverMutex.Lock()
  1160. defer config.resolverMutex.Unlock()
  1161. config.resolver = resolver
  1162. }
  1163. // GetResolver returns the current resolver. May return nil.
  1164. func (config *Config) GetResolver() *resolver.Resolver {
  1165. config.resolverMutex.Lock()
  1166. defer config.resolverMutex.Unlock()
  1167. return config.resolver
  1168. }
  1169. // SetDynamicConfig sets the current client sponsor ID and authorizations.
  1170. // Invalid values for sponsor ID are ignored. The caller must not modify the
  1171. // input authorizations slice.
  1172. func (config *Config) SetDynamicConfig(sponsorID string, authorizations []string) {
  1173. config.dynamicConfigMutex.Lock()
  1174. defer config.dynamicConfigMutex.Unlock()
  1175. if sponsorID != "" {
  1176. config.sponsorID = sponsorID
  1177. }
  1178. config.authorizations = authorizations
  1179. }
  1180. // GetSponsorID returns the current client sponsor ID.
  1181. func (config *Config) GetSponsorID() string {
  1182. config.dynamicConfigMutex.Lock()
  1183. defer config.dynamicConfigMutex.Unlock()
  1184. return config.sponsorID
  1185. }
  1186. // IsSplitTunnelEnabled indicates if split tunnel mode is enabled, either for
  1187. // the client's own country, a specified list of countries, or both.
  1188. func (config *Config) IsSplitTunnelEnabled() bool {
  1189. return config.SplitTunnelOwnRegion || len(config.SplitTunnelRegions) > 0
  1190. }
  1191. // GetAuthorizations returns the current client authorizations.
  1192. // The caller must not modify the returned slice.
  1193. func (config *Config) GetAuthorizations() []string {
  1194. config.dynamicConfigMutex.Lock()
  1195. defer config.dynamicConfigMutex.Unlock()
  1196. return config.authorizations
  1197. }
  1198. // GetPsiphonDataDirectory returns the directory under which all persistent
  1199. // files should be stored. This directory is created under
  1200. // config.DataRootDirectory. The motivation for an additional directory is that
  1201. // config.DataRootDirectory defaults to the current working directory, which may
  1202. // include non-tunnel-core files that should be excluded from directory-spanning
  1203. // operations (e.g. excluding all tunnel-core files from backup).
  1204. func (config *Config) GetPsiphonDataDirectory() string {
  1205. return filepath.Join(config.DataRootDirectory, PsiphonDataDirectoryName)
  1206. }
  1207. // GetHomePageFilename the path where the homepage notices file will be created.
  1208. func (config *Config) GetHomePageFilename() string {
  1209. return filepath.Join(config.GetPsiphonDataDirectory(), HomepageFilename)
  1210. }
  1211. // GetNoticesFilename returns the path where the notices file will be created.
  1212. // When the file is rotated it will be moved to config.GetOldNoticesFilename().
  1213. func (config *Config) GetNoticesFilename() string {
  1214. return filepath.Join(config.GetPsiphonDataDirectory(), NoticesFilename)
  1215. }
  1216. // GetOldNoticeFilename returns the path where the rotated notices file will be
  1217. // created.
  1218. func (config *Config) GetOldNoticesFilename() string {
  1219. return filepath.Join(config.GetPsiphonDataDirectory(), OldNoticesFilename)
  1220. }
  1221. // GetDataStoreDirectory returns the directory in which the persistent database
  1222. // will be stored. Created in Config.Commit(). The persistent database contains
  1223. // information such as server entries.
  1224. func (config *Config) GetDataStoreDirectory() string {
  1225. return filepath.Join(config.GetPsiphonDataDirectory(), "datastore")
  1226. }
  1227. // GetObfuscatedServerListDownloadDirectory returns the directory in which
  1228. // obfuscated remote server list downloads will be stored. Created in
  1229. // Config.Commit().
  1230. func (config *Config) GetObfuscatedServerListDownloadDirectory() string {
  1231. return filepath.Join(config.GetPsiphonDataDirectory(), "osl")
  1232. }
  1233. // GetRemoteServerListDownloadFilename returns the filename where the remote
  1234. // server list download will be stored. Data is stored in co-located files
  1235. // (RemoteServerListDownloadFilename.part*) to allow for resumable downloading.
  1236. func (config *Config) GetRemoteServerListDownloadFilename() string {
  1237. return filepath.Join(config.GetPsiphonDataDirectory(), "remote_server_list")
  1238. }
  1239. // GetUpgradeDownloadFilename specifies the filename where upgrade downloads
  1240. // will be stored. This filename is valid when UpgradeDownloadURLs
  1241. // (or UpgradeDownloadUrl) is specified. Data is stored in co-located files
  1242. // (UpgradeDownloadFilename.part*) to allow for resumable downloading.
  1243. func (config *Config) GetUpgradeDownloadFilename() string {
  1244. return filepath.Join(config.GetPsiphonDataDirectory(), UpgradeDownloadFilename)
  1245. }
  1246. // UseUpstreamProxy indicates if an upstream proxy has been
  1247. // configured.
  1248. func (config *Config) UseUpstreamProxy() bool {
  1249. return config.UpstreamProxyURL != ""
  1250. }
  1251. // GetNetworkID returns the current network ID. When NetworkIDGetter
  1252. // is set, this calls into the host application; otherwise, a default
  1253. // value is returned.
  1254. func (config *Config) GetNetworkID() string {
  1255. return config.networkIDGetter.GetNetworkID()
  1256. }
  1257. func (config *Config) makeConfigParameters() map[string]interface{} {
  1258. // Build set of config values to apply to parameters.
  1259. //
  1260. // Note: names of some config fields such as
  1261. // StaggerConnectionWorkersMilliseconds and LimitMeekBufferSizes have
  1262. // changed in the parameters. The existing config fields are retained for
  1263. // backwards compatibility.
  1264. applyParameters := make(map[string]interface{})
  1265. // To support platform clients that configure NetworkLatencyMultiplier, set
  1266. // the NetworkLatencyMultiplierMin/NetworkLatencyMultiplierMax range to the
  1267. // specified value. Also set the older NetworkLatencyMultiplier tactic, since
  1268. // that will be used in the case of replaying with dial parameters persisted
  1269. // by an older client version.
  1270. if config.NetworkLatencyMultiplier > 0.0 {
  1271. applyParameters[parameters.NetworkLatencyMultiplier] = config.NetworkLatencyMultiplier
  1272. applyParameters[parameters.NetworkLatencyMultiplierMin] = config.NetworkLatencyMultiplier
  1273. applyParameters[parameters.NetworkLatencyMultiplierMax] = config.NetworkLatencyMultiplier
  1274. }
  1275. if config.NetworkLatencyMultiplierMin > 0.0 {
  1276. applyParameters[parameters.NetworkLatencyMultiplierMin] = config.NetworkLatencyMultiplierMin
  1277. }
  1278. if config.NetworkLatencyMultiplierMax > 0.0 {
  1279. applyParameters[parameters.NetworkLatencyMultiplierMax] = config.NetworkLatencyMultiplierMax
  1280. }
  1281. if config.NetworkLatencyMultiplierLambda > 0.0 {
  1282. applyParameters[parameters.NetworkLatencyMultiplierLambda] = config.NetworkLatencyMultiplierLambda
  1283. }
  1284. if len(config.LimitTunnelProtocols) > 0 {
  1285. applyParameters[parameters.LimitTunnelProtocols] = protocol.TunnelProtocols(config.LimitTunnelProtocols)
  1286. }
  1287. if len(config.InitialLimitTunnelProtocols) > 0 && config.InitialLimitTunnelProtocolsCandidateCount > 0 {
  1288. applyParameters[parameters.InitialLimitTunnelProtocols] = protocol.TunnelProtocols(config.InitialLimitTunnelProtocols)
  1289. applyParameters[parameters.InitialLimitTunnelProtocolsCandidateCount] = config.InitialLimitTunnelProtocolsCandidateCount
  1290. }
  1291. if len(config.LimitTLSProfiles) > 0 {
  1292. applyParameters[parameters.LimitTLSProfiles] = protocol.TunnelProtocols(config.LimitTLSProfiles)
  1293. }
  1294. if len(config.LimitQUICVersions) > 0 {
  1295. applyParameters[parameters.LimitQUICVersions] = protocol.QUICVersions(config.LimitQUICVersions)
  1296. }
  1297. if config.EstablishTunnelTimeoutSeconds != nil {
  1298. applyParameters[parameters.EstablishTunnelTimeout] = fmt.Sprintf("%ds", *config.EstablishTunnelTimeoutSeconds)
  1299. }
  1300. if config.EstablishTunnelServerAffinityGracePeriodMilliseconds != nil {
  1301. applyParameters[parameters.EstablishTunnelServerAffinityGracePeriod] = fmt.Sprintf("%dms", *config.EstablishTunnelServerAffinityGracePeriodMilliseconds)
  1302. }
  1303. if config.EstablishTunnelPausePeriodSeconds != nil {
  1304. applyParameters[parameters.EstablishTunnelPausePeriod] = fmt.Sprintf("%ds", *config.EstablishTunnelPausePeriodSeconds)
  1305. }
  1306. if config.ConnectionWorkerPoolSize != 0 {
  1307. applyParameters[parameters.ConnectionWorkerPoolSize] = config.ConnectionWorkerPoolSize
  1308. }
  1309. if config.TunnelPoolSize != 0 {
  1310. applyParameters[parameters.TunnelPoolSize] = config.TunnelPoolSize
  1311. }
  1312. if config.StaggerConnectionWorkersMilliseconds > 0 {
  1313. applyParameters[parameters.StaggerConnectionWorkersPeriod] = fmt.Sprintf("%dms", config.StaggerConnectionWorkersMilliseconds)
  1314. }
  1315. if config.LimitIntensiveConnectionWorkers > 0 {
  1316. applyParameters[parameters.LimitIntensiveConnectionWorkers] = config.LimitIntensiveConnectionWorkers
  1317. }
  1318. applyParameters[parameters.MeekLimitBufferSizes] = config.LimitMeekBufferSizes
  1319. applyParameters[parameters.IgnoreHandshakeStatsRegexps] = config.IgnoreHandshakeStatsRegexps
  1320. if config.EstablishTunnelTimeoutSeconds != nil {
  1321. applyParameters[parameters.EstablishTunnelTimeout] = fmt.Sprintf("%ds", *config.EstablishTunnelTimeoutSeconds)
  1322. }
  1323. if config.FetchRemoteServerListRetryPeriodMilliseconds != nil {
  1324. applyParameters[parameters.FetchRemoteServerListRetryPeriod] = fmt.Sprintf("%dms", *config.FetchRemoteServerListRetryPeriodMilliseconds)
  1325. }
  1326. if config.FetchUpgradeRetryPeriodMilliseconds != nil {
  1327. applyParameters[parameters.FetchUpgradeRetryPeriod] = fmt.Sprintf("%dms", *config.FetchUpgradeRetryPeriodMilliseconds)
  1328. }
  1329. if !config.DisableRemoteServerListFetcher {
  1330. if config.RemoteServerListURLs != nil {
  1331. applyParameters[parameters.RemoteServerListSignaturePublicKey] = config.RemoteServerListSignaturePublicKey
  1332. applyParameters[parameters.RemoteServerListURLs] = config.RemoteServerListURLs
  1333. }
  1334. if config.ObfuscatedServerListRootURLs != nil {
  1335. applyParameters[parameters.RemoteServerListSignaturePublicKey] = config.RemoteServerListSignaturePublicKey
  1336. applyParameters[parameters.ObfuscatedServerListRootURLs] = config.ObfuscatedServerListRootURLs
  1337. }
  1338. }
  1339. if config.UpgradeDownloadURLs != nil {
  1340. applyParameters[parameters.UpgradeDownloadClientVersionHeader] = config.UpgradeDownloadClientVersionHeader
  1341. applyParameters[parameters.UpgradeDownloadURLs] = config.UpgradeDownloadURLs
  1342. }
  1343. if len(config.FeedbackUploadURLs) > 0 {
  1344. applyParameters[parameters.FeedbackUploadURLs] = config.FeedbackUploadURLs
  1345. }
  1346. if config.FeedbackEncryptionPublicKey != "" {
  1347. applyParameters[parameters.FeedbackEncryptionPublicKey] = config.FeedbackEncryptionPublicKey
  1348. }
  1349. applyParameters[parameters.TunnelRateLimits] = config.RateLimits
  1350. if config.TransformHostNameProbability != nil {
  1351. applyParameters[parameters.TransformHostNameProbability] = *config.TransformHostNameProbability
  1352. }
  1353. if config.FragmentorProbability != nil {
  1354. applyParameters[parameters.FragmentorProbability] = *config.FragmentorProbability
  1355. }
  1356. if len(config.FragmentorLimitProtocols) > 0 {
  1357. applyParameters[parameters.FragmentorLimitProtocols] = protocol.TunnelProtocols(config.FragmentorLimitProtocols)
  1358. }
  1359. if config.FragmentorMinTotalBytes != nil {
  1360. applyParameters[parameters.FragmentorMinTotalBytes] = *config.FragmentorMinTotalBytes
  1361. }
  1362. if config.FragmentorMaxTotalBytes != nil {
  1363. applyParameters[parameters.FragmentorMaxTotalBytes] = *config.FragmentorMaxTotalBytes
  1364. }
  1365. if config.FragmentorMinWriteBytes != nil {
  1366. applyParameters[parameters.FragmentorMinWriteBytes] = *config.FragmentorMinWriteBytes
  1367. }
  1368. if config.FragmentorMaxWriteBytes != nil {
  1369. applyParameters[parameters.FragmentorMaxWriteBytes] = *config.FragmentorMaxWriteBytes
  1370. }
  1371. if config.FragmentorMinDelayMicroseconds != nil {
  1372. applyParameters[parameters.FragmentorMinDelay] = fmt.Sprintf("%dus", *config.FragmentorMinDelayMicroseconds)
  1373. }
  1374. if config.FragmentorMaxDelayMicroseconds != nil {
  1375. applyParameters[parameters.FragmentorMaxDelay] = fmt.Sprintf("%dus", *config.FragmentorMaxDelayMicroseconds)
  1376. }
  1377. if config.MeekTrafficShapingProbability != nil {
  1378. applyParameters[parameters.MeekTrafficShapingProbability] = *config.MeekTrafficShapingProbability
  1379. }
  1380. if len(config.MeekTrafficShapingLimitProtocols) > 0 {
  1381. applyParameters[parameters.MeekTrafficShapingLimitProtocols] = protocol.TunnelProtocols(config.MeekTrafficShapingLimitProtocols)
  1382. }
  1383. if config.MeekMinTLSPadding != nil {
  1384. applyParameters[parameters.MeekMinTLSPadding] = *config.MeekMinTLSPadding
  1385. }
  1386. if config.MeekMaxTLSPadding != nil {
  1387. applyParameters[parameters.MeekMaxTLSPadding] = *config.MeekMaxTLSPadding
  1388. }
  1389. if config.MeekMinLimitRequestPayloadLength != nil {
  1390. applyParameters[parameters.MeekMinLimitRequestPayloadLength] = *config.MeekMinLimitRequestPayloadLength
  1391. }
  1392. if config.MeekMaxLimitRequestPayloadLength != nil {
  1393. applyParameters[parameters.MeekMaxLimitRequestPayloadLength] = *config.MeekMaxLimitRequestPayloadLength
  1394. }
  1395. if config.MeekRedialTLSProbability != nil {
  1396. applyParameters[parameters.MeekRedialTLSProbability] = *config.MeekRedialTLSProbability
  1397. }
  1398. if config.MeekAlternateCookieNameProbability != nil {
  1399. applyParameters[parameters.MeekAlternateCookieNameProbability] = *config.MeekAlternateCookieNameProbability
  1400. }
  1401. if config.MeekAlternateContentTypeProbability != nil {
  1402. applyParameters[parameters.MeekAlternateContentTypeProbability] = *config.MeekAlternateContentTypeProbability
  1403. }
  1404. if config.ObfuscatedSSHMinPadding != nil {
  1405. applyParameters[parameters.ObfuscatedSSHMinPadding] = *config.ObfuscatedSSHMinPadding
  1406. }
  1407. if config.ObfuscatedSSHMaxPadding != nil {
  1408. applyParameters[parameters.ObfuscatedSSHMaxPadding] = *config.ObfuscatedSSHMaxPadding
  1409. }
  1410. if config.LivenessTestMinUpstreamBytes != nil {
  1411. applyParameters[parameters.LivenessTestMinUpstreamBytes] = *config.LivenessTestMinUpstreamBytes
  1412. }
  1413. if config.LivenessTestMaxUpstreamBytes != nil {
  1414. applyParameters[parameters.LivenessTestMaxUpstreamBytes] = *config.LivenessTestMaxUpstreamBytes
  1415. }
  1416. if config.LivenessTestMinDownstreamBytes != nil {
  1417. applyParameters[parameters.LivenessTestMinDownstreamBytes] = *config.LivenessTestMinDownstreamBytes
  1418. }
  1419. if config.LivenessTestMaxDownstreamBytes != nil {
  1420. applyParameters[parameters.LivenessTestMaxDownstreamBytes] = *config.LivenessTestMaxDownstreamBytes
  1421. }
  1422. if config.ReplayCandidateCount != nil {
  1423. applyParameters[parameters.ReplayCandidateCount] = *config.ReplayCandidateCount
  1424. }
  1425. if config.ReplayDialParametersTTLSeconds != nil {
  1426. applyParameters[parameters.ReplayDialParametersTTL] = fmt.Sprintf("%ds", *config.ReplayDialParametersTTLSeconds)
  1427. }
  1428. if config.ReplayTargetUpstreamBytes != nil {
  1429. applyParameters[parameters.ReplayTargetUpstreamBytes] = *config.ReplayTargetUpstreamBytes
  1430. }
  1431. if config.ReplayTargetDownstreamBytes != nil {
  1432. applyParameters[parameters.ReplayTargetDownstreamBytes] = *config.ReplayTargetDownstreamBytes
  1433. }
  1434. if config.ReplayTargetTunnelDurationSeconds != nil {
  1435. applyParameters[parameters.ReplayTargetTunnelDuration] = fmt.Sprintf("%ds", *config.ReplayTargetTunnelDurationSeconds)
  1436. }
  1437. if config.ReplayLaterRoundMoveToFrontProbability != nil {
  1438. applyParameters[parameters.ReplayLaterRoundMoveToFrontProbability] = *config.ReplayLaterRoundMoveToFrontProbability
  1439. }
  1440. if config.ReplayRetainFailedProbability != nil {
  1441. applyParameters[parameters.ReplayRetainFailedProbability] = *config.ReplayRetainFailedProbability
  1442. }
  1443. if config.ReplayIgnoreChangedConfigState != nil {
  1444. applyParameters[parameters.ReplayIgnoreChangedConfigState] = *config.ReplayIgnoreChangedConfigState
  1445. }
  1446. if config.UseOnlyCustomTLSProfiles != nil {
  1447. applyParameters[parameters.UseOnlyCustomTLSProfiles] = *config.UseOnlyCustomTLSProfiles
  1448. }
  1449. if len(config.CustomTLSProfiles) > 0 {
  1450. applyParameters[parameters.CustomTLSProfiles] = config.CustomTLSProfiles
  1451. }
  1452. if config.SelectRandomizedTLSProfileProbability != nil {
  1453. applyParameters[parameters.SelectRandomizedTLSProfileProbability] = *config.SelectRandomizedTLSProfileProbability
  1454. }
  1455. if config.NoDefaultTLSSessionIDProbability != nil {
  1456. applyParameters[parameters.NoDefaultTLSSessionIDProbability] = *config.NoDefaultTLSSessionIDProbability
  1457. }
  1458. if len(config.DisableFrontingProviderTLSProfiles) > 0 {
  1459. applyParameters[parameters.DisableFrontingProviderTLSProfiles] = config.DisableFrontingProviderTLSProfiles
  1460. }
  1461. if config.ClientBurstUpstreamTargetBytes != nil {
  1462. applyParameters[parameters.ClientBurstUpstreamTargetBytes] = *config.ClientBurstUpstreamTargetBytes
  1463. }
  1464. if config.ClientBurstUpstreamDeadlineMilliseconds != nil {
  1465. applyParameters[parameters.ClientBurstUpstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstUpstreamDeadlineMilliseconds)
  1466. }
  1467. if config.ClientBurstDownstreamTargetBytes != nil {
  1468. applyParameters[parameters.ClientBurstDownstreamTargetBytes] = *config.ClientBurstDownstreamTargetBytes
  1469. }
  1470. if config.ClientBurstDownstreamDeadlineMilliseconds != nil {
  1471. applyParameters[parameters.ClientBurstDownstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstDownstreamDeadlineMilliseconds)
  1472. }
  1473. if config.ApplicationParameters != nil {
  1474. applyParameters[parameters.ApplicationParameters] = config.ApplicationParameters
  1475. }
  1476. if config.CustomHostNameRegexes != nil {
  1477. applyParameters[parameters.CustomHostNameRegexes] = parameters.RegexStrings(config.CustomHostNameRegexes)
  1478. }
  1479. if config.CustomHostNameProbability != nil {
  1480. applyParameters[parameters.CustomHostNameProbability] = *config.CustomHostNameProbability
  1481. }
  1482. if config.CustomHostNameLimitProtocols != nil {
  1483. applyParameters[parameters.CustomHostNameLimitProtocols] = protocol.TunnelProtocols(config.CustomHostNameLimitProtocols)
  1484. }
  1485. if config.ConjureCachedRegistrationTTLSeconds != nil {
  1486. applyParameters[parameters.ConjureCachedRegistrationTTL] = fmt.Sprintf("%ds", *config.ConjureCachedRegistrationTTLSeconds)
  1487. }
  1488. if config.ConjureAPIRegistrarBidirectionalURL != "" {
  1489. applyParameters[parameters.ConjureAPIRegistrarBidirectionalURL] = config.ConjureAPIRegistrarBidirectionalURL
  1490. }
  1491. if len(config.ConjureAPIRegistrarFrontingSpecs) > 0 {
  1492. applyParameters[parameters.ConjureAPIRegistrarFrontingSpecs] = config.ConjureAPIRegistrarFrontingSpecs
  1493. }
  1494. if config.ConjureAPIRegistrarMinDelayMilliseconds != nil {
  1495. applyParameters[parameters.ConjureAPIRegistrarMinDelay] = fmt.Sprintf("%dms", *config.ConjureAPIRegistrarMinDelayMilliseconds)
  1496. }
  1497. if config.ConjureAPIRegistrarMaxDelayMilliseconds != nil {
  1498. applyParameters[parameters.ConjureAPIRegistrarMaxDelay] = fmt.Sprintf("%dms", *config.ConjureAPIRegistrarMaxDelayMilliseconds)
  1499. }
  1500. if config.ConjureDecoyRegistrarProbability != nil {
  1501. applyParameters[parameters.ConjureDecoyRegistrarProbability] = *config.ConjureDecoyRegistrarProbability
  1502. }
  1503. if config.ConjureDecoyRegistrarWidth != nil {
  1504. applyParameters[parameters.ConjureDecoyRegistrarWidth] = *config.ConjureDecoyRegistrarWidth
  1505. }
  1506. if config.ConjureDecoyRegistrarMinDelayMilliseconds != nil {
  1507. applyParameters[parameters.ConjureDecoyRegistrarMinDelay] = fmt.Sprintf("%dms", *config.ConjureDecoyRegistrarMinDelayMilliseconds)
  1508. }
  1509. if config.ConjureDecoyRegistrarMaxDelayMilliseconds != nil {
  1510. applyParameters[parameters.ConjureDecoyRegistrarMaxDelay] = fmt.Sprintf("%dms", *config.ConjureDecoyRegistrarMaxDelayMilliseconds)
  1511. }
  1512. if config.HoldOffTunnelMinDurationMilliseconds != nil {
  1513. applyParameters[parameters.HoldOffTunnelMinDuration] = fmt.Sprintf("%dms", *config.HoldOffTunnelMinDurationMilliseconds)
  1514. }
  1515. if config.HoldOffTunnelMaxDurationMilliseconds != nil {
  1516. applyParameters[parameters.HoldOffTunnelMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffTunnelMaxDurationMilliseconds)
  1517. }
  1518. if len(config.HoldOffTunnelProtocols) > 0 {
  1519. applyParameters[parameters.HoldOffTunnelProtocols] = protocol.TunnelProtocols(config.HoldOffTunnelProtocols)
  1520. }
  1521. if len(config.HoldOffTunnelFrontingProviderIDs) > 0 {
  1522. applyParameters[parameters.HoldOffTunnelFrontingProviderIDs] = config.HoldOffTunnelFrontingProviderIDs
  1523. }
  1524. if config.HoldOffTunnelProbability != nil {
  1525. applyParameters[parameters.HoldOffTunnelProbability] = *config.HoldOffTunnelProbability
  1526. }
  1527. if len(config.RestrictFrontingProviderIDs) > 0 {
  1528. applyParameters[parameters.RestrictFrontingProviderIDs] = config.RestrictFrontingProviderIDs
  1529. }
  1530. if config.RestrictFrontingProviderIDsClientProbability != nil {
  1531. applyParameters[parameters.RestrictFrontingProviderIDsClientProbability] = *config.RestrictFrontingProviderIDsClientProbability
  1532. }
  1533. if config.UpstreamProxyAllowAllServerEntrySources != nil {
  1534. applyParameters[parameters.UpstreamProxyAllowAllServerEntrySources] = *config.UpstreamProxyAllowAllServerEntrySources
  1535. }
  1536. if len(config.LimitTunnelDialPortNumbers) > 0 {
  1537. applyParameters[parameters.LimitTunnelDialPortNumbers] = config.LimitTunnelDialPortNumbers
  1538. }
  1539. if config.QUICDisablePathMTUDiscoveryProbability != nil {
  1540. applyParameters[parameters.QUICDisableClientPathMTUDiscoveryProbability] = *config.QUICDisablePathMTUDiscoveryProbability
  1541. }
  1542. if config.DNSResolverAttemptsPerServer != nil {
  1543. applyParameters[parameters.DNSResolverAttemptsPerServer] = *config.DNSResolverAttemptsPerServer
  1544. }
  1545. if config.DNSResolverAttemptsPerPreferredServer != nil {
  1546. applyParameters[parameters.DNSResolverAttemptsPerPreferredServer] = *config.DNSResolverAttemptsPerPreferredServer
  1547. }
  1548. if config.DNSResolverRequestTimeoutMilliseconds != nil {
  1549. applyParameters[parameters.DNSResolverRequestTimeout] = fmt.Sprintf("%dms", *config.DNSResolverRequestTimeoutMilliseconds)
  1550. }
  1551. if config.DNSResolverAwaitTimeoutMilliseconds != nil {
  1552. applyParameters[parameters.DNSResolverAwaitTimeout] = fmt.Sprintf("%dms", *config.DNSResolverAwaitTimeoutMilliseconds)
  1553. }
  1554. if config.DNSResolverPreresolvedIPAddressProbability != nil {
  1555. applyParameters[parameters.DNSResolverPreresolvedIPAddressProbability] = *config.DNSResolverPreresolvedIPAddressProbability
  1556. }
  1557. if config.DNSResolverPreresolvedIPAddressCIDRs != nil {
  1558. applyParameters[parameters.DNSResolverPreresolvedIPAddressCIDRs] = config.DNSResolverPreresolvedIPAddressCIDRs
  1559. }
  1560. if config.DNSResolverAlternateServers != nil {
  1561. applyParameters[parameters.DNSResolverAlternateServers] = config.DNSResolverAlternateServers
  1562. }
  1563. if config.DNSResolverPreferredAlternateServers != nil {
  1564. applyParameters[parameters.DNSResolverPreferredAlternateServers] = config.DNSResolverPreferredAlternateServers
  1565. }
  1566. if config.DNSResolverPreferAlternateServerProbability != nil {
  1567. applyParameters[parameters.DNSResolverPreferAlternateServerProbability] = *config.DNSResolverPreferAlternateServerProbability
  1568. }
  1569. if config.DNSResolverProtocolTransformSpecs != nil {
  1570. applyParameters[parameters.DNSResolverProtocolTransformSpecs] = config.DNSResolverProtocolTransformSpecs
  1571. }
  1572. if config.DNSResolverProtocolTransformScopedSpecNames != nil {
  1573. applyParameters[parameters.DNSResolverProtocolTransformScopedSpecNames] = config.DNSResolverProtocolTransformScopedSpecNames
  1574. }
  1575. if config.DNSResolverProtocolTransformProbability != nil {
  1576. applyParameters[parameters.DNSResolverProtocolTransformProbability] = *config.DNSResolverProtocolTransformProbability
  1577. }
  1578. if config.DNSResolverIncludeEDNS0Probability != nil {
  1579. applyParameters[parameters.DNSResolverIncludeEDNS0Probability] = *config.DNSResolverIncludeEDNS0Probability
  1580. }
  1581. if config.DNSResolverCacheExtensionInitialTTLMilliseconds != nil {
  1582. applyParameters[parameters.DNSResolverCacheExtensionInitialTTL] = fmt.Sprintf("%dms", *config.DNSResolverCacheExtensionInitialTTLMilliseconds)
  1583. }
  1584. if config.DNSResolverCacheExtensionVerifiedTTLMilliseconds != nil {
  1585. applyParameters[parameters.DNSResolverCacheExtensionVerifiedTTL] = fmt.Sprintf("%dms", *config.DNSResolverCacheExtensionVerifiedTTLMilliseconds)
  1586. }
  1587. if config.DirectHTTPProtocolTransformSpecs != nil {
  1588. applyParameters[parameters.DirectHTTPProtocolTransformSpecs] = config.DirectHTTPProtocolTransformSpecs
  1589. }
  1590. if config.DirectHTTPProtocolTransformScopedSpecNames != nil {
  1591. applyParameters[parameters.DirectHTTPProtocolTransformScopedSpecNames] = config.DirectHTTPProtocolTransformScopedSpecNames
  1592. }
  1593. if config.DirectHTTPProtocolTransformProbability != nil {
  1594. applyParameters[parameters.DirectHTTPProtocolTransformProbability] = *config.DirectHTTPProtocolTransformProbability
  1595. }
  1596. if config.FrontedHTTPProtocolTransformSpecs != nil {
  1597. applyParameters[parameters.FrontedHTTPProtocolTransformSpecs] = config.FrontedHTTPProtocolTransformSpecs
  1598. }
  1599. if config.FrontedHTTPProtocolTransformScopedSpecNames != nil {
  1600. applyParameters[parameters.FrontedHTTPProtocolTransformScopedSpecNames] = config.FrontedHTTPProtocolTransformScopedSpecNames
  1601. }
  1602. if config.FrontedHTTPProtocolTransformProbability != nil {
  1603. applyParameters[parameters.FrontedHTTPProtocolTransformProbability] = *config.FrontedHTTPProtocolTransformProbability
  1604. }
  1605. if config.OSSHObfuscatorSeedTransformSpecs != nil {
  1606. applyParameters[parameters.OSSHObfuscatorSeedTransformSpecs] = config.OSSHObfuscatorSeedTransformSpecs
  1607. }
  1608. if config.OSSHObfuscatorSeedTransformScopedSpecNames != nil {
  1609. applyParameters[parameters.OSSHObfuscatorSeedTransformScopedSpecNames] = config.OSSHObfuscatorSeedTransformScopedSpecNames
  1610. }
  1611. if config.OSSHObfuscatorSeedTransformProbability != nil {
  1612. applyParameters[parameters.OSSHObfuscatorSeedTransformProbability] = *config.OSSHObfuscatorSeedTransformProbability
  1613. }
  1614. if config.ObfuscatedQUICNonceTransformSpecs != nil {
  1615. applyParameters[parameters.ObfuscatedQUICNonceTransformSpecs] = config.ObfuscatedQUICNonceTransformSpecs
  1616. }
  1617. if config.ObfuscatedQUICNonceTransformScopedSpecNames != nil {
  1618. applyParameters[parameters.ObfuscatedQUICNonceTransformScopedSpecNames] = config.ObfuscatedQUICNonceTransformScopedSpecNames
  1619. }
  1620. if config.ObfuscatedQUICNonceTransformProbability != nil {
  1621. applyParameters[parameters.ObfuscatedQUICNonceTransformProbability] = *config.ObfuscatedQUICNonceTransformProbability
  1622. }
  1623. // When adding new config dial parameters that may override tactics, also
  1624. // update setDialParametersHash.
  1625. return applyParameters
  1626. }
  1627. func (config *Config) setDialParametersHash() {
  1628. // Calculate and store a hash of the config values that may impact
  1629. // dial parameters. This hash is used as part of the dial parameters
  1630. // replay mechanism to detect when persisted dial parameters should
  1631. // be discarded due to conflicting config changes.
  1632. //
  1633. // With a couple of minor exceptions, configuring dial parameters via the
  1634. // config is intended for testing only, and so these parameters are expected
  1635. // to be present in test runs only. It remains an important case to discard
  1636. // replay dial parameters when test config parameters are varied.
  1637. //
  1638. // Hashing the parameter names detects some ambiguous hash cases, such as two
  1639. // consecutive int64 parameters, one omitted and one not, that are flipped.
  1640. // The serialization is not completely unambiguous, and the format is
  1641. // currently limited by legacy cases (not invalidating replay dial parameters
  1642. // for production clients is more important than invalidating for test runs).
  1643. // We cannot hash the entire config JSON as it contains non-dial parameter
  1644. // fields which may frequently change across runs.
  1645. //
  1646. // MD5 hash is used solely as a data checksum and not for any security
  1647. // purpose.
  1648. hash := md5.New()
  1649. if len(config.LimitTunnelProtocols) > 0 {
  1650. hash.Write([]byte("LimitTunnelProtocols"))
  1651. for _, protocol := range config.LimitTunnelProtocols {
  1652. hash.Write([]byte(protocol))
  1653. }
  1654. }
  1655. if len(config.InitialLimitTunnelProtocols) > 0 && config.InitialLimitTunnelProtocolsCandidateCount > 0 {
  1656. hash.Write([]byte("InitialLimitTunnelProtocols"))
  1657. for _, protocol := range config.InitialLimitTunnelProtocols {
  1658. hash.Write([]byte(protocol))
  1659. }
  1660. binary.Write(hash, binary.LittleEndian, int64(config.InitialLimitTunnelProtocolsCandidateCount))
  1661. }
  1662. if len(config.LimitTLSProfiles) > 0 {
  1663. hash.Write([]byte("LimitTLSProfiles"))
  1664. for _, profile := range config.LimitTLSProfiles {
  1665. hash.Write([]byte(profile))
  1666. }
  1667. }
  1668. if len(config.LimitQUICVersions) > 0 {
  1669. hash.Write([]byte("LimitQUICVersions"))
  1670. for _, version := range config.LimitQUICVersions {
  1671. hash.Write([]byte(version))
  1672. }
  1673. }
  1674. // Whether a custom User-Agent is specified is a binary flag: when not set,
  1675. // the replay dial parameters value applies. When set, external
  1676. // considerations apply.
  1677. if _, ok := config.CustomHeaders["User-Agent"]; ok {
  1678. hash.Write([]byte("CustomHeaders User-Agent"))
  1679. hash.Write([]byte{1})
  1680. }
  1681. if config.UpstreamProxyURL != "" {
  1682. hash.Write([]byte("UpstreamProxyURL"))
  1683. hash.Write([]byte(config.UpstreamProxyURL))
  1684. }
  1685. if config.TransformHostNameProbability != nil {
  1686. hash.Write([]byte("TransformHostNameProbability"))
  1687. binary.Write(hash, binary.LittleEndian, *config.TransformHostNameProbability)
  1688. }
  1689. if config.FragmentorProbability != nil {
  1690. hash.Write([]byte("FragmentorProbability"))
  1691. binary.Write(hash, binary.LittleEndian, *config.FragmentorProbability)
  1692. }
  1693. if len(config.FragmentorLimitProtocols) > 0 {
  1694. hash.Write([]byte("FragmentorLimitProtocols"))
  1695. for _, protocol := range config.FragmentorLimitProtocols {
  1696. hash.Write([]byte(protocol))
  1697. }
  1698. }
  1699. if config.FragmentorMinTotalBytes != nil {
  1700. hash.Write([]byte("FragmentorMinTotalBytes"))
  1701. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinTotalBytes))
  1702. }
  1703. if config.FragmentorMaxTotalBytes != nil {
  1704. hash.Write([]byte("FragmentorMaxTotalBytes"))
  1705. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxTotalBytes))
  1706. }
  1707. if config.FragmentorMinWriteBytes != nil {
  1708. hash.Write([]byte("FragmentorMinWriteBytes"))
  1709. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinWriteBytes))
  1710. }
  1711. if config.FragmentorMaxWriteBytes != nil {
  1712. hash.Write([]byte("FragmentorMaxWriteBytes"))
  1713. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxWriteBytes))
  1714. }
  1715. if config.FragmentorMinDelayMicroseconds != nil {
  1716. hash.Write([]byte("FragmentorMinDelayMicroseconds"))
  1717. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinDelayMicroseconds))
  1718. }
  1719. if config.FragmentorMaxDelayMicroseconds != nil {
  1720. hash.Write([]byte("FragmentorMaxDelayMicroseconds"))
  1721. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxDelayMicroseconds))
  1722. }
  1723. if config.MeekTrafficShapingProbability != nil {
  1724. hash.Write([]byte("MeekTrafficShapingProbability"))
  1725. binary.Write(hash, binary.LittleEndian, int64(*config.MeekTrafficShapingProbability))
  1726. }
  1727. if len(config.MeekTrafficShapingLimitProtocols) > 0 {
  1728. hash.Write([]byte("MeekTrafficShapingLimitProtocols"))
  1729. for _, protocol := range config.MeekTrafficShapingLimitProtocols {
  1730. hash.Write([]byte(protocol))
  1731. }
  1732. }
  1733. if config.MeekMinLimitRequestPayloadLength != nil {
  1734. hash.Write([]byte("MeekMinLimitRequestPayloadLength"))
  1735. binary.Write(hash, binary.LittleEndian, int64(*config.MeekMinLimitRequestPayloadLength))
  1736. }
  1737. if config.MeekMaxLimitRequestPayloadLength != nil {
  1738. hash.Write([]byte("MeekMaxLimitRequestPayloadLength"))
  1739. binary.Write(hash, binary.LittleEndian, int64(*config.MeekMaxLimitRequestPayloadLength))
  1740. }
  1741. if config.MeekRedialTLSProbability != nil {
  1742. hash.Write([]byte("MeekRedialTLSProbability"))
  1743. binary.Write(hash, binary.LittleEndian, *config.MeekRedialTLSProbability)
  1744. }
  1745. if config.ObfuscatedSSHMinPadding != nil {
  1746. hash.Write([]byte("ObfuscatedSSHMinPadding"))
  1747. binary.Write(hash, binary.LittleEndian, int64(*config.ObfuscatedSSHMinPadding))
  1748. }
  1749. if config.ObfuscatedSSHMaxPadding != nil {
  1750. hash.Write([]byte("ObfuscatedSSHMaxPadding"))
  1751. binary.Write(hash, binary.LittleEndian, int64(*config.ObfuscatedSSHMaxPadding))
  1752. }
  1753. if config.LivenessTestMinUpstreamBytes != nil {
  1754. hash.Write([]byte("LivenessTestMinUpstreamBytes"))
  1755. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMinUpstreamBytes))
  1756. }
  1757. if config.LivenessTestMaxUpstreamBytes != nil {
  1758. hash.Write([]byte("LivenessTestMaxUpstreamBytes"))
  1759. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMaxUpstreamBytes))
  1760. }
  1761. if config.LivenessTestMinDownstreamBytes != nil {
  1762. hash.Write([]byte("LivenessTestMinDownstreamBytes"))
  1763. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMinDownstreamBytes))
  1764. }
  1765. if config.LivenessTestMaxDownstreamBytes != nil {
  1766. hash.Write([]byte("LivenessTestMaxDownstreamBytes"))
  1767. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMaxDownstreamBytes))
  1768. }
  1769. // Legacy case: these parameters are included in the hash unconditionally,
  1770. // and so will impact almost all production clients. These parameter names
  1771. // are not hashed since that would invalidate all replay dial parameters for
  1772. // existing clients whose hashes predate the inclusion of parameter names.
  1773. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierMin)
  1774. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierMax)
  1775. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierLambda)
  1776. if config.UseOnlyCustomTLSProfiles != nil {
  1777. hash.Write([]byte("UseOnlyCustomTLSProfiles"))
  1778. binary.Write(hash, binary.LittleEndian, *config.UseOnlyCustomTLSProfiles)
  1779. }
  1780. if len(config.CustomTLSProfiles) > 0 {
  1781. hash.Write([]byte("CustomTLSProfiles"))
  1782. for _, customTLSProfile := range config.CustomTLSProfiles {
  1783. encodedCustomTLSProofile, _ := json.Marshal(customTLSProfile)
  1784. hash.Write(encodedCustomTLSProofile)
  1785. }
  1786. }
  1787. if config.SelectRandomizedTLSProfileProbability != nil {
  1788. hash.Write([]byte("SelectRandomizedTLSProfileProbability"))
  1789. binary.Write(hash, binary.LittleEndian, *config.SelectRandomizedTLSProfileProbability)
  1790. }
  1791. if config.NoDefaultTLSSessionIDProbability != nil {
  1792. hash.Write([]byte("NoDefaultTLSSessionIDProbability"))
  1793. binary.Write(hash, binary.LittleEndian, *config.NoDefaultTLSSessionIDProbability)
  1794. }
  1795. if len(config.DisableFrontingProviderTLSProfiles) > 0 {
  1796. hash.Write([]byte("DisableFrontingProviderTLSProfiles"))
  1797. encodedDisableFrontingProviderTLSProfiles, _ :=
  1798. json.Marshal(config.DisableFrontingProviderTLSProfiles)
  1799. hash.Write(encodedDisableFrontingProviderTLSProfiles)
  1800. }
  1801. if len(config.CustomHostNameRegexes) > 0 {
  1802. hash.Write([]byte("CustomHostNameRegexes"))
  1803. for _, customHostNameRegex := range config.CustomHostNameRegexes {
  1804. hash.Write([]byte(customHostNameRegex))
  1805. }
  1806. }
  1807. if config.CustomHostNameProbability != nil {
  1808. hash.Write([]byte("CustomHostNameProbability"))
  1809. binary.Write(hash, binary.LittleEndian, *config.CustomHostNameProbability)
  1810. }
  1811. if len(config.CustomHostNameLimitProtocols) > 0 {
  1812. hash.Write([]byte("CustomHostNameLimitProtocols"))
  1813. for _, protocol := range config.CustomHostNameLimitProtocols {
  1814. hash.Write([]byte(protocol))
  1815. }
  1816. }
  1817. if config.ConjureCachedRegistrationTTLSeconds != nil {
  1818. hash.Write([]byte("ConjureCachedRegistrationTTLSeconds"))
  1819. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureCachedRegistrationTTLSeconds))
  1820. }
  1821. if config.ConjureAPIRegistrarBidirectionalURL != "" {
  1822. hash.Write([]byte("ConjureAPIRegistrarBidirectionalURL"))
  1823. hash.Write([]byte(config.ConjureAPIRegistrarBidirectionalURL))
  1824. }
  1825. if len(config.ConjureAPIRegistrarFrontingSpecs) > 0 {
  1826. hash.Write([]byte("ConjureAPIRegistrarFrontingSpecs"))
  1827. for _, frontingSpec := range config.ConjureAPIRegistrarFrontingSpecs {
  1828. encodedFrontSpec, _ := json.Marshal(frontingSpec)
  1829. hash.Write(encodedFrontSpec)
  1830. }
  1831. }
  1832. if config.ConjureAPIRegistrarMinDelayMilliseconds != nil {
  1833. hash.Write([]byte("ConjureAPIRegistrarMinDelayMilliseconds"))
  1834. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureAPIRegistrarMinDelayMilliseconds))
  1835. }
  1836. if config.ConjureAPIRegistrarMaxDelayMilliseconds != nil {
  1837. hash.Write([]byte("ConjureAPIRegistrarMaxDelayMilliseconds"))
  1838. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureAPIRegistrarMaxDelayMilliseconds))
  1839. }
  1840. if config.ConjureDecoyRegistrarWidth != nil {
  1841. hash.Write([]byte("ConjureDecoyRegistrarWidth"))
  1842. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarWidth))
  1843. }
  1844. if config.ConjureDecoyRegistrarMinDelayMilliseconds != nil {
  1845. hash.Write([]byte("ConjureDecoyRegistrarMinDelayMilliseconds"))
  1846. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarMinDelayMilliseconds))
  1847. }
  1848. if config.ConjureDecoyRegistrarMaxDelayMilliseconds != nil {
  1849. hash.Write([]byte("ConjureDecoyRegistrarMaxDelayMilliseconds"))
  1850. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarMaxDelayMilliseconds))
  1851. }
  1852. if config.HoldOffTunnelMinDurationMilliseconds != nil {
  1853. hash.Write([]byte("HoldOffTunnelMinDurationMilliseconds"))
  1854. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffTunnelMinDurationMilliseconds))
  1855. }
  1856. if config.HoldOffTunnelMaxDurationMilliseconds != nil {
  1857. hash.Write([]byte("HoldOffTunnelMaxDurationMilliseconds"))
  1858. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffTunnelMaxDurationMilliseconds))
  1859. }
  1860. if len(config.HoldOffTunnelProtocols) > 0 {
  1861. hash.Write([]byte("HoldOffTunnelProtocols"))
  1862. for _, protocol := range config.HoldOffTunnelProtocols {
  1863. hash.Write([]byte(protocol))
  1864. }
  1865. }
  1866. if len(config.HoldOffTunnelFrontingProviderIDs) > 0 {
  1867. hash.Write([]byte("HoldOffTunnelFrontingProviderIDs"))
  1868. for _, providerID := range config.HoldOffTunnelFrontingProviderIDs {
  1869. hash.Write([]byte(providerID))
  1870. }
  1871. }
  1872. if config.HoldOffTunnelProbability != nil {
  1873. hash.Write([]byte("HoldOffTunnelProbability"))
  1874. binary.Write(hash, binary.LittleEndian, *config.HoldOffTunnelProbability)
  1875. }
  1876. if len(config.RestrictFrontingProviderIDs) > 0 {
  1877. hash.Write([]byte("RestrictFrontingProviderIDs"))
  1878. for _, providerID := range config.RestrictFrontingProviderIDs {
  1879. hash.Write([]byte(providerID))
  1880. }
  1881. }
  1882. if config.RestrictFrontingProviderIDsClientProbability != nil {
  1883. hash.Write([]byte("RestrictFrontingProviderIDsClientProbability"))
  1884. binary.Write(hash, binary.LittleEndian, *config.RestrictFrontingProviderIDsClientProbability)
  1885. }
  1886. if config.UpstreamProxyAllowAllServerEntrySources != nil {
  1887. hash.Write([]byte("UpstreamProxyAllowAllServerEntrySources"))
  1888. binary.Write(hash, binary.LittleEndian, *config.UpstreamProxyAllowAllServerEntrySources)
  1889. }
  1890. if len(config.LimitTunnelDialPortNumbers) > 0 {
  1891. hash.Write([]byte("LimitTunnelDialPortNumbers"))
  1892. encodedLimitTunnelDialPortNumbers, _ :=
  1893. json.Marshal(config.LimitTunnelDialPortNumbers)
  1894. hash.Write(encodedLimitTunnelDialPortNumbers)
  1895. }
  1896. if config.QUICDisablePathMTUDiscoveryProbability != nil {
  1897. hash.Write([]byte("QUICDisablePathMTUDiscoveryProbability"))
  1898. binary.Write(hash, binary.LittleEndian, *config.QUICDisablePathMTUDiscoveryProbability)
  1899. }
  1900. if config.DNSResolverAttemptsPerServer != nil {
  1901. hash.Write([]byte("DNSResolverAttemptsPerServer"))
  1902. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverAttemptsPerServer))
  1903. }
  1904. if config.DNSResolverRequestTimeoutMilliseconds != nil {
  1905. hash.Write([]byte("DNSResolverRequestTimeoutMilliseconds"))
  1906. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverRequestTimeoutMilliseconds))
  1907. }
  1908. if config.DNSResolverAwaitTimeoutMilliseconds != nil {
  1909. hash.Write([]byte("DNSResolverAwaitTimeoutMilliseconds"))
  1910. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverAwaitTimeoutMilliseconds))
  1911. }
  1912. if config.DNSResolverPreresolvedIPAddressCIDRs != nil {
  1913. hash.Write([]byte("DNSResolverPreresolvedIPAddressCIDRs"))
  1914. encodedDNSResolverPreresolvedIPAddressCIDRs, _ :=
  1915. json.Marshal(config.DNSResolverPreresolvedIPAddressCIDRs)
  1916. hash.Write(encodedDNSResolverPreresolvedIPAddressCIDRs)
  1917. }
  1918. if config.DNSResolverPreresolvedIPAddressProbability != nil {
  1919. hash.Write([]byte("DNSResolverPreresolvedIPAddressProbability"))
  1920. binary.Write(hash, binary.LittleEndian, *config.DNSResolverPreresolvedIPAddressProbability)
  1921. }
  1922. if config.DNSResolverAlternateServers != nil {
  1923. hash.Write([]byte("DNSResolverAlternateServers"))
  1924. for _, server := range config.DNSResolverAlternateServers {
  1925. hash.Write([]byte(server))
  1926. }
  1927. }
  1928. if config.DNSResolverPreferAlternateServerProbability != nil {
  1929. hash.Write([]byte("DNSResolverPreferAlternateServerProbability"))
  1930. binary.Write(hash, binary.LittleEndian, *config.DNSResolverPreferAlternateServerProbability)
  1931. }
  1932. if config.DNSResolverProtocolTransformSpecs != nil {
  1933. hash.Write([]byte("DNSResolverProtocolTransformSpecs"))
  1934. encodedDNSResolverProtocolTransformSpecs, _ :=
  1935. json.Marshal(config.DNSResolverProtocolTransformSpecs)
  1936. hash.Write(encodedDNSResolverProtocolTransformSpecs)
  1937. }
  1938. if config.DNSResolverProtocolTransformScopedSpecNames != nil {
  1939. hash.Write([]byte(""))
  1940. encodedDNSResolverProtocolTransformScopedSpecNames, _ :=
  1941. json.Marshal(config.DNSResolverProtocolTransformScopedSpecNames)
  1942. hash.Write(encodedDNSResolverProtocolTransformScopedSpecNames)
  1943. }
  1944. if config.DNSResolverProtocolTransformProbability != nil {
  1945. hash.Write([]byte("DNSResolverProtocolTransformProbability"))
  1946. binary.Write(hash, binary.LittleEndian, *config.DNSResolverProtocolTransformProbability)
  1947. }
  1948. if config.DNSResolverIncludeEDNS0Probability != nil {
  1949. hash.Write([]byte("DNSResolverIncludeEDNS0Probability"))
  1950. binary.Write(hash, binary.LittleEndian, *config.DNSResolverIncludeEDNS0Probability)
  1951. }
  1952. if config.DNSResolverCacheExtensionInitialTTLMilliseconds != nil {
  1953. hash.Write([]byte("DNSResolverCacheExtensionInitialTTLMilliseconds"))
  1954. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverCacheExtensionInitialTTLMilliseconds))
  1955. }
  1956. if config.DNSResolverCacheExtensionVerifiedTTLMilliseconds != nil {
  1957. hash.Write([]byte("DNSResolverCacheExtensionVerifiedTTLMilliseconds"))
  1958. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverCacheExtensionVerifiedTTLMilliseconds))
  1959. }
  1960. if config.DirectHTTPProtocolTransformSpecs != nil {
  1961. hash.Write([]byte("DirectHTTPProtocolTransformSpecs"))
  1962. encodedDirectHTTPProtocolTransformSpecs, _ :=
  1963. json.Marshal(config.DirectHTTPProtocolTransformSpecs)
  1964. hash.Write(encodedDirectHTTPProtocolTransformSpecs)
  1965. }
  1966. if config.DirectHTTPProtocolTransformScopedSpecNames != nil {
  1967. hash.Write([]byte(""))
  1968. encodedDirectHTTPProtocolTransformScopedSpecNames, _ :=
  1969. json.Marshal(config.DirectHTTPProtocolTransformScopedSpecNames)
  1970. hash.Write(encodedDirectHTTPProtocolTransformScopedSpecNames)
  1971. }
  1972. if config.DirectHTTPProtocolTransformProbability != nil {
  1973. hash.Write([]byte("DirectHTTPProtocolTransformProbability"))
  1974. binary.Write(hash, binary.LittleEndian, *config.DirectHTTPProtocolTransformProbability)
  1975. }
  1976. if config.FrontedHTTPProtocolTransformSpecs != nil {
  1977. hash.Write([]byte("FrontedHTTPProtocolTransformSpecs"))
  1978. encodedFrontedHTTPProtocolTransformSpecs, _ :=
  1979. json.Marshal(config.FrontedHTTPProtocolTransformSpecs)
  1980. hash.Write(encodedFrontedHTTPProtocolTransformSpecs)
  1981. }
  1982. if config.FrontedHTTPProtocolTransformScopedSpecNames != nil {
  1983. hash.Write([]byte(""))
  1984. encodedFrontedHTTPProtocolTransformScopedSpecNames, _ :=
  1985. json.Marshal(config.FrontedHTTPProtocolTransformScopedSpecNames)
  1986. hash.Write(encodedFrontedHTTPProtocolTransformScopedSpecNames)
  1987. }
  1988. if config.FrontedHTTPProtocolTransformProbability != nil {
  1989. hash.Write([]byte("FrontedHTTPProtocolTransformProbability"))
  1990. binary.Write(hash, binary.LittleEndian, *config.FrontedHTTPProtocolTransformProbability)
  1991. }
  1992. if config.OSSHObfuscatorSeedTransformSpecs != nil {
  1993. hash.Write([]byte("OSSHObfuscatorSeedTransformSpecs"))
  1994. encodedOSSHObfuscatorSeedTransformSpecs, _ :=
  1995. json.Marshal(config.OSSHObfuscatorSeedTransformSpecs)
  1996. hash.Write(encodedOSSHObfuscatorSeedTransformSpecs)
  1997. }
  1998. if config.OSSHObfuscatorSeedTransformScopedSpecNames != nil {
  1999. hash.Write([]byte(""))
  2000. encodedOSSHObfuscatorSeedTransformScopedSpecNames, _ :=
  2001. json.Marshal(config.OSSHObfuscatorSeedTransformScopedSpecNames)
  2002. hash.Write(encodedOSSHObfuscatorSeedTransformScopedSpecNames)
  2003. }
  2004. if config.OSSHObfuscatorSeedTransformProbability != nil {
  2005. hash.Write([]byte("OSSHObfuscatorSeedTransformProbability"))
  2006. binary.Write(hash, binary.LittleEndian, *config.OSSHObfuscatorSeedTransformProbability)
  2007. }
  2008. if config.ObfuscatedQUICNonceTransformSpecs != nil {
  2009. hash.Write([]byte("ObfuscatedQUICNonceTransformSpecs"))
  2010. encodedObfuscatedQUICNonceTransformSpecs, _ :=
  2011. json.Marshal(config.ObfuscatedQUICNonceTransformSpecs)
  2012. hash.Write(encodedObfuscatedQUICNonceTransformSpecs)
  2013. }
  2014. if config.ObfuscatedQUICNonceTransformScopedSpecNames != nil {
  2015. hash.Write([]byte(""))
  2016. encodedObfuscatedQUICNonceTransformScopedSpecNames, _ :=
  2017. json.Marshal(config.ObfuscatedQUICNonceTransformScopedSpecNames)
  2018. hash.Write(encodedObfuscatedQUICNonceTransformScopedSpecNames)
  2019. }
  2020. if config.ObfuscatedQUICNonceTransformProbability != nil {
  2021. hash.Write([]byte("ObfuscatedQUICNonceTransformProbability"))
  2022. binary.Write(hash, binary.LittleEndian, *config.ObfuscatedQUICNonceTransformProbability)
  2023. }
  2024. config.dialParametersHash = hash.Sum(nil)
  2025. }
  2026. func promoteLegacyTransferURL(URL string) parameters.TransferURLs {
  2027. transferURLs := make(parameters.TransferURLs, 1)
  2028. transferURLs[0] = &parameters.TransferURL{
  2029. URL: base64.StdEncoding.EncodeToString([]byte(URL)),
  2030. SkipVerify: false,
  2031. OnlyAfterAttempts: 0,
  2032. }
  2033. return transferURLs
  2034. }
  2035. type loggingDeviceBinder struct {
  2036. d DeviceBinder
  2037. }
  2038. func newLoggingDeviceBinder(d DeviceBinder) *loggingDeviceBinder {
  2039. return &loggingDeviceBinder{d: d}
  2040. }
  2041. func (d *loggingDeviceBinder) BindToDevice(fileDescriptor int) (string, error) {
  2042. deviceInfo, err := d.d.BindToDevice(fileDescriptor)
  2043. if err == nil && deviceInfo != "" {
  2044. NoticeBindToDevice(deviceInfo)
  2045. }
  2046. return deviceInfo, err
  2047. }
  2048. type staticNetworkGetter struct {
  2049. networkID string
  2050. }
  2051. func newStaticNetworkGetter(networkID string) *staticNetworkGetter {
  2052. return &staticNetworkGetter{networkID: networkID}
  2053. }
  2054. func (n *staticNetworkGetter) GetNetworkID() string {
  2055. return n.networkID
  2056. }
  2057. type loggingNetworkIDGetter struct {
  2058. n NetworkIDGetter
  2059. }
  2060. func newLoggingNetworkIDGetter(n NetworkIDGetter) *loggingNetworkIDGetter {
  2061. return &loggingNetworkIDGetter{n: n}
  2062. }
  2063. func (n *loggingNetworkIDGetter) GetNetworkID() string {
  2064. networkID := n.n.GetNetworkID()
  2065. // All PII must appear after the initial "-"
  2066. // See: https://godoc.org/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon#NetworkIDGetter
  2067. logNetworkID := networkID
  2068. index := strings.Index(logNetworkID, "-")
  2069. if index != -1 {
  2070. logNetworkID = logNetworkID[:index]
  2071. }
  2072. if len(logNetworkID)+1 < len(networkID) {
  2073. // Indicate when additional network info was present after the first "-".
  2074. logNetworkID += "+[redacted]"
  2075. }
  2076. NoticeNetworkID(logNetworkID)
  2077. return networkID
  2078. }
  2079. // migrationsFromLegacyNoticeFilePaths returns the file migrations which must be
  2080. // performed to move notice files from legacy file paths, which were configured
  2081. // with the legacy config fields HomepageNoticesFilename and
  2082. // RotatingNoticesFilename, to the new file paths used by Psiphon which exist
  2083. // under the data root directory.
  2084. func migrationsFromLegacyNoticeFilePaths(config *Config) []FileMigration {
  2085. var noticeMigrations []FileMigration
  2086. if config.MigrateHomepageNoticesFilename != "" {
  2087. noticeMigrations = append(noticeMigrations, FileMigration{
  2088. Name: "hompage",
  2089. OldPath: config.MigrateHomepageNoticesFilename,
  2090. NewPath: config.GetHomePageFilename(),
  2091. })
  2092. }
  2093. if config.MigrateRotatingNoticesFilename != "" {
  2094. migrations := []FileMigration{
  2095. {
  2096. Name: "notices",
  2097. OldPath: config.MigrateRotatingNoticesFilename,
  2098. NewPath: config.GetNoticesFilename(),
  2099. IsDir: false,
  2100. },
  2101. {
  2102. Name: "notices.1",
  2103. OldPath: config.MigrateRotatingNoticesFilename + ".1",
  2104. NewPath: config.GetNoticesFilename() + ".1",
  2105. },
  2106. }
  2107. noticeMigrations = append(noticeMigrations, migrations...)
  2108. }
  2109. return noticeMigrations
  2110. }
  2111. // migrationsFromLegacyFilePaths returns the file migrations which must be
  2112. // performed to move files from legacy file paths, which were configured with
  2113. // legacy config fields, to the new file paths used by Psiphon which exist
  2114. // under the data root directory.
  2115. // Note: an attempt is made to redact any file paths from the returned error.
  2116. func migrationsFromLegacyFilePaths(config *Config) ([]FileMigration, error) {
  2117. migrations := []FileMigration{
  2118. {
  2119. Name: "psiphon.boltdb",
  2120. OldPath: filepath.Join(config.MigrateDataStoreDirectory, "psiphon.boltdb"),
  2121. NewPath: filepath.Join(config.GetDataStoreDirectory(), "psiphon.boltdb"),
  2122. },
  2123. {
  2124. Name: "psiphon.boltdb.lock",
  2125. OldPath: filepath.Join(config.MigrateDataStoreDirectory, "psiphon.boltdb.lock"),
  2126. NewPath: filepath.Join(config.GetDataStoreDirectory(), "psiphon.boltdb.lock"),
  2127. },
  2128. }
  2129. if config.MigrateRemoteServerListDownloadFilename != "" {
  2130. // Migrate remote server list files
  2131. rslMigrations := []FileMigration{
  2132. {
  2133. Name: "remote_server_list",
  2134. OldPath: config.MigrateRemoteServerListDownloadFilename,
  2135. NewPath: config.GetRemoteServerListDownloadFilename(),
  2136. },
  2137. {
  2138. Name: "remote_server_list.part",
  2139. OldPath: config.MigrateRemoteServerListDownloadFilename + ".part",
  2140. NewPath: config.GetRemoteServerListDownloadFilename() + ".part",
  2141. },
  2142. {
  2143. Name: "remote_server_list.part.etag",
  2144. OldPath: config.MigrateRemoteServerListDownloadFilename + ".part.etag",
  2145. NewPath: config.GetRemoteServerListDownloadFilename() + ".part.etag",
  2146. },
  2147. }
  2148. migrations = append(migrations, rslMigrations...)
  2149. }
  2150. if config.MigrateObfuscatedServerListDownloadDirectory != "" {
  2151. // Migrate OSL registry file and downloads
  2152. oslFileRegex, err := regexp.Compile(`^osl-.+$`)
  2153. if err != nil {
  2154. return nil, errors.TraceMsg(err, "failed to compile regex for osl files")
  2155. }
  2156. files, err := ioutil.ReadDir(config.MigrateObfuscatedServerListDownloadDirectory)
  2157. if err != nil {
  2158. NoticeWarning(
  2159. "Migration: failed to read OSL download directory with error %s",
  2160. common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory))
  2161. } else {
  2162. for _, file := range files {
  2163. if oslFileRegex.MatchString(file.Name()) {
  2164. fileMigration := FileMigration{
  2165. Name: "osl",
  2166. OldPath: filepath.Join(config.MigrateObfuscatedServerListDownloadDirectory, file.Name()),
  2167. NewPath: filepath.Join(config.GetObfuscatedServerListDownloadDirectory(), file.Name()),
  2168. }
  2169. migrations = append(migrations, fileMigration)
  2170. }
  2171. }
  2172. }
  2173. }
  2174. if config.MigrateUpgradeDownloadFilename != "" {
  2175. // Migrate downloaded upgrade files
  2176. oldUpgradeDownloadFilename := filepath.Base(config.MigrateUpgradeDownloadFilename)
  2177. // Create regex for:
  2178. // <old_upgrade_download_filename>
  2179. // <old_upgrade_download_filename>.<client_version_number>
  2180. // <old_upgrade_download_filename>.<client_version_number>.part
  2181. // <old_upgrade_download_filename>.<client_version_number>.part.etag
  2182. upgradeDownloadFileRegex, err := regexp.Compile(`^` + oldUpgradeDownloadFilename + `(\.\d+(\.part(\.etag)?)?)?$`)
  2183. if err != nil {
  2184. return nil, errors.TraceMsg(err, "failed to compile regex for upgrade files")
  2185. }
  2186. upgradeDownloadDir := filepath.Dir(config.MigrateUpgradeDownloadFilename)
  2187. files, err := ioutil.ReadDir(upgradeDownloadDir)
  2188. if err != nil {
  2189. NoticeWarning(
  2190. "Migration: failed to read upgrade download directory with error %s",
  2191. common.RedactFilePathsError(err, upgradeDownloadDir))
  2192. } else {
  2193. for _, file := range files {
  2194. if upgradeDownloadFileRegex.MatchString(file.Name()) {
  2195. oldFileSuffix := strings.TrimPrefix(file.Name(), oldUpgradeDownloadFilename)
  2196. fileMigration := FileMigration{
  2197. Name: "upgrade",
  2198. OldPath: filepath.Join(upgradeDownloadDir, file.Name()),
  2199. NewPath: config.GetUpgradeDownloadFilename() + oldFileSuffix,
  2200. }
  2201. migrations = append(migrations, fileMigration)
  2202. }
  2203. }
  2204. }
  2205. }
  2206. return migrations, nil
  2207. }