config.go 175 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157
  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. "reflect"
  31. "regexp"
  32. "strconv"
  33. "strings"
  34. "sync"
  35. "sync/atomic"
  36. "time"
  37. "unicode"
  38. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  39. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  40. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy"
  41. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/networkid"
  42. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
  43. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
  44. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
  45. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/transforms"
  46. "golang.org/x/crypto/nacl/secretbox"
  47. )
  48. const (
  49. TUNNEL_POOL_SIZE = 1
  50. MAX_TUNNEL_POOL_SIZE = 32
  51. // Psiphon data directory name, relative to config.DataRootDirectory.
  52. // See config.GetPsiphonDataDirectory().
  53. PsiphonDataDirectoryName = "ca.psiphon.PsiphonTunnel.tunnel-core"
  54. // Filename constants, all relative to config.GetPsiphonDataDirectory().
  55. HomepageFilename = "homepage"
  56. NoticesFilename = "notices"
  57. OldNoticesFilename = "notices.1"
  58. UpgradeDownloadFilename = "upgrade"
  59. )
  60. // Config is the Psiphon configuration specified by the application. This
  61. // configuration controls the behavior of the core tunnel functionality.
  62. //
  63. // To distinguish omitted timeout params from explicit 0 value timeout params,
  64. // corresponding fields are int pointers. nil means no value was supplied and
  65. // to use the default; a non-nil pointer to 0 means no timeout.
  66. type Config struct {
  67. // DataRootDirectory is the directory in which to store persistent files,
  68. // which contain information such as server entries. By default, current
  69. // working directory.
  70. //
  71. // Psiphon will assume full control of files under this directory. They may
  72. // be deleted, moved or overwritten.
  73. DataRootDirectory string `json:",omitempty"`
  74. // UseNoticeFiles configures notice files for writing. If set, homepages
  75. // will be written to a file created at config.GetHomePageFilename()
  76. // and notices will be written to a file created at
  77. // config.GetNoticesFilename().
  78. //
  79. // The homepage file may be read after the Tunnels notice with count of 1.
  80. //
  81. // The value of UseNoticeFiles sets the size and frequency at which the
  82. // notices file, config.GetNoticesFilename(), will be rotated. See the
  83. // comment for UseNoticeFiles for more details. One rotated older file,
  84. // config.GetOldNoticesFilename(), is retained.
  85. //
  86. // The notice files may be may be read at any time; and should be opened
  87. // read-only for reading. Diagnostic notices are omitted from the notice
  88. // files.
  89. //
  90. // See comment for setNoticeFiles in notice.go for further details.
  91. UseNoticeFiles *UseNoticeFiles `json:",omitempty"`
  92. // PropagationChannelId is a string identifier which indicates how the
  93. // Psiphon client was distributed. This parameter is required. This value
  94. // is supplied by and depends on the Psiphon Network, and is typically
  95. // embedded in the client binary.
  96. PropagationChannelId string `json:",omitempty"`
  97. // SponsorId is a string identifier which indicates who is sponsoring this
  98. // Psiphon client. One purpose of this value is to determine the home
  99. // pages for display. This parameter is required. This value is supplied
  100. // by and depends on the Psiphon Network, and is typically embedded in the
  101. // client binary.
  102. SponsorId string `json:",omitempty"`
  103. // ClientVersion is the client version number that the client reports to
  104. // the server. The version number refers to the host client application,
  105. // not the core tunnel library. One purpose of this value is to enable
  106. // automatic updates. This value is supplied by and depends on the Psiphon
  107. // Network, and is typically embedded in the client binary.
  108. //
  109. // Note that sending a ClientPlatform string which includes "windows"
  110. // (case insensitive) and a ClientVersion of <= 44 will cause an error in
  111. // processing the response to DoConnectedRequest calls.
  112. ClientVersion string `json:",omitempty"`
  113. // ClientPlatform is the client platform ("Windows", "Android", etc.) that
  114. // the client reports to the server.
  115. ClientPlatform string `json:",omitempty"`
  116. // ClientAPILevel is the client API or SDK level, such as
  117. // Build.VERSION.SDK_INT on Android. This value is used for local
  118. // configuration, as required, and not reported to the server.
  119. // ClientAPILevel is ignored when 0.
  120. ClientAPILevel int `json:",omitempty"`
  121. // ClientFeatures is a list of feature names denoting enabled application
  122. // features. Clients report enabled features to the server for stats
  123. // purposes.
  124. ClientFeatures []string `json:",omitempty"`
  125. // EgressRegion is a ISO 3166-1 alpha-2 country code which indicates which
  126. // country to egress from. For the default, "", the best performing server
  127. // in any country is selected.
  128. EgressRegion string `json:",omitempty"`
  129. // SplitTunnelOwnRegion enables split tunnel mode for the client's own
  130. // country. When enabled, TCP port forward destinations that resolve to
  131. // the same GeoIP country as the client are connected to directly,
  132. // untunneled.
  133. SplitTunnelOwnRegion bool `json:",omitempty"`
  134. // SplitTunnelRegions enables selected split tunnel mode in which the
  135. // client specifies a list of ISO 3166-1 alpha-2 country codes for which
  136. // traffic should be untunneled. TCP port forwards destined to any
  137. // country specified in SplitTunnelRegions will be untunneled, regardless
  138. // of whether SplitTunnelOwnRegion is on or off.
  139. SplitTunnelRegions []string `json:",omitempty"`
  140. // ListenInterface specifies which interface to listen on. If no
  141. // interface is provided then listen on 127.0.0.1. If 'any' is provided
  142. // then use 0.0.0.0. If there are multiple IP addresses on an interface
  143. // use the first IPv4 address.
  144. ListenInterface string `json:",omitempty"`
  145. // DisableLocalSocksProxy disables running the local SOCKS proxy.
  146. DisableLocalSocksProxy bool `json:",omitempty"`
  147. // LocalSocksProxyPort specifies a port number for the local SOCKS proxy
  148. // running at 127.0.0.1. For the default value, 0, the system selects a
  149. // free port (a notice reporting the selected port is emitted).
  150. LocalSocksProxyPort int `json:",omitempty"`
  151. // LocalHttpProxyPort specifies a port number for the local HTTP proxy
  152. // running at 127.0.0.1. For the default value, 0, the system selects a
  153. // free port (a notice reporting the selected port is emitted).
  154. LocalHttpProxyPort int `json:",omitempty"`
  155. // DisableLocalHTTPProxy disables running the local HTTP proxy.
  156. DisableLocalHTTPProxy bool `json:",omitempty"`
  157. // NetworkLatencyMultiplier is a multiplier that is to be applied to
  158. // default network event timeouts. Set this to tune performance for
  159. // slow networks.
  160. // When set, must be >= 1.0.
  161. NetworkLatencyMultiplier float64 `json:",omitempty"`
  162. // LimitTunnelProtocols indicates which protocols to use. Valid values
  163. // include: "SSH", "OSSH", "TLS-OSSH", "UNFRONTED-MEEK-OSSH",
  164. // "UNFRONTED-MEEK-HTTPS-OSSH", "UNFRONTED-MEEK-SESSION-TICKET-OSSH",
  165. // "FRONTED-MEEK-OSSH", "FRONTED-MEEK-HTTP-OSSH", "QUIC-OSSH",
  166. // "FRONTED-MEEK-QUIC-OSSH", "TAPDANCE-OSSH", "CONJURE-OSSH", and
  167. // "SHADOWSOCKS-OSSH".
  168. // For the default, an empty list, all protocols are used.
  169. LimitTunnelProtocols []string `json:",omitempty"`
  170. // InitialLimitTunnelProtocols is an optional initial phase of limited
  171. // protocols for the first InitialLimitTunnelProtocolsCandidateCount
  172. // candidates; after these candidates, LimitTunnelProtocols applies.
  173. //
  174. // For the default, an empty list, InitialLimitTunnelProtocols is off.
  175. InitialLimitTunnelProtocols []string `json:",omitempty"`
  176. // InitialLimitTunnelProtocolsCandidateCount is the number of candidates
  177. // to which InitialLimitTunnelProtocols is applied instead of
  178. // LimitTunnelProtocols.
  179. //
  180. // For the default, 0, InitialLimitTunnelProtocols is off.
  181. InitialLimitTunnelProtocolsCandidateCount int `json:",omitempty"`
  182. // LimitTLSProfiles indicates which TLS profiles to select from. Valid
  183. // values are listed in protocols.SupportedTLSProfiles.
  184. // For the default, an empty list, all profiles are candidates for
  185. // selection.
  186. LimitTLSProfiles []string `json:",omitempty"`
  187. // LimitQUICVersions indicates which QUIC versions to select from. Valid
  188. // values are listed in protocols.SupportedQUICVersions.
  189. // For the default, an empty list, all versions are candidates for
  190. // selection.
  191. LimitQUICVersions []string `json:",omitempty"`
  192. // EstablishTunnelTimeoutSeconds specifies a time limit after which to
  193. // halt the core tunnel controller if no tunnel has been established. The
  194. // default is parameters.EstablishTunnelTimeout.
  195. EstablishTunnelTimeoutSeconds *int `json:",omitempty"`
  196. // EstablishTunnelPausePeriodSeconds specifies the delay between attempts
  197. // to establish tunnels. Briefly pausing allows for network conditions to
  198. // improve and for asynchronous operations such as fetch remote server
  199. // list to complete. If omitted, a default value is used. This value is
  200. // typical overridden for testing.
  201. EstablishTunnelPausePeriodSeconds *int `json:",omitempty"`
  202. // EstablishTunnelPausePeriodSeconds specifies the grace period, or head
  203. // start, provided to the affinity server candidate when establishing. The
  204. // affinity server is the server used for the last established tunnel.
  205. EstablishTunnelServerAffinityGracePeriodMilliseconds *int `json:",omitempty"`
  206. // ConnectionWorkerPoolSize specifies how many connection attempts to
  207. // attempt in parallel. If omitted or when 0, a default is used; this is
  208. // recommended.
  209. ConnectionWorkerPoolSize int `json:",omitempty"`
  210. // DisableConnectionWorkerPool forces ConnectionWorkerPoolSize to 0; this
  211. // may be used to load cached tactics or perform an untunneled tactics
  212. // request and then post tactics-related notices, including Application
  213. // Parameters, without establishing a tunnel. When
  214. // DisableConnectionWorkerPool is set, server list bootstrapping remains
  215. // enabled.
  216. DisableConnectionWorkerPool bool `json:",omitempty"`
  217. // TunnelPoolSize specifies how many tunnels to run in parallel. Port
  218. // forwards are multiplexed over multiple tunnels. If omitted or when 0,
  219. // the default is TUNNEL_POOL_SIZE, which is recommended. Any value over
  220. // MAX_TUNNEL_POOL_SIZE is treated as MAX_TUNNEL_POOL_SIZE.
  221. TunnelPoolSize int `json:",omitempty"`
  222. // StaggerConnectionWorkersMilliseconds adds a specified delay before
  223. // making each server candidate available to connection workers. This
  224. // option is enabled when StaggerConnectionWorkersMilliseconds > 0.
  225. StaggerConnectionWorkersMilliseconds int `json:",omitempty"`
  226. // LimitIntensiveConnectionWorkers limits the number of concurrent
  227. // connection workers attempting connections with resource intensive
  228. // protocols. This option is enabled when LimitIntensiveConnectionWorkers
  229. // > 0.
  230. LimitIntensiveConnectionWorkers int `json:",omitempty"`
  231. // LimitMeekBufferSizes selects smaller buffers for meek protocols.
  232. LimitMeekBufferSizes bool `json:",omitempty"`
  233. // LimitCPUThreads minimizes the number of CPU threads -- and associated
  234. // overhead -- the are used.
  235. LimitCPUThreads bool `json:",omitempty"`
  236. // LimitRelayBufferSizes selects smaller buffers for port forward relaying.
  237. LimitRelayBufferSizes bool `json:",omitempty"`
  238. // IgnoreHandshakeStatsRegexps skips compiling and using stats regexes.
  239. IgnoreHandshakeStatsRegexps bool `json:",omitempty"`
  240. // UpstreamProxyURL is a URL specifying an upstream proxy to use for all
  241. // outbound connections. The URL should include proxy type and
  242. // authentication information, as required. See example URLs here:
  243. // https://github.com/Psiphon-Labs/psiphon-tunnel-core/tree/master/psiphon/upstreamproxy
  244. UpstreamProxyURL string `json:",omitempty"`
  245. // CustomHeaders is a set of additional arbitrary HTTP headers that are
  246. // added to all plaintext HTTP requests and requests made through an HTTP
  247. // upstream proxy when specified by UpstreamProxyURL.
  248. CustomHeaders http.Header `json:",omitempty"`
  249. // MeekAdditionalHeaders is a set of additional arbitrary HTTP headers
  250. // that are added to all meek HTTP requests. An additional header is
  251. // ignored when the header name is already present in a meek request.
  252. MeekAdditionalHeaders http.Header `json:",omitempty"`
  253. // NetworkConnectivityChecker is an interface that enables tunnel-core to
  254. // call into the host application to check for network connectivity. See:
  255. // NetworkConnectivityChecker doc.
  256. NetworkConnectivityChecker NetworkConnectivityChecker `json:",omitempty"`
  257. // DeviceBinder is an interface that enables tunnel-core to call into the
  258. // host application to bind sockets to specific devices. See: DeviceBinder
  259. // doc.
  260. //
  261. // When DeviceBinder is set, the "VPN" feature name is automatically added
  262. // when reporting ClientFeatures.
  263. DeviceBinder DeviceBinder `json:",omitempty"`
  264. // AllowDefaultDNSResolverWithBindToDevice indicates that it's safe to use
  265. // the default resolver when DeviceBinder is configured, as the host OS
  266. // will automatically exclude DNS requests from the VPN.
  267. AllowDefaultDNSResolverWithBindToDevice bool `json:",omitempty"`
  268. // IPv6Synthesizer is an interface that allows tunnel-core to call into
  269. // the host application to synthesize IPv6 addresses. See: IPv6Synthesizer
  270. // doc.
  271. IPv6Synthesizer IPv6Synthesizer `json:",omitempty"`
  272. // HasIPv6RouteGetter is an interface that allows tunnel-core to call into
  273. // the host application to determine if the host has an IPv6 route. See:
  274. // HasIPv6RouteGetter doc.
  275. HasIPv6RouteGetter HasIPv6RouteGetter `json:",omitempty"`
  276. // DNSServerGetter is an interface that enables tunnel-core to call into
  277. // the host application to discover the native network DNS server
  278. // settings. See: DNSServerGetter doc.
  279. DNSServerGetter DNSServerGetter `json:",omitempty"`
  280. // NetworkIDGetter in an interface that enables tunnel-core to call into
  281. // the host application to get an identifier for the host's current active
  282. // network. See: NetworkIDGetter doc.
  283. NetworkIDGetter NetworkIDGetter `json:",omitempty"`
  284. // NetworkID, when not blank, is used as the identifier for the host's
  285. // current active network.
  286. // NetworkID is ignored when NetworkIDGetter is set, or when
  287. // common/networkid is enabled.
  288. NetworkID string `json:",omitempty"`
  289. // DisableTactics disables tactics operations including requests, payload
  290. // handling, and application of parameters.
  291. DisableTactics bool `json:",omitempty"`
  292. // DisableReplay causes any persisted dial parameters to be ignored when
  293. // they would otherwise be used for replay.
  294. DisableReplay bool `json:",omitempty"`
  295. // TargetServerEntry is an encoded server entry. When specified, this
  296. // server entry is used exclusively and all other known servers are
  297. // ignored; also, when set, ConnectionWorkerPoolSize is ignored and
  298. // the pool size is 1.
  299. TargetServerEntry string `json:",omitempty"`
  300. // DisableApi disables Psiphon server API calls including handshake,
  301. // connected, status, etc. This is used for special case temporary tunnels
  302. // (Windows VPN mode).
  303. DisableApi bool `json:",omitempty"`
  304. // TargetAPIProtocol specifies whether to force use of "ssh" or "web" API
  305. // protocol. When blank, the default, the optimal API protocol is used.
  306. // Note that this capability check is not applied before the
  307. // "CandidateServers" count is emitted.
  308. //
  309. // This parameter is intended for testing and debugging only. Not all
  310. // parameters are supported in the legacy "web" API protocol, including
  311. // speed test samples.
  312. TargetAPIProtocol string `json:",omitempty"`
  313. // TargetAPIProtocol specifies whether to use "json" or "cbor" API
  314. // protocol parameter encodings. When blank, the default is to use "cbor"
  315. // where supported.
  316. TargetAPIEncoding string `json:",omitempty"`
  317. // RemoteServerListURLs is list of URLs which specify locations to fetch
  318. // out-of-band server entries. This facility is used when a tunnel cannot
  319. // be established to known servers. This value is supplied by and depends
  320. // on the Psiphon Network, and is typically embedded in the client binary.
  321. // All URLs must point to the same entity with the same ETag. At least one
  322. // TransferURL must have OnlyAfterAttempts = 0.
  323. RemoteServerListURLs parameters.TransferURLs `json:",omitempty"`
  324. // RemoteServerListSignaturePublicKey specifies a public key that's used
  325. // to authenticate the remote server list payload. This value is supplied
  326. // by and depends on the Psiphon Network, and is typically embedded in the
  327. // client binary.
  328. RemoteServerListSignaturePublicKey string `json:",omitempty"`
  329. // DisableRemoteServerListFetcher disables fetching remote server lists.
  330. // This is used for special case temporary tunnels.
  331. DisableRemoteServerListFetcher bool `json:",omitempty"`
  332. // FetchRemoteServerListRetryPeriodMilliseconds specifies the delay before
  333. // resuming a remote server list download after a failure. If omitted, a
  334. // default value is used. This value is typical overridden for testing.
  335. FetchRemoteServerListRetryPeriodMilliseconds *int `json:",omitempty"`
  336. // ObfuscatedServerListRootURLs is a list of URLs which specify root
  337. // locations from which to fetch obfuscated server list files. This value
  338. // is supplied by and depends on the Psiphon Network, and is typically
  339. // embedded in the client binary. All URLs must point to the same entity
  340. // with the same ETag. At least one DownloadURL must have
  341. // OnlyAfterAttempts = 0.
  342. ObfuscatedServerListRootURLs parameters.TransferURLs `json:",omitempty"`
  343. // EnableUpgradeDownload indicates whether to check for and download
  344. // upgrades. When set, UpgradeDownloadURLs and
  345. // UpgradeDownloadClientVersionHeader must also be set. ClientPlatform
  346. // and ClientVersion should also be set.
  347. EnableUpgradeDownload bool `json:",omitempty"`
  348. // UpgradeDownloadURLs is list of URLs which specify locations from which
  349. // to download a host client upgrade file, when one is available. The core
  350. // tunnel controller provides a resumable download facility which
  351. // downloads this resource and emits a notice when complete. This value is
  352. // supplied by and depends on the Psiphon Network, and is typically
  353. // embedded in the client binary. All URLs must point to the same entity
  354. // with the same ETag. At least one DownloadURL must have
  355. // OnlyAfterAttempts = 0.
  356. UpgradeDownloadURLs parameters.TransferURLs `json:",omitempty"`
  357. // UpgradeDownloadClientVersionHeader specifies the HTTP header name for
  358. // the entity at UpgradeDownloadURLs which specifies the client version
  359. // (an integer value). A HEAD request may be made to check the version
  360. // number available at UpgradeDownloadURLs.
  361. // UpgradeDownloadClientVersionHeader is required when UpgradeDownloadURLs
  362. // is specified.
  363. UpgradeDownloadClientVersionHeader string `json:",omitempty"`
  364. // FetchUpgradeRetryPeriodMilliseconds specifies the delay before resuming
  365. // a client upgrade download after a failure. If omitted, a default value
  366. // is used. This value is typical overridden for testing.
  367. FetchUpgradeRetryPeriodMilliseconds *int `json:",omitempty"`
  368. // EnableFeedbackUpload indicates whether to enable uploading feedback
  369. // data. When set, FeedbackUploadURLs and FeedbackEncryptionPublicKey
  370. // must also be set.
  371. EnableFeedbackUpload bool `json:",omitempty"`
  372. // FeedbackUploadURLs is a list of SecureTransferURLs which specify
  373. // locations where feedback data can be uploaded, pairing with each
  374. // location a public key with which to encrypt the feedback data. This
  375. // value is supplied by and depends on the Psiphon Network, and is
  376. // typically embedded in the client binary. At least one TransferURL must
  377. // have OnlyAfterAttempts = 0.
  378. FeedbackUploadURLs parameters.TransferURLs `json:",omitempty"`
  379. // FeedbackEncryptionPublicKey is a default base64-encoded, RSA public key
  380. // value used to encrypt feedback data. Used when uploading feedback with a
  381. // TransferURL which has no public key value configured, i.e.
  382. // B64EncodedPublicKey = "".
  383. FeedbackEncryptionPublicKey string `json:",omitempty"`
  384. // TrustedCACertificatesFilename specifies a file containing trusted CA
  385. // certs. When set, this toggles use of the trusted CA certs, specified in
  386. // TrustedCACertificatesFilename, for tunneled TLS connections that expect
  387. // server certificates signed with public certificate authorities
  388. // (currently, only upgrade downloads). This option is used with stock Go
  389. // TLS in cases where Go may fail to obtain a list of root CAs from the
  390. // operating system.
  391. TrustedCACertificatesFilename string `json:",omitempty"`
  392. // DisableSystemRootCAs, when true, disables loading system root CAs when
  393. // verifying TLS certificates for all remote server list downloads, upgrade
  394. // downloads, and feedback uploads. Each of these transfers has additional
  395. // security at the payload level. Verifying TLS certificates is preferred,
  396. // as an additional security and circumvention layer; set
  397. // DisableSystemRootCAs only in cases where system root CAs cannot be
  398. // loaded; for example, if unsupported (iOS < 12) or insufficient memory
  399. // (VPN extension on iOS < 15).
  400. DisableSystemRootCAs bool `json:",omitempty"`
  401. // DisablePeriodicSshKeepAlive indicates whether to send an SSH keepalive
  402. // every 1-2 minutes, when the tunnel is idle. If the SSH keepalive times
  403. // out, the tunnel is considered to have failed.
  404. DisablePeriodicSshKeepAlive bool `json:",omitempty"`
  405. // DeviceLocation is the optional, reported location the host device is
  406. // running in. This input value should be a string representing location
  407. // geohash. The device location is reported to the server in the connected
  408. // request and recorded for Psiphon stats.
  409. DeviceLocation string `json:",omitempty"`
  410. // DeviceRegion is the optional, reported region the host device is
  411. // running in. This input value should be a ISO 3166-1 alpha-2 country
  412. // code. The device region is reported to the server in the connected
  413. // request and recorded for Psiphon stats.
  414. //
  415. // When provided, this value may be used, pre-connection, to select
  416. // performance or circumvention optimization strategies for the given
  417. // region.
  418. DeviceRegion string `json:",omitempty"`
  419. // EmitDiagnosticNotices indicates whether to output notices containing
  420. // detailed information about the Psiphon session. As these notices may
  421. // contain sensitive information, they should not be insecurely distributed
  422. // or displayed to users. Default is off.
  423. EmitDiagnosticNotices bool `json:",omitempty"`
  424. // EmitDiagnosticNetworkParameters indicates whether to include network
  425. // parameters in diagnostic notices. As these parameters are sensitive
  426. // circumvention network information, they should not be insecurely
  427. // distributed or displayed to users. Default is off.
  428. EmitDiagnosticNetworkParameters bool `json:",omitempty"`
  429. // EmitBytesTransferred indicates whether to emit frequent notices showing
  430. // bytes sent and received.
  431. EmitBytesTransferred bool `json:",omitempty"`
  432. // EmitSLOKs indicates whether to emit notices for each seeded SLOK. As
  433. // this could reveal user browsing activity, it's intended for debugging
  434. // and testing only.
  435. EmitSLOKs bool `json:",omitempty"`
  436. // EmitRefractionNetworkingLogs indicates whether to emit gotapdance log
  437. // messages to stdout. Note that gotapdance log messages do not conform to
  438. // the Notice format standard. Default is off.
  439. EmitRefractionNetworkingLogs bool `json:",omitempty"`
  440. // EmitServerAlerts indicates whether to emit notices for server alerts.
  441. EmitServerAlerts bool `json:",omitempty"`
  442. // EmitClientAddress indicates whether to emit the client's public network
  443. // address, IP and port, as seen by the server. For non-direct protocols,
  444. // such as FRONTED and INPROXY, where the client isn't connecting
  445. // directly to the server, the reported port number is 0.
  446. EmitClientAddress bool `json:",omitempty"`
  447. // RateLimits specify throttling configuration for the tunnel.
  448. RateLimits *common.RateLimits `json:",omitempty"`
  449. // PacketTunnelTunDeviceFileDescriptor specifies a tun device file
  450. // descriptor to use for running a packet tunnel. When this value is > 0,
  451. // a packet tunnel is established through the server and packets are
  452. // relayed via the tun device file descriptor. The file descriptor is
  453. // duped in NewController. When PacketTunnelTunDeviceFileDescriptor is
  454. // set, TunnelPoolSize must be 1.
  455. PacketTunnelTunFileDescriptor int `json:",omitempty"`
  456. // PacketTunnelTransparentDNSIPv4Address is the IPv4 address of the DNS
  457. // server configured by a VPN using a packet tunnel. All DNS packets
  458. // destined to this DNS server are transparently redirected to the
  459. // Psiphon server DNS.
  460. PacketTunnelTransparentDNSIPv4Address string `json:",omitempty"`
  461. // PacketTunnelTransparentDNSIPv6Address is the IPv6 address of the DNS
  462. // server configured by a VPN using a packet tunnel. All DNS packets
  463. // destined to this DNS server are transparently redirected to the
  464. // Psiphon server DNS.
  465. PacketTunnelTransparentDNSIPv6Address string `json:",omitempty"`
  466. // SessionID specifies a client session ID to use in the Psiphon API. The
  467. // session ID should be a randomly generated value that is used only for a
  468. // single session, which is defined as the period between a user starting
  469. // a Psiphon client and stopping the client.
  470. //
  471. // A session ID must be 32 hex digits (lower case). When blank, a random
  472. // session ID is automatically generated. Supply a session ID when a
  473. // single client session will cross multiple Controller instances.
  474. SessionID string `json:",omitempty"`
  475. // Authorizations is a list of encoded, signed access control
  476. // authorizations that the client has obtained and will present to the
  477. // server.
  478. Authorizations []string `json:",omitempty"`
  479. // ServerEntrySignaturePublicKey is a base64-encoded, ed25519 public
  480. // key value used to verify individual server entry signatures. This value
  481. // is supplied by and depends on the Psiphon Network, and is typically
  482. // embedded in the client binary.
  483. ServerEntrySignaturePublicKey string `json:",omitempty"`
  484. // ExchangeObfuscationKey is a base64-encoded, NaCl secretbox key used to
  485. // obfuscate server info exchanges between clients.
  486. // Required for the exchange functionality.
  487. ExchangeObfuscationKey string `json:",omitempty"`
  488. // MigrateHomepageNoticesFilename migrates a homepage file from the path
  489. // previously configured with setNoticeFiles to the new path for homepage
  490. // files under the data root directory. The file specified by this config
  491. // value will be moved to config.GetHomePageFilename().
  492. //
  493. // Note: see comment for config.Commit() for a description of how file
  494. // migrations are performed.
  495. //
  496. // If not set, no migration operation will be performed.
  497. MigrateHomepageNoticesFilename string `json:",omitempty"`
  498. // MigrateRotatingNoticesFilename migrates notice files from the path
  499. // previously configured with setNoticeFiles to the new path for notice
  500. // files under the data root directory.
  501. //
  502. // MigrateRotatingNoticesFilename will be moved to
  503. // config.GetNoticesFilename().
  504. //
  505. // MigrateRotatingNoticesFilename.1 will be moved to
  506. // config.GetOldNoticesFilename().
  507. //
  508. // Note: see comment for config.Commit() for a description of how file
  509. // migrations are performed.
  510. //
  511. // If not set, no migration operation will be performed.
  512. MigrateRotatingNoticesFilename string `json:",omitempty"`
  513. // MigrateDataStoreDirectory indicates the location of the datastore
  514. // directory, as previously configured with the deprecated
  515. // DataStoreDirectory config field. Datastore files found in the specified
  516. // directory will be moved under the data root directory.
  517. //
  518. // Note: see comment for config.Commit() for a description of how file
  519. // migrations are performed.
  520. MigrateDataStoreDirectory string `json:",omitempty"`
  521. // MigrateRemoteServerListDownloadFilename indicates the location of
  522. // remote server list download files. The remote server list files found at
  523. // the specified path will be moved under the data root directory.
  524. //
  525. // Note: see comment for config.Commit() for a description of how file
  526. // migrations are performed.
  527. MigrateRemoteServerListDownloadFilename string `json:",omitempty"`
  528. // MigrateObfuscatedServerListDownloadDirectory indicates the location of
  529. // the obfuscated server list downloads directory, as previously configured
  530. // with ObfuscatedServerListDownloadDirectory. Obfuscated server list
  531. // download files found in the specified directory will be moved under the
  532. // data root directory.
  533. //
  534. // Warning: if the directory is empty after obfuscated server
  535. // list files are moved, then it will be deleted.
  536. //
  537. // Note: see comment for config.Commit() for a description of how file
  538. // migrations are performed.
  539. MigrateObfuscatedServerListDownloadDirectory string `json:",omitempty"`
  540. // MigrateUpgradeDownloadFilename indicates the location of downloaded
  541. // application upgrade files. Downloaded upgrade files found at the
  542. // specified path will be moved under the data root directory.
  543. //
  544. // Note: see comment for config.Commit() for a description of how file
  545. // migrations are performed.
  546. MigrateUpgradeDownloadFilename string `json:",omitempty"`
  547. // DisableTunnels disables establishing a client tunnel. Set
  548. // DisableTunnels when running a stand-alone in-proxy proxy.
  549. DisableTunnels bool `json:",omitempty"`
  550. // InproxyEnableProxy enables running an in-proxy proxy.
  551. InproxyEnableProxy bool `json:",omitempty"`
  552. // InproxyProxySessionPrivateKey specifies a long-term in-proxy proxy
  553. // private key and corresponding, derived proxy ID to use. If blank, an
  554. // ephemeral key will be generated.
  555. InproxyProxySessionPrivateKey string `json:",omitempty"`
  556. // InproxyMaxClients specifies the maximum number of in-proxy clients to
  557. // be proxied concurrently. Must be > 0 when InproxyEnableProxy is set.
  558. InproxyMaxClients int `json:",omitempty"`
  559. // InproxyLimitUpstreamBytesPerSecond specifies the upstream byte transfer
  560. // rate limit for each proxied client. When 0, there is no limit.
  561. InproxyLimitUpstreamBytesPerSecond int `json:",omitempty"`
  562. // InproxyLimitDownstreamBytesPerSecond specifies the downstream byte
  563. // transfer rate limit for each proxied client. When 0, there is no limit.
  564. InproxyLimitDownstreamBytesPerSecond int `json:",omitempty"`
  565. // InproxyProxyPersonalCompartmentID specifies the personal compartment
  566. // ID used by an in-proxy proxy. Personal compartment IDs are
  567. // distributed from proxy operators to client users out-of-band and
  568. // provide a mechanism to allow only certain clients to use a proxy.
  569. InproxyProxyPersonalCompartmentID string `json:",omitempty"`
  570. // InproxyClientPersonalCompartmentID specifies the personal compartment
  571. // ID used by an in-proxy client. Personal compartment IDs are
  572. // distributed from proxy operators to client users out-of-band and
  573. // provide a mechanism to ensure a client uses only a certain proxy for
  574. // all tunnels connections.
  575. //
  576. // When an InproxyClientPersonalCompartmentID is set, the client will use
  577. // only in-proxy protocols, ensuring that all connections go through the
  578. // proxy or proxies with the same personal compartment ID.
  579. InproxyClientPersonalCompartmentID string `json:",omitempty"`
  580. // InproxyPersonalPairingConnectionWorkerPoolSize specifies the value for
  581. // ConnectionWorkerPoolSize in personal pairing mode. If omitted or when
  582. // 0, a default is used; this is recommended.
  583. InproxyPersonalPairingConnectionWorkerPoolSize int `json:",omitempty"`
  584. // EmitInproxyProxyActivity indicates whether to emit frequent notices
  585. // showing proxy connection information and bytes transferred.
  586. EmitInproxyProxyActivity bool `json:",omitempty"`
  587. // ShutdownGoroutineProfileDeadlineSeconds is the number of seconds to
  588. // await shutdown in Controller.Run before dumping a goroutine profile to
  589. // diagnostics. Specify 0 to disable. When not specified, the default is
  590. // 60 seconds.
  591. ShutdownGoroutineProfileDeadlineSeconds *int `json:",omitempty"`
  592. // DisableDSLFetcher disables DSL fetches. If set, this overrides the
  593. // EnableDSLFetcher tactics parameter. This may be used for special case
  594. // temporary tunnels.
  595. DisableDSLFetcher bool `json:",omitempty"`
  596. //
  597. // The following parameters are deprecated.
  598. //
  599. // DataStoreDirectory is the directory in which to store the persistent
  600. // database, which contains information such as server entries. By
  601. // default, current working directory.
  602. //
  603. // Deprecated:
  604. // Use MigrateDataStoreDirectory. When MigrateDataStoreDirectory
  605. // is set, this parameter is ignored.
  606. //
  607. // DataStoreDirectory has been subsumed by the new data root directory,
  608. // which is configured with DataRootDirectory. If set, datastore files
  609. // found in the specified directory will be moved under the data root
  610. // directory.
  611. DataStoreDirectory string `json:",omitempty"`
  612. // RemoteServerListDownloadFilename specifies a target filename for
  613. // storing the remote server list download. Data is stored in co-located
  614. // files (RemoteServerListDownloadFilename.part*) to allow for resumable
  615. // downloading.
  616. //
  617. // Deprecated:
  618. // Use MigrateRemoteServerListDownloadFilename. When
  619. // MigrateRemoteServerListDownloadFilename is set, this parameter is
  620. // ignored.
  621. //
  622. // If set, remote server list download files found at the specified path
  623. // will be moved under the data root directory.
  624. RemoteServerListDownloadFilename string `json:",omitempty"`
  625. // ObfuscatedServerListDownloadDirectory specifies a target directory for
  626. // storing the obfuscated remote server list downloads. Data is stored in
  627. // co-located files (<OSL filename>.part*) to allow for resumable
  628. // downloading.
  629. //
  630. // Deprecated:
  631. // Use MigrateObfuscatedServerListDownloadDirectory. When
  632. // MigrateObfuscatedServerListDownloadDirectory is set, this parameter is
  633. // ignored.
  634. //
  635. // If set, obfuscated server list download files found at the specified path
  636. // will be moved under the data root directory.
  637. ObfuscatedServerListDownloadDirectory string `json:",omitempty"`
  638. // UpgradeDownloadFilename is the local target filename for an upgrade
  639. // download. This parameter is required when UpgradeDownloadURLs (or
  640. // UpgradeDownloadUrl) is specified. Data is stored in co-located files
  641. // (UpgradeDownloadFilename.part*) to allow for resumable downloading.
  642. //
  643. // Deprecated:
  644. // Use MigrateUpgradeDownloadFilename. When MigrateUpgradeDownloadFilename
  645. // is set, this parameter is ignored.
  646. //
  647. // If set, upgrade download files found at the specified path will be moved
  648. // under the data root directory.
  649. UpgradeDownloadFilename string `json:",omitempty"`
  650. // TunnelProtocol indicates which protocol to use. For the default, "",
  651. // all protocols are used.
  652. //
  653. // Deprecated: Use LimitTunnelProtocols. When LimitTunnelProtocols is not
  654. // nil, this parameter is ignored.
  655. TunnelProtocol string `json:",omitempty"`
  656. // Deprecated: Use CustomHeaders. When CustomHeaders is not nil, this
  657. // parameter is ignored.
  658. UpstreamProxyCustomHeaders http.Header `json:",omitempty"`
  659. // RemoteServerListUrl is a URL which specifies a location to fetch out-
  660. // of-band server entries. This facility is used when a tunnel cannot be
  661. // established to known servers. This value is supplied by and depends on
  662. // the Psiphon Network, and is typically embedded in the client binary.
  663. //
  664. // Deprecated: Use RemoteServerListURLs. When RemoteServerListURLs is not
  665. // nil, this parameter is ignored.
  666. RemoteServerListUrl string `json:",omitempty"`
  667. // ObfuscatedServerListRootURL is a URL which specifies the root location
  668. // from which to fetch obfuscated server list files. This value is
  669. // supplied by and depends on the Psiphon Network, and is typically
  670. // embedded in the client binary.
  671. //
  672. // Deprecated: Use ObfuscatedServerListRootURLs. When
  673. // ObfuscatedServerListRootURLs is not nil, this parameter is ignored.
  674. ObfuscatedServerListRootURL string `json:",omitempty"`
  675. // UpgradeDownloadUrl specifies a URL from which to download a host client
  676. // upgrade file, when one is available. The core tunnel controller
  677. // provides a resumable download facility which downloads this resource
  678. // and emits a notice when complete. This value is supplied by and depends
  679. // on the Psiphon Network, and is typically embedded in the client binary.
  680. //
  681. // Deprecated: Use UpgradeDownloadURLs. When UpgradeDownloadURLs is not
  682. // nil, this parameter is ignored.
  683. UpgradeDownloadUrl string `json:",omitempty"`
  684. //
  685. // The following parameters are for testing purposes.
  686. //
  687. // TransformHostNameProbability is for testing purposes.
  688. TransformHostNameProbability *float64 `json:",omitempty"`
  689. // FragmentorProbability and associated Fragmentor fields are for testing
  690. // purposes.
  691. FragmentorProbability *float64 `json:",omitempty"`
  692. FragmentorLimitProtocols []string `json:",omitempty"`
  693. FragmentorMinTotalBytes *int `json:",omitempty"`
  694. FragmentorMaxTotalBytes *int `json:",omitempty"`
  695. FragmentorMinWriteBytes *int `json:",omitempty"`
  696. FragmentorMaxWriteBytes *int `json:",omitempty"`
  697. FragmentorMinDelayMicroseconds *int `json:",omitempty"`
  698. FragmentorMaxDelayMicroseconds *int `json:",omitempty"`
  699. // MeekTrafficShapingProbability and associated fields are for testing
  700. // purposes.
  701. MeekTrafficShapingProbability *float64 `json:",omitempty"`
  702. MeekTrafficShapingLimitProtocols []string `json:",omitempty"`
  703. MeekMinTLSPadding *int `json:",omitempty"`
  704. MeekMaxTLSPadding *int `json:",omitempty"`
  705. MeekMinLimitRequestPayloadLength *int `json:",omitempty"`
  706. MeekMaxLimitRequestPayloadLength *int `json:",omitempty"`
  707. MeekRedialTLSProbability *float64 `json:",omitempty"`
  708. MeekAlternateCookieNameProbability *float64 `json:",omitempty"`
  709. MeekAlternateContentTypeProbability *float64 `json:",omitempty"`
  710. // ObfuscatedSSHAlgorithms and associated ObfuscatedSSH fields are for
  711. // testing purposes. If specified, ObfuscatedSSHAlgorithms must have 4 SSH
  712. // KEX elements in order: the kex algorithm, cipher, MAC, and server host
  713. // key algorithm.
  714. ObfuscatedSSHAlgorithms []string `json:",omitempty"`
  715. ObfuscatedSSHMinPadding *int `json:",omitempty"`
  716. ObfuscatedSSHMaxPadding *int `json:",omitempty"`
  717. // LivenessTestMinUpstreamBytes and other LivenessTest fields are for
  718. // testing purposes.
  719. InitialLivenessTest parameters.LivenessTestSpecs `json:",omitempty"`
  720. LivenessTest parameters.LivenessTestSpecs `json:",omitempty"`
  721. LivenessTestMinUpstreamBytes *int `json:",omitempty"`
  722. LivenessTestMaxUpstreamBytes *int `json:",omitempty"`
  723. LivenessTestMinDownstreamBytes *int `json:",omitempty"`
  724. LivenessTestMaxDownstreamBytes *int `json:",omitempty"`
  725. // ReplayCandidateCount and other Replay fields are for testing purposes.
  726. ReplayCandidateCount *int `json:",omitempty"`
  727. ReplayDialParametersTTLSeconds *int `json:",omitempty"`
  728. ReplayTargetUpstreamBytes *int `json:",omitempty"`
  729. ReplayTargetDownstreamBytes *int `json:",omitempty"`
  730. ReplayTargetTunnelDurationSeconds *int `json:",omitempty"`
  731. ReplayLaterRoundMoveToFrontProbability *float64 `json:",omitempty"`
  732. ReplayRetainFailedProbability *float64 `json:",omitempty"`
  733. ReplayIgnoreChangedConfigStateProbability *float64 `json:",omitempty"`
  734. // NetworkLatencyMultiplierMin and other NetworkLatencyMultiplier fields are
  735. // for testing purposes.
  736. NetworkLatencyMultiplierMin float64 `json:",omitempty"`
  737. NetworkLatencyMultiplierMax float64 `json:",omitempty"`
  738. NetworkLatencyMultiplierLambda float64 `json:",omitempty"`
  739. // UseOnlyCustomTLSProfiles and other TLS configuration fields are for
  740. // testing purposes.
  741. UseOnlyCustomTLSProfiles *bool `json:",omitempty"`
  742. CustomTLSProfiles protocol.CustomTLSProfiles `json:",omitempty"`
  743. SelectRandomizedTLSProfileProbability *float64 `json:",omitempty"`
  744. NoDefaultTLSSessionIDProbability *float64 `json:",omitempty"`
  745. DisableFrontingProviderTLSProfiles protocol.LabeledTLSProfiles `json:",omitempty"`
  746. // ClientBurstUpstreamTargetBytes and other burst metric fields are for
  747. // testing purposes.
  748. ClientBurstUpstreamTargetBytes *int `json:",omitempty"`
  749. ClientBurstUpstreamDeadlineMilliseconds *int `json:",omitempty"`
  750. ClientBurstDownstreamTargetBytes *int `json:",omitempty"`
  751. ClientBurstDownstreamDeadlineMilliseconds *int `json:",omitempty"`
  752. // CustomHostNameRegexes and other custom host name fields are for testing
  753. // purposes.
  754. CustomHostNameRegexes []string `json:",omitempty"`
  755. CustomHostNameProbability *float64 `json:",omitempty"`
  756. CustomHostNameLimitProtocols []string `json:",omitempty"`
  757. // ConjureCachedRegistrationTTLSeconds and other Conjure fields are for
  758. // testing purposes.
  759. ConjureCachedRegistrationTTLSeconds *int `json:",omitempty"`
  760. ConjureAPIRegistrarBidirectionalURL string `json:",omitempty"`
  761. ConjureAPIRegistrarFrontingSpecs parameters.FrontingSpecs `json:",omitempty"`
  762. ConjureAPIRegistrarMinDelayMilliseconds *int `json:",omitempty"`
  763. ConjureAPIRegistrarMaxDelayMilliseconds *int `json:",omitempty"`
  764. ConjureDecoyRegistrarProbability *float64 `json:",omitempty"`
  765. ConjureDecoyRegistrarWidth *int `json:",omitempty"`
  766. ConjureDecoyRegistrarMinDelayMilliseconds *int `json:",omitempty"`
  767. ConjureDecoyRegistrarMaxDelayMilliseconds *int `json:",omitempty"`
  768. ConjureEnableIPv6Dials *bool `json:",omitempty"`
  769. ConjureEnablePortRandomization *bool `json:",omitempty"`
  770. ConjureEnableRegistrationOverrides *bool `json:",omitempty"`
  771. ConjureLimitTransports protocol.ConjureTransports `json:",omitempty"`
  772. ConjureSTUNServerAddresses []string `json:",omitempty"`
  773. ConjureDTLSEmptyInitialPacketProbability *float64 `json:",omitempty"`
  774. // HoldOffTunnelProtocolMinDurationMilliseconds and other
  775. // HoldOffTunnelProtocol fields are for testing purposes.
  776. HoldOffTunnelProtocolMinDurationMilliseconds *int `json:",omitempty"`
  777. HoldOffTunnelProtocolMaxDurationMilliseconds *int `json:",omitempty"`
  778. HoldOffTunnelProtocolNames []string `json:",omitempty"`
  779. HoldOffTunnelProtocolProbability *float64 `json:",omitempty"`
  780. // HoldOffFrontingTunnelMinDurationMilliseconds and other
  781. // HoldOffFrontingTunnel fields are for testing purposes.
  782. HoldOffFrontingTunnelMinDurationMilliseconds *int `json:",omitempty"`
  783. HoldOffFrontingTunnelMaxDurationMilliseconds *int `json:",omitempty"`
  784. HoldOffFrontingTunnelProviderIDs []string `json:",omitempty"`
  785. HoldOffFrontingTunnelProbability *float64 `json:",omitempty"`
  786. // RestrictFrontingProviderIDs and other RestrictFrontingProviderIDs fields
  787. // are for testing purposes.
  788. RestrictFrontingProviderIDs []string `json:",omitempty"`
  789. RestrictFrontingProviderIDsClientProbability *float64 `json:",omitempty"`
  790. // HoldOffDirectTunnelMinDurationMilliseconds and other HoldOffDirect
  791. // fields are for testing purposes.
  792. HoldOffDirectTunnelMinDurationMilliseconds *int `json:",omitempty"`
  793. HoldOffDirectTunnelMaxDurationMilliseconds *int `json:",omitempty"`
  794. HoldOffDirectTunnelProviderRegions map[string][]string `json:",omitempty"`
  795. HoldOffDirectTunnelProbability *float64 `json:",omitempty"`
  796. // RestrictDirectProviderRegions and other RestrictDirect fields are for
  797. // testing purposes.
  798. RestrictDirectProviderRegions map[string][]string `json:",omitempty"`
  799. RestrictDirectProviderIDsClientProbability *float64 `json:",omitempty"`
  800. // HoldOffInproxyTunnelMinDurationMilliseconds and other HoldOffInproxy
  801. // fields are for testing purposes.
  802. HoldOffInproxyTunnelMinDurationMilliseconds *int `json:",omitempty"`
  803. HoldOffInproxyTunnelMaxDurationMilliseconds *int `json:",omitempty"`
  804. HoldOffInproxyTunnelProviderRegions map[string][]string `json:",omitempty"`
  805. HoldOffInproxyTunnelProbability *float64 `json:",omitempty"`
  806. // RestrictInproxyProviderRegions and other RestrictInproxy fields are for
  807. // testing purposes.
  808. RestrictInproxyProviderRegions map[string][]string `json:",omitempty"`
  809. RestrictInproxyProviderIDsClientProbability *float64 `json:",omitempty"`
  810. // UpstreamProxyAllowAllServerEntrySources is for testing purposes.
  811. UpstreamProxyAllowAllServerEntrySources *bool `json:",omitempty"`
  812. // LimitTunnelDialPortNumbers is for testing purposes.
  813. LimitTunnelDialPortNumbers parameters.TunnelProtocolPortLists `json:",omitempty"`
  814. // QUICDialEarlyProbability is for testing purposes.
  815. QUICDialEarlyProbability *float64 `json:",omitempty"`
  816. // QUICObfuscatedPSKProbability is for testing purposes.
  817. QUICObfuscatedPSKProbability *float64 `json:",omitempty"`
  818. // QUICDisablePathMTUDiscoveryProbability is for testing purposes.
  819. QUICDisablePathMTUDiscoveryProbability *float64 `json:",omitempty"`
  820. // DNSResolverAttemptsPerServer and other DNSResolver fields are for
  821. // testing purposes.
  822. DNSResolverAttemptsPerServer *int `json:",omitempty"`
  823. DNSResolverAttemptsPerPreferredServer *int `json:",omitempty"`
  824. DNSResolverRequestTimeoutMilliseconds *int `json:",omitempty"`
  825. DNSResolverAwaitTimeoutMilliseconds *int `json:",omitempty"`
  826. DNSResolverPreresolvedIPAddressCIDRs parameters.LabeledCIDRs `json:",omitempty"`
  827. DNSResolverPreresolvedIPAddressProbability *float64 `json:",omitempty"`
  828. DNSResolverAlternateServers []string `json:",omitempty"`
  829. DNSResolverPreferredAlternateServers []string `json:",omitempty"`
  830. DNSResolverPreferAlternateServerProbability *float64 `json:",omitempty"`
  831. DNSResolverProtocolTransformSpecs transforms.Specs `json:",omitempty"`
  832. DNSResolverProtocolTransformScopedSpecNames transforms.ScopedSpecNames `json:",omitempty"`
  833. DNSResolverProtocolTransformProbability *float64 `json:",omitempty"`
  834. DNSResolverQNameRandomizeCasingProbability *float64 `json:",omitempty"`
  835. DNSResolverQNameMustMatchProbability *float64 `json:",omitempty"`
  836. DNSResolverIncludeEDNS0Probability *float64 `json:",omitempty"`
  837. DNSResolverCacheExtensionInitialTTLMilliseconds *int `json:",omitempty"`
  838. DNSResolverCacheExtensionVerifiedTTLMilliseconds *int `json:",omitempty"`
  839. DirectHTTPProtocolTransformSpecs transforms.Specs `json:",omitempty"`
  840. DirectHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames `json:",omitempty"`
  841. DirectHTTPProtocolTransformProbability *float64 `json:",omitempty"`
  842. FrontedHTTPProtocolTransformSpecs transforms.Specs `json:",omitempty"`
  843. FrontedHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames `json:",omitempty"`
  844. FrontedHTTPProtocolTransformProbability *float64 `json:",omitempty"`
  845. OSSHObfuscatorSeedTransformSpecs transforms.Specs `json:",omitempty"`
  846. OSSHObfuscatorSeedTransformScopedSpecNames transforms.ScopedSpecNames `json:",omitempty"`
  847. OSSHObfuscatorSeedTransformProbability *float64 `json:",omitempty"`
  848. ObfuscatedQUICNonceTransformSpecs transforms.Specs `json:",omitempty"`
  849. ObfuscatedQUICNonceTransformScopedSpecNames transforms.ScopedSpecNames `json:",omitempty"`
  850. ObfuscatedQUICNonceTransformProbability *float64 `json:",omitempty"`
  851. // OSSHPrefix parameters are for testing purposes only.
  852. OSSHPrefixSpecs transforms.Specs `json:",omitempty"`
  853. OSSHPrefixScopedSpecNames transforms.ScopedSpecNames `json:",omitempty"`
  854. OSSHPrefixProbability *float64 `json:",omitempty"`
  855. OSSHPrefixSplitMinDelayMilliseconds *int `json:",omitempty"`
  856. OSSHPrefixSplitMaxDelayMilliseconds *int `json:",omitempty"`
  857. OSSHPrefixEnableFragmentor *bool `json:",omitempty"`
  858. // ShadowsocksPrefix parameters are for testing purposes only.
  859. ShadowsocksPrefixSpecs transforms.Specs `json:",omitempty"`
  860. ShadowsocksPrefixScopedSpecNames transforms.ScopedSpecNames `json:",omitempty"`
  861. ShadowsocksPrefixProbability *float64 `json:",omitempty"`
  862. // TLSTunnelTrafficShapingProbability and associated fields are for testing.
  863. TLSTunnelObfuscatedPSKProbability *float64 `json:",omitempty"`
  864. TLSTunnelTrafficShapingProbability *float64 `json:",omitempty"`
  865. TLSTunnelMinTLSPadding *int `json:",omitempty"`
  866. TLSTunnelMaxTLSPadding *int `json:",omitempty"`
  867. // TLSFragmentClientHello fields are for testing purposes only.
  868. TLSFragmentClientHelloProbability *float64 `json:",omitempty"`
  869. TLSFragmentClientHelloLimitProtocols []string `json:",omitempty"`
  870. // AdditionalParameters is used for testing.
  871. AdditionalParameters string `json:",omitempty"`
  872. // SteeringIP fields are for testing purposes only.
  873. SteeringIPCacheTTLSeconds *int `json:",omitempty"`
  874. SteeringIPCacheMaxEntries *int `json:",omitempty"`
  875. SteeringIPProbability *float64 `json:",omitempty"`
  876. // FrontedHTTPClientReplayDialParametersTTL and other FrontedHTTPClient
  877. // fields are for testing purposes only.
  878. FrontedHTTPClientReplayDialParametersTTLSeconds *int `json:",omitempty"`
  879. FrontedHTTPClientReplayUpdateFrequencySeconds *int `json:",omitempty"`
  880. FrontedHTTPClientReplayDialParametersProbability *float64 `json:",omitempty"`
  881. FrontedHTTPClientReplayRetainFailedProbability *float64 `json:",omitempty"`
  882. // The following in-proxy fields are for testing purposes only.
  883. InproxyAllowProxy *bool `json:",omitempty"`
  884. InproxyAllowClient *bool `json:",omitempty"`
  885. InproxyTunnelProtocolSelectionProbability *float64 `json:",omitempty"`
  886. InproxyBrokerSpecs parameters.InproxyBrokerSpecsValue `json:",omitempty"`
  887. InproxyPersonalPairingBrokerSpecs parameters.InproxyBrokerSpecsValue `json:",omitempty"`
  888. InproxyProxyBrokerSpecs parameters.InproxyBrokerSpecsValue `json:",omitempty"`
  889. InproxyProxyPersonalPairingBrokerSpecs parameters.InproxyBrokerSpecsValue `json:",omitempty"`
  890. InproxyClientBrokerSpecs parameters.InproxyBrokerSpecsValue `json:",omitempty"`
  891. InproxyClientPersonalPairingBrokerSpecs parameters.InproxyBrokerSpecsValue `json:",omitempty"`
  892. InproxyReplayBrokerDialParametersTTLSeconds *int `json:",omitempty"`
  893. InproxyReplayBrokerUpdateFrequencySeconds *int `json:",omitempty"`
  894. InproxyReplayBrokerDialParametersProbability *float64 `json:",omitempty"`
  895. InproxyReplayBrokerRetainFailedProbability *float64 `json:",omitempty"`
  896. InproxyCommonCompartmentIDs parameters.InproxyCompartmentIDsValue `json:",omitempty"`
  897. InproxyMaxCompartmentIDListLength *int `json:",omitempty"`
  898. InproxyProxyAnnounceRequestTimeoutMilliseconds *int `json:",omitempty"`
  899. InproxyProxyAnnounceDelayMilliseconds *int `json:",omitempty"`
  900. InproxyProxyAnnounceMaxBackoffDelayMilliseconds *int `json:",omitempty"`
  901. InproxyProxyAnnounceDelayJitter *float64 `json:",omitempty"`
  902. InproxyProxyAnswerRequestTimeoutMilliseconds *int `json:",omitempty"`
  903. InproxyClientOfferRequestTimeoutMilliseconds *int `json:",omitempty"`
  904. InproxyClientOfferRequestPersonalTimeoutMilliseconds *int `json:",omitempty"`
  905. InproxyClientOfferRetryDelayMilliseconds *int `json:",omitempty"`
  906. InproxyClientOfferRetryJitter *float64 `json:",omitempty"`
  907. InproxyClientRelayedPacketRequestTimeoutMilliseconds *int `json:",omitempty"`
  908. InproxyDTLSRandomizationProbability *float64 `json:",omitempty"`
  909. InproxyWebRTCMediaStreamsProbability *float64 `json:",omitempty"`
  910. InproxyWebRTCDataChannelTrafficShapingProbability *float64 `json:",omitempty"`
  911. InproxyWebRTCDataChannelTrafficShapingParameters *parameters.InproxyTrafficShapingParametersValue `json:",omitempty"`
  912. InproxyWebRTCMediaStreamsTrafficShapingProbability *float64 `json:",omitempty"`
  913. InproxyWebRTCMediaStreamsTrafficShapingParameters *parameters.InproxyTrafficShapingParametersValue `json:",omitempty"`
  914. InproxySTUNServerAddresses []string `json:",omitempty"`
  915. InproxySTUNServerAddressesRFC5780 []string `json:",omitempty"`
  916. InproxyProxySTUNServerAddresses []string `json:",omitempty"`
  917. InproxyProxySTUNServerAddressesRFC5780 []string `json:",omitempty"`
  918. InproxyClientSTUNServerAddresses []string `json:",omitempty"`
  919. InproxyClientSTUNServerAddressesRFC5780 []string `json:",omitempty"`
  920. InproxyClientDiscoverNATProbability *float64 `json:",omitempty"`
  921. InproxyDisableSTUN *bool `json:",omitempty"`
  922. InproxyDisablePortMapping *bool `json:",omitempty"`
  923. InproxyDisableInboundForMobileNetworks *bool `json:",omitempty"`
  924. InproxyDisableIPv6ICECandidates *bool `json:",omitempty"`
  925. InproxyProxyDisableSTUN *bool `json:",omitempty"`
  926. InproxyProxyDisablePortMapping *bool `json:",omitempty"`
  927. InproxyProxyDisableInboundForMobileNetworks *bool `json:",omitempty"`
  928. InproxyProxyDisableIPv6ICECandidates *bool `json:",omitempty"`
  929. InproxyClientDisableSTUN *bool `json:",omitempty"`
  930. InproxyClientDisablePortMapping *bool `json:",omitempty"`
  931. InproxyClientDisableInboundForMobileNetworks *bool `json:",omitempty"`
  932. InproxyClientDisableIPv6ICECandidates *bool `json:",omitempty"`
  933. InproxyProxyDiscoverNATTimeoutMilliseconds *int `json:",omitempty"`
  934. InproxyClientDiscoverNATTimeoutMilliseconds *int `json:",omitempty"`
  935. InproxyWebRTCAnswerTimeoutMilliseconds *int `json:",omitempty"`
  936. InproxyProxyWebRTCAwaitReadyToProxyTimeoutMilliseconds *int `json:",omitempty"`
  937. InproxyClientWebRTCAwaitReadyToProxyTimeoutMilliseconds *int `json:",omitempty"`
  938. InproxyProxyDestinationDialTimeoutMilliseconds *int `json:",omitempty"`
  939. InproxyPsiphonAPIRequestTimeoutMilliseconds *int `json:",omitempty"`
  940. InproxyProxyTotalActivityNoticePeriodMilliseconds *int `json:",omitempty"`
  941. InproxyClientDialRateLimitQuantity *int `json:",omitempty"`
  942. InproxyClientDialRateLimitIntervalMilliseconds *int `json:",omitempty"`
  943. InproxyClientNoMatchFailoverProbability *float64 `json:",omitempty"`
  944. InproxyClientNoMatchFailoverPersonalProbability *float64 `json:",omitempty"`
  945. InproxyFrontingProviderClientMaxRequestTimeouts map[string]string `json:",omitempty"`
  946. InproxyProxyOnBrokerClientFailedRetryPeriodMilliseconds *int `json:",omitempty"`
  947. InproxyProxyIncompatibleNetworkTypes []string `json:",omitempty"`
  948. InproxyClientIncompatibleNetworkTypes []string `json:",omitempty"`
  949. InproxyReplayRetainFailedProbability *float64 `json:",omitempty"`
  950. InproxyProxyDisableWaitToShareSession *bool `json:",omitempty"`
  951. InproxyClientDisableWaitToShareSession *bool `json:",omitempty"`
  952. InproxyTunnelProtocolPreferProbability *float64 `json:",omitempty"`
  953. InproxyTunnelProtocolForceSelectionCount *int `json:",omitempty"`
  954. InproxySkipAwaitFullyConnected bool `json:",omitempty"`
  955. InproxyEnableWebRTCDebugLogging bool `json:",omitempty"`
  956. NetworkIDCacheTTLMilliseconds *int `json:",omitempty"`
  957. CompressTactics *bool `json:",omitempty"`
  958. EnableDSLFetcher *bool `json:",omitempty"`
  959. DSLPrioritizeDialNewServerEntryProbability *float64 `json:",omitempty"`
  960. DSLPrioritizeDialExistingServerEntryProbability *float64 `json:",omitempty"`
  961. DSLPrioritizeDialRetainFailedProbability *float64 `json:",omitempty"`
  962. DSLPrioritizeDialPlaceholderTTLSeconds *int `json:",omitempty"`
  963. ServerEntryIteratorMaxMoveToFront *int `json:",omitempty"`
  964. ServerEntryIteratorResetProbability *float64 `json:",omitempty"`
  965. // params is the active parameters.Parameters with defaults, config values,
  966. // and, optionally, tactics applied.
  967. //
  968. // New tactics must be applied by calling Config.SetParameters; calling
  969. // params.Set directly will fail to add config values.
  970. paramsMutex sync.Mutex
  971. params *parameters.Parameters
  972. dialParametersHash []byte
  973. dynamicConfigMutex sync.Mutex
  974. sponsorID string
  975. authorizations []string
  976. deviceBinder DeviceBinder
  977. networkIDGetter *cachingNetworkIDGetter
  978. clientFeatures []string
  979. resolverMutex sync.Mutex
  980. resolver *resolver.Resolver
  981. committed bool
  982. loadTimestamp string
  983. tacticsAppliedReceiversMutex sync.Mutex
  984. tacticsAppliedReceivers []TacticsAppliedReceiver
  985. signalComponentFailure atomic.Value
  986. inproxyMustUpgradePosted int32
  987. serverEntryIterationMetricsUpdater atomic.Value
  988. }
  989. // TacticsAppliedReceiver specifies the interface for a component that is
  990. // signaled when tactics are applied. TacticsApplied is invoked when any
  991. // tactics are applied after initial start up, and then whenever new tactics
  992. // are received and applied while running.
  993. type TacticsAppliedReceiver interface {
  994. TacticsApplied() error
  995. }
  996. // Config field which specifies if notice files should be used and at which
  997. // frequency and size they should be rotated.
  998. //
  999. // If either RotatingFileSize or RotatingSyncFrequency are <= 0, default values
  1000. // are used.
  1001. //
  1002. // See comment for setNoticeFiles in notice.go for further details.
  1003. type UseNoticeFiles struct {
  1004. RotatingFileSize int
  1005. RotatingSyncFrequency int
  1006. }
  1007. // LoadConfig parses a JSON format Psiphon config JSON string and returns a
  1008. // Config struct populated with config values.
  1009. //
  1010. // The Config struct may then be programmatically populated with additional
  1011. // values, including callbacks such as DeviceBinder.
  1012. //
  1013. // Before using the Config, Commit must be called, which will perform further
  1014. // validation and initialize internal data structures.
  1015. func LoadConfig(configJson []byte) (*Config, error) {
  1016. var config Config
  1017. err := json.Unmarshal(configJson, &config)
  1018. if err != nil {
  1019. return nil, errors.Trace(err)
  1020. }
  1021. config.loadTimestamp = common.TruncateTimestampToHour(
  1022. common.GetCurrentTimestamp())
  1023. config.signalComponentFailure.Store(func() {})
  1024. config.serverEntryIterationMetricsUpdater.Store(func(int) {})
  1025. return &config, nil
  1026. }
  1027. // IsCommitted checks if Commit was called.
  1028. func (config *Config) IsCommitted() bool {
  1029. return config.committed
  1030. }
  1031. // Commit validates Config fields finalizes initialization.
  1032. //
  1033. // Config fields should not be set after calling Config, as any changes may
  1034. // not be reflected in internal data structures.
  1035. //
  1036. // If migrateFromLegacyFields is set to true, then an attempt to migrate from
  1037. // legacy fields is made.
  1038. //
  1039. // Migration from legacy fields:
  1040. // Config fields of the naming Migrate* (e.g. MigrateDataStoreDirectory) specify
  1041. // a file migration operation which should be performed. These fields correspond
  1042. // to deprecated fields, which previously could be used to specify where Psiphon
  1043. // stored different sets of persistent files (e.g. MigrateDataStoreDirectory
  1044. // corresponds to the deprecated field DataStoreDirectory).
  1045. //
  1046. // Psiphon now stores all persistent data under the configurable
  1047. // DataRootDirectory (see Config.DataRootDirectory). The deprecated fields, and
  1048. // corresponding Migrate* fields, are now used to specify the file or directory
  1049. // path where, or under which, persistent files and directories created by
  1050. // previous versions of Psiphon exist, so they can be moved under the
  1051. // DataRootDirectory.
  1052. //
  1053. // For each migration operation:
  1054. // - In the case of directories that could have defaulted to the current working
  1055. // directory, persistent files and directories created by Psiphon are
  1056. // precisely targeted to avoid moving files which were not created by Psiphon.
  1057. // - If no file is found at the specified path, or an error is encountered while
  1058. // migrating the file, then an error is logged and execution continues
  1059. // normally.
  1060. //
  1061. // A sentinel file which signals that file migration has been completed, and
  1062. // should not be attempted again, is created under DataRootDirectory after one
  1063. // full pass through Commit(), regardless of whether file migration succeeds or
  1064. // fails. It is better to not endlessly retry file migrations on each Commit()
  1065. // because file system errors are expected to be rare and persistent files will
  1066. // be re-populated over time.
  1067. func (config *Config) Commit(migrateFromLegacyFields bool) error {
  1068. // Apply any additional parameters first
  1069. additionalParametersInfoMsgs, err := config.applyAdditionalParameters()
  1070. if err != nil {
  1071. return errors.TraceMsg(err, "failed to apply additional parameters")
  1072. }
  1073. // Do SetEmitDiagnosticNotices first, to ensure config file errors are
  1074. // emitted.
  1075. if config.EmitDiagnosticNotices {
  1076. SetEmitDiagnosticNotices(
  1077. true, config.EmitDiagnosticNetworkParameters)
  1078. }
  1079. // Migrate and set notice files before any operations that may emit an
  1080. // error. This is to ensure config file errors are written to file when
  1081. // notice files are configured with config.UseNoticeFiles.
  1082. //
  1083. // Note:
  1084. // Errors encountered while configuring the data directory cannot be written
  1085. // to notice files. This is because notices files are created within the
  1086. // data directory.
  1087. if config.DataRootDirectory == "" {
  1088. wd, err := os.Getwd()
  1089. if err != nil {
  1090. return errors.Trace(common.RedactFilePathsError(err))
  1091. }
  1092. config.DataRootDirectory = wd
  1093. }
  1094. // Create root directory
  1095. dataDirectoryPath := config.GetPsiphonDataDirectory()
  1096. if !common.FileExists(dataDirectoryPath) {
  1097. err := os.Mkdir(dataDirectoryPath, os.ModePerm)
  1098. if err != nil {
  1099. return errors.Tracef(
  1100. "failed to create datastore directory with error: %s",
  1101. common.RedactFilePathsError(err, dataDirectoryPath))
  1102. }
  1103. }
  1104. // Check if the migration from legacy config fields has already been
  1105. // completed. See the Migrate* config fields for more details.
  1106. migrationCompleteFilePath := filepath.Join(config.GetPsiphonDataDirectory(), "migration_complete")
  1107. needMigration := !common.FileExists(migrationCompleteFilePath)
  1108. // Collect notices to emit them after notice files are set
  1109. var noticeMigrationAlertMsgs []string
  1110. var noticeMigrationInfoMsgs []string
  1111. // Migrate notices first to ensure notice files are used for notices if
  1112. // UseNoticeFiles is set.
  1113. homepageFilePath := config.GetHomePageFilename()
  1114. noticesFilePath := config.GetNoticesFilename()
  1115. if migrateFromLegacyFields {
  1116. if needMigration {
  1117. // Move notice files that exist at legacy file paths under the data root
  1118. // directory.
  1119. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, "Config migration: need migration")
  1120. noticeMigrations := migrationsFromLegacyNoticeFilePaths(config)
  1121. successfulMigrations := 0
  1122. for _, migration := range noticeMigrations {
  1123. err := DoFileMigration(migration)
  1124. if err != nil {
  1125. alertMsg := fmt.Sprintf("Config migration: %s", errors.Trace(err))
  1126. noticeMigrationAlertMsgs = append(noticeMigrationAlertMsgs, alertMsg)
  1127. } else {
  1128. successfulMigrations += 1
  1129. }
  1130. }
  1131. infoMsg := fmt.Sprintf("Config migration: %d/%d notice files successfully migrated", successfulMigrations, len(noticeMigrations))
  1132. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, infoMsg)
  1133. } else {
  1134. noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, "Config migration: migration already completed")
  1135. }
  1136. }
  1137. if config.UseNoticeFiles != nil {
  1138. err := setNoticeFiles(
  1139. homepageFilePath,
  1140. noticesFilePath,
  1141. config.UseNoticeFiles.RotatingFileSize,
  1142. config.UseNoticeFiles.RotatingSyncFrequency)
  1143. if err != nil {
  1144. return errors.Trace(err)
  1145. }
  1146. }
  1147. // Emit notices now that notice files are set if configured
  1148. for _, msg := range additionalParametersInfoMsgs {
  1149. NoticeInfo(msg)
  1150. }
  1151. for _, msg := range noticeMigrationAlertMsgs {
  1152. NoticeWarning(msg)
  1153. }
  1154. for _, msg := range noticeMigrationInfoMsgs {
  1155. NoticeInfo(msg)
  1156. }
  1157. // Promote legacy fields.
  1158. if config.CustomHeaders == nil {
  1159. config.CustomHeaders = config.UpstreamProxyCustomHeaders
  1160. config.UpstreamProxyCustomHeaders = nil
  1161. }
  1162. if config.RemoteServerListUrl != "" && config.RemoteServerListURLs == nil {
  1163. config.RemoteServerListURLs = promoteLegacyTransferURL(config.RemoteServerListUrl)
  1164. }
  1165. if config.ObfuscatedServerListRootURL != "" && config.ObfuscatedServerListRootURLs == nil {
  1166. config.ObfuscatedServerListRootURLs = promoteLegacyTransferURL(config.ObfuscatedServerListRootURL)
  1167. }
  1168. if config.UpgradeDownloadUrl != "" && config.UpgradeDownloadURLs == nil {
  1169. config.UpgradeDownloadURLs = promoteLegacyTransferURL(config.UpgradeDownloadUrl)
  1170. }
  1171. if config.TunnelProtocol != "" && len(config.LimitTunnelProtocols) == 0 {
  1172. config.LimitTunnelProtocols = []string{config.TunnelProtocol}
  1173. }
  1174. if config.DataStoreDirectory != "" && config.MigrateDataStoreDirectory == "" {
  1175. config.MigrateDataStoreDirectory = config.DataStoreDirectory
  1176. }
  1177. if config.RemoteServerListDownloadFilename != "" && config.MigrateRemoteServerListDownloadFilename == "" {
  1178. config.MigrateRemoteServerListDownloadFilename = config.RemoteServerListDownloadFilename
  1179. }
  1180. if config.ObfuscatedServerListDownloadDirectory != "" && config.MigrateObfuscatedServerListDownloadDirectory == "" {
  1181. config.MigrateObfuscatedServerListDownloadDirectory = config.ObfuscatedServerListDownloadDirectory
  1182. }
  1183. if config.UpgradeDownloadFilename != "" && config.MigrateUpgradeDownloadFilename == "" {
  1184. config.MigrateUpgradeDownloadFilename = config.UpgradeDownloadFilename
  1185. }
  1186. // Supply default values.
  1187. // Create datastore directory.
  1188. dataStoreDirectoryPath := config.GetDataStoreDirectory()
  1189. if !common.FileExists(dataStoreDirectoryPath) {
  1190. err := os.Mkdir(dataStoreDirectoryPath, os.ModePerm)
  1191. if err != nil {
  1192. return errors.Tracef(
  1193. "failed to create datastore directory with error: %s",
  1194. common.RedactFilePathsError(err, dataStoreDirectoryPath))
  1195. }
  1196. }
  1197. // Create OSL directory.
  1198. oslDirectoryPath := config.GetObfuscatedServerListDownloadDirectory()
  1199. if !common.FileExists(oslDirectoryPath) {
  1200. err := os.Mkdir(oslDirectoryPath, os.ModePerm)
  1201. if err != nil {
  1202. return errors.Tracef(
  1203. "failed to create osl directory with error: %s",
  1204. common.RedactFilePathsError(err, oslDirectoryPath))
  1205. }
  1206. }
  1207. if config.ClientVersion == "" {
  1208. config.ClientVersion = "0"
  1209. }
  1210. if config.TunnelPoolSize == 0 {
  1211. config.TunnelPoolSize = TUNNEL_POOL_SIZE
  1212. }
  1213. // Validate config fields.
  1214. if !common.FileExists(config.DataRootDirectory) {
  1215. return errors.TraceNew("DataRootDirectory does not exist")
  1216. }
  1217. if config.PropagationChannelId == "" {
  1218. return errors.TraceNew("propagation channel ID is missing from the configuration file")
  1219. }
  1220. if config.SponsorId == "" {
  1221. return errors.TraceNew("sponsor ID is missing from the configuration file")
  1222. }
  1223. _, err = strconv.Atoi(config.ClientVersion)
  1224. if err != nil {
  1225. return errors.Tracef("invalid client version: %s", err)
  1226. }
  1227. if config.TargetAPIProtocol != "" &&
  1228. !protocol.PsiphonAPIProtocolIsValid(config.TargetAPIProtocol) {
  1229. return errors.TraceNew("invalid TargetAPIProtocol")
  1230. }
  1231. if config.TargetAPIEncoding != "" &&
  1232. !protocol.PsiphonAPIEncodingIsValid(config.TargetAPIEncoding) {
  1233. return errors.TraceNew("invalid TargetAPIEncoding")
  1234. }
  1235. if !config.DisableRemoteServerListFetcher {
  1236. if config.RemoteServerListURLs != nil {
  1237. if config.RemoteServerListSignaturePublicKey == "" {
  1238. return errors.TraceNew("missing RemoteServerListSignaturePublicKey")
  1239. }
  1240. }
  1241. if config.ObfuscatedServerListRootURLs != nil {
  1242. if config.RemoteServerListSignaturePublicKey == "" {
  1243. return errors.TraceNew("missing RemoteServerListSignaturePublicKey")
  1244. }
  1245. }
  1246. }
  1247. if config.EnableUpgradeDownload {
  1248. if len(config.UpgradeDownloadURLs) == 0 {
  1249. return errors.TraceNew("missing UpgradeDownloadURLs")
  1250. }
  1251. if config.UpgradeDownloadClientVersionHeader == "" {
  1252. return errors.TraceNew("missing UpgradeDownloadClientVersionHeader")
  1253. }
  1254. }
  1255. if config.EnableFeedbackUpload {
  1256. if len(config.FeedbackUploadURLs) == 0 {
  1257. return errors.TraceNew("missing FeedbackUploadURLs")
  1258. }
  1259. if config.FeedbackEncryptionPublicKey == "" {
  1260. return errors.TraceNew("missing FeedbackEncryptionPublicKey")
  1261. }
  1262. }
  1263. if config.ObfuscatedSSHAlgorithms != nil &&
  1264. len(config.ObfuscatedSSHAlgorithms) != 4 {
  1265. // TODO: validate each algorithm?
  1266. return errors.TraceNew("invalid ObfuscatedSSHAlgorithms")
  1267. }
  1268. if config.InproxyEnableProxy && config.InproxyMaxClients <= 0 {
  1269. return errors.TraceNew("invalid InproxyMaxClients")
  1270. }
  1271. if !config.DisableTunnels &&
  1272. config.InproxyEnableProxy &&
  1273. !GetAllowOverlappingPersonalCompartmentIDs() &&
  1274. len(config.InproxyProxyPersonalCompartmentID) > 0 &&
  1275. config.InproxyProxyPersonalCompartmentID ==
  1276. config.InproxyClientPersonalCompartmentID {
  1277. // Don't allow an in-proxy client and proxy run in the same app to match.
  1278. return errors.TraceNew("invalid overlapping personal compartment IDs")
  1279. }
  1280. if len(config.InproxyProxyPersonalCompartmentID) > 0 &&
  1281. !inproxy.Enabled() {
  1282. // When in-proxy personal pairing mode is on, fail if the build was
  1283. // made without the PSIPHON_ENABLE_INPROXY build tag.
  1284. //
  1285. // Note that this check could also be enforced in the case of a
  1286. // LimitTunnelProtocols.IsOnlyInproxyTunnelProtocols configuration,
  1287. // but that can be overridden by tactics so we allow it.
  1288. return errors.TraceNew("build does not enable required in-proxy functionality")
  1289. }
  1290. // This constraint is expected by logic in Controller.runTunnels().
  1291. if config.PacketTunnelTunFileDescriptor > 0 && config.TunnelPoolSize != 1 {
  1292. return errors.TraceNew("packet tunnel mode requires TunnelPoolSize to be 1")
  1293. }
  1294. // SessionID must be PSIPHON_API_CLIENT_SESSION_ID_LENGTH lowercase hex-encoded bytes.
  1295. if config.SessionID == "" {
  1296. sessionID, err := MakeSessionId()
  1297. if err != nil {
  1298. return errors.Trace(err)
  1299. }
  1300. config.SessionID = sessionID
  1301. }
  1302. if len(config.SessionID) != 2*protocol.PSIPHON_API_CLIENT_SESSION_ID_LENGTH ||
  1303. -1 != strings.IndexFunc(config.SessionID, func(c rune) bool {
  1304. return !unicode.Is(unicode.ASCII_Hex_Digit, c) || unicode.IsUpper(c)
  1305. }) {
  1306. return errors.TraceNew("invalid SessionID")
  1307. }
  1308. config.paramsMutex.Lock()
  1309. config.params, err = parameters.NewParameters(
  1310. func(err error) {
  1311. NoticeWarning("Parameters getValue failed: %s", err)
  1312. })
  1313. config.paramsMutex.Unlock()
  1314. if err != nil {
  1315. return errors.Trace(err)
  1316. }
  1317. // parameters.Parameters.Set will validate the config fields applied to
  1318. // parameters.Parameters.
  1319. err = config.SetParameters("", false, nil)
  1320. if err != nil {
  1321. return errors.Trace(err)
  1322. }
  1323. // Calculate and set the dial parameters hash. After this point, related
  1324. // config fields must not change.
  1325. config.setDialParametersHash()
  1326. // Set defaults for dynamic config fields.
  1327. config.SetDynamicConfig(config.SponsorId, config.Authorizations)
  1328. // Initialize config.deviceBinder and config.config.networkIDGetter. These
  1329. // wrap config.DeviceBinder and config.NetworkIDGetter/NetworkID with
  1330. // loggers.
  1331. //
  1332. // The network ID getter is further wrapped with a cache (see
  1333. // cachingNetworkIDGetter doc).
  1334. //
  1335. // New variables are set to avoid mutating input config fields.
  1336. // Internally, code must use config.deviceBinder and
  1337. // config.networkIDGetter and not the input/exported fields.
  1338. if config.DeviceBinder != nil {
  1339. config.deviceBinder = newLoggingDeviceBinder(config.DeviceBinder)
  1340. }
  1341. networkIDGetter := config.NetworkIDGetter
  1342. if networkIDGetter == nil {
  1343. if networkid.Enabled() {
  1344. networkIDGetter = newCommonNetworkIDGetter()
  1345. } else {
  1346. // Limitation: unlike NetworkIDGetter, which calls back to platform APIs
  1347. // this method of network identification is not dynamic and will not reflect
  1348. // network changes that occur while running.
  1349. if config.NetworkID != "" {
  1350. networkIDGetter = newStaticNetworkIDGetter(config.NetworkID)
  1351. } else {
  1352. networkIDGetter = newStaticNetworkIDGetter(unknownNetworkID)
  1353. }
  1354. }
  1355. }
  1356. config.networkIDGetter = newCachingNetworkIDGetter(
  1357. config,
  1358. newLoggingNetworkIDGetter(networkIDGetter))
  1359. // Initialize config.clientFeatures, which adds feature names on top of
  1360. // those specified by the host application in config.ClientFeatures.
  1361. config.clientFeatures = config.ClientFeatures
  1362. feature := "VPN"
  1363. if config.DeviceBinder != nil && !common.Contains(config.clientFeatures, feature) {
  1364. config.clientFeatures = append(config.clientFeatures, feature)
  1365. }
  1366. // Migrate from old config fields. This results in files being moved under
  1367. // a config specified data root directory.
  1368. if migrateFromLegacyFields && needMigration {
  1369. // If unset, set MigrateDataStoreDirectory to the previous default value for
  1370. // DataStoreDirectory to ensure that datastore files are migrated.
  1371. if config.MigrateDataStoreDirectory == "" {
  1372. wd, err := os.Getwd()
  1373. if err != nil {
  1374. return errors.Trace(err)
  1375. }
  1376. NoticeInfo("MigrateDataStoreDirectory unset, using working directory")
  1377. config.MigrateDataStoreDirectory = wd
  1378. }
  1379. // Move files that exist at legacy file paths under the data root
  1380. // directory.
  1381. migrations, err := migrationsFromLegacyFilePaths(config)
  1382. if err != nil {
  1383. return errors.Trace(err)
  1384. }
  1385. // Do migrations
  1386. successfulMigrations := 0
  1387. for _, migration := range migrations {
  1388. err := DoFileMigration(migration)
  1389. if err != nil {
  1390. NoticeWarning("Config migration: %s", errors.Trace(err))
  1391. } else {
  1392. successfulMigrations += 1
  1393. }
  1394. }
  1395. NoticeInfo(fmt.Sprintf(
  1396. "Config migration: %d/%d legacy files successfully migrated",
  1397. successfulMigrations, len(migrations)))
  1398. // Remove OSL directory if empty
  1399. if config.MigrateObfuscatedServerListDownloadDirectory != "" {
  1400. files, err := ioutil.ReadDir(config.MigrateObfuscatedServerListDownloadDirectory)
  1401. if err != nil {
  1402. NoticeWarning(
  1403. "Error reading OSL directory: %s",
  1404. errors.Trace(common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory)))
  1405. } else if len(files) == 0 {
  1406. err := os.Remove(config.MigrateObfuscatedServerListDownloadDirectory)
  1407. if err != nil {
  1408. NoticeWarning(
  1409. "Error deleting empty OSL directory: %s",
  1410. errors.Trace(common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory)))
  1411. }
  1412. }
  1413. }
  1414. f, err := os.Create(migrationCompleteFilePath)
  1415. if err != nil {
  1416. NoticeWarning(
  1417. "Config migration: failed to create migration completed file with error %s",
  1418. errors.Trace(common.RedactFilePathsError(err, migrationCompleteFilePath)))
  1419. } else {
  1420. NoticeInfo("Config migration: completed")
  1421. f.Close()
  1422. }
  1423. }
  1424. config.committed = true
  1425. return nil
  1426. }
  1427. // GetParameters returns the current parameters.Parameters.
  1428. func (config *Config) GetParameters() *parameters.Parameters {
  1429. config.paramsMutex.Lock()
  1430. defer config.paramsMutex.Unlock()
  1431. return config.params
  1432. }
  1433. // SetParameters resets the parameters.Parameters to the default values,
  1434. // applies any config file values, and then applies the input parameters (from
  1435. // tactics, etc.)
  1436. //
  1437. // Set skipOnError to false when initially applying only config values, as
  1438. // this will validate the values and should fail. Set skipOnError to true when
  1439. // applying tactics to ignore invalid or unknown parameter values from tactics.
  1440. //
  1441. // In the case of applying tactics, do not call Config.parameters.Set
  1442. // directly as this will not first apply config values.
  1443. //
  1444. // If there is an error, the existing Config.parameters are left
  1445. // entirely unmodified.
  1446. func (config *Config) SetParameters(
  1447. tag string, skipOnError bool, applyParameters map[string]interface{}) error {
  1448. setParameters := []map[string]interface{}{config.makeConfigParameters()}
  1449. if applyParameters != nil {
  1450. setParameters = append(setParameters, applyParameters)
  1451. }
  1452. // Don't hold the lock on config.paramsMutex when signalling
  1453. // GetTacticsAppliedReceivers, or else GetParameters will deadlock.
  1454. // Releasing the lock early here also ensures we don't hold the lock when
  1455. // posting notices.
  1456. config.paramsMutex.Lock()
  1457. tagUnchanged := tag != "" && tag == config.params.Get().Tag()
  1458. validationFlags := 0
  1459. if skipOnError {
  1460. validationFlags |= parameters.ValidationSkipOnError
  1461. }
  1462. counts, err := config.params.Set(tag, validationFlags, setParameters...)
  1463. if err != nil {
  1464. config.paramsMutex.Unlock()
  1465. return errors.Trace(err)
  1466. }
  1467. p := config.params.Get()
  1468. config.paramsMutex.Unlock()
  1469. // Skip emitting notices and invoking GetTacticsAppliedReceivers when the
  1470. // tactics tag is unchanged. The notices are redundant, and the receivers
  1471. // will unnecessarily reset components such as in-proxy broker clients.
  1472. //
  1473. // At this time, the GetTactics call in launchEstablishing can result in
  1474. // redundant SetParameters calls with an unchanged tag.
  1475. //
  1476. // As a fail safe, and since there should not be any unwanted side
  1477. // effects, the above params.Set is still executed even for unchanged tags.
  1478. if tagUnchanged {
  1479. return nil
  1480. }
  1481. NoticeInfo("applied %v parameters with tag '%s'", counts, tag)
  1482. // Emit certain individual parameter values for quick reference in diagnostics.
  1483. NoticeInfo(
  1484. "NetworkLatencyMultiplier Min/Max/Lambda: %f/%f/%f",
  1485. p.Float(parameters.NetworkLatencyMultiplierMin),
  1486. p.Float(parameters.NetworkLatencyMultiplierMax),
  1487. p.Float(parameters.NetworkLatencyMultiplierLambda))
  1488. // Application Parameters are feature flags/config info, delivered as Client
  1489. // Parameters via tactics/etc., to be communicated to the outer application.
  1490. // Emit these now, as notices.
  1491. //
  1492. // Only emit when tactics are received (applyParameters != nil), to avoid
  1493. // triggering the outer application with empty Application Parameters via
  1494. // the SetParameters call from Commit.
  1495. if applyParameters != nil {
  1496. NoticeApplicationParameters(p.KeyValues(parameters.ApplicationParameters))
  1497. }
  1498. // Signal all registered TacticsAppliedReceivers that new tactics have
  1499. // been applied. Each receiver is responsible for checking if its
  1500. // individual tactics parameters have actually changed.
  1501. for _, receiver := range config.GetTacticsAppliedReceivers() {
  1502. err := receiver.TacticsApplied()
  1503. if err != nil {
  1504. NoticeError("TacticsApplied failed: %v", errors.Trace(err))
  1505. // Log and continue running.
  1506. }
  1507. }
  1508. return nil
  1509. }
  1510. // SetResolver sets the current resolver.
  1511. func (config *Config) SetResolver(resolver *resolver.Resolver) {
  1512. config.resolverMutex.Lock()
  1513. defer config.resolverMutex.Unlock()
  1514. config.resolver = resolver
  1515. }
  1516. // GetResolver returns the current resolver. May return nil.
  1517. func (config *Config) GetResolver() *resolver.Resolver {
  1518. config.resolverMutex.Lock()
  1519. defer config.resolverMutex.Unlock()
  1520. return config.resolver
  1521. }
  1522. // SetTacticsAppliedReceivers registers the list of TacticsAppliedReceivers.
  1523. func (config *Config) SetTacticsAppliedReceivers(receivers []TacticsAppliedReceiver) {
  1524. config.tacticsAppliedReceiversMutex.Lock()
  1525. defer config.tacticsAppliedReceiversMutex.Unlock()
  1526. config.tacticsAppliedReceivers = receivers
  1527. }
  1528. // GetTacticsAppliedReceivers gets the list of registered
  1529. // TacticsAppliedReceivers.
  1530. func (config *Config) GetTacticsAppliedReceivers() []TacticsAppliedReceiver {
  1531. config.tacticsAppliedReceiversMutex.Lock()
  1532. defer config.tacticsAppliedReceiversMutex.Unlock()
  1533. return config.tacticsAppliedReceivers
  1534. }
  1535. // SetDynamicConfig sets the current client sponsor ID and authorizations.
  1536. // Invalid values for sponsor ID are ignored. The caller must not modify the
  1537. // input authorizations slice.
  1538. func (config *Config) SetDynamicConfig(sponsorID string, authorizations []string) {
  1539. config.dynamicConfigMutex.Lock()
  1540. defer config.dynamicConfigMutex.Unlock()
  1541. if sponsorID != "" {
  1542. config.sponsorID = sponsorID
  1543. }
  1544. config.authorizations = authorizations
  1545. }
  1546. // GetSponsorID returns the current client sponsor ID.
  1547. func (config *Config) GetSponsorID() string {
  1548. config.dynamicConfigMutex.Lock()
  1549. defer config.dynamicConfigMutex.Unlock()
  1550. return config.sponsorID
  1551. }
  1552. // IsSplitTunnelEnabled indicates if split tunnel mode is enabled, either for
  1553. // the client's own country, a specified list of countries, or both.
  1554. func (config *Config) IsSplitTunnelEnabled() bool {
  1555. return config.SplitTunnelOwnRegion || len(config.SplitTunnelRegions) > 0
  1556. }
  1557. // GetAuthorizations returns the current client authorizations.
  1558. // The caller must not modify the returned slice.
  1559. func (config *Config) GetAuthorizations() []string {
  1560. config.dynamicConfigMutex.Lock()
  1561. defer config.dynamicConfigMutex.Unlock()
  1562. return config.authorizations
  1563. }
  1564. // GetPsiphonDataDirectory returns the directory under which all persistent
  1565. // files should be stored. This directory is created under
  1566. // config.DataRootDirectory. The motivation for an additional directory is that
  1567. // config.DataRootDirectory defaults to the current working directory, which may
  1568. // include non-tunnel-core files that should be excluded from directory-spanning
  1569. // operations (e.g. excluding all tunnel-core files from backup).
  1570. func (config *Config) GetPsiphonDataDirectory() string {
  1571. return filepath.Join(config.DataRootDirectory, PsiphonDataDirectoryName)
  1572. }
  1573. // GetHomePageFilename the path where the homepage notices file will be created.
  1574. func (config *Config) GetHomePageFilename() string {
  1575. return filepath.Join(config.GetPsiphonDataDirectory(), HomepageFilename)
  1576. }
  1577. // GetNoticesFilename returns the path where the notices file will be created.
  1578. // When the file is rotated it will be moved to config.GetOldNoticesFilename().
  1579. func (config *Config) GetNoticesFilename() string {
  1580. return filepath.Join(config.GetPsiphonDataDirectory(), NoticesFilename)
  1581. }
  1582. // GetOldNoticeFilename returns the path where the rotated notices file will be
  1583. // created.
  1584. func (config *Config) GetOldNoticesFilename() string {
  1585. return filepath.Join(config.GetPsiphonDataDirectory(), OldNoticesFilename)
  1586. }
  1587. // GetDataStoreDirectory returns the directory in which the persistent database
  1588. // will be stored. Created in Config.Commit(). The persistent database contains
  1589. // information such as server entries.
  1590. func (config *Config) GetDataStoreDirectory() string {
  1591. return filepath.Join(config.GetPsiphonDataDirectory(), "datastore")
  1592. }
  1593. // GetObfuscatedServerListDownloadDirectory returns the directory in which
  1594. // obfuscated remote server list downloads will be stored. Created in
  1595. // Config.Commit().
  1596. func (config *Config) GetObfuscatedServerListDownloadDirectory() string {
  1597. return filepath.Join(config.GetPsiphonDataDirectory(), "osl")
  1598. }
  1599. // GetRemoteServerListDownloadFilename returns the filename where the remote
  1600. // server list download will be stored. Data is stored in co-located files
  1601. // (RemoteServerListDownloadFilename.part*) to allow for resumable downloading.
  1602. func (config *Config) GetRemoteServerListDownloadFilename() string {
  1603. return filepath.Join(config.GetPsiphonDataDirectory(), "remote_server_list")
  1604. }
  1605. // GetUpgradeDownloadFilename specifies the filename where upgrade downloads
  1606. // will be stored. This filename is valid when UpgradeDownloadURLs
  1607. // (or UpgradeDownloadUrl) is specified. Data is stored in co-located files
  1608. // (UpgradeDownloadFilename.part*) to allow for resumable downloading.
  1609. func (config *Config) GetUpgradeDownloadFilename() string {
  1610. return filepath.Join(config.GetPsiphonDataDirectory(), UpgradeDownloadFilename)
  1611. }
  1612. // UseUpstreamProxy indicates if an upstream proxy has been
  1613. // configured.
  1614. func (config *Config) UseUpstreamProxy() bool {
  1615. return config.UpstreamProxyURL != ""
  1616. }
  1617. // GetNetworkID returns the current network ID. When NetworkIDGetter
  1618. // is set, this calls into the host application; otherwise, a default
  1619. // value is returned.
  1620. func (config *Config) GetNetworkID() string {
  1621. return config.networkIDGetter.GetNetworkID()
  1622. }
  1623. func (config *Config) SetSignalComponentFailure(signalComponentFailure func()) {
  1624. config.signalComponentFailure.Store(signalComponentFailure)
  1625. }
  1626. // IsInproxyClientPersonalPairingMode indicates that the client is in in-proxy
  1627. // personal pairing mode, where connections are made only through in-proxy
  1628. // proxies with the corresponding personal compartment ID.
  1629. func (config *Config) IsInproxyClientPersonalPairingMode() bool {
  1630. return len(config.InproxyClientPersonalCompartmentID) > 0
  1631. }
  1632. // IsInproxyProxyPersonalPairingMode indicates that the proxy is in in-proxy
  1633. // personal pairing mode, where connections are made only with in-proxy
  1634. // clients with the corresponding personal compartment ID.
  1635. func (config *Config) IsInproxyProxyPersonalPairingMode() bool {
  1636. return len(config.InproxyProxyPersonalCompartmentID) > 0
  1637. }
  1638. // OnInproxyMustUpgrade is invoked when the in-proxy broker returns the
  1639. // MustUpgrade response. When either running a proxy, or when running a
  1640. // client in personal-pairing mode -- two states that require in-proxy
  1641. // functionality -- onInproxyMustUpgrade initiates a shutdown after emitting
  1642. // the InproxyMustUpgrade notice.
  1643. func (config *Config) OnInproxyMustUpgrade() {
  1644. // TODO: check if LimitTunnelProtocols is set to allow only INPROXY tunnel
  1645. // protocols; this is another case where in-proxy functionality is
  1646. // required.
  1647. if config.InproxyEnableProxy || config.IsInproxyClientPersonalPairingMode() {
  1648. if atomic.CompareAndSwapInt32(&config.inproxyMustUpgradePosted, 0, 1) {
  1649. NoticeInproxyMustUpgrade()
  1650. }
  1651. config.signalComponentFailure.Load().(func())()
  1652. }
  1653. }
  1654. func (config *Config) SetServerEntryIterationMetricsUpdater(
  1655. updater func(movedToFront int)) {
  1656. config.serverEntryIterationMetricsUpdater.Store(updater)
  1657. }
  1658. func (config *Config) GetServerEntryIterationMetricsUpdater() func(movedToFront int) {
  1659. updater := config.serverEntryIterationMetricsUpdater.Load()
  1660. if updater != nil {
  1661. return updater.(func(int))
  1662. }
  1663. return nil
  1664. }
  1665. func (config *Config) makeConfigParameters() map[string]interface{} {
  1666. // Build set of config values to apply to parameters.
  1667. //
  1668. // Note: names of some config fields such as
  1669. // StaggerConnectionWorkersMilliseconds and LimitMeekBufferSizes have
  1670. // changed in the parameters. The existing config fields are retained for
  1671. // backwards compatibility.
  1672. applyParameters := make(map[string]interface{})
  1673. // To support platform clients that configure NetworkLatencyMultiplier, set
  1674. // the NetworkLatencyMultiplierMin/NetworkLatencyMultiplierMax range to the
  1675. // specified value. Also set the older NetworkLatencyMultiplier tactic, since
  1676. // that will be used in the case of replaying with dial parameters persisted
  1677. // by an older client version.
  1678. if config.NetworkLatencyMultiplier > 0.0 {
  1679. applyParameters[parameters.NetworkLatencyMultiplier] = config.NetworkLatencyMultiplier
  1680. applyParameters[parameters.NetworkLatencyMultiplierMin] = config.NetworkLatencyMultiplier
  1681. applyParameters[parameters.NetworkLatencyMultiplierMax] = config.NetworkLatencyMultiplier
  1682. }
  1683. if config.NetworkLatencyMultiplierMin > 0.0 {
  1684. applyParameters[parameters.NetworkLatencyMultiplierMin] = config.NetworkLatencyMultiplierMin
  1685. }
  1686. if config.NetworkLatencyMultiplierMax > 0.0 {
  1687. applyParameters[parameters.NetworkLatencyMultiplierMax] = config.NetworkLatencyMultiplierMax
  1688. }
  1689. if config.NetworkLatencyMultiplierLambda > 0.0 {
  1690. applyParameters[parameters.NetworkLatencyMultiplierLambda] = config.NetworkLatencyMultiplierLambda
  1691. }
  1692. if len(config.LimitTunnelProtocols) > 0 {
  1693. applyParameters[parameters.LimitTunnelProtocols] = protocol.TunnelProtocols(config.LimitTunnelProtocols)
  1694. }
  1695. if len(config.InitialLimitTunnelProtocols) > 0 && config.InitialLimitTunnelProtocolsCandidateCount > 0 {
  1696. applyParameters[parameters.InitialLimitTunnelProtocols] = protocol.TunnelProtocols(config.InitialLimitTunnelProtocols)
  1697. applyParameters[parameters.InitialLimitTunnelProtocolsCandidateCount] = config.InitialLimitTunnelProtocolsCandidateCount
  1698. }
  1699. if len(config.LimitTLSProfiles) > 0 {
  1700. applyParameters[parameters.LimitTLSProfiles] = protocol.TunnelProtocols(config.LimitTLSProfiles)
  1701. }
  1702. if len(config.LimitQUICVersions) > 0 {
  1703. applyParameters[parameters.LimitQUICVersions] = protocol.QUICVersions(config.LimitQUICVersions)
  1704. }
  1705. if config.EstablishTunnelTimeoutSeconds != nil {
  1706. applyParameters[parameters.EstablishTunnelTimeout] = fmt.Sprintf("%ds", *config.EstablishTunnelTimeoutSeconds)
  1707. }
  1708. if config.EstablishTunnelServerAffinityGracePeriodMilliseconds != nil {
  1709. applyParameters[parameters.EstablishTunnelServerAffinityGracePeriod] = fmt.Sprintf("%dms", *config.EstablishTunnelServerAffinityGracePeriodMilliseconds)
  1710. }
  1711. if config.EstablishTunnelPausePeriodSeconds != nil {
  1712. applyParameters[parameters.EstablishTunnelPausePeriod] = fmt.Sprintf("%ds", *config.EstablishTunnelPausePeriodSeconds)
  1713. }
  1714. if config.ConnectionWorkerPoolSize != 0 {
  1715. applyParameters[parameters.ConnectionWorkerPoolSize] = config.ConnectionWorkerPoolSize
  1716. }
  1717. if config.TunnelPoolSize != 0 {
  1718. applyParameters[parameters.TunnelPoolSize] = config.TunnelPoolSize
  1719. }
  1720. if config.StaggerConnectionWorkersMilliseconds > 0 {
  1721. applyParameters[parameters.StaggerConnectionWorkersPeriod] = fmt.Sprintf("%dms", config.StaggerConnectionWorkersMilliseconds)
  1722. }
  1723. if config.LimitIntensiveConnectionWorkers > 0 {
  1724. applyParameters[parameters.LimitIntensiveConnectionWorkers] = config.LimitIntensiveConnectionWorkers
  1725. }
  1726. applyParameters[parameters.MeekLimitBufferSizes] = config.LimitMeekBufferSizes
  1727. applyParameters[parameters.IgnoreHandshakeStatsRegexps] = config.IgnoreHandshakeStatsRegexps
  1728. if config.EstablishTunnelTimeoutSeconds != nil {
  1729. applyParameters[parameters.EstablishTunnelTimeout] = fmt.Sprintf("%ds", *config.EstablishTunnelTimeoutSeconds)
  1730. }
  1731. if config.FetchRemoteServerListRetryPeriodMilliseconds != nil {
  1732. applyParameters[parameters.FetchRemoteServerListRetryPeriod] = fmt.Sprintf("%dms", *config.FetchRemoteServerListRetryPeriodMilliseconds)
  1733. }
  1734. if config.FetchUpgradeRetryPeriodMilliseconds != nil {
  1735. applyParameters[parameters.FetchUpgradeRetryPeriod] = fmt.Sprintf("%dms", *config.FetchUpgradeRetryPeriodMilliseconds)
  1736. }
  1737. if !config.DisableRemoteServerListFetcher {
  1738. if config.RemoteServerListURLs != nil {
  1739. applyParameters[parameters.RemoteServerListSignaturePublicKey] = config.RemoteServerListSignaturePublicKey
  1740. applyParameters[parameters.RemoteServerListURLs] = config.RemoteServerListURLs
  1741. }
  1742. if config.ObfuscatedServerListRootURLs != nil {
  1743. applyParameters[parameters.RemoteServerListSignaturePublicKey] = config.RemoteServerListSignaturePublicKey
  1744. applyParameters[parameters.ObfuscatedServerListRootURLs] = config.ObfuscatedServerListRootURLs
  1745. }
  1746. }
  1747. if config.EnableUpgradeDownload {
  1748. applyParameters[parameters.UpgradeDownloadURLs] = config.UpgradeDownloadURLs
  1749. applyParameters[parameters.UpgradeDownloadClientVersionHeader] = config.UpgradeDownloadClientVersionHeader
  1750. }
  1751. if config.EnableFeedbackUpload {
  1752. applyParameters[parameters.FeedbackUploadURLs] = config.FeedbackUploadURLs
  1753. applyParameters[parameters.FeedbackEncryptionPublicKey] = config.FeedbackEncryptionPublicKey
  1754. }
  1755. if config.RateLimits != nil {
  1756. applyParameters[parameters.TunnelRateLimits] = *config.RateLimits
  1757. }
  1758. if config.TransformHostNameProbability != nil {
  1759. applyParameters[parameters.TransformHostNameProbability] = *config.TransformHostNameProbability
  1760. }
  1761. if config.FragmentorProbability != nil {
  1762. applyParameters[parameters.FragmentorProbability] = *config.FragmentorProbability
  1763. }
  1764. if len(config.FragmentorLimitProtocols) > 0 {
  1765. applyParameters[parameters.FragmentorLimitProtocols] = protocol.TunnelProtocols(config.FragmentorLimitProtocols)
  1766. }
  1767. if config.FragmentorMinTotalBytes != nil {
  1768. applyParameters[parameters.FragmentorMinTotalBytes] = *config.FragmentorMinTotalBytes
  1769. }
  1770. if config.FragmentorMaxTotalBytes != nil {
  1771. applyParameters[parameters.FragmentorMaxTotalBytes] = *config.FragmentorMaxTotalBytes
  1772. }
  1773. if config.FragmentorMinWriteBytes != nil {
  1774. applyParameters[parameters.FragmentorMinWriteBytes] = *config.FragmentorMinWriteBytes
  1775. }
  1776. if config.FragmentorMaxWriteBytes != nil {
  1777. applyParameters[parameters.FragmentorMaxWriteBytes] = *config.FragmentorMaxWriteBytes
  1778. }
  1779. if config.FragmentorMinDelayMicroseconds != nil {
  1780. applyParameters[parameters.FragmentorMinDelay] = fmt.Sprintf("%dus", *config.FragmentorMinDelayMicroseconds)
  1781. }
  1782. if config.FragmentorMaxDelayMicroseconds != nil {
  1783. applyParameters[parameters.FragmentorMaxDelay] = fmt.Sprintf("%dus", *config.FragmentorMaxDelayMicroseconds)
  1784. }
  1785. if config.MeekTrafficShapingProbability != nil {
  1786. applyParameters[parameters.MeekTrafficShapingProbability] = *config.MeekTrafficShapingProbability
  1787. }
  1788. if len(config.MeekTrafficShapingLimitProtocols) > 0 {
  1789. applyParameters[parameters.MeekTrafficShapingLimitProtocols] = protocol.TunnelProtocols(config.MeekTrafficShapingLimitProtocols)
  1790. }
  1791. if config.MeekMinTLSPadding != nil {
  1792. applyParameters[parameters.MeekMinTLSPadding] = *config.MeekMinTLSPadding
  1793. }
  1794. if config.MeekMaxTLSPadding != nil {
  1795. applyParameters[parameters.MeekMaxTLSPadding] = *config.MeekMaxTLSPadding
  1796. }
  1797. if config.MeekMinLimitRequestPayloadLength != nil {
  1798. applyParameters[parameters.MeekMinLimitRequestPayloadLength] = *config.MeekMinLimitRequestPayloadLength
  1799. }
  1800. if config.MeekMaxLimitRequestPayloadLength != nil {
  1801. applyParameters[parameters.MeekMaxLimitRequestPayloadLength] = *config.MeekMaxLimitRequestPayloadLength
  1802. }
  1803. if config.MeekRedialTLSProbability != nil {
  1804. applyParameters[parameters.MeekRedialTLSProbability] = *config.MeekRedialTLSProbability
  1805. }
  1806. if config.MeekAlternateCookieNameProbability != nil {
  1807. applyParameters[parameters.MeekAlternateCookieNameProbability] = *config.MeekAlternateCookieNameProbability
  1808. }
  1809. if config.MeekAlternateContentTypeProbability != nil {
  1810. applyParameters[parameters.MeekAlternateContentTypeProbability] = *config.MeekAlternateContentTypeProbability
  1811. }
  1812. if config.ObfuscatedSSHMinPadding != nil {
  1813. applyParameters[parameters.ObfuscatedSSHMinPadding] = *config.ObfuscatedSSHMinPadding
  1814. }
  1815. if config.ObfuscatedSSHMaxPadding != nil {
  1816. applyParameters[parameters.ObfuscatedSSHMaxPadding] = *config.ObfuscatedSSHMaxPadding
  1817. }
  1818. if len(config.InitialLivenessTest) > 0 {
  1819. applyParameters[parameters.InitialLivenessTest] = config.InitialLivenessTest
  1820. }
  1821. if len(config.LivenessTest) > 0 {
  1822. applyParameters[parameters.LivenessTest] = config.LivenessTest
  1823. }
  1824. if config.LivenessTestMinUpstreamBytes != nil {
  1825. applyParameters[parameters.LivenessTestMinUpstreamBytes] = *config.LivenessTestMinUpstreamBytes
  1826. }
  1827. if config.LivenessTestMaxUpstreamBytes != nil {
  1828. applyParameters[parameters.LivenessTestMaxUpstreamBytes] = *config.LivenessTestMaxUpstreamBytes
  1829. }
  1830. if config.LivenessTestMinDownstreamBytes != nil {
  1831. applyParameters[parameters.LivenessTestMinDownstreamBytes] = *config.LivenessTestMinDownstreamBytes
  1832. }
  1833. if config.LivenessTestMaxDownstreamBytes != nil {
  1834. applyParameters[parameters.LivenessTestMaxDownstreamBytes] = *config.LivenessTestMaxDownstreamBytes
  1835. }
  1836. if config.ReplayCandidateCount != nil {
  1837. applyParameters[parameters.ReplayCandidateCount] = *config.ReplayCandidateCount
  1838. }
  1839. if config.ReplayDialParametersTTLSeconds != nil {
  1840. applyParameters[parameters.ReplayDialParametersTTL] = fmt.Sprintf("%ds", *config.ReplayDialParametersTTLSeconds)
  1841. }
  1842. if config.ReplayTargetUpstreamBytes != nil {
  1843. applyParameters[parameters.ReplayTargetUpstreamBytes] = *config.ReplayTargetUpstreamBytes
  1844. }
  1845. if config.ReplayTargetDownstreamBytes != nil {
  1846. applyParameters[parameters.ReplayTargetDownstreamBytes] = *config.ReplayTargetDownstreamBytes
  1847. }
  1848. if config.ReplayTargetTunnelDurationSeconds != nil {
  1849. applyParameters[parameters.ReplayTargetTunnelDuration] = fmt.Sprintf("%ds", *config.ReplayTargetTunnelDurationSeconds)
  1850. }
  1851. if config.ReplayLaterRoundMoveToFrontProbability != nil {
  1852. applyParameters[parameters.ReplayLaterRoundMoveToFrontProbability] = *config.ReplayLaterRoundMoveToFrontProbability
  1853. }
  1854. if config.ReplayRetainFailedProbability != nil {
  1855. applyParameters[parameters.ReplayRetainFailedProbability] = *config.ReplayRetainFailedProbability
  1856. }
  1857. if config.ReplayIgnoreChangedConfigStateProbability != nil {
  1858. applyParameters[parameters.ReplayIgnoreChangedConfigStateProbability] = *config.ReplayIgnoreChangedConfigStateProbability
  1859. }
  1860. if config.UseOnlyCustomTLSProfiles != nil {
  1861. applyParameters[parameters.UseOnlyCustomTLSProfiles] = *config.UseOnlyCustomTLSProfiles
  1862. }
  1863. if len(config.CustomTLSProfiles) > 0 {
  1864. applyParameters[parameters.CustomTLSProfiles] = config.CustomTLSProfiles
  1865. }
  1866. if config.SelectRandomizedTLSProfileProbability != nil {
  1867. applyParameters[parameters.SelectRandomizedTLSProfileProbability] = *config.SelectRandomizedTLSProfileProbability
  1868. }
  1869. if config.NoDefaultTLSSessionIDProbability != nil {
  1870. applyParameters[parameters.NoDefaultTLSSessionIDProbability] = *config.NoDefaultTLSSessionIDProbability
  1871. }
  1872. if len(config.DisableFrontingProviderTLSProfiles) > 0 {
  1873. applyParameters[parameters.DisableFrontingProviderTLSProfiles] = config.DisableFrontingProviderTLSProfiles
  1874. }
  1875. if config.ClientBurstUpstreamTargetBytes != nil {
  1876. applyParameters[parameters.ClientBurstUpstreamTargetBytes] = *config.ClientBurstUpstreamTargetBytes
  1877. }
  1878. if config.ClientBurstUpstreamDeadlineMilliseconds != nil {
  1879. applyParameters[parameters.ClientBurstUpstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstUpstreamDeadlineMilliseconds)
  1880. }
  1881. if config.ClientBurstDownstreamTargetBytes != nil {
  1882. applyParameters[parameters.ClientBurstDownstreamTargetBytes] = *config.ClientBurstDownstreamTargetBytes
  1883. }
  1884. if config.ClientBurstDownstreamDeadlineMilliseconds != nil {
  1885. applyParameters[parameters.ClientBurstDownstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstDownstreamDeadlineMilliseconds)
  1886. }
  1887. if config.CustomHostNameRegexes != nil {
  1888. applyParameters[parameters.CustomHostNameRegexes] = parameters.RegexStrings(config.CustomHostNameRegexes)
  1889. }
  1890. if config.CustomHostNameProbability != nil {
  1891. applyParameters[parameters.CustomHostNameProbability] = *config.CustomHostNameProbability
  1892. }
  1893. if config.CustomHostNameLimitProtocols != nil {
  1894. applyParameters[parameters.CustomHostNameLimitProtocols] = protocol.TunnelProtocols(config.CustomHostNameLimitProtocols)
  1895. }
  1896. if config.ConjureCachedRegistrationTTLSeconds != nil {
  1897. applyParameters[parameters.ConjureCachedRegistrationTTL] = fmt.Sprintf("%ds", *config.ConjureCachedRegistrationTTLSeconds)
  1898. }
  1899. if config.ConjureAPIRegistrarBidirectionalURL != "" {
  1900. applyParameters[parameters.ConjureAPIRegistrarBidirectionalURL] = config.ConjureAPIRegistrarBidirectionalURL
  1901. }
  1902. if len(config.ConjureAPIRegistrarFrontingSpecs) > 0 {
  1903. applyParameters[parameters.ConjureAPIRegistrarFrontingSpecs] = config.ConjureAPIRegistrarFrontingSpecs
  1904. }
  1905. if config.ConjureAPIRegistrarMinDelayMilliseconds != nil {
  1906. applyParameters[parameters.ConjureAPIRegistrarMinDelay] = fmt.Sprintf("%dms", *config.ConjureAPIRegistrarMinDelayMilliseconds)
  1907. }
  1908. if config.ConjureAPIRegistrarMaxDelayMilliseconds != nil {
  1909. applyParameters[parameters.ConjureAPIRegistrarMaxDelay] = fmt.Sprintf("%dms", *config.ConjureAPIRegistrarMaxDelayMilliseconds)
  1910. }
  1911. if config.ConjureDecoyRegistrarProbability != nil {
  1912. applyParameters[parameters.ConjureDecoyRegistrarProbability] = *config.ConjureDecoyRegistrarProbability
  1913. }
  1914. if config.ConjureDecoyRegistrarWidth != nil {
  1915. applyParameters[parameters.ConjureDecoyRegistrarWidth] = *config.ConjureDecoyRegistrarWidth
  1916. }
  1917. if config.ConjureDecoyRegistrarMinDelayMilliseconds != nil {
  1918. applyParameters[parameters.ConjureDecoyRegistrarMinDelay] = fmt.Sprintf("%dms", *config.ConjureDecoyRegistrarMinDelayMilliseconds)
  1919. }
  1920. if config.ConjureDecoyRegistrarMaxDelayMilliseconds != nil {
  1921. applyParameters[parameters.ConjureDecoyRegistrarMaxDelay] = fmt.Sprintf("%dms", *config.ConjureDecoyRegistrarMaxDelayMilliseconds)
  1922. }
  1923. if config.ConjureEnableIPv6Dials != nil {
  1924. applyParameters[parameters.ConjureEnableIPv6Dials] = *config.ConjureEnableIPv6Dials
  1925. }
  1926. if config.ConjureEnablePortRandomization != nil {
  1927. applyParameters[parameters.ConjureEnablePortRandomization] = *config.ConjureEnablePortRandomization
  1928. }
  1929. if config.ConjureEnableRegistrationOverrides != nil {
  1930. applyParameters[parameters.ConjureEnableRegistrationOverrides] = *config.ConjureEnableRegistrationOverrides
  1931. }
  1932. if config.ConjureLimitTransports != nil {
  1933. applyParameters[parameters.ConjureLimitTransports] = config.ConjureLimitTransports
  1934. }
  1935. if config.ConjureSTUNServerAddresses != nil {
  1936. applyParameters[parameters.ConjureSTUNServerAddresses] = config.ConjureSTUNServerAddresses
  1937. }
  1938. if config.ConjureDTLSEmptyInitialPacketProbability != nil {
  1939. applyParameters[parameters.ConjureDTLSEmptyInitialPacketProbability] = *config.ConjureDTLSEmptyInitialPacketProbability
  1940. }
  1941. if config.HoldOffTunnelProtocolMinDurationMilliseconds != nil {
  1942. applyParameters[parameters.HoldOffTunnelProtocolMinDuration] = fmt.Sprintf("%dms", *config.HoldOffTunnelProtocolMinDurationMilliseconds)
  1943. }
  1944. if config.HoldOffTunnelProtocolMaxDurationMilliseconds != nil {
  1945. applyParameters[parameters.HoldOffTunnelProtocolMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffTunnelProtocolMaxDurationMilliseconds)
  1946. }
  1947. if len(config.HoldOffTunnelProtocolNames) > 0 {
  1948. applyParameters[parameters.HoldOffTunnelProtocolNames] = protocol.TunnelProtocols(config.HoldOffTunnelProtocolNames)
  1949. }
  1950. if config.HoldOffTunnelProtocolProbability != nil {
  1951. applyParameters[parameters.HoldOffTunnelProtocolProbability] = *config.HoldOffTunnelProtocolProbability
  1952. }
  1953. if config.HoldOffFrontingTunnelMinDurationMilliseconds != nil {
  1954. applyParameters[parameters.HoldOffFrontingTunnelMinDuration] = fmt.Sprintf("%dms", *config.HoldOffFrontingTunnelMinDurationMilliseconds)
  1955. }
  1956. if config.HoldOffFrontingTunnelMaxDurationMilliseconds != nil {
  1957. applyParameters[parameters.HoldOffFrontingTunnelMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffFrontingTunnelMaxDurationMilliseconds)
  1958. }
  1959. if len(config.HoldOffFrontingTunnelProviderIDs) > 0 {
  1960. applyParameters[parameters.HoldOffFrontingTunnelProviderIDs] = config.HoldOffFrontingTunnelProviderIDs
  1961. }
  1962. if config.HoldOffFrontingTunnelProbability != nil {
  1963. applyParameters[parameters.HoldOffFrontingTunnelProbability] = *config.HoldOffFrontingTunnelProbability
  1964. }
  1965. if config.HoldOffDirectTunnelMinDurationMilliseconds != nil {
  1966. applyParameters[parameters.HoldOffDirectTunnelMinDuration] = fmt.Sprintf("%dms", *config.HoldOffDirectTunnelMinDurationMilliseconds)
  1967. }
  1968. if config.HoldOffDirectTunnelMaxDurationMilliseconds != nil {
  1969. applyParameters[parameters.HoldOffDirectTunnelMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffDirectTunnelMaxDurationMilliseconds)
  1970. }
  1971. if len(config.HoldOffDirectTunnelProviderRegions) > 0 {
  1972. applyParameters[parameters.HoldOffDirectTunnelProviderRegions] = parameters.KeyStrings(config.HoldOffDirectTunnelProviderRegions)
  1973. }
  1974. if config.HoldOffDirectTunnelProbability != nil {
  1975. applyParameters[parameters.HoldOffDirectTunnelProbability] = *config.HoldOffDirectTunnelProbability
  1976. }
  1977. if len(config.RestrictDirectProviderRegions) > 0 {
  1978. applyParameters[parameters.RestrictDirectProviderRegions] = parameters.KeyStrings(config.RestrictDirectProviderRegions)
  1979. }
  1980. if config.RestrictDirectProviderIDsClientProbability != nil {
  1981. applyParameters[parameters.RestrictDirectProviderIDsClientProbability] = *config.RestrictDirectProviderIDsClientProbability
  1982. }
  1983. if len(config.RestrictFrontingProviderIDs) > 0 {
  1984. applyParameters[parameters.RestrictFrontingProviderIDs] = config.RestrictFrontingProviderIDs
  1985. }
  1986. if config.RestrictFrontingProviderIDsClientProbability != nil {
  1987. applyParameters[parameters.RestrictFrontingProviderIDsClientProbability] = *config.RestrictFrontingProviderIDsClientProbability
  1988. }
  1989. if config.HoldOffInproxyTunnelMinDurationMilliseconds != nil {
  1990. applyParameters[parameters.HoldOffInproxyTunnelMinDuration] = fmt.Sprintf("%dms", *config.HoldOffInproxyTunnelMinDurationMilliseconds)
  1991. }
  1992. if config.HoldOffInproxyTunnelMaxDurationMilliseconds != nil {
  1993. applyParameters[parameters.HoldOffInproxyTunnelMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffInproxyTunnelMaxDurationMilliseconds)
  1994. }
  1995. if len(config.HoldOffInproxyTunnelProviderRegions) > 0 {
  1996. applyParameters[parameters.HoldOffInproxyTunnelProviderRegions] = parameters.KeyStrings(config.HoldOffInproxyTunnelProviderRegions)
  1997. }
  1998. if config.HoldOffInproxyTunnelProbability != nil {
  1999. applyParameters[parameters.HoldOffInproxyTunnelProbability] = *config.HoldOffInproxyTunnelProbability
  2000. }
  2001. if config.UpstreamProxyAllowAllServerEntrySources != nil {
  2002. applyParameters[parameters.UpstreamProxyAllowAllServerEntrySources] = *config.UpstreamProxyAllowAllServerEntrySources
  2003. }
  2004. if len(config.LimitTunnelDialPortNumbers) > 0 {
  2005. applyParameters[parameters.LimitTunnelDialPortNumbers] = config.LimitTunnelDialPortNumbers
  2006. }
  2007. if config.QUICDialEarlyProbability != nil {
  2008. applyParameters[parameters.QUICDialEarlyProbability] = *config.QUICDialEarlyProbability
  2009. }
  2010. if config.QUICObfuscatedPSKProbability != nil {
  2011. applyParameters[parameters.QUICObfuscatedPSKProbability] = *config.QUICObfuscatedPSKProbability
  2012. }
  2013. if config.QUICDisablePathMTUDiscoveryProbability != nil {
  2014. applyParameters[parameters.QUICDisableClientPathMTUDiscoveryProbability] = *config.QUICDisablePathMTUDiscoveryProbability
  2015. }
  2016. if config.DNSResolverAttemptsPerServer != nil {
  2017. applyParameters[parameters.DNSResolverAttemptsPerServer] = *config.DNSResolverAttemptsPerServer
  2018. }
  2019. if config.DNSResolverAttemptsPerPreferredServer != nil {
  2020. applyParameters[parameters.DNSResolverAttemptsPerPreferredServer] = *config.DNSResolverAttemptsPerPreferredServer
  2021. }
  2022. if config.DNSResolverRequestTimeoutMilliseconds != nil {
  2023. applyParameters[parameters.DNSResolverRequestTimeout] = fmt.Sprintf("%dms", *config.DNSResolverRequestTimeoutMilliseconds)
  2024. }
  2025. if config.DNSResolverAwaitTimeoutMilliseconds != nil {
  2026. applyParameters[parameters.DNSResolverAwaitTimeout] = fmt.Sprintf("%dms", *config.DNSResolverAwaitTimeoutMilliseconds)
  2027. }
  2028. if config.DNSResolverPreresolvedIPAddressProbability != nil {
  2029. applyParameters[parameters.DNSResolverPreresolvedIPAddressProbability] = *config.DNSResolverPreresolvedIPAddressProbability
  2030. }
  2031. if config.DNSResolverPreresolvedIPAddressCIDRs != nil {
  2032. applyParameters[parameters.DNSResolverPreresolvedIPAddressCIDRs] = config.DNSResolverPreresolvedIPAddressCIDRs
  2033. }
  2034. if config.DNSResolverAlternateServers != nil {
  2035. applyParameters[parameters.DNSResolverAlternateServers] = config.DNSResolverAlternateServers
  2036. }
  2037. if config.DNSResolverPreferredAlternateServers != nil {
  2038. applyParameters[parameters.DNSResolverPreferredAlternateServers] = config.DNSResolverPreferredAlternateServers
  2039. }
  2040. if config.DNSResolverPreferAlternateServerProbability != nil {
  2041. applyParameters[parameters.DNSResolverPreferAlternateServerProbability] = *config.DNSResolverPreferAlternateServerProbability
  2042. }
  2043. if config.DNSResolverProtocolTransformSpecs != nil {
  2044. applyParameters[parameters.DNSResolverProtocolTransformSpecs] = config.DNSResolverProtocolTransformSpecs
  2045. }
  2046. if config.DNSResolverProtocolTransformScopedSpecNames != nil {
  2047. applyParameters[parameters.DNSResolverProtocolTransformScopedSpecNames] = config.DNSResolverProtocolTransformScopedSpecNames
  2048. }
  2049. if config.DNSResolverProtocolTransformProbability != nil {
  2050. applyParameters[parameters.DNSResolverProtocolTransformProbability] = *config.DNSResolverProtocolTransformProbability
  2051. }
  2052. if config.DNSResolverQNameRandomizeCasingProbability != nil {
  2053. applyParameters[parameters.DNSResolverQNameRandomizeCasingProbability] = *config.DNSResolverQNameRandomizeCasingProbability
  2054. }
  2055. if config.DNSResolverQNameMustMatchProbability != nil {
  2056. applyParameters[parameters.DNSResolverQNameMustMatchProbability] = *config.DNSResolverQNameMustMatchProbability
  2057. }
  2058. if config.DNSResolverIncludeEDNS0Probability != nil {
  2059. applyParameters[parameters.DNSResolverIncludeEDNS0Probability] = *config.DNSResolverIncludeEDNS0Probability
  2060. }
  2061. if config.DNSResolverCacheExtensionInitialTTLMilliseconds != nil {
  2062. applyParameters[parameters.DNSResolverCacheExtensionInitialTTL] = fmt.Sprintf("%dms", *config.DNSResolverCacheExtensionInitialTTLMilliseconds)
  2063. }
  2064. if config.DNSResolverCacheExtensionVerifiedTTLMilliseconds != nil {
  2065. applyParameters[parameters.DNSResolverCacheExtensionVerifiedTTL] = fmt.Sprintf("%dms", *config.DNSResolverCacheExtensionVerifiedTTLMilliseconds)
  2066. }
  2067. if config.DirectHTTPProtocolTransformSpecs != nil {
  2068. applyParameters[parameters.DirectHTTPProtocolTransformSpecs] = config.DirectHTTPProtocolTransformSpecs
  2069. }
  2070. if config.DirectHTTPProtocolTransformScopedSpecNames != nil {
  2071. applyParameters[parameters.DirectHTTPProtocolTransformScopedSpecNames] = config.DirectHTTPProtocolTransformScopedSpecNames
  2072. }
  2073. if config.DirectHTTPProtocolTransformProbability != nil {
  2074. applyParameters[parameters.DirectHTTPProtocolTransformProbability] = *config.DirectHTTPProtocolTransformProbability
  2075. }
  2076. if config.FrontedHTTPProtocolTransformSpecs != nil {
  2077. applyParameters[parameters.FrontedHTTPProtocolTransformSpecs] = config.FrontedHTTPProtocolTransformSpecs
  2078. }
  2079. if config.FrontedHTTPProtocolTransformScopedSpecNames != nil {
  2080. applyParameters[parameters.FrontedHTTPProtocolTransformScopedSpecNames] = config.FrontedHTTPProtocolTransformScopedSpecNames
  2081. }
  2082. if config.FrontedHTTPProtocolTransformProbability != nil {
  2083. applyParameters[parameters.FrontedHTTPProtocolTransformProbability] = *config.FrontedHTTPProtocolTransformProbability
  2084. }
  2085. if config.OSSHObfuscatorSeedTransformSpecs != nil {
  2086. applyParameters[parameters.OSSHObfuscatorSeedTransformSpecs] = config.OSSHObfuscatorSeedTransformSpecs
  2087. }
  2088. if config.OSSHObfuscatorSeedTransformScopedSpecNames != nil {
  2089. applyParameters[parameters.OSSHObfuscatorSeedTransformScopedSpecNames] = config.OSSHObfuscatorSeedTransformScopedSpecNames
  2090. }
  2091. if config.OSSHObfuscatorSeedTransformProbability != nil {
  2092. applyParameters[parameters.OSSHObfuscatorSeedTransformProbability] = *config.OSSHObfuscatorSeedTransformProbability
  2093. }
  2094. if config.ObfuscatedQUICNonceTransformSpecs != nil {
  2095. applyParameters[parameters.ObfuscatedQUICNonceTransformSpecs] = config.ObfuscatedQUICNonceTransformSpecs
  2096. }
  2097. if config.ObfuscatedQUICNonceTransformScopedSpecNames != nil {
  2098. applyParameters[parameters.ObfuscatedQUICNonceTransformScopedSpecNames] = config.ObfuscatedQUICNonceTransformScopedSpecNames
  2099. }
  2100. if config.ObfuscatedQUICNonceTransformProbability != nil {
  2101. applyParameters[parameters.ObfuscatedQUICNonceTransformProbability] = *config.ObfuscatedQUICNonceTransformProbability
  2102. }
  2103. if config.OSSHPrefixSpecs != nil {
  2104. applyParameters[parameters.OSSHPrefixSpecs] = config.OSSHPrefixSpecs
  2105. }
  2106. if config.OSSHPrefixScopedSpecNames != nil {
  2107. applyParameters[parameters.OSSHPrefixScopedSpecNames] = config.OSSHPrefixScopedSpecNames
  2108. }
  2109. if config.OSSHPrefixProbability != nil {
  2110. applyParameters[parameters.OSSHPrefixProbability] = *config.OSSHPrefixProbability
  2111. }
  2112. if config.OSSHPrefixSplitMinDelayMilliseconds != nil {
  2113. applyParameters[parameters.OSSHPrefixSplitMinDelay] = fmt.Sprintf("%dms", *config.OSSHPrefixSplitMinDelayMilliseconds)
  2114. }
  2115. if config.OSSHPrefixSplitMaxDelayMilliseconds != nil {
  2116. applyParameters[parameters.OSSHPrefixSplitMaxDelay] = fmt.Sprintf("%dms", *config.OSSHPrefixSplitMaxDelayMilliseconds)
  2117. }
  2118. if config.OSSHPrefixEnableFragmentor != nil {
  2119. applyParameters[parameters.OSSHPrefixEnableFragmentor] = *config.OSSHPrefixEnableFragmentor
  2120. }
  2121. if config.ShadowsocksPrefixSpecs != nil {
  2122. applyParameters[parameters.ShadowsocksPrefixSpecs] = config.ShadowsocksPrefixSpecs
  2123. }
  2124. if config.ShadowsocksPrefixScopedSpecNames != nil {
  2125. applyParameters[parameters.ShadowsocksPrefixScopedSpecNames] = config.ShadowsocksPrefixScopedSpecNames
  2126. }
  2127. if config.ShadowsocksPrefixProbability != nil {
  2128. applyParameters[parameters.ShadowsocksPrefixProbability] = *config.ShadowsocksPrefixProbability
  2129. }
  2130. if config.TLSTunnelObfuscatedPSKProbability != nil {
  2131. applyParameters[parameters.TLSTunnelObfuscatedPSKProbability] = *config.TLSTunnelObfuscatedPSKProbability
  2132. }
  2133. if config.TLSTunnelTrafficShapingProbability != nil {
  2134. applyParameters[parameters.TLSTunnelTrafficShapingProbability] = *config.TLSTunnelTrafficShapingProbability
  2135. }
  2136. if config.TLSTunnelMinTLSPadding != nil {
  2137. applyParameters[parameters.TLSTunnelMinTLSPadding] = *config.TLSTunnelMinTLSPadding
  2138. }
  2139. if config.TLSTunnelMaxTLSPadding != nil {
  2140. applyParameters[parameters.TLSTunnelMaxTLSPadding] = *config.TLSTunnelMaxTLSPadding
  2141. }
  2142. if config.TLSFragmentClientHelloProbability != nil {
  2143. applyParameters[parameters.TLSFragmentClientHelloProbability] = *config.TLSFragmentClientHelloProbability
  2144. }
  2145. if len(config.TLSFragmentClientHelloLimitProtocols) > 0 {
  2146. applyParameters[parameters.TLSFragmentClientHelloLimitProtocols] = protocol.TunnelProtocols(config.TLSFragmentClientHelloLimitProtocols)
  2147. }
  2148. if config.SteeringIPCacheTTLSeconds != nil {
  2149. applyParameters[parameters.SteeringIPCacheTTL] = fmt.Sprintf("%ds", *config.SteeringIPCacheTTLSeconds)
  2150. }
  2151. if config.SteeringIPCacheMaxEntries != nil {
  2152. applyParameters[parameters.SteeringIPCacheMaxEntries] = *config.SteeringIPCacheMaxEntries
  2153. }
  2154. if config.SteeringIPProbability != nil {
  2155. applyParameters[parameters.SteeringIPProbability] = *config.SteeringIPProbability
  2156. }
  2157. if config.FrontedHTTPClientReplayDialParametersTTLSeconds != nil {
  2158. applyParameters[parameters.FrontedHTTPClientReplayDialParametersTTL] = fmt.Sprintf("%ds", *config.FrontedHTTPClientReplayDialParametersTTLSeconds)
  2159. }
  2160. if config.FrontedHTTPClientReplayUpdateFrequencySeconds != nil {
  2161. applyParameters[parameters.FrontedHTTPClientReplayUpdateFrequency] = fmt.Sprintf("%ds", *config.FrontedHTTPClientReplayUpdateFrequencySeconds)
  2162. }
  2163. if config.FrontedHTTPClientReplayDialParametersProbability != nil {
  2164. applyParameters[parameters.FrontedHTTPClientReplayDialParametersProbability] = *config.FrontedHTTPClientReplayDialParametersProbability
  2165. }
  2166. if config.FrontedHTTPClientReplayRetainFailedProbability != nil {
  2167. applyParameters[parameters.FrontedHTTPClientReplayRetainFailedProbability] = *config.FrontedHTTPClientReplayRetainFailedProbability
  2168. }
  2169. if config.InproxyPersonalPairingConnectionWorkerPoolSize != 0 {
  2170. applyParameters[parameters.InproxyPersonalPairingConnectionWorkerPoolSize] = config.InproxyPersonalPairingConnectionWorkerPoolSize
  2171. }
  2172. if config.InproxyAllowProxy != nil {
  2173. applyParameters[parameters.InproxyAllowProxy] = *config.InproxyAllowProxy
  2174. }
  2175. if config.InproxyAllowClient != nil {
  2176. applyParameters[parameters.InproxyAllowClient] = *config.InproxyAllowClient
  2177. }
  2178. if config.InproxyTunnelProtocolSelectionProbability != nil {
  2179. applyParameters[parameters.InproxyTunnelProtocolSelectionProbability] = *config.InproxyTunnelProtocolSelectionProbability
  2180. }
  2181. if len(config.InproxyBrokerSpecs) > 0 {
  2182. applyParameters[parameters.InproxyBrokerSpecs] = config.InproxyBrokerSpecs
  2183. }
  2184. if len(config.InproxyPersonalPairingBrokerSpecs) > 0 {
  2185. applyParameters[parameters.InproxyPersonalPairingBrokerSpecs] = config.InproxyPersonalPairingBrokerSpecs
  2186. }
  2187. if len(config.InproxyProxyBrokerSpecs) > 0 {
  2188. applyParameters[parameters.InproxyProxyBrokerSpecs] = config.InproxyProxyBrokerSpecs
  2189. }
  2190. if len(config.InproxyProxyPersonalPairingBrokerSpecs) > 0 {
  2191. applyParameters[parameters.InproxyProxyPersonalPairingBrokerSpecs] = config.InproxyProxyPersonalPairingBrokerSpecs
  2192. }
  2193. if len(config.InproxyClientBrokerSpecs) > 0 {
  2194. applyParameters[parameters.InproxyClientBrokerSpecs] = config.InproxyClientBrokerSpecs
  2195. }
  2196. if len(config.InproxyClientPersonalPairingBrokerSpecs) > 0 {
  2197. applyParameters[parameters.InproxyClientPersonalPairingBrokerSpecs] = config.InproxyClientPersonalPairingBrokerSpecs
  2198. }
  2199. if config.InproxyReplayBrokerDialParametersTTLSeconds != nil {
  2200. applyParameters[parameters.InproxyReplayBrokerDialParametersTTL] = fmt.Sprintf("%ds", *config.InproxyReplayBrokerDialParametersTTLSeconds)
  2201. }
  2202. if config.InproxyReplayBrokerUpdateFrequencySeconds != nil {
  2203. applyParameters[parameters.InproxyReplayBrokerUpdateFrequency] = fmt.Sprintf("%ds", *config.InproxyReplayBrokerUpdateFrequencySeconds)
  2204. }
  2205. if config.InproxyReplayBrokerDialParametersProbability != nil {
  2206. applyParameters[parameters.InproxyReplayBrokerDialParametersProbability] = *config.InproxyReplayBrokerDialParametersProbability
  2207. }
  2208. if config.InproxyReplayBrokerRetainFailedProbability != nil {
  2209. applyParameters[parameters.InproxyReplayBrokerRetainFailedProbability] = *config.InproxyReplayBrokerRetainFailedProbability
  2210. }
  2211. if len(config.InproxyCommonCompartmentIDs) > 0 {
  2212. applyParameters[parameters.InproxyCommonCompartmentIDs] = config.InproxyCommonCompartmentIDs
  2213. }
  2214. if config.InproxyMaxCompartmentIDListLength != nil {
  2215. applyParameters[parameters.InproxyMaxCompartmentIDListLength] = *config.InproxyMaxCompartmentIDListLength
  2216. }
  2217. if config.InproxyProxyAnnounceRequestTimeoutMilliseconds != nil {
  2218. applyParameters[parameters.InproxyProxyAnnounceRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyAnnounceRequestTimeoutMilliseconds)
  2219. }
  2220. if config.InproxyProxyAnnounceDelayMilliseconds != nil {
  2221. applyParameters[parameters.InproxyProxyAnnounceDelay] = fmt.Sprintf("%dms", *config.InproxyProxyAnnounceDelayMilliseconds)
  2222. }
  2223. if config.InproxyProxyAnnounceMaxBackoffDelayMilliseconds != nil {
  2224. applyParameters[parameters.InproxyProxyAnnounceMaxBackoffDelay] = fmt.Sprintf("%dms", *config.InproxyProxyAnnounceMaxBackoffDelayMilliseconds)
  2225. }
  2226. if config.InproxyProxyAnnounceDelayJitter != nil {
  2227. applyParameters[parameters.InproxyProxyAnnounceDelayJitter] = *config.InproxyProxyAnnounceDelayJitter
  2228. }
  2229. if config.InproxyProxyAnswerRequestTimeoutMilliseconds != nil {
  2230. applyParameters[parameters.InproxyProxyAnswerRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyAnswerRequestTimeoutMilliseconds)
  2231. }
  2232. if config.InproxyClientOfferRequestTimeoutMilliseconds != nil {
  2233. applyParameters[parameters.InproxyClientOfferRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyClientOfferRequestTimeoutMilliseconds)
  2234. }
  2235. if config.InproxyClientOfferRequestPersonalTimeoutMilliseconds != nil {
  2236. applyParameters[parameters.InproxyClientOfferRequestPersonalTimeout] = fmt.Sprintf("%dms", *config.InproxyClientOfferRequestPersonalTimeoutMilliseconds)
  2237. }
  2238. if config.InproxyClientOfferRetryDelayMilliseconds != nil {
  2239. applyParameters[parameters.InproxyClientOfferRetryDelay] = fmt.Sprintf("%dms", *config.InproxyClientOfferRetryDelayMilliseconds)
  2240. }
  2241. if config.InproxyClientOfferRetryJitter != nil {
  2242. applyParameters[parameters.InproxyClientOfferRetryJitter] = *config.InproxyClientOfferRetryJitter
  2243. }
  2244. if config.InproxyClientRelayedPacketRequestTimeoutMilliseconds != nil {
  2245. applyParameters[parameters.InproxyClientRelayedPacketRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyClientRelayedPacketRequestTimeoutMilliseconds)
  2246. }
  2247. if config.InproxyDTLSRandomizationProbability != nil {
  2248. applyParameters[parameters.InproxyDTLSRandomizationProbability] = *config.InproxyDTLSRandomizationProbability
  2249. }
  2250. if config.InproxyWebRTCMediaStreamsProbability != nil {
  2251. applyParameters[parameters.InproxyWebRTCMediaStreamsProbability] = *config.InproxyWebRTCMediaStreamsProbability
  2252. }
  2253. if config.InproxyWebRTCDataChannelTrafficShapingProbability != nil {
  2254. applyParameters[parameters.InproxyWebRTCDataChannelTrafficShapingProbability] = *config.InproxyWebRTCDataChannelTrafficShapingProbability
  2255. }
  2256. if config.InproxyWebRTCDataChannelTrafficShapingParameters != nil {
  2257. applyParameters[parameters.InproxyWebRTCDataChannelTrafficShapingParameters] = *config.InproxyWebRTCDataChannelTrafficShapingParameters
  2258. }
  2259. if config.InproxyWebRTCMediaStreamsTrafficShapingProbability != nil {
  2260. applyParameters[parameters.InproxyWebRTCMediaStreamsTrafficShapingProbability] = *config.InproxyWebRTCMediaStreamsTrafficShapingProbability
  2261. }
  2262. if config.InproxyWebRTCMediaStreamsTrafficShapingParameters != nil {
  2263. applyParameters[parameters.InproxyWebRTCMediaStreamsTrafficShapingParameters] = *config.InproxyWebRTCMediaStreamsTrafficShapingParameters
  2264. }
  2265. if len(config.InproxySTUNServerAddresses) > 0 {
  2266. applyParameters[parameters.InproxySTUNServerAddresses] = config.InproxySTUNServerAddresses
  2267. }
  2268. if len(config.InproxySTUNServerAddressesRFC5780) > 0 {
  2269. applyParameters[parameters.InproxySTUNServerAddressesRFC5780] = config.InproxySTUNServerAddressesRFC5780
  2270. }
  2271. if len(config.InproxyProxySTUNServerAddresses) > 0 {
  2272. applyParameters[parameters.InproxyProxySTUNServerAddresses] = config.InproxyProxySTUNServerAddresses
  2273. }
  2274. if len(config.InproxyProxySTUNServerAddressesRFC5780) > 0 {
  2275. applyParameters[parameters.InproxyProxySTUNServerAddressesRFC5780] = config.InproxyProxySTUNServerAddressesRFC5780
  2276. }
  2277. if len(config.InproxyClientSTUNServerAddresses) > 0 {
  2278. applyParameters[parameters.InproxyClientSTUNServerAddresses] = config.InproxyClientSTUNServerAddresses
  2279. }
  2280. if len(config.InproxyClientSTUNServerAddressesRFC5780) > 0 {
  2281. applyParameters[parameters.InproxyClientSTUNServerAddressesRFC5780] = config.InproxyClientSTUNServerAddressesRFC5780
  2282. }
  2283. if config.InproxyClientDiscoverNATProbability != nil {
  2284. applyParameters[parameters.InproxyClientDiscoverNATProbability] = *config.InproxyClientDiscoverNATProbability
  2285. }
  2286. if config.InproxyDisableSTUN != nil {
  2287. applyParameters[parameters.InproxyDisableSTUN] = *config.InproxyDisableSTUN
  2288. }
  2289. if config.InproxyDisablePortMapping != nil {
  2290. applyParameters[parameters.InproxyDisablePortMapping] = *config.InproxyDisablePortMapping
  2291. }
  2292. if config.InproxyDisableInboundForMobileNetworks != nil {
  2293. applyParameters[parameters.InproxyDisableInboundForMobileNetworks] = *config.InproxyDisableInboundForMobileNetworks
  2294. }
  2295. if config.InproxyDisableIPv6ICECandidates != nil {
  2296. applyParameters[parameters.InproxyDisableIPv6ICECandidates] = *config.InproxyDisableIPv6ICECandidates
  2297. }
  2298. if config.InproxyProxyDisableSTUN != nil {
  2299. applyParameters[parameters.InproxyProxyDisableSTUN] = *config.InproxyProxyDisableSTUN
  2300. }
  2301. if config.InproxyProxyDisablePortMapping != nil {
  2302. applyParameters[parameters.InproxyProxyDisablePortMapping] = *config.InproxyProxyDisablePortMapping
  2303. }
  2304. if config.InproxyProxyDisableInboundForMobileNetworks != nil {
  2305. applyParameters[parameters.InproxyProxyDisableInboundForMobileNetworks] = *config.InproxyProxyDisableInboundForMobileNetworks
  2306. }
  2307. if config.InproxyProxyDisableIPv6ICECandidates != nil {
  2308. applyParameters[parameters.InproxyProxyDisableIPv6ICECandidates] = *config.InproxyProxyDisableIPv6ICECandidates
  2309. }
  2310. if config.InproxyClientDisableSTUN != nil {
  2311. applyParameters[parameters.InproxyClientDisableSTUN] = *config.InproxyClientDisableSTUN
  2312. }
  2313. if config.InproxyClientDisablePortMapping != nil {
  2314. applyParameters[parameters.InproxyClientDisablePortMapping] = *config.InproxyClientDisablePortMapping
  2315. }
  2316. if config.InproxyClientDisableInboundForMobileNetworks != nil {
  2317. applyParameters[parameters.InproxyClientDisableInboundForMobileNetworks] = *config.InproxyClientDisableInboundForMobileNetworks
  2318. }
  2319. if config.InproxyClientDisableIPv6ICECandidates != nil {
  2320. applyParameters[parameters.InproxyClientDisableIPv6ICECandidates] = *config.InproxyClientDisableIPv6ICECandidates
  2321. }
  2322. if config.InproxyProxyDiscoverNATTimeoutMilliseconds != nil {
  2323. applyParameters[parameters.InproxyProxyDiscoverNATTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyDiscoverNATTimeoutMilliseconds)
  2324. }
  2325. if config.InproxyClientDiscoverNATTimeoutMilliseconds != nil {
  2326. applyParameters[parameters.InproxyClientDiscoverNATTimeout] = fmt.Sprintf("%dms", *config.InproxyClientDiscoverNATTimeoutMilliseconds)
  2327. }
  2328. if config.InproxyWebRTCAnswerTimeoutMilliseconds != nil {
  2329. applyParameters[parameters.InproxyWebRTCAnswerTimeout] = fmt.Sprintf("%dms", *config.InproxyWebRTCAnswerTimeoutMilliseconds)
  2330. }
  2331. if config.InproxyProxyWebRTCAwaitReadyToProxyTimeoutMilliseconds != nil {
  2332. applyParameters[parameters.InproxyProxyWebRTCAwaitReadyToProxyTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyWebRTCAwaitReadyToProxyTimeoutMilliseconds)
  2333. }
  2334. if config.InproxyClientWebRTCAwaitReadyToProxyTimeoutMilliseconds != nil {
  2335. applyParameters[parameters.InproxyClientWebRTCAwaitReadyToProxyTimeout] = fmt.Sprintf("%dms", *config.InproxyClientWebRTCAwaitReadyToProxyTimeoutMilliseconds)
  2336. }
  2337. if config.InproxyProxyDestinationDialTimeoutMilliseconds != nil {
  2338. applyParameters[parameters.InproxyProxyDestinationDialTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyDestinationDialTimeoutMilliseconds)
  2339. }
  2340. if config.InproxyPsiphonAPIRequestTimeoutMilliseconds != nil {
  2341. applyParameters[parameters.InproxyPsiphonAPIRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyPsiphonAPIRequestTimeoutMilliseconds)
  2342. }
  2343. if config.InproxyProxyTotalActivityNoticePeriodMilliseconds != nil {
  2344. applyParameters[parameters.InproxyProxyTotalActivityNoticePeriod] = fmt.Sprintf("%dms", *config.InproxyProxyTotalActivityNoticePeriodMilliseconds)
  2345. }
  2346. if config.InproxyClientDialRateLimitQuantity != nil {
  2347. applyParameters[parameters.InproxyClientDialRateLimitQuantity] = *config.InproxyClientDialRateLimitQuantity
  2348. }
  2349. if config.InproxyClientDialRateLimitIntervalMilliseconds != nil {
  2350. applyParameters[parameters.InproxyClientDialRateLimitInterval] = fmt.Sprintf("%dms", *config.InproxyClientDialRateLimitIntervalMilliseconds)
  2351. }
  2352. if config.InproxyClientNoMatchFailoverProbability != nil {
  2353. applyParameters[parameters.InproxyClientNoMatchFailoverProbability] = *config.InproxyClientNoMatchFailoverProbability
  2354. }
  2355. if config.InproxyClientNoMatchFailoverPersonalProbability != nil {
  2356. applyParameters[parameters.InproxyClientNoMatchFailoverPersonalProbability] = *config.InproxyClientNoMatchFailoverPersonalProbability
  2357. }
  2358. if config.InproxyFrontingProviderClientMaxRequestTimeouts != nil {
  2359. applyParameters[parameters.InproxyFrontingProviderClientMaxRequestTimeouts] = config.InproxyFrontingProviderClientMaxRequestTimeouts
  2360. }
  2361. if config.InproxyProxyOnBrokerClientFailedRetryPeriodMilliseconds != nil {
  2362. applyParameters[parameters.InproxyProxyOnBrokerClientFailedRetryPeriod] = fmt.Sprintf("%dms", *config.InproxyProxyOnBrokerClientFailedRetryPeriodMilliseconds)
  2363. }
  2364. if len(config.InproxyProxyIncompatibleNetworkTypes) > 0 {
  2365. applyParameters[parameters.InproxyProxyIncompatibleNetworkTypes] = config.InproxyProxyIncompatibleNetworkTypes
  2366. }
  2367. if len(config.InproxyClientIncompatibleNetworkTypes) > 0 {
  2368. applyParameters[parameters.InproxyClientIncompatibleNetworkTypes] = config.InproxyClientIncompatibleNetworkTypes
  2369. }
  2370. if config.InproxyReplayRetainFailedProbability != nil {
  2371. applyParameters[parameters.InproxyReplayRetainFailedProbability] = *config.InproxyReplayRetainFailedProbability
  2372. }
  2373. if config.InproxyProxyDisableWaitToShareSession != nil {
  2374. applyParameters[parameters.InproxyProxyDisableWaitToShareSession] = *config.InproxyProxyDisableWaitToShareSession
  2375. }
  2376. if config.InproxyClientDisableWaitToShareSession != nil {
  2377. applyParameters[parameters.InproxyClientDisableWaitToShareSession] = *config.InproxyClientDisableWaitToShareSession
  2378. }
  2379. if config.InproxyTunnelProtocolPreferProbability != nil {
  2380. applyParameters[parameters.InproxyTunnelProtocolPreferProbability] = *config.InproxyTunnelProtocolPreferProbability
  2381. }
  2382. if config.InproxyTunnelProtocolForceSelectionCount != nil {
  2383. applyParameters[parameters.InproxyTunnelProtocolForceSelectionCount] = *config.InproxyTunnelProtocolForceSelectionCount
  2384. }
  2385. if config.NetworkIDCacheTTLMilliseconds != nil {
  2386. applyParameters[parameters.NetworkIDCacheTTL] = fmt.Sprintf("%dms", *config.NetworkIDCacheTTLMilliseconds)
  2387. }
  2388. if config.CompressTactics != nil {
  2389. applyParameters[parameters.CompressTactics] = *config.CompressTactics
  2390. }
  2391. if config.EnableDSLFetcher != nil {
  2392. applyParameters[parameters.EnableDSLFetcher] = *config.EnableDSLFetcher
  2393. }
  2394. if config.DSLPrioritizeDialNewServerEntryProbability != nil {
  2395. applyParameters[parameters.DSLPrioritizeDialNewServerEntryProbability] = *config.DSLPrioritizeDialNewServerEntryProbability
  2396. }
  2397. if config.DSLPrioritizeDialExistingServerEntryProbability != nil {
  2398. applyParameters[parameters.DSLPrioritizeDialExistingServerEntryProbability] = *config.DSLPrioritizeDialExistingServerEntryProbability
  2399. }
  2400. if config.DSLPrioritizeDialRetainFailedProbability != nil {
  2401. applyParameters[parameters.DSLPrioritizeDialRetainFailedProbability] = *config.DSLPrioritizeDialRetainFailedProbability
  2402. }
  2403. if config.DSLPrioritizeDialPlaceholderTTLSeconds != nil {
  2404. applyParameters[parameters.DSLPrioritizeDialPlaceholderTTL] = fmt.Sprintf("%ds", *config.DSLPrioritizeDialPlaceholderTTLSeconds)
  2405. }
  2406. if config.ServerEntryIteratorMaxMoveToFront != nil {
  2407. applyParameters[parameters.ServerEntryIteratorResetProbability] = *config.ServerEntryIteratorResetProbability
  2408. }
  2409. if config.EnableDSLFetcher != nil {
  2410. applyParameters[parameters.EnableDSLFetcher] = *config.EnableDSLFetcher
  2411. }
  2412. // When adding new config dial parameters that may override tactics, also
  2413. // update setDialParametersHash.
  2414. return applyParameters
  2415. }
  2416. func (config *Config) setDialParametersHash() {
  2417. // Calculate and store a hash of the config values that may impact
  2418. // dial parameters. This hash is used as part of the dial parameters
  2419. // replay mechanism to detect when persisted dial parameters should
  2420. // be discarded due to conflicting config changes.
  2421. //
  2422. // With a couple of minor exceptions, configuring dial parameters via the
  2423. // config is intended for testing only, and so these parameters are expected
  2424. // to be present in test runs only. It remains an important case to discard
  2425. // replay dial parameters when test config parameters are varied.
  2426. //
  2427. // Hashing the parameter names detects some ambiguous hash cases, such as two
  2428. // consecutive int64 parameters, one omitted and one not, that are flipped.
  2429. // The serialization is not completely unambiguous, and the format is
  2430. // currently limited by legacy cases (not invalidating replay dial parameters
  2431. // for production clients is more important than invalidating for test runs).
  2432. // We cannot hash the entire config JSON as it contains non-dial parameter
  2433. // fields which may frequently change across runs.
  2434. //
  2435. // MD5 hash is used solely as a data checksum and not for any security
  2436. // purpose.
  2437. hash := md5.New()
  2438. if len(config.LimitTunnelProtocols) > 0 {
  2439. hash.Write([]byte("LimitTunnelProtocols"))
  2440. for _, protocol := range config.LimitTunnelProtocols {
  2441. hash.Write([]byte(protocol))
  2442. }
  2443. }
  2444. if len(config.InitialLimitTunnelProtocols) > 0 && config.InitialLimitTunnelProtocolsCandidateCount > 0 {
  2445. hash.Write([]byte("InitialLimitTunnelProtocols"))
  2446. for _, protocol := range config.InitialLimitTunnelProtocols {
  2447. hash.Write([]byte(protocol))
  2448. }
  2449. binary.Write(hash, binary.LittleEndian, int64(config.InitialLimitTunnelProtocolsCandidateCount))
  2450. }
  2451. if len(config.LimitTLSProfiles) > 0 {
  2452. hash.Write([]byte("LimitTLSProfiles"))
  2453. for _, profile := range config.LimitTLSProfiles {
  2454. hash.Write([]byte(profile))
  2455. }
  2456. }
  2457. if len(config.LimitQUICVersions) > 0 {
  2458. hash.Write([]byte("LimitQUICVersions"))
  2459. for _, version := range config.LimitQUICVersions {
  2460. hash.Write([]byte(version))
  2461. }
  2462. }
  2463. // Whether a custom User-Agent is specified is a binary flag: when not set,
  2464. // the replay dial parameters value applies. When set, external
  2465. // considerations apply.
  2466. if _, ok := config.CustomHeaders["User-Agent"]; ok {
  2467. hash.Write([]byte("CustomHeaders User-Agent"))
  2468. hash.Write([]byte{1})
  2469. }
  2470. if config.UpstreamProxyURL != "" {
  2471. hash.Write([]byte("UpstreamProxyURL"))
  2472. hash.Write([]byte(config.UpstreamProxyURL))
  2473. }
  2474. if config.TransformHostNameProbability != nil {
  2475. hash.Write([]byte("TransformHostNameProbability"))
  2476. binary.Write(hash, binary.LittleEndian, *config.TransformHostNameProbability)
  2477. }
  2478. if config.FragmentorProbability != nil {
  2479. hash.Write([]byte("FragmentorProbability"))
  2480. binary.Write(hash, binary.LittleEndian, *config.FragmentorProbability)
  2481. }
  2482. if len(config.FragmentorLimitProtocols) > 0 {
  2483. hash.Write([]byte("FragmentorLimitProtocols"))
  2484. for _, protocol := range config.FragmentorLimitProtocols {
  2485. hash.Write([]byte(protocol))
  2486. }
  2487. }
  2488. if config.FragmentorMinTotalBytes != nil {
  2489. hash.Write([]byte("FragmentorMinTotalBytes"))
  2490. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinTotalBytes))
  2491. }
  2492. if config.FragmentorMaxTotalBytes != nil {
  2493. hash.Write([]byte("FragmentorMaxTotalBytes"))
  2494. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxTotalBytes))
  2495. }
  2496. if config.FragmentorMinWriteBytes != nil {
  2497. hash.Write([]byte("FragmentorMinWriteBytes"))
  2498. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinWriteBytes))
  2499. }
  2500. if config.FragmentorMaxWriteBytes != nil {
  2501. hash.Write([]byte("FragmentorMaxWriteBytes"))
  2502. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxWriteBytes))
  2503. }
  2504. if config.FragmentorMinDelayMicroseconds != nil {
  2505. hash.Write([]byte("FragmentorMinDelayMicroseconds"))
  2506. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinDelayMicroseconds))
  2507. }
  2508. if config.FragmentorMaxDelayMicroseconds != nil {
  2509. hash.Write([]byte("FragmentorMaxDelayMicroseconds"))
  2510. binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxDelayMicroseconds))
  2511. }
  2512. if config.MeekTrafficShapingProbability != nil {
  2513. hash.Write([]byte("MeekTrafficShapingProbability"))
  2514. binary.Write(hash, binary.LittleEndian, *config.MeekTrafficShapingProbability)
  2515. }
  2516. if len(config.MeekTrafficShapingLimitProtocols) > 0 {
  2517. hash.Write([]byte("MeekTrafficShapingLimitProtocols"))
  2518. for _, protocol := range config.MeekTrafficShapingLimitProtocols {
  2519. hash.Write([]byte(protocol))
  2520. }
  2521. }
  2522. if config.MeekMinLimitRequestPayloadLength != nil {
  2523. hash.Write([]byte("MeekMinLimitRequestPayloadLength"))
  2524. binary.Write(hash, binary.LittleEndian, int64(*config.MeekMinLimitRequestPayloadLength))
  2525. }
  2526. if config.MeekMaxLimitRequestPayloadLength != nil {
  2527. hash.Write([]byte("MeekMaxLimitRequestPayloadLength"))
  2528. binary.Write(hash, binary.LittleEndian, int64(*config.MeekMaxLimitRequestPayloadLength))
  2529. }
  2530. if config.MeekRedialTLSProbability != nil {
  2531. hash.Write([]byte("MeekRedialTLSProbability"))
  2532. binary.Write(hash, binary.LittleEndian, *config.MeekRedialTLSProbability)
  2533. }
  2534. if config.ObfuscatedSSHMinPadding != nil {
  2535. hash.Write([]byte("ObfuscatedSSHMinPadding"))
  2536. binary.Write(hash, binary.LittleEndian, int64(*config.ObfuscatedSSHMinPadding))
  2537. }
  2538. if config.ObfuscatedSSHMaxPadding != nil {
  2539. hash.Write([]byte("ObfuscatedSSHMaxPadding"))
  2540. binary.Write(hash, binary.LittleEndian, int64(*config.ObfuscatedSSHMaxPadding))
  2541. }
  2542. if config.LivenessTestMinUpstreamBytes != nil {
  2543. hash.Write([]byte("LivenessTestMinUpstreamBytes"))
  2544. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMinUpstreamBytes))
  2545. }
  2546. if config.LivenessTestMaxUpstreamBytes != nil {
  2547. hash.Write([]byte("LivenessTestMaxUpstreamBytes"))
  2548. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMaxUpstreamBytes))
  2549. }
  2550. if config.LivenessTestMinDownstreamBytes != nil {
  2551. hash.Write([]byte("LivenessTestMinDownstreamBytes"))
  2552. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMinDownstreamBytes))
  2553. }
  2554. if config.LivenessTestMaxDownstreamBytes != nil {
  2555. hash.Write([]byte("LivenessTestMaxDownstreamBytes"))
  2556. binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMaxDownstreamBytes))
  2557. }
  2558. // Legacy case: these parameters are included in the hash unconditionally,
  2559. // and so will impact almost all production clients. These parameter names
  2560. // are not hashed since that would invalidate all replay dial parameters for
  2561. // existing clients whose hashes predate the inclusion of parameter names.
  2562. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierMin)
  2563. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierMax)
  2564. binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierLambda)
  2565. if config.UseOnlyCustomTLSProfiles != nil {
  2566. hash.Write([]byte("UseOnlyCustomTLSProfiles"))
  2567. binary.Write(hash, binary.LittleEndian, *config.UseOnlyCustomTLSProfiles)
  2568. }
  2569. if len(config.CustomTLSProfiles) > 0 {
  2570. hash.Write([]byte("CustomTLSProfiles"))
  2571. for _, customTLSProfile := range config.CustomTLSProfiles {
  2572. encodedCustomTLSProofile, _ := json.Marshal(customTLSProfile)
  2573. hash.Write(encodedCustomTLSProofile)
  2574. }
  2575. }
  2576. if config.SelectRandomizedTLSProfileProbability != nil {
  2577. hash.Write([]byte("SelectRandomizedTLSProfileProbability"))
  2578. binary.Write(hash, binary.LittleEndian, *config.SelectRandomizedTLSProfileProbability)
  2579. }
  2580. if config.NoDefaultTLSSessionIDProbability != nil {
  2581. hash.Write([]byte("NoDefaultTLSSessionIDProbability"))
  2582. binary.Write(hash, binary.LittleEndian, *config.NoDefaultTLSSessionIDProbability)
  2583. }
  2584. if len(config.DisableFrontingProviderTLSProfiles) > 0 {
  2585. hash.Write([]byte("DisableFrontingProviderTLSProfiles"))
  2586. encodedDisableFrontingProviderTLSProfiles, _ :=
  2587. json.Marshal(config.DisableFrontingProviderTLSProfiles)
  2588. hash.Write(encodedDisableFrontingProviderTLSProfiles)
  2589. }
  2590. if len(config.CustomHostNameRegexes) > 0 {
  2591. hash.Write([]byte("CustomHostNameRegexes"))
  2592. for _, customHostNameRegex := range config.CustomHostNameRegexes {
  2593. hash.Write([]byte(customHostNameRegex))
  2594. }
  2595. }
  2596. if config.CustomHostNameProbability != nil {
  2597. hash.Write([]byte("CustomHostNameProbability"))
  2598. binary.Write(hash, binary.LittleEndian, *config.CustomHostNameProbability)
  2599. }
  2600. if len(config.CustomHostNameLimitProtocols) > 0 {
  2601. hash.Write([]byte("CustomHostNameLimitProtocols"))
  2602. for _, protocol := range config.CustomHostNameLimitProtocols {
  2603. hash.Write([]byte(protocol))
  2604. }
  2605. }
  2606. if config.ConjureCachedRegistrationTTLSeconds != nil {
  2607. hash.Write([]byte("ConjureCachedRegistrationTTLSeconds"))
  2608. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureCachedRegistrationTTLSeconds))
  2609. }
  2610. if config.ConjureAPIRegistrarBidirectionalURL != "" {
  2611. hash.Write([]byte("ConjureAPIRegistrarBidirectionalURL"))
  2612. hash.Write([]byte(config.ConjureAPIRegistrarBidirectionalURL))
  2613. }
  2614. if len(config.ConjureAPIRegistrarFrontingSpecs) > 0 {
  2615. hash.Write([]byte("ConjureAPIRegistrarFrontingSpecs"))
  2616. for _, frontingSpec := range config.ConjureAPIRegistrarFrontingSpecs {
  2617. encodedFrontSpec, _ := json.Marshal(frontingSpec)
  2618. hash.Write(encodedFrontSpec)
  2619. }
  2620. }
  2621. if config.ConjureAPIRegistrarMinDelayMilliseconds != nil {
  2622. hash.Write([]byte("ConjureAPIRegistrarMinDelayMilliseconds"))
  2623. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureAPIRegistrarMinDelayMilliseconds))
  2624. }
  2625. if config.ConjureAPIRegistrarMaxDelayMilliseconds != nil {
  2626. hash.Write([]byte("ConjureAPIRegistrarMaxDelayMilliseconds"))
  2627. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureAPIRegistrarMaxDelayMilliseconds))
  2628. }
  2629. if config.ConjureDecoyRegistrarWidth != nil {
  2630. hash.Write([]byte("ConjureDecoyRegistrarWidth"))
  2631. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarWidth))
  2632. }
  2633. if config.ConjureDecoyRegistrarMinDelayMilliseconds != nil {
  2634. hash.Write([]byte("ConjureDecoyRegistrarMinDelayMilliseconds"))
  2635. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarMinDelayMilliseconds))
  2636. }
  2637. if config.ConjureDecoyRegistrarMaxDelayMilliseconds != nil {
  2638. hash.Write([]byte("ConjureDecoyRegistrarMaxDelayMilliseconds"))
  2639. binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarMaxDelayMilliseconds))
  2640. }
  2641. if config.ConjureLimitTransports != nil {
  2642. hash.Write([]byte("ConjureLimitTransports"))
  2643. for _, transport := range config.ConjureLimitTransports {
  2644. hash.Write([]byte(transport))
  2645. }
  2646. }
  2647. if config.ConjureSTUNServerAddresses != nil {
  2648. hash.Write([]byte("ConjureSTUNServerAddresses"))
  2649. for _, address := range config.ConjureSTUNServerAddresses {
  2650. hash.Write([]byte(address))
  2651. }
  2652. }
  2653. if config.HoldOffTunnelProtocolMinDurationMilliseconds != nil {
  2654. hash.Write([]byte("HoldOffTunnelProtocolMinDurationMilliseconds"))
  2655. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffTunnelProtocolMinDurationMilliseconds))
  2656. }
  2657. if config.HoldOffTunnelProtocolMaxDurationMilliseconds != nil {
  2658. hash.Write([]byte("HoldOffTunnelProtocolMaxDurationMilliseconds"))
  2659. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffTunnelProtocolMaxDurationMilliseconds))
  2660. }
  2661. if len(config.HoldOffTunnelProtocolNames) > 0 {
  2662. hash.Write([]byte("HoldOffTunnelProtocolNames"))
  2663. for _, protocol := range config.HoldOffTunnelProtocolNames {
  2664. hash.Write([]byte(protocol))
  2665. }
  2666. }
  2667. if config.HoldOffTunnelProtocolProbability != nil {
  2668. hash.Write([]byte("HoldOffTunnelProtocolProbability"))
  2669. binary.Write(hash, binary.LittleEndian, *config.HoldOffTunnelProtocolProbability)
  2670. }
  2671. if config.HoldOffFrontingTunnelMinDurationMilliseconds != nil {
  2672. hash.Write([]byte("HoldOffFrontingTunnelMinDurationMilliseconds"))
  2673. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffFrontingTunnelMinDurationMilliseconds))
  2674. }
  2675. if config.HoldOffFrontingTunnelMaxDurationMilliseconds != nil {
  2676. hash.Write([]byte("HoldOffFrontingTunnelMaxDurationMilliseconds"))
  2677. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffFrontingTunnelMaxDurationMilliseconds))
  2678. }
  2679. if len(config.HoldOffFrontingTunnelProviderIDs) > 0 {
  2680. hash.Write([]byte("HoldOffFrontingTunnelProviderIDs"))
  2681. for _, providerID := range config.HoldOffFrontingTunnelProviderIDs {
  2682. hash.Write([]byte(providerID))
  2683. }
  2684. }
  2685. if config.HoldOffFrontingTunnelProbability != nil {
  2686. hash.Write([]byte("HoldOffFrontingTunnelProbability"))
  2687. binary.Write(hash, binary.LittleEndian, *config.HoldOffFrontingTunnelProbability)
  2688. }
  2689. if config.HoldOffDirectTunnelProbability != nil {
  2690. hash.Write([]byte("HoldOffDirectTunnelProbability"))
  2691. binary.Write(hash, binary.LittleEndian, *config.HoldOffDirectTunnelProbability)
  2692. }
  2693. if config.HoldOffDirectTunnelMinDurationMilliseconds != nil {
  2694. hash.Write([]byte("HoldOffDirectTunnelMinDurationMilliseconds"))
  2695. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffDirectTunnelMinDurationMilliseconds))
  2696. }
  2697. if config.HoldOffDirectTunnelMaxDurationMilliseconds != nil {
  2698. hash.Write([]byte("HoldOffDirectTunnelMaxDurationMilliseconds"))
  2699. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffDirectTunnelMaxDurationMilliseconds))
  2700. }
  2701. if len(config.HoldOffDirectTunnelProviderRegions) > 0 {
  2702. hash.Write([]byte("HoldOffDirectTunnelProviderRegions"))
  2703. for providerID, regions := range config.HoldOffDirectTunnelProviderRegions {
  2704. hash.Write([]byte(providerID))
  2705. for _, region := range regions {
  2706. hash.Write([]byte(region))
  2707. }
  2708. }
  2709. }
  2710. if len(config.RestrictDirectProviderRegions) > 0 {
  2711. hash.Write([]byte("RestrictDirectProviderRegions"))
  2712. for providerID, regions := range config.RestrictDirectProviderRegions {
  2713. hash.Write([]byte(providerID))
  2714. for _, region := range regions {
  2715. hash.Write([]byte(region))
  2716. }
  2717. }
  2718. }
  2719. if config.RestrictDirectProviderIDsClientProbability != nil {
  2720. hash.Write([]byte("RestrictDirectProviderIDsClientProbability"))
  2721. binary.Write(hash, binary.LittleEndian, *config.RestrictDirectProviderIDsClientProbability)
  2722. }
  2723. if len(config.RestrictFrontingProviderIDs) > 0 {
  2724. hash.Write([]byte("RestrictFrontingProviderIDs"))
  2725. for _, providerID := range config.RestrictFrontingProviderIDs {
  2726. hash.Write([]byte(providerID))
  2727. }
  2728. }
  2729. if config.RestrictFrontingProviderIDsClientProbability != nil {
  2730. hash.Write([]byte("RestrictFrontingProviderIDsClientProbability"))
  2731. binary.Write(hash, binary.LittleEndian, *config.RestrictFrontingProviderIDsClientProbability)
  2732. }
  2733. if config.HoldOffInproxyTunnelProbability != nil {
  2734. hash.Write([]byte("HoldOffInproxyTunnelProbability"))
  2735. binary.Write(hash, binary.LittleEndian, *config.HoldOffInproxyTunnelProbability)
  2736. }
  2737. if config.HoldOffInproxyTunnelMinDurationMilliseconds != nil {
  2738. hash.Write([]byte("HoldOffInproxyTunnelMinDurationMilliseconds"))
  2739. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffInproxyTunnelMinDurationMilliseconds))
  2740. }
  2741. if config.HoldOffInproxyTunnelMaxDurationMilliseconds != nil {
  2742. hash.Write([]byte("HoldOffInproxyTunnelMaxDurationMilliseconds"))
  2743. binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffInproxyTunnelMaxDurationMilliseconds))
  2744. }
  2745. if len(config.HoldOffInproxyTunnelProviderRegions) > 0 {
  2746. hash.Write([]byte("HoldOffInproxyTunnelProviderRegions"))
  2747. for providerID, regions := range config.HoldOffInproxyTunnelProviderRegions {
  2748. hash.Write([]byte(providerID))
  2749. for _, region := range regions {
  2750. hash.Write([]byte(region))
  2751. }
  2752. }
  2753. }
  2754. if len(config.RestrictInproxyProviderRegions) > 0 {
  2755. hash.Write([]byte("RestrictInproxyProviderRegions"))
  2756. for providerID, regions := range config.RestrictInproxyProviderRegions {
  2757. hash.Write([]byte(providerID))
  2758. for _, region := range regions {
  2759. hash.Write([]byte(region))
  2760. }
  2761. }
  2762. }
  2763. if config.RestrictInproxyProviderIDsClientProbability != nil {
  2764. hash.Write([]byte("RestrictInproxyProviderIDsClientProbability"))
  2765. binary.Write(hash, binary.LittleEndian, *config.RestrictInproxyProviderIDsClientProbability)
  2766. }
  2767. if config.UpstreamProxyAllowAllServerEntrySources != nil {
  2768. hash.Write([]byte("UpstreamProxyAllowAllServerEntrySources"))
  2769. binary.Write(hash, binary.LittleEndian, *config.UpstreamProxyAllowAllServerEntrySources)
  2770. }
  2771. if len(config.LimitTunnelDialPortNumbers) > 0 {
  2772. hash.Write([]byte("LimitTunnelDialPortNumbers"))
  2773. encodedLimitTunnelDialPortNumbers, _ :=
  2774. json.Marshal(config.LimitTunnelDialPortNumbers)
  2775. hash.Write(encodedLimitTunnelDialPortNumbers)
  2776. }
  2777. if config.QUICDialEarlyProbability != nil {
  2778. hash.Write([]byte("QUICDialEarlyProbability"))
  2779. binary.Write(hash, binary.LittleEndian, *config.QUICDialEarlyProbability)
  2780. }
  2781. if config.QUICObfuscatedPSKProbability != nil {
  2782. hash.Write([]byte("QUICObfuscatedPSKProbability"))
  2783. binary.Write(hash, binary.LittleEndian, *config.QUICObfuscatedPSKProbability)
  2784. }
  2785. if config.QUICDisablePathMTUDiscoveryProbability != nil {
  2786. hash.Write([]byte("QUICDisablePathMTUDiscoveryProbability"))
  2787. binary.Write(hash, binary.LittleEndian, *config.QUICDisablePathMTUDiscoveryProbability)
  2788. }
  2789. if config.DNSResolverAttemptsPerServer != nil {
  2790. hash.Write([]byte("DNSResolverAttemptsPerServer"))
  2791. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverAttemptsPerServer))
  2792. }
  2793. if config.DNSResolverRequestTimeoutMilliseconds != nil {
  2794. hash.Write([]byte("DNSResolverRequestTimeoutMilliseconds"))
  2795. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverRequestTimeoutMilliseconds))
  2796. }
  2797. if config.DNSResolverAwaitTimeoutMilliseconds != nil {
  2798. hash.Write([]byte("DNSResolverAwaitTimeoutMilliseconds"))
  2799. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverAwaitTimeoutMilliseconds))
  2800. }
  2801. if config.DNSResolverPreresolvedIPAddressCIDRs != nil {
  2802. hash.Write([]byte("DNSResolverPreresolvedIPAddressCIDRs"))
  2803. encodedDNSResolverPreresolvedIPAddressCIDRs, _ :=
  2804. json.Marshal(config.DNSResolverPreresolvedIPAddressCIDRs)
  2805. hash.Write(encodedDNSResolverPreresolvedIPAddressCIDRs)
  2806. }
  2807. if config.DNSResolverPreresolvedIPAddressProbability != nil {
  2808. hash.Write([]byte("DNSResolverPreresolvedIPAddressProbability"))
  2809. binary.Write(hash, binary.LittleEndian, *config.DNSResolverPreresolvedIPAddressProbability)
  2810. }
  2811. if config.DNSResolverAlternateServers != nil {
  2812. hash.Write([]byte("DNSResolverAlternateServers"))
  2813. for _, server := range config.DNSResolverAlternateServers {
  2814. hash.Write([]byte(server))
  2815. }
  2816. }
  2817. if config.DNSResolverPreferAlternateServerProbability != nil {
  2818. hash.Write([]byte("DNSResolverPreferAlternateServerProbability"))
  2819. binary.Write(hash, binary.LittleEndian, *config.DNSResolverPreferAlternateServerProbability)
  2820. }
  2821. if config.DNSResolverProtocolTransformSpecs != nil {
  2822. hash.Write([]byte("DNSResolverProtocolTransformSpecs"))
  2823. encodedDNSResolverProtocolTransformSpecs, _ :=
  2824. json.Marshal(config.DNSResolverProtocolTransformSpecs)
  2825. hash.Write(encodedDNSResolverProtocolTransformSpecs)
  2826. }
  2827. if config.DNSResolverProtocolTransformScopedSpecNames != nil {
  2828. hash.Write([]byte("DNSResolverProtocolTransformScopedSpecNames"))
  2829. encodedDNSResolverProtocolTransformScopedSpecNames, _ :=
  2830. json.Marshal(config.DNSResolverProtocolTransformScopedSpecNames)
  2831. hash.Write(encodedDNSResolverProtocolTransformScopedSpecNames)
  2832. }
  2833. if config.DNSResolverProtocolTransformProbability != nil {
  2834. hash.Write([]byte("DNSResolverProtocolTransformProbability"))
  2835. binary.Write(hash, binary.LittleEndian, *config.DNSResolverProtocolTransformProbability)
  2836. }
  2837. if config.DNSResolverQNameRandomizeCasingProbability != nil {
  2838. hash.Write([]byte("DNSResolverQNameRandomizeCasingProbability"))
  2839. binary.Write(hash, binary.LittleEndian, *config.DNSResolverQNameRandomizeCasingProbability)
  2840. }
  2841. if config.DNSResolverQNameMustMatchProbability != nil {
  2842. hash.Write([]byte("DNSResolverQNameMustMatchProbability"))
  2843. binary.Write(hash, binary.LittleEndian, *config.DNSResolverQNameMustMatchProbability)
  2844. }
  2845. if config.DNSResolverIncludeEDNS0Probability != nil {
  2846. hash.Write([]byte("DNSResolverIncludeEDNS0Probability"))
  2847. binary.Write(hash, binary.LittleEndian, *config.DNSResolverIncludeEDNS0Probability)
  2848. }
  2849. if config.DNSResolverCacheExtensionInitialTTLMilliseconds != nil {
  2850. hash.Write([]byte("DNSResolverCacheExtensionInitialTTLMilliseconds"))
  2851. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverCacheExtensionInitialTTLMilliseconds))
  2852. }
  2853. if config.DNSResolverCacheExtensionVerifiedTTLMilliseconds != nil {
  2854. hash.Write([]byte("DNSResolverCacheExtensionVerifiedTTLMilliseconds"))
  2855. binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverCacheExtensionVerifiedTTLMilliseconds))
  2856. }
  2857. if config.DirectHTTPProtocolTransformSpecs != nil {
  2858. hash.Write([]byte("DirectHTTPProtocolTransformSpecs"))
  2859. encodedDirectHTTPProtocolTransformSpecs, _ :=
  2860. json.Marshal(config.DirectHTTPProtocolTransformSpecs)
  2861. hash.Write(encodedDirectHTTPProtocolTransformSpecs)
  2862. }
  2863. if config.DirectHTTPProtocolTransformScopedSpecNames != nil {
  2864. hash.Write([]byte("DirectHTTPProtocolTransformScopedSpecNames"))
  2865. encodedDirectHTTPProtocolTransformScopedSpecNames, _ :=
  2866. json.Marshal(config.DirectHTTPProtocolTransformScopedSpecNames)
  2867. hash.Write(encodedDirectHTTPProtocolTransformScopedSpecNames)
  2868. }
  2869. if config.DirectHTTPProtocolTransformProbability != nil {
  2870. hash.Write([]byte("DirectHTTPProtocolTransformProbability"))
  2871. binary.Write(hash, binary.LittleEndian, *config.DirectHTTPProtocolTransformProbability)
  2872. }
  2873. if config.FrontedHTTPProtocolTransformSpecs != nil {
  2874. hash.Write([]byte("FrontedHTTPProtocolTransformSpecs"))
  2875. encodedFrontedHTTPProtocolTransformSpecs, _ :=
  2876. json.Marshal(config.FrontedHTTPProtocolTransformSpecs)
  2877. hash.Write(encodedFrontedHTTPProtocolTransformSpecs)
  2878. }
  2879. if config.FrontedHTTPProtocolTransformScopedSpecNames != nil {
  2880. hash.Write([]byte("FrontedHTTPProtocolTransformScopedSpecNames"))
  2881. encodedFrontedHTTPProtocolTransformScopedSpecNames, _ :=
  2882. json.Marshal(config.FrontedHTTPProtocolTransformScopedSpecNames)
  2883. hash.Write(encodedFrontedHTTPProtocolTransformScopedSpecNames)
  2884. }
  2885. if config.FrontedHTTPProtocolTransformProbability != nil {
  2886. hash.Write([]byte("FrontedHTTPProtocolTransformProbability"))
  2887. binary.Write(hash, binary.LittleEndian, *config.FrontedHTTPProtocolTransformProbability)
  2888. }
  2889. if config.OSSHObfuscatorSeedTransformSpecs != nil {
  2890. hash.Write([]byte("OSSHObfuscatorSeedTransformSpecs"))
  2891. encodedOSSHObfuscatorSeedTransformSpecs, _ :=
  2892. json.Marshal(config.OSSHObfuscatorSeedTransformSpecs)
  2893. hash.Write(encodedOSSHObfuscatorSeedTransformSpecs)
  2894. }
  2895. if config.OSSHObfuscatorSeedTransformScopedSpecNames != nil {
  2896. hash.Write([]byte("OSSHObfuscatorSeedTransformScopedSpecNames"))
  2897. encodedOSSHObfuscatorSeedTransformScopedSpecNames, _ :=
  2898. json.Marshal(config.OSSHObfuscatorSeedTransformScopedSpecNames)
  2899. hash.Write(encodedOSSHObfuscatorSeedTransformScopedSpecNames)
  2900. }
  2901. if config.OSSHObfuscatorSeedTransformProbability != nil {
  2902. hash.Write([]byte("OSSHObfuscatorSeedTransformProbability"))
  2903. binary.Write(hash, binary.LittleEndian, *config.OSSHObfuscatorSeedTransformProbability)
  2904. }
  2905. if config.ObfuscatedQUICNonceTransformSpecs != nil {
  2906. hash.Write([]byte("ObfuscatedQUICNonceTransformSpecs"))
  2907. encodedObfuscatedQUICNonceTransformSpecs, _ :=
  2908. json.Marshal(config.ObfuscatedQUICNonceTransformSpecs)
  2909. hash.Write(encodedObfuscatedQUICNonceTransformSpecs)
  2910. }
  2911. if config.ObfuscatedQUICNonceTransformScopedSpecNames != nil {
  2912. hash.Write([]byte("ObfuscatedQUICNonceTransformScopedSpecNames"))
  2913. encodedObfuscatedQUICNonceTransformScopedSpecNames, _ :=
  2914. json.Marshal(config.ObfuscatedQUICNonceTransformScopedSpecNames)
  2915. hash.Write(encodedObfuscatedQUICNonceTransformScopedSpecNames)
  2916. }
  2917. if config.ObfuscatedQUICNonceTransformProbability != nil {
  2918. hash.Write([]byte("ObfuscatedQUICNonceTransformProbability"))
  2919. binary.Write(hash, binary.LittleEndian, *config.ObfuscatedQUICNonceTransformProbability)
  2920. }
  2921. if config.OSSHPrefixSpecs != nil {
  2922. hash.Write([]byte("OSSHPrefixSpecs"))
  2923. encodedOSSHPrefixSpecs, _ := json.Marshal(config.OSSHPrefixSpecs)
  2924. hash.Write(encodedOSSHPrefixSpecs)
  2925. }
  2926. if config.OSSHPrefixScopedSpecNames != nil {
  2927. hash.Write([]byte("OSSHPrefixScopedSpecNames"))
  2928. encodedOSSHPrefixScopedSpecNames, _ := json.Marshal(config.OSSHPrefixScopedSpecNames)
  2929. hash.Write(encodedOSSHPrefixScopedSpecNames)
  2930. }
  2931. if config.OSSHPrefixProbability != nil {
  2932. hash.Write([]byte("OSSHPrefixProbability"))
  2933. binary.Write(hash, binary.LittleEndian, *config.OSSHPrefixProbability)
  2934. }
  2935. if config.OSSHPrefixSplitMinDelayMilliseconds != nil {
  2936. hash.Write([]byte("OSSHPrefixSplitMinDelayMilliseconds"))
  2937. binary.Write(hash, binary.LittleEndian, int64(*config.OSSHPrefixSplitMinDelayMilliseconds))
  2938. }
  2939. if config.OSSHPrefixSplitMaxDelayMilliseconds != nil {
  2940. hash.Write([]byte("OSSHPrefixSplitMaxDelayMilliseconds"))
  2941. binary.Write(hash, binary.LittleEndian, int64(*config.OSSHPrefixSplitMaxDelayMilliseconds))
  2942. }
  2943. if config.OSSHPrefixEnableFragmentor != nil {
  2944. hash.Write([]byte("OSSHPrefixEnableFragmentor"))
  2945. binary.Write(hash, binary.LittleEndian, *config.OSSHPrefixEnableFragmentor)
  2946. }
  2947. if config.ShadowsocksPrefixSpecs != nil {
  2948. hash.Write([]byte("ShadowsocksPrefixSpecs"))
  2949. encodedShadowsocksPrefixSpecs, _ := json.Marshal(config.ShadowsocksPrefixSpecs)
  2950. hash.Write(encodedShadowsocksPrefixSpecs)
  2951. }
  2952. if config.ShadowsocksPrefixScopedSpecNames != nil {
  2953. hash.Write([]byte("ShadowsocksPrefixScopedSpecNames"))
  2954. encodedShadowsocksPrefixScopedSpecNames, _ := json.Marshal(config.ShadowsocksPrefixScopedSpecNames)
  2955. hash.Write(encodedShadowsocksPrefixScopedSpecNames)
  2956. }
  2957. if config.ShadowsocksPrefixProbability != nil {
  2958. hash.Write([]byte("ShadowsocksPrefixProbability"))
  2959. binary.Write(hash, binary.LittleEndian, *config.ShadowsocksPrefixProbability)
  2960. }
  2961. if config.TLSTunnelObfuscatedPSKProbability != nil {
  2962. hash.Write([]byte("TLSTunnelObfuscatedPSKProbability"))
  2963. binary.Write(hash, binary.LittleEndian, *config.TLSTunnelObfuscatedPSKProbability)
  2964. }
  2965. if config.TLSTunnelTrafficShapingProbability != nil {
  2966. hash.Write([]byte("TLSTunnelTrafficShapingProbability"))
  2967. binary.Write(hash, binary.LittleEndian, *config.TLSTunnelTrafficShapingProbability)
  2968. }
  2969. if config.TLSTunnelMinTLSPadding != nil {
  2970. hash.Write([]byte("TLSTunnelMinTLSPadding"))
  2971. binary.Write(hash, binary.LittleEndian, int64(*config.TLSTunnelMinTLSPadding))
  2972. }
  2973. if config.TLSTunnelMaxTLSPadding != nil {
  2974. hash.Write([]byte("TLSTunnelMaxTLSPadding"))
  2975. binary.Write(hash, binary.LittleEndian, int64(*config.TLSTunnelMaxTLSPadding))
  2976. }
  2977. if config.TLSFragmentClientHelloProbability != nil {
  2978. hash.Write([]byte("TLSFragmentClientHelloProbability"))
  2979. binary.Write(hash, binary.LittleEndian, *config.TLSFragmentClientHelloProbability)
  2980. }
  2981. if len(config.TLSFragmentClientHelloLimitProtocols) > 0 {
  2982. hash.Write([]byte("TLSFragmentClientHelloLimitProtocols"))
  2983. for _, protocol := range config.TLSFragmentClientHelloLimitProtocols {
  2984. hash.Write([]byte(protocol))
  2985. }
  2986. }
  2987. // Steering IPs are ephemeral and not replayed, so steering IP parameters
  2988. // are excluded here.
  2989. if config.InproxyTunnelProtocolSelectionProbability != nil {
  2990. hash.Write([]byte("InproxyTunnelProtocolSelectionProbability"))
  2991. binary.Write(hash, binary.LittleEndian, *config.InproxyTunnelProtocolSelectionProbability)
  2992. }
  2993. if len(config.InproxyBrokerSpecs) > 0 {
  2994. hash.Write([]byte("InproxyBrokerSpecs"))
  2995. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyBrokerSpecs)))
  2996. }
  2997. if len(config.InproxyPersonalPairingBrokerSpecs) > 0 {
  2998. hash.Write([]byte("InproxyPersonalPairingBrokerSpecs"))
  2999. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyPersonalPairingBrokerSpecs)))
  3000. }
  3001. if len(config.InproxyProxyBrokerSpecs) > 0 {
  3002. hash.Write([]byte("InproxyProxyBrokerSpecs"))
  3003. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxyBrokerSpecs)))
  3004. }
  3005. if len(config.InproxyProxyPersonalPairingBrokerSpecs) > 0 {
  3006. hash.Write([]byte("InproxyProxyPersonalPairingBrokerSpecs"))
  3007. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxyPersonalPairingBrokerSpecs)))
  3008. }
  3009. if len(config.InproxyClientBrokerSpecs) > 0 {
  3010. hash.Write([]byte("InproxyClientBrokerSpecs"))
  3011. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyClientBrokerSpecs)))
  3012. }
  3013. if len(config.InproxyClientPersonalPairingBrokerSpecs) > 0 {
  3014. hash.Write([]byte("InproxyClientPersonalPairingBrokerSpecs"))
  3015. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyClientPersonalPairingBrokerSpecs)))
  3016. }
  3017. if config.InproxyReplayBrokerDialParametersTTLSeconds != nil {
  3018. hash.Write([]byte("InproxyReplayBrokerDialParametersTTLSeconds"))
  3019. binary.Write(hash, binary.LittleEndian, int64(*config.InproxyReplayBrokerDialParametersTTLSeconds))
  3020. }
  3021. if config.InproxyReplayBrokerUpdateFrequencySeconds != nil {
  3022. hash.Write([]byte("InproxyReplayBrokerUpdateFrequencySeconds"))
  3023. binary.Write(hash, binary.LittleEndian, int64(*config.InproxyReplayBrokerUpdateFrequencySeconds))
  3024. }
  3025. if config.InproxyReplayBrokerDialParametersProbability != nil {
  3026. hash.Write([]byte("InproxyReplayBrokerDialParametersProbability"))
  3027. binary.Write(hash, binary.LittleEndian, *config.InproxyReplayBrokerDialParametersProbability)
  3028. }
  3029. if config.InproxyReplayBrokerRetainFailedProbability != nil {
  3030. hash.Write([]byte("InproxyReplayBrokerRetainFailedProbability"))
  3031. binary.Write(hash, binary.LittleEndian, *config.InproxyReplayBrokerRetainFailedProbability)
  3032. }
  3033. if len(config.InproxyCommonCompartmentIDs) > 0 {
  3034. hash.Write([]byte("InproxyCommonCompartmentIDs"))
  3035. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyCommonCompartmentIDs)))
  3036. }
  3037. if config.InproxyMaxCompartmentIDListLength != nil {
  3038. hash.Write([]byte("InproxyMaxCompartmentIDListLength"))
  3039. binary.Write(hash, binary.LittleEndian, int64(*config.InproxyMaxCompartmentIDListLength))
  3040. }
  3041. if config.InproxyDTLSRandomizationProbability != nil {
  3042. hash.Write([]byte("InproxyDTLSRandomizationProbability"))
  3043. binary.Write(hash, binary.LittleEndian, *config.InproxyDTLSRandomizationProbability)
  3044. }
  3045. if config.InproxyWebRTCMediaStreamsProbability != nil {
  3046. hash.Write([]byte("InproxyWebRTCMediaStreamsProbability"))
  3047. binary.Write(hash, binary.LittleEndian, *config.InproxyWebRTCMediaStreamsProbability)
  3048. }
  3049. if config.InproxyWebRTCDataChannelTrafficShapingProbability != nil {
  3050. hash.Write([]byte("InproxyWebRTCDataChannelTrafficShapingProbability"))
  3051. binary.Write(hash, binary.LittleEndian, *config.InproxyWebRTCDataChannelTrafficShapingProbability)
  3052. }
  3053. if config.InproxyWebRTCDataChannelTrafficShapingParameters != nil {
  3054. hash.Write([]byte("InproxyWebRTCDataChannelTrafficShapingParameters"))
  3055. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyWebRTCDataChannelTrafficShapingParameters)))
  3056. }
  3057. if config.InproxyWebRTCMediaStreamsTrafficShapingProbability != nil {
  3058. hash.Write([]byte("InproxyWebRTCMediaStreamsTrafficShapingProbability"))
  3059. binary.Write(hash, binary.LittleEndian, *config.InproxyWebRTCMediaStreamsTrafficShapingProbability)
  3060. }
  3061. if config.InproxyWebRTCMediaStreamsTrafficShapingParameters != nil {
  3062. hash.Write([]byte("InproxyWebRTCMediaStreamsTrafficShapingParameters"))
  3063. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyWebRTCMediaStreamsTrafficShapingParameters)))
  3064. }
  3065. if config.InproxySTUNServerAddresses != nil {
  3066. hash.Write([]byte("InproxySTUNServerAddresses"))
  3067. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxySTUNServerAddresses)))
  3068. }
  3069. if config.InproxySTUNServerAddressesRFC5780 != nil {
  3070. hash.Write([]byte("InproxySTUNServerAddressesRFC5780"))
  3071. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxySTUNServerAddressesRFC5780)))
  3072. }
  3073. if config.InproxyProxySTUNServerAddresses != nil {
  3074. hash.Write([]byte("InproxyProxySTUNServerAddresses"))
  3075. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxySTUNServerAddresses)))
  3076. }
  3077. if config.InproxyProxySTUNServerAddressesRFC5780 != nil {
  3078. hash.Write([]byte("InproxyProxySTUNServerAddressesRFC5780"))
  3079. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxySTUNServerAddressesRFC5780)))
  3080. }
  3081. if config.InproxyClientSTUNServerAddresses != nil {
  3082. hash.Write([]byte("InproxyClientSTUNServerAddresses"))
  3083. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyClientSTUNServerAddresses)))
  3084. }
  3085. if config.InproxyClientSTUNServerAddressesRFC5780 != nil {
  3086. hash.Write([]byte("InproxyClientSTUNServerAddressesRFC5780"))
  3087. hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyClientSTUNServerAddressesRFC5780)))
  3088. }
  3089. if config.InproxyClientDiscoverNATProbability != nil {
  3090. hash.Write([]byte("InproxyClientDiscoverNATProbability"))
  3091. binary.Write(hash, binary.LittleEndian, *config.InproxyClientDiscoverNATProbability)
  3092. }
  3093. if config.InproxyDisableSTUN != nil {
  3094. hash.Write([]byte("InproxyDisableSTUN"))
  3095. binary.Write(hash, binary.LittleEndian, *config.InproxyDisableSTUN)
  3096. }
  3097. if config.InproxyDisablePortMapping != nil {
  3098. hash.Write([]byte("InproxyDisablePortMapping"))
  3099. binary.Write(hash, binary.LittleEndian, *config.InproxyDisablePortMapping)
  3100. }
  3101. if config.InproxyDisableInboundForMobileNetworks != nil {
  3102. hash.Write([]byte("InproxyDisableInboundForMobileNetworks"))
  3103. binary.Write(hash, binary.LittleEndian, *config.InproxyDisableInboundForMobileNetworks)
  3104. }
  3105. if config.InproxyDisableIPv6ICECandidates != nil {
  3106. hash.Write([]byte("InproxyDisableIPv6ICECandidates"))
  3107. binary.Write(hash, binary.LittleEndian, *config.InproxyDisableIPv6ICECandidates)
  3108. }
  3109. if config.InproxyProxyDisableSTUN != nil {
  3110. hash.Write([]byte("InproxyProxyDisableSTUN"))
  3111. binary.Write(hash, binary.LittleEndian, *config.InproxyProxyDisableSTUN)
  3112. }
  3113. if config.InproxyProxyDisablePortMapping != nil {
  3114. hash.Write([]byte("InproxyProxyDisablePortMapping"))
  3115. binary.Write(hash, binary.LittleEndian, *config.InproxyProxyDisablePortMapping)
  3116. }
  3117. if config.InproxyProxyDisableInboundForMobileNetworks != nil {
  3118. hash.Write([]byte("InproxyProxyDisableInboundForMobileNetworks"))
  3119. binary.Write(hash, binary.LittleEndian, *config.InproxyProxyDisableInboundForMobileNetworks)
  3120. }
  3121. if config.InproxyProxyDisableIPv6ICECandidates != nil {
  3122. hash.Write([]byte("InproxyProxyDisableIPv6ICECandidates"))
  3123. binary.Write(hash, binary.LittleEndian, *config.InproxyProxyDisableIPv6ICECandidates)
  3124. }
  3125. if config.InproxyClientDisableSTUN != nil {
  3126. hash.Write([]byte("InproxyClientDisableSTUN"))
  3127. binary.Write(hash, binary.LittleEndian, *config.InproxyClientDisableSTUN)
  3128. }
  3129. if config.InproxyClientDisablePortMapping != nil {
  3130. hash.Write([]byte("InproxyClientDisablePortMapping"))
  3131. binary.Write(hash, binary.LittleEndian, *config.InproxyClientDisablePortMapping)
  3132. }
  3133. if config.InproxyClientDisableInboundForMobileNetworks != nil {
  3134. hash.Write([]byte("InproxyClientDisableInboundForMobileNetworks"))
  3135. binary.Write(hash, binary.LittleEndian, *config.InproxyClientDisableInboundForMobileNetworks)
  3136. }
  3137. if config.InproxyClientDisableIPv6ICECandidates != nil {
  3138. hash.Write([]byte("InproxyClientDisableIPv6ICECandidates"))
  3139. binary.Write(hash, binary.LittleEndian, *config.InproxyClientDisableIPv6ICECandidates)
  3140. }
  3141. config.dialParametersHash = hash.Sum(nil)
  3142. }
  3143. // applyAdditionalParameters decodes and applies any additional parameters
  3144. // stored in config.AdditionalParameter to the Config and returns an array
  3145. // of notices which should be logged at the info level. If there is no error,
  3146. // then config.AdditionalParameter is set to "" to conserve memory and further
  3147. // calls will do nothing. This function should only be called once.
  3148. //
  3149. // If there is an error, the existing Config is left entirely unmodified.
  3150. func (config *Config) applyAdditionalParameters() ([]string, error) {
  3151. if config.AdditionalParameters == "" {
  3152. return nil, nil
  3153. }
  3154. b, err := base64.StdEncoding.DecodeString(config.AdditionalParameters)
  3155. if err != nil {
  3156. return nil, errors.Trace(err)
  3157. }
  3158. if len(b) < 32 {
  3159. return nil, errors.Tracef("invalid length, len(b) == %d", len(b))
  3160. }
  3161. var key [32]byte
  3162. copy(key[:], b[:32])
  3163. decrypted, ok := secretbox.Open(nil, b[32:], &[24]byte{}, &key)
  3164. if !ok {
  3165. return nil, errors.TraceNew("secretbox.Open failed")
  3166. }
  3167. var additionalParameters Config
  3168. err = json.Unmarshal(decrypted, &additionalParameters)
  3169. if err != nil {
  3170. return nil, errors.Trace(err)
  3171. }
  3172. src := reflect.ValueOf(&additionalParameters).Elem()
  3173. dest := reflect.ValueOf(config).Elem()
  3174. var infoNotices []string
  3175. for i := 0; i < src.NumField(); i++ {
  3176. if !src.Field(i).IsZero() {
  3177. dest.Field(i).Set(src.Field(i))
  3178. infoNotice := fmt.Sprintf("%s overridden by AdditionalParameters", dest.Type().Field(i).Name)
  3179. infoNotices = append(infoNotices, infoNotice)
  3180. }
  3181. }
  3182. // Reset field to conserve memory since this is a one-time operation.
  3183. config.AdditionalParameters = ""
  3184. return infoNotices, nil
  3185. }
  3186. func promoteLegacyTransferURL(URL string) parameters.TransferURLs {
  3187. transferURLs := make(parameters.TransferURLs, 1)
  3188. transferURLs[0] = &parameters.TransferURL{
  3189. URL: base64.StdEncoding.EncodeToString([]byte(URL)),
  3190. SkipVerify: false,
  3191. OnlyAfterAttempts: 0,
  3192. }
  3193. return transferURLs
  3194. }
  3195. type loggingDeviceBinder struct {
  3196. d DeviceBinder
  3197. }
  3198. func newLoggingDeviceBinder(d DeviceBinder) *loggingDeviceBinder {
  3199. return &loggingDeviceBinder{d: d}
  3200. }
  3201. func (d *loggingDeviceBinder) BindToDevice(fileDescriptor int) (string, error) {
  3202. deviceInfo, err := d.d.BindToDevice(fileDescriptor)
  3203. if err == nil && deviceInfo != "" {
  3204. NoticeBindToDevice(deviceInfo)
  3205. }
  3206. return deviceInfo, err
  3207. }
  3208. const unknownNetworkID = "UNKNOWN"
  3209. type staticNetworkIDGetter struct {
  3210. networkID string
  3211. }
  3212. func newStaticNetworkIDGetter(networkID string) *staticNetworkIDGetter {
  3213. return &staticNetworkIDGetter{networkID: networkID}
  3214. }
  3215. func (n *staticNetworkIDGetter) GetNetworkID() string {
  3216. return n.networkID
  3217. }
  3218. type commonNetworkIDGetter struct {
  3219. }
  3220. func newCommonNetworkIDGetter() *commonNetworkIDGetter {
  3221. return &commonNetworkIDGetter{}
  3222. }
  3223. func (n *commonNetworkIDGetter) GetNetworkID() string {
  3224. networkID, err := networkid.Get()
  3225. if err != nil {
  3226. NoticeError("networkid.Get failed: %v", errors.Trace(err))
  3227. return unknownNetworkID
  3228. }
  3229. return networkID
  3230. }
  3231. type loggingNetworkIDGetter struct {
  3232. n NetworkIDGetter
  3233. }
  3234. func newLoggingNetworkIDGetter(n NetworkIDGetter) *loggingNetworkIDGetter {
  3235. return &loggingNetworkIDGetter{n: n}
  3236. }
  3237. func (n *loggingNetworkIDGetter) GetNetworkID() string {
  3238. networkID := n.n.GetNetworkID()
  3239. // All PII must appear after the initial "-"
  3240. // See: https://godoc.org/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon#NetworkIDGetter
  3241. logNetworkID := networkID
  3242. index := strings.Index(logNetworkID, "-")
  3243. if index != -1 {
  3244. logNetworkID = logNetworkID[:index]
  3245. }
  3246. if len(logNetworkID)+1 < len(networkID) {
  3247. // Indicate when additional network info was present after the first "-".
  3248. logNetworkID += "+[redacted]"
  3249. }
  3250. NoticeNetworkID(logNetworkID)
  3251. return networkID
  3252. }
  3253. // cachingNetworkIDGetter caches the GetNetworkID result from the underlying
  3254. // network ID getter. The current GetNetworkID implementations take in the
  3255. // range of 1-7ms (Android); 2-3ms (iOS); ~3.5ms (Windows) to execute, on
  3256. // modern devices. To minimize delaying dials and other operations that start
  3257. // with fetching the current network ID, the return values are cached for a
  3258. // short time. On platforms that invoke NetworkChanged, the cache is flushed
  3259. // immediately upon a network change.
  3260. type cachingNetworkIDGetter struct {
  3261. config *Config
  3262. n NetworkIDGetter
  3263. mutex sync.Mutex
  3264. cachedNetworkID string
  3265. cacheExpiry time.Time
  3266. }
  3267. func newCachingNetworkIDGetter(
  3268. config *Config, n NetworkIDGetter) *cachingNetworkIDGetter {
  3269. return &cachingNetworkIDGetter{
  3270. config: config,
  3271. n: n,
  3272. }
  3273. }
  3274. func (n *cachingNetworkIDGetter) GetNetworkID() string {
  3275. n.mutex.Lock()
  3276. defer n.mutex.Unlock()
  3277. if n.cachedNetworkID != "" && n.cacheExpiry.After(time.Now()) {
  3278. return n.cachedNetworkID
  3279. }
  3280. networkID := n.n.GetNetworkID()
  3281. p := n.config.GetParameters().Get()
  3282. ttl := p.Duration(parameters.NetworkIDCacheTTL)
  3283. if ttl > 0 {
  3284. n.cachedNetworkID = networkID
  3285. n.cacheExpiry = time.Now().Add(ttl)
  3286. }
  3287. return networkID
  3288. }
  3289. func (n *cachingNetworkIDGetter) FlushCache() {
  3290. n.mutex.Lock()
  3291. defer n.mutex.Unlock()
  3292. n.cachedNetworkID = ""
  3293. n.cacheExpiry = time.Time{}
  3294. }
  3295. // migrationsFromLegacyNoticeFilePaths returns the file migrations which must be
  3296. // performed to move notice files from legacy file paths, which were configured
  3297. // with the legacy config fields HomepageNoticesFilename and
  3298. // RotatingNoticesFilename, to the new file paths used by Psiphon which exist
  3299. // under the data root directory.
  3300. func migrationsFromLegacyNoticeFilePaths(config *Config) []FileMigration {
  3301. var noticeMigrations []FileMigration
  3302. if config.MigrateHomepageNoticesFilename != "" {
  3303. noticeMigrations = append(noticeMigrations, FileMigration{
  3304. Name: "hompage",
  3305. OldPath: config.MigrateHomepageNoticesFilename,
  3306. NewPath: config.GetHomePageFilename(),
  3307. })
  3308. }
  3309. if config.MigrateRotatingNoticesFilename != "" {
  3310. migrations := []FileMigration{
  3311. {
  3312. Name: "notices",
  3313. OldPath: config.MigrateRotatingNoticesFilename,
  3314. NewPath: config.GetNoticesFilename(),
  3315. IsDir: false,
  3316. },
  3317. {
  3318. Name: "notices.1",
  3319. OldPath: config.MigrateRotatingNoticesFilename + ".1",
  3320. NewPath: config.GetNoticesFilename() + ".1",
  3321. },
  3322. }
  3323. noticeMigrations = append(noticeMigrations, migrations...)
  3324. }
  3325. return noticeMigrations
  3326. }
  3327. // migrationsFromLegacyFilePaths returns the file migrations which must be
  3328. // performed to move files from legacy file paths, which were configured with
  3329. // legacy config fields, to the new file paths used by Psiphon which exist
  3330. // under the data root directory.
  3331. // Note: an attempt is made to redact any file paths from the returned error.
  3332. func migrationsFromLegacyFilePaths(config *Config) ([]FileMigration, error) {
  3333. migrations := []FileMigration{
  3334. {
  3335. Name: "psiphon.boltdb",
  3336. OldPath: filepath.Join(config.MigrateDataStoreDirectory, "psiphon.boltdb"),
  3337. NewPath: filepath.Join(config.GetDataStoreDirectory(), "psiphon.boltdb"),
  3338. },
  3339. {
  3340. Name: "psiphon.boltdb.lock",
  3341. OldPath: filepath.Join(config.MigrateDataStoreDirectory, "psiphon.boltdb.lock"),
  3342. NewPath: filepath.Join(config.GetDataStoreDirectory(), "psiphon.boltdb.lock"),
  3343. },
  3344. }
  3345. if config.MigrateRemoteServerListDownloadFilename != "" {
  3346. // Migrate remote server list files
  3347. rslMigrations := []FileMigration{
  3348. {
  3349. Name: "remote_server_list",
  3350. OldPath: config.MigrateRemoteServerListDownloadFilename,
  3351. NewPath: config.GetRemoteServerListDownloadFilename(),
  3352. },
  3353. {
  3354. Name: "remote_server_list.part",
  3355. OldPath: config.MigrateRemoteServerListDownloadFilename + ".part",
  3356. NewPath: config.GetRemoteServerListDownloadFilename() + ".part",
  3357. },
  3358. {
  3359. Name: "remote_server_list.part.etag",
  3360. OldPath: config.MigrateRemoteServerListDownloadFilename + ".part.etag",
  3361. NewPath: config.GetRemoteServerListDownloadFilename() + ".part.etag",
  3362. },
  3363. }
  3364. migrations = append(migrations, rslMigrations...)
  3365. }
  3366. if config.MigrateObfuscatedServerListDownloadDirectory != "" {
  3367. // Migrate OSL registry file and downloads
  3368. oslFileRegex, err := regexp.Compile(`^osl-.+$`)
  3369. if err != nil {
  3370. return nil, errors.TraceMsg(err, "failed to compile regex for osl files")
  3371. }
  3372. files, err := ioutil.ReadDir(config.MigrateObfuscatedServerListDownloadDirectory)
  3373. if err != nil {
  3374. NoticeWarning(
  3375. "Migration: failed to read OSL download directory with error %s",
  3376. common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory))
  3377. } else {
  3378. for _, file := range files {
  3379. if oslFileRegex.MatchString(file.Name()) {
  3380. fileMigration := FileMigration{
  3381. Name: "osl",
  3382. OldPath: filepath.Join(config.MigrateObfuscatedServerListDownloadDirectory, file.Name()),
  3383. NewPath: filepath.Join(config.GetObfuscatedServerListDownloadDirectory(), file.Name()),
  3384. }
  3385. migrations = append(migrations, fileMigration)
  3386. }
  3387. }
  3388. }
  3389. }
  3390. if config.MigrateUpgradeDownloadFilename != "" {
  3391. // Migrate downloaded upgrade files
  3392. oldUpgradeDownloadFilename := filepath.Base(config.MigrateUpgradeDownloadFilename)
  3393. // Create regex for:
  3394. // <old_upgrade_download_filename>
  3395. // <old_upgrade_download_filename>.<client_version_number>
  3396. // <old_upgrade_download_filename>.<client_version_number>.part
  3397. // <old_upgrade_download_filename>.<client_version_number>.part.etag
  3398. upgradeDownloadFileRegex, err := regexp.Compile(`^` + oldUpgradeDownloadFilename + `(\.\d+(\.part(\.etag)?)?)?$`)
  3399. if err != nil {
  3400. return nil, errors.TraceMsg(err, "failed to compile regex for upgrade files")
  3401. }
  3402. upgradeDownloadDir := filepath.Dir(config.MigrateUpgradeDownloadFilename)
  3403. files, err := ioutil.ReadDir(upgradeDownloadDir)
  3404. if err != nil {
  3405. NoticeWarning(
  3406. "Migration: failed to read upgrade download directory with error %s",
  3407. common.RedactFilePathsError(err, upgradeDownloadDir))
  3408. } else {
  3409. for _, file := range files {
  3410. if upgradeDownloadFileRegex.MatchString(file.Name()) {
  3411. oldFileSuffix := strings.TrimPrefix(file.Name(), oldUpgradeDownloadFilename)
  3412. fileMigration := FileMigration{
  3413. Name: "upgrade",
  3414. OldPath: filepath.Join(upgradeDownloadDir, file.Name()),
  3415. NewPath: config.GetUpgradeDownloadFilename() + oldFileSuffix,
  3416. }
  3417. migrations = append(migrations, fileMigration)
  3418. }
  3419. }
  3420. }
  3421. }
  3422. return migrations, nil
  3423. }