dialParameters.go 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580
  1. /*
  2. * Copyright (c) 2018, 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. "bytes"
  22. "context"
  23. "crypto/md5"
  24. "encoding/binary"
  25. std_errors "errors"
  26. "fmt"
  27. "net"
  28. "net/http"
  29. "strconv"
  30. "sync/atomic"
  31. "time"
  32. tls "github.com/Psiphon-Labs/psiphon-tls"
  33. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  34. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  35. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/fragmentor"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy"
  37. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
  38. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
  39. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  40. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
  41. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/regen"
  42. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
  43. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/transforms"
  44. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
  45. utls "github.com/Psiphon-Labs/utls"
  46. lrucache "github.com/cognusion/go-cache-lru"
  47. "golang.org/x/net/bpf"
  48. )
  49. // DialParameters represents a selected protocol and all the related selected
  50. // protocol attributes, many chosen at random, for a tunnel dial attempt.
  51. //
  52. // DialParameters is used:
  53. // - to configure dialers
  54. // - as a persistent record to store successful dial parameters for replay
  55. // - to report dial stats in notices and Psiphon API calls.
  56. //
  57. // MeekResolvedIPAddress is set asynchronously, as it is not known until the
  58. // dial process has begun. The atomic.Value will contain a string, initialized
  59. // to "", and set to the resolved IP address once that part of the dial
  60. // process has completed.
  61. //
  62. // DialParameters is not safe for concurrent use.
  63. type DialParameters struct {
  64. ServerEntry *protocol.ServerEntry `json:"-"`
  65. NetworkID string `json:"-"`
  66. IsReplay bool `json:"-"`
  67. ReplayIgnoredChange bool `json:"-"`
  68. CandidateNumber int `json:"-"`
  69. EstablishedTunnelsCount int `json:"-"`
  70. ServerEntryIterationUniqueCandidateEstimate int `json:"-"`
  71. ServerEntryIterationMovedToFrontCount int `json:"-"`
  72. ServerEntryIterationFirstFrontedMeekCandidate int `json:"-"`
  73. IsExchanged bool `json:",omitempty"`
  74. LastUsedTimestamp time.Time `json:",omitempty"`
  75. LastUsedConfigStateHash []byte `json:",omitempty"`
  76. LastUsedServerEntryHash []byte `json:",omitempty"`
  77. NetworkLatencyMultiplier float64 `json:",omitempty"`
  78. TunnelProtocol string `json:",omitempty"`
  79. DirectDialAddress string `json:",omitempty"`
  80. DialPortNumber string `json:",omitempty"`
  81. UpstreamProxyType string `json:"-"`
  82. UpstreamProxyCustomHeaderNames []string `json:"-"`
  83. BPFProgramName string `json:",omitempty"`
  84. BPFProgramInstructions []bpf.RawInstruction `json:",omitempty"`
  85. SelectedSSHClientVersion bool `json:",omitempty"`
  86. SSHClientVersion string `json:",omitempty"`
  87. SSHKEXSeed *prng.Seed `json:",omitempty"`
  88. ObfuscatorPaddingSeed *prng.Seed `json:",omitempty"`
  89. OSSHObfuscatorSeedTransformerParameters *transforms.ObfuscatorSeedTransformerParameters `json:",omitempty"`
  90. OSSHPrefixSpec *obfuscator.OSSHPrefixSpec `json:",omitempty"`
  91. OSSHPrefixSplitConfig *obfuscator.OSSHPrefixSplitConfig `json:",omitempty"`
  92. ShadowsocksPrefixSpec *ShadowsocksPrefixSpec `json:",omitempty"`
  93. FragmentorSeed *prng.Seed `json:",omitempty"`
  94. FrontingProviderID string `json:",omitempty"`
  95. MeekFrontingDialAddress string `json:",omitempty"`
  96. MeekFrontingHost string `json:",omitempty"`
  97. MeekDialAddress string `json:",omitempty"`
  98. MeekTransformedHostName bool `json:",omitempty"`
  99. MeekSNIServerName string `json:",omitempty"`
  100. MeekVerifyServerName string `json:",omitempty"`
  101. MeekVerifyPins []string `json:",omitempty"`
  102. MeekHostHeader string `json:",omitempty"`
  103. MeekObfuscatorPaddingSeed *prng.Seed `json:",omitempty"`
  104. MeekResolvedIPAddress atomic.Value `json:"-"`
  105. TLSOSSHTransformedSNIServerName bool `json:",omitempty"`
  106. TLSOSSHSNIServerName string `json:",omitempty"`
  107. TLSOSSHObfuscatorPaddingSeed *prng.Seed `json:",omitempty"`
  108. SelectedUserAgent bool `json:",omitempty"`
  109. UserAgent string `json:",omitempty"`
  110. SelectedTLSProfile bool `json:",omitempty"`
  111. TLSProfile string `json:",omitempty"`
  112. NoDefaultTLSSessionID bool `json:",omitempty"`
  113. TLSVersion string `json:",omitempty"`
  114. RandomizedTLSProfileSeed *prng.Seed `json:",omitempty"`
  115. TLSFragmentClientHello bool `json:",omitempty"`
  116. QUICVersion string `json:",omitempty"`
  117. QUICDialSNIAddress string `json:",omitempty"`
  118. QUICClientHelloSeed *prng.Seed `json:",omitempty"`
  119. ObfuscatedQUICPaddingSeed *prng.Seed `json:",omitempty"`
  120. ObfuscatedQUICNonceTransformerParameters *transforms.ObfuscatorSeedTransformerParameters `json:",omitempty"`
  121. QUICDialEarly bool `json:",omitempty"`
  122. QUICUseObfuscatedPSK bool `json:",omitempty"`
  123. QUICDisablePathMTUDiscovery bool `json:",omitempty"`
  124. QUICMaxPacketSizeAdjustment int `json:",omitempty"`
  125. ConjureCachedRegistrationTTL time.Duration `json:",omitempty"`
  126. ConjureAPIRegistration bool `json:",omitempty"`
  127. ConjureAPIRegistrarBidirectionalURL string `json:",omitempty"`
  128. ConjureAPIRegistrarDelay time.Duration `json:",omitempty"`
  129. ConjureDecoyRegistration bool `json:",omitempty"`
  130. ConjureDecoyRegistrarDelay time.Duration `json:",omitempty"`
  131. ConjureDecoyRegistrarWidth int `json:",omitempty"`
  132. ConjureTransport string `json:",omitempty"`
  133. ConjureSTUNServerAddress string `json:",omitempty"`
  134. ConjureDTLSEmptyInitialPacket bool `json:",omitempty"`
  135. LivenessTestSeed *prng.Seed `json:",omitempty"`
  136. APIRequestPaddingSeed *prng.Seed `json:",omitempty"`
  137. HoldOffTunnelDuration time.Duration `json:",omitempty"`
  138. DialConnMetrics common.MetricsSource `json:"-"`
  139. DialConnNoticeMetrics common.NoticeMetricsSource `json:"-"`
  140. ObfuscatedSSHConnMetrics common.MetricsSource `json:"-"`
  141. DialDuration time.Duration `json:"-"`
  142. resolver *resolver.Resolver `json:"-"`
  143. ResolveParameters *resolver.ResolveParameters `json:",omitempty"`
  144. HTTPTransformerParameters *transforms.HTTPTransformerParameters `json:",omitempty"`
  145. SteeringIP string `json:",omitempty"`
  146. steeringIPCache *lrucache.Cache `json:"-"`
  147. steeringIPCacheKey string `json:"-"`
  148. DSLPendingPrioritizeDialTimestamp time.Time `json:",omitempty"`
  149. DSLPrioritizedDial bool `json:",omitempty"`
  150. quicTLSClientSessionCache *common.TLSClientSessionCacheWrapper `json:"-"`
  151. tlsClientSessionCache *common.UtlsClientSessionCacheWrapper `json:"-"`
  152. inproxyDialInitialized bool `json:"-"`
  153. inproxyBrokerClient *inproxy.BrokerClient `json:"-"`
  154. inproxyBrokerDialParameters *InproxyBrokerDialParameters `json:"-"`
  155. inproxyPackedSignedServerEntry []byte `json:"-"`
  156. inproxyNATStateManager *InproxyNATStateManager `json:"-"`
  157. InproxySTUNDialParameters *InproxySTUNDialParameters `json:",omitempty"`
  158. InproxyWebRTCDialParameters *InproxyWebRTCDialParameters `json:",omitempty"`
  159. inproxyConn atomic.Value `json:"-"`
  160. dialConfig *DialConfig `json:"-"`
  161. meekConfig *MeekConfig `json:"-"`
  162. }
  163. // MakeDialParameters creates a new DialParameters for the candidate server
  164. // entry, including selecting a protocol and all the various protocol
  165. // attributes. The input selectProtocol is used to comply with any active
  166. // protocol selection constraints.
  167. //
  168. // When stored dial parameters are available and may be used,
  169. // MakeDialParameters may replay previous dial parameters in an effort to
  170. // leverage "known working" values instead of always chosing at random from a
  171. // large space.
  172. //
  173. // MakeDialParameters will return nil/nil in cases where the candidate server
  174. // entry should be skipped.
  175. //
  176. // To support replay, the caller must call DialParameters.Succeeded when a
  177. // successful tunnel is established with the returned DialParameters; and must
  178. // call DialParameters.Failed when a tunnel dial or activation fails, except
  179. // when establishment is cancelled.
  180. func MakeDialParameters(
  181. config *Config,
  182. steeringIPCache *lrucache.Cache,
  183. quicTLSClientSessionCache tls.ClientSessionCache,
  184. tlsClientSessionCache utls.ClientSessionCache,
  185. upstreamProxyErrorCallback func(error),
  186. canReplay func(serverEntry *protocol.ServerEntry, replayProtocol string) bool,
  187. selectProtocol func(serverEntry *protocol.ServerEntry) (string, bool),
  188. serverEntry *protocol.ServerEntry,
  189. inproxyClientBrokerClientManager *InproxyBrokerClientManager,
  190. inproxyClientNATStateManager *InproxyNATStateManager,
  191. isTactics bool,
  192. candidateNumber int,
  193. establishedTunnelsCount int) (*DialParameters, error) {
  194. // Note: a subset of this code is duplicated in
  195. // MakeInproxyBrokerDialParameters and makeFrontedHTTPClient, and all
  196. // functions need to be updated when, e.g., new TLS obfuscation
  197. // parameters are added.
  198. currentTimestamp := time.Now()
  199. networkID := config.GetNetworkID()
  200. p := config.GetParameters().Get()
  201. ttl := p.Duration(parameters.ReplayDialParametersTTL)
  202. dslPlaceholderTTL := p.Duration(parameters.DSLPrioritizeDialPlaceholderTTL)
  203. // Replay ignoring tactics changes with a probability allows for a mix of
  204. // sticking with replay and exploring use of new tactics.
  205. replayIgnoreChangedConfigState := p.WeightedCoinFlip(
  206. parameters.ReplayIgnoreChangedConfigStateProbability)
  207. replayBPF := p.Bool(parameters.ReplayBPF)
  208. replaySSH := p.Bool(parameters.ReplaySSH)
  209. replayObfuscatorPadding := p.Bool(parameters.ReplayObfuscatorPadding)
  210. replayFragmentor := p.Bool(parameters.ReplayFragmentor)
  211. replayTLSProfile := p.Bool(parameters.ReplayTLSProfile)
  212. replayTLSFragmentClientHello := p.Bool(parameters.ReplayTLSFragmentClientHello)
  213. replayFronting := p.Bool(parameters.ReplayFronting)
  214. replayHostname := p.Bool(parameters.ReplayHostname)
  215. replayQUICVersion := p.Bool(parameters.ReplayQUICVersion)
  216. replayObfuscatedQUIC := p.Bool(parameters.ReplayObfuscatedQUIC)
  217. replayObfuscatedQUICNonceTransformer := p.Bool(parameters.ReplayObfuscatedQUICNonceTransformer)
  218. replayConjureRegistration := p.Bool(parameters.ReplayConjureRegistration)
  219. replayConjureTransport := p.Bool(parameters.ReplayConjureTransport)
  220. replayLivenessTest := p.Bool(parameters.ReplayLivenessTest)
  221. replayUserAgent := p.Bool(parameters.ReplayUserAgent)
  222. replayAPIRequestPadding := p.Bool(parameters.ReplayAPIRequestPadding)
  223. replayHoldOffTunnel := p.Bool(parameters.ReplayHoldOffTunnel)
  224. replayResolveParameters := p.Bool(parameters.ReplayResolveParameters)
  225. replayHTTPTransformerParameters := p.Bool(parameters.ReplayHTTPTransformerParameters)
  226. replayOSSHSeedTransformerParameters := p.Bool(parameters.ReplayOSSHSeedTransformerParameters)
  227. replayOSSHPrefix := p.Bool(parameters.ReplayOSSHPrefix)
  228. replayShadowsocksPrefix := p.Bool(parameters.ReplayShadowsocksPrefix)
  229. replayInproxySTUN := p.Bool(parameters.ReplayInproxySTUN)
  230. replayInproxyWebRTC := p.Bool(parameters.ReplayInproxyWebRTC)
  231. // Check for existing dial parameters for this server/network ID.
  232. dialParams, err := GetDialParameters(
  233. config, serverEntry.IpAddress, networkID)
  234. if err != nil {
  235. NoticeWarning("GetDialParameters failed: %s", err)
  236. dialParams = nil
  237. // Proceed, without existing dial parameters.
  238. }
  239. // DSLPendingPrioritizeDial is a placeholder which indicates that the
  240. // server entry was prioritized for selection due to a hint from the DSL
  241. // backend. No other dial parameters are set in the placeholder.
  242. // Prioritized selection is implemented by storing a
  243. // DSLPendingPrioritizeDial dial parameters record, and relying on the
  244. // move-to-front logic in the server entry iterator shuffle.
  245. //
  246. // The DSLPendingPrioritizeDial placeholder remains valid until it exceeds
  247. // the configured TTL or is removed in Failed. When the placeholder is
  248. // selected and attempted, new dial parameters are selected.
  249. //
  250. // The DSLPrioritizedDial field is set and used to record dsl_prioritized
  251. // metrics indicating that the dial was DSL prioritized. The
  252. // DSLPrioritizedDial flag is retained, and dsl_prioritized reported, as
  253. // long as the dial parameters are successfully replayed. Once the replay
  254. // ends, the DSLPrioritizedDial/dsl_prioritized state is dropped.
  255. //
  256. // The isTactics case is not excluded from this DSLPrioritizedDial logic,
  257. // since a DSLPendingPrioritizeDial placeholder may be created for a
  258. // TACTICS-capable server entry. Note that tactics doesn't invoke
  259. // DialParameters.Succeed to replay, and will only replay if the same
  260. // server entry happens to have been used for a tunnel protocol. See
  261. // fetchTactics.
  262. dslPendingPrioritizeDial :=
  263. dialParams != nil && !dialParams.DSLPendingPrioritizeDialTimestamp.IsZero()
  264. if dslPendingPrioritizeDial {
  265. if dslPlaceholderTTL > 0 &&
  266. dialParams.DSLPendingPrioritizeDialTimestamp.
  267. Before(currentTimestamp.Add(-dslPlaceholderTTL)) {
  268. // If the DSLPendingPrioritizeDial placeholder is expired, delete it.
  269. //
  270. // Limitation: at this point, the expired placeholder has already
  271. // resulted in a server entry iterator move-to-front for one last
  272. // round. For this reason, dslPendingPrioritizeDial isn't reset
  273. // to false and dialParams.DSLPrioritizedDial will still be set to true.
  274. err = DeleteDialParameters(serverEntry.IpAddress, networkID)
  275. if err != nil {
  276. NoticeWarning("DeleteDialParameters failed: %s", err)
  277. }
  278. }
  279. // Replace the placeholder with new dial parameters.
  280. dialParams = nil
  281. }
  282. // Check if replay is permitted:
  283. // - TTL must be > 0 and existing dial parameters must not have expired
  284. // as indicated by LastUsedTimestamp + TTL.
  285. // - Config/tactics/server entry values must be unchanged from when
  286. // previous dial parameters were established.
  287. // - The protocol selection constraints must permit replay, as indicated
  288. // by canReplay.
  289. // - Must not be using an obsolete TLS profile that is no longer supported.
  290. // - Must be using the latest Conjure API URL.
  291. //
  292. // When existing dial parameters don't meet these conditions, dialParams
  293. // is reset to nil and new dial parameters will be generated.
  294. var configStateHash []byte
  295. var serverEntryHash []byte
  296. var configChanged bool
  297. // When TTL is 0, replay is disabled; the timestamp remains 0 and the
  298. // output DialParameters will not be stored by Success.
  299. if ttl > 0 {
  300. configStateHash, serverEntryHash = getDialStateHashes(config, p, serverEntry)
  301. configChanged = dialParams != nil && !bytes.Equal(
  302. dialParams.LastUsedConfigStateHash, configStateHash)
  303. }
  304. if dialParams != nil &&
  305. (ttl <= 0 ||
  306. dialParams.LastUsedTimestamp.Before(currentTimestamp.Add(-ttl)) ||
  307. // Replay is disabled when the current config state hash -- config
  308. // dial parameters and the current tactics tag -- have changed
  309. // since the last dial. This prioritizes applying any potential
  310. // tactics change over redialing with parameters that may have
  311. // changed in tactics.
  312. //
  313. // Because of this, frequent tactics changes may degrade replay
  314. // effectiveness. When replayIgnoreChangedConfigState is set,
  315. // differences in the config state hash are ignored.
  316. //
  317. // Limitation: some code which previously assumed that replay
  318. // always implied unchanged tactics parameters may now use newer
  319. // tactics parameters in replay cases when
  320. // replayIgnoreChangedConfigState is set. One case is the call
  321. // below to fragmentor.NewUpstreamConfig, made when initializing
  322. // dialParams.dialConfig.
  323. (!replayIgnoreChangedConfigState && configChanged) ||
  324. // Replay is disabled when the server entry has changed.
  325. !bytes.Equal(dialParams.LastUsedServerEntryHash, serverEntryHash) ||
  326. (dialParams.TLSProfile != "" &&
  327. !common.Contains(protocol.SupportedTLSProfiles, dialParams.TLSProfile)) ||
  328. (dialParams.QUICVersion != "" &&
  329. !common.Contains(protocol.SupportedQUICVersions, dialParams.QUICVersion)) ||
  330. // Prioritize adjusting use of 3rd party infrastructure -- public
  331. // STUN servers -- over replay, even with IgnoreChangedConfigState set.
  332. (dialParams.ConjureSTUNServerAddress != "" &&
  333. !common.Contains(
  334. p.Strings(parameters.ConjureSTUNServerAddresses),
  335. dialParams.ConjureSTUNServerAddress)) ||
  336. (dialParams.InproxySTUNDialParameters != nil &&
  337. dialParams.InproxySTUNDialParameters.IsValidClientReplay(p)) ||
  338. // Legacy clients use ConjureAPIRegistrarURL with
  339. // gotapdance.tapdance.APIRegistrar and new clients use
  340. // ConjureAPIRegistrarBidirectionalURL with
  341. // gotapdance.tapdance.APIRegistrarBidirectional. Updated clients
  342. // may have replay dial parameters with the old
  343. // ConjureAPIRegistrarURL field, which is now ignored. In this
  344. // case, ConjureAPIRegistrarBidirectionalURL will be blank. Reset
  345. // this replay.
  346. (dialParams.ConjureAPIRegistration && dialParams.ConjureAPIRegistrarBidirectionalURL == "")) {
  347. // In these cases, existing dial parameters are expired or no longer
  348. // match the config state and so are cleared to avoid rechecking them.
  349. err = DeleteDialParameters(serverEntry.IpAddress, networkID)
  350. if err != nil {
  351. NoticeWarning("DeleteDialParameters failed: %s", err)
  352. }
  353. // Reselect new dial parameters.
  354. dialParams = nil
  355. }
  356. if dialParams != nil {
  357. if config.DisableReplay ||
  358. !canReplay(serverEntry, dialParams.TunnelProtocol) {
  359. // In these ephemeral cases, existing dial parameters may still be valid
  360. // and used in future establishment phases, and so are retained.
  361. dialParams = nil
  362. }
  363. }
  364. // IsExchanged:
  365. //
  366. // Dial parameters received via client-to-client exchange are partially
  367. // initialized. Only the exchange fields are retained, and all other dial
  368. // parameters fields must be initialized. This is not considered or logged as
  369. // a replay. The exchange case is identified by the IsExchanged flag.
  370. //
  371. // When previously stored, IsExchanged dial parameters will have set the same
  372. // timestamp and state hash used for regular dial parameters and the same
  373. // logic above should invalidate expired or invalid exchanged dial
  374. // parameters.
  375. //
  376. // Limitation: metrics will indicate when an exchanged server entry is used
  377. // (source "EXCHANGED") but will not indicate when exchanged dial parameters
  378. // are used vs. a redial after discarding dial parameters.
  379. isReplay := (dialParams != nil)
  380. isExchanged := isReplay && dialParams.IsExchanged
  381. if !isReplay {
  382. dialParams = &DialParameters{}
  383. }
  384. if isExchanged {
  385. // Set isReplay to false to cause all non-exchanged values to be
  386. // initialized; this also causes the exchange case to not log as replay.
  387. isReplay = false
  388. }
  389. // Set IsExchanged such that full dial parameters are stored and replayed
  390. // upon success.
  391. dialParams.IsExchanged = false
  392. // Point to the current resolver to be used in dials.
  393. dialParams.resolver = config.GetResolver()
  394. if dialParams.resolver == nil {
  395. return nil, errors.TraceNew("missing resolver")
  396. }
  397. dialParams.steeringIPCache = steeringIPCache
  398. dialParams.ServerEntry = serverEntry
  399. dialParams.NetworkID = networkID
  400. dialParams.IsReplay = isReplay
  401. dialParams.ReplayIgnoredChange = isReplay && configChanged
  402. dialParams.CandidateNumber = candidateNumber
  403. dialParams.EstablishedTunnelsCount = establishedTunnelsCount
  404. // Set the DSLPrioritizedDial flag for metrics. The flag is set after
  405. // replacing the pending placholder and retained as long as the dial
  406. // parameters are replayed.
  407. dialParams.DSLPrioritizedDial =
  408. dslPendingPrioritizeDial || (isReplay && dialParams.DSLPrioritizedDial)
  409. // Even when replaying, LastUsedTimestamp is updated to extend the TTL of
  410. // replayed dial parameters which will be updated in the datastore upon
  411. // success.
  412. if ttl > 0 {
  413. dialParams.LastUsedTimestamp = currentTimestamp
  414. } else {
  415. dialParams.LastUsedTimestamp = time.Time{}
  416. }
  417. dialParams.LastUsedConfigStateHash = configStateHash
  418. dialParams.LastUsedServerEntryHash = serverEntryHash
  419. // Initialize dial parameters.
  420. //
  421. // When not replaying, all required parameters are initialized. When
  422. // replaying, existing parameters are retained, subject to the replay-X
  423. // tactics flags.
  424. // Select a network latency multiplier for this dial. This allows clients to
  425. // explore and discover timeout values appropriate for the current network.
  426. // The selection applies per tunnel, to avoid delaying all establishment
  427. // candidates due to excessive timeouts. The random selection is bounded by a
  428. // min/max set in tactics and an exponential distribution is used so as to
  429. // heavily favor values close to the min, which should be set to the
  430. // singleton NetworkLatencyMultiplier tactics value.
  431. //
  432. // For NetworkLatencyMultiplierLambda close to 2.0, values near min are
  433. // very approximately 10x more likely to be selected than values near
  434. // max, while for NetworkLatencyMultiplierLambda close to 0.1, the
  435. // distribution is close to uniform.
  436. //
  437. // Not all existing, persisted DialParameters will have a custom
  438. // NetworkLatencyMultiplier value. Its zero value will cause the singleton
  439. // NetworkLatencyMultiplier tactics value to be used instead, which is
  440. // consistent with the pre-custom multiplier behavior in the older client
  441. // version which persisted that DialParameters.
  442. networkLatencyMultiplierMin := p.Float(parameters.NetworkLatencyMultiplierMin)
  443. networkLatencyMultiplierMax := p.Float(parameters.NetworkLatencyMultiplierMax)
  444. if !isReplay ||
  445. // Was selected...
  446. (dialParams.NetworkLatencyMultiplier != 0.0 &&
  447. // But is now outside tactics range...
  448. (dialParams.NetworkLatencyMultiplier < networkLatencyMultiplierMin ||
  449. dialParams.NetworkLatencyMultiplier > networkLatencyMultiplierMax)) {
  450. dialParams.NetworkLatencyMultiplier = prng.ExpFloat64Range(
  451. networkLatencyMultiplierMin,
  452. networkLatencyMultiplierMax,
  453. p.Float(parameters.NetworkLatencyMultiplierLambda))
  454. }
  455. // After this point, any tactics parameters that apply the network latency
  456. // multiplier will use this selected value.
  457. p = config.GetParameters().GetCustom(dialParams.NetworkLatencyMultiplier)
  458. if !isReplay && !isExchanged {
  459. // TODO: should there be a pre-check of selectProtocol before incurring
  460. // overhead of unmarshaling dial parameters? In may be that a server entry
  461. // is fully incapable of satisfying the current protocol selection
  462. // constraints.
  463. selectedProtocol, ok := selectProtocol(serverEntry)
  464. if !ok {
  465. return nil, nil
  466. }
  467. dialParams.TunnelProtocol = selectedProtocol
  468. }
  469. if isTactics && !protocol.TunnelProtocolSupportsTactics(dialParams.TunnelProtocol) {
  470. NoticeSkipServerEntry(
  471. "protocol does not support tactics request: %s",
  472. dialParams.TunnelProtocol)
  473. return nil, nil
  474. }
  475. // Skip this candidate when the clients tactics restrict usage of the
  476. // provider ID. See the corresponding server-side enforcement comments in
  477. // server.TacticsListener.accept.
  478. if protocol.TunnelProtocolIsDirect(dialParams.TunnelProtocol) &&
  479. common.ContainsAny(
  480. p.KeyStrings(
  481. parameters.RestrictDirectProviderRegions,
  482. dialParams.ServerEntry.ProviderID),
  483. []string{"", serverEntry.Region}) {
  484. if p.WeightedCoinFlip(
  485. parameters.RestrictDirectProviderIDsClientProbability) {
  486. // When skipping, return nil/nil as no error should be logged.
  487. // NoticeSkipServerEntry emits each skip reason, regardless
  488. // of server entry, at most once per session.
  489. NoticeSkipServerEntry(
  490. "restricted provider ID: %s",
  491. dialParams.ServerEntry.ProviderID)
  492. return nil, nil
  493. }
  494. }
  495. // Skip this candidate when the clients tactics restrict usage of the
  496. // provider ID. See the corresponding server-side enforcement comments in
  497. // server.sshClient.setHandshakeState.
  498. if protocol.TunnelProtocolUsesInproxy(dialParams.TunnelProtocol) &&
  499. common.ContainsAny(
  500. p.KeyStrings(
  501. parameters.RestrictInproxyProviderRegions,
  502. dialParams.ServerEntry.ProviderID),
  503. []string{"", serverEntry.Region}) {
  504. if p.WeightedCoinFlip(
  505. parameters.RestrictInproxyProviderIDsClientProbability) {
  506. // When skipping, return nil/nil as no error should be logged.
  507. // NoticeSkipServerEntry emits each skip reason, regardless
  508. // of server entry, at most once per session.
  509. NoticeSkipServerEntry(
  510. "restricted in-proxy provider ID: %s",
  511. dialParams.ServerEntry.ProviderID)
  512. return nil, nil
  513. }
  514. }
  515. // Skip this candidate when the clients tactics restrict usage of the
  516. // fronting provider ID. See the corresponding server-side enforcement
  517. // comments in server.MeekServer.getSessionOrEndpoint.
  518. //
  519. // RestrictFrontingProviderIDs applies only to fronted meek tunnels, where
  520. // all traffic is relayed through a fronting provider.
  521. if protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) &&
  522. common.Contains(
  523. p.Strings(parameters.RestrictFrontingProviderIDs),
  524. dialParams.ServerEntry.FrontingProviderID) {
  525. if p.WeightedCoinFlip(
  526. parameters.RestrictFrontingProviderIDsClientProbability) {
  527. // When skipping, return nil/nil as no error should be logged.
  528. // NoticeSkipServerEntry emits each skip reason, regardless
  529. // of server entry, at most once per session.
  530. NoticeSkipServerEntry(
  531. "restricted fronting provider ID: %s",
  532. dialParams.ServerEntry.FrontingProviderID)
  533. return nil, nil
  534. }
  535. }
  536. if config.UseUpstreamProxy() {
  537. // When UpstreamProxy is configured, ServerEntry.GetSupportedProtocols, when
  538. // called via selectProtocol, will filter out protocols such that will not
  539. // select a protocol incompatible with UpstreamProxy. This additional check
  540. // will catch cases where selectProtocol does not apply this filter.
  541. if !protocol.TunnelProtocolSupportsUpstreamProxy(dialParams.TunnelProtocol) {
  542. NoticeSkipServerEntry(
  543. "protocol does not support upstream proxy: %s",
  544. dialParams.TunnelProtocol)
  545. return nil, nil
  546. }
  547. // Skip this candidate when the server entry is not to be used with an
  548. // upstream proxy. By not exposing servers from sources that are
  549. // relatively hard to enumerate, this mechanism mitigates the risk of
  550. // a malicious upstream proxy enumerating Psiphon servers. Populate
  551. // the allowed sources with fronted servers to provide greater
  552. // blocking resistence for clients using upstream proxy clients that
  553. // are subject to blocking.
  554. source := dialParams.ServerEntry.LocalSource
  555. if !protocol.AllowServerEntrySourceWithUpstreamProxy(source) &&
  556. !p.Bool(parameters.UpstreamProxyAllowAllServerEntrySources) {
  557. NoticeSkipServerEntry(
  558. "server entry source disallowed with upstream proxy: %s",
  559. source)
  560. return nil, nil
  561. }
  562. }
  563. if (!isReplay || !replayBPF) &&
  564. ClientBPFEnabled() &&
  565. protocol.TunnelProtocolMayUseClientBPF(dialParams.TunnelProtocol) {
  566. if p.WeightedCoinFlip(parameters.BPFClientTCPProbability) {
  567. dialParams.BPFProgramName = ""
  568. dialParams.BPFProgramInstructions = nil
  569. ok, name, rawInstructions := p.BPFProgram(parameters.BPFClientTCPProgram)
  570. if ok {
  571. dialParams.BPFProgramName = name
  572. dialParams.BPFProgramInstructions = rawInstructions
  573. }
  574. }
  575. }
  576. if !isReplay || !replaySSH {
  577. dialParams.SelectedSSHClientVersion = true
  578. dialParams.SSHClientVersion = values.GetSSHClientVersion()
  579. dialParams.SSHKEXSeed, err = prng.NewSeed()
  580. if err != nil {
  581. return nil, errors.Trace(err)
  582. }
  583. }
  584. if !isReplay || !replayObfuscatorPadding {
  585. dialParams.ObfuscatorPaddingSeed, err = prng.NewSeed()
  586. if err != nil {
  587. return nil, errors.Trace(err)
  588. }
  589. if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) {
  590. dialParams.MeekObfuscatorPaddingSeed, err = prng.NewSeed()
  591. if err != nil {
  592. return nil, errors.Trace(err)
  593. }
  594. } else if protocol.TunnelProtocolUsesTLSOSSH(dialParams.TunnelProtocol) {
  595. dialParams.TLSOSSHObfuscatorPaddingSeed, err = prng.NewSeed()
  596. if err != nil {
  597. return nil, errors.Trace(err)
  598. }
  599. }
  600. }
  601. if !isReplay || !replayFragmentor {
  602. dialParams.FragmentorSeed, err = prng.NewSeed()
  603. if err != nil {
  604. return nil, errors.Trace(err)
  605. }
  606. }
  607. if (!isReplay || !replayConjureRegistration) &&
  608. protocol.TunnelProtocolUsesConjure(dialParams.TunnelProtocol) {
  609. dialParams.ConjureCachedRegistrationTTL = p.Duration(parameters.ConjureCachedRegistrationTTL)
  610. apiURL := p.String(parameters.ConjureAPIRegistrarBidirectionalURL)
  611. decoyWidth := p.Int(parameters.ConjureDecoyRegistrarWidth)
  612. dialParams.ConjureAPIRegistration = apiURL != ""
  613. dialParams.ConjureDecoyRegistration = decoyWidth != 0
  614. // We select only one of API or decoy registration. When both are enabled,
  615. // ConjureDecoyRegistrarProbability determines the probability of using
  616. // decoy registration.
  617. //
  618. // In general, we disable retries in gotapdance and rely on Psiphon
  619. // establishment to try/retry different registration schemes. This allows us
  620. // to control the proportion of registration types attempted. And, in good
  621. // network conditions, individual candidates are most likely to be cancelled
  622. // before they exhaust their retry options.
  623. if dialParams.ConjureAPIRegistration && dialParams.ConjureDecoyRegistration {
  624. if p.WeightedCoinFlip(parameters.ConjureDecoyRegistrarProbability) {
  625. dialParams.ConjureAPIRegistration = false
  626. }
  627. }
  628. if dialParams.ConjureAPIRegistration {
  629. // While Conjure API registration uses MeekConn and specifies common meek
  630. // parameters, the meek address and SNI configuration is implemented in this
  631. // code block and not in common code blocks below. The exception is TLS
  632. // configuration.
  633. //
  634. // Accordingly, replayFronting/replayHostname have no effect on Conjure API
  635. // registration replay.
  636. dialParams.ConjureAPIRegistrarBidirectionalURL = apiURL
  637. frontingSpecs := p.FrontingSpecs(parameters.ConjureAPIRegistrarFrontingSpecs)
  638. var frontingTransport string
  639. dialParams.FrontingProviderID,
  640. frontingTransport,
  641. dialParams.MeekFrontingDialAddress,
  642. dialParams.MeekSNIServerName,
  643. dialParams.MeekVerifyServerName,
  644. dialParams.MeekVerifyPins,
  645. dialParams.MeekFrontingHost,
  646. err = frontingSpecs.SelectParameters()
  647. if err != nil {
  648. return nil, errors.Trace(err)
  649. }
  650. if frontingTransport != protocol.FRONTING_TRANSPORT_HTTPS {
  651. return nil, errors.TraceNew("unsupported fronting transport")
  652. }
  653. if config.DisableSystemRootCAs {
  654. return nil, errors.TraceNew("TLS certificates must be verified in Conjure API registration")
  655. }
  656. dialParams.MeekDialAddress = net.JoinHostPort(dialParams.MeekFrontingDialAddress, "443")
  657. dialParams.MeekHostHeader = dialParams.MeekFrontingHost
  658. // For a FrontingSpec, an SNI value of "" indicates to disable/omit SNI, so
  659. // never transform in that case.
  660. if dialParams.MeekSNIServerName != "" {
  661. if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
  662. dialParams.MeekSNIServerName = selectHostName(dialParams.TunnelProtocol, p)
  663. dialParams.MeekTransformedHostName = true
  664. }
  665. }
  666. // The minimum delay value is determined by the Conjure station, which
  667. // performs an asynchronous "liveness test" against the selected phantom
  668. // IPs. The min/max range allows us to introduce some jitter so that we
  669. // don't present a trivial inter-flow fingerprint: CDN connection, fixed
  670. // delay, phantom dial.
  671. minDelay := p.Duration(parameters.ConjureAPIRegistrarMinDelay)
  672. maxDelay := p.Duration(parameters.ConjureAPIRegistrarMaxDelay)
  673. dialParams.ConjureAPIRegistrarDelay = prng.Period(minDelay, maxDelay)
  674. } else if dialParams.ConjureDecoyRegistration {
  675. dialParams.ConjureDecoyRegistrarWidth = decoyWidth
  676. minDelay := p.Duration(parameters.ConjureDecoyRegistrarMinDelay)
  677. maxDelay := p.Duration(parameters.ConjureDecoyRegistrarMaxDelay)
  678. dialParams.ConjureAPIRegistrarDelay = prng.Period(minDelay, maxDelay)
  679. } else {
  680. return nil, errors.TraceNew("no Conjure registrar configured")
  681. }
  682. }
  683. if (!isReplay || !replayConjureTransport) &&
  684. protocol.TunnelProtocolUsesConjure(dialParams.TunnelProtocol) {
  685. // None of ConjureEnableIPv6Dials, ConjureEnablePortRandomization, or
  686. // ConjureEnableRegistrationOverrides are set here for replay. The
  687. // current value of these flag parameters is always applied.
  688. dialParams.ConjureTransport = selectConjureTransport(p)
  689. if protocol.ConjureTransportUsesSTUN(dialParams.ConjureTransport) {
  690. stunServerAddresses := p.Strings(parameters.ConjureSTUNServerAddresses)
  691. if len(stunServerAddresses) == 0 {
  692. return nil, errors.Tracef(
  693. "no Conjure STUN servers addresses configured for transport %s", dialParams.ConjureTransport)
  694. }
  695. dialParams.ConjureSTUNServerAddress = stunServerAddresses[prng.Intn(len(stunServerAddresses))]
  696. dialParams.ConjureDTLSEmptyInitialPacket = p.WeightedCoinFlip(
  697. parameters.ConjureDTLSEmptyInitialPacketProbability)
  698. }
  699. }
  700. usingTLS := protocol.TunnelProtocolUsesMeekHTTPS(dialParams.TunnelProtocol) ||
  701. protocol.TunnelProtocolUsesTLSOSSH(dialParams.TunnelProtocol) ||
  702. dialParams.ConjureAPIRegistration
  703. // Note that ConjureAPIRegistartion is not wired to use the TLS session cache.
  704. if tlsClientSessionCache != nil && usingTLS {
  705. var sessionKey string
  706. if protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) {
  707. // UsesMeekHTTPS and UsesFrontedMeek
  708. // Special case: the session key is the resolved IP address of the CDN edge at dial time.
  709. sessionKey = common.TLS_NULL_SESSION_KEY
  710. } else {
  711. sessionKey, err = serverEntry.GetTLSSessionCacheKeyAddress(dialParams.TunnelProtocol)
  712. if err != nil {
  713. return nil, errors.Trace(err)
  714. }
  715. }
  716. dialParams.tlsClientSessionCache = common.WrapUtlsClientSessionCache(tlsClientSessionCache, sessionKey)
  717. if !isReplay {
  718. // Remove the cache entry to make a fresh dial when !isReplay.
  719. dialParams.tlsClientSessionCache.RemoveCacheEntry()
  720. }
  721. }
  722. if (!isReplay || !replayTLSProfile) && usingTLS {
  723. dialParams.SelectedTLSProfile = true
  724. requireTLS12SessionTickets := protocol.TunnelProtocolRequiresTLS12SessionTickets(
  725. dialParams.TunnelProtocol)
  726. requireTLS13Support := protocol.TunnelProtocolRequiresTLS13Support(dialParams.TunnelProtocol)
  727. isFronted := protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) ||
  728. dialParams.ConjureAPIRegistration
  729. dialParams.TLSProfile, dialParams.TLSVersion, dialParams.RandomizedTLSProfileSeed, err = SelectTLSProfile(
  730. requireTLS12SessionTickets, requireTLS13Support, isFronted, serverEntry.FrontingProviderID, p)
  731. if err != nil {
  732. return nil, errors.Trace(err)
  733. }
  734. if dialParams.TLSProfile == "" && (requireTLS12SessionTickets || requireTLS13Support) {
  735. return nil, errors.TraceNew("required TLS profile not found")
  736. }
  737. dialParams.NoDefaultTLSSessionID = p.WeightedCoinFlip(
  738. parameters.NoDefaultTLSSessionIDProbability)
  739. }
  740. if (!isReplay || !replayFronting) &&
  741. protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) {
  742. dialParams.FrontingProviderID = serverEntry.FrontingProviderID
  743. dialParams.MeekFrontingDialAddress, dialParams.MeekFrontingHost, err =
  744. selectFrontingParameters(serverEntry)
  745. if err != nil {
  746. return nil, errors.Trace(err)
  747. }
  748. }
  749. if !isReplay || !replayHostname {
  750. // Any MeekHostHeader selections made here will be overridden below,
  751. // as required, for fronting cases.
  752. if protocol.TunnelProtocolUsesMeekHTTPS(dialParams.TunnelProtocol) ||
  753. protocol.TunnelProtocolUsesFrontedMeekQUIC(dialParams.TunnelProtocol) {
  754. dialParams.MeekSNIServerName = ""
  755. hostname := ""
  756. if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
  757. dialParams.MeekSNIServerName = selectHostName(dialParams.TunnelProtocol, p)
  758. hostname = dialParams.MeekSNIServerName
  759. dialParams.MeekTransformedHostName = true
  760. } else {
  761. // Always select a hostname for the Host header in this case.
  762. // Unlike HTTP, the Host header isn't plaintext on the wire,
  763. // and so there's no anti-fingerprint benefit from presenting
  764. // the server IP address in the Host header. Omitting the
  765. // server IP here can prevent exposing it in certain
  766. // scenarios where the traffic is rerouted and arrives at a
  767. // different HTTPS server.
  768. hostname = selectHostName(dialParams.TunnelProtocol, p)
  769. }
  770. if serverEntry.MeekServerPort == 443 {
  771. dialParams.MeekHostHeader = hostname
  772. } else {
  773. dialParams.MeekHostHeader = net.JoinHostPort(
  774. hostname, strconv.Itoa(serverEntry.MeekServerPort))
  775. }
  776. } else if protocol.TunnelProtocolUsesTLSOSSH(dialParams.TunnelProtocol) {
  777. dialParams.TLSOSSHSNIServerName = ""
  778. if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
  779. dialParams.TLSOSSHSNIServerName = selectHostName(dialParams.TunnelProtocol, p)
  780. dialParams.TLSOSSHTransformedSNIServerName = true
  781. }
  782. } else if protocol.TunnelProtocolUsesMeekHTTP(dialParams.TunnelProtocol) {
  783. dialParams.MeekHostHeader = ""
  784. hostname := serverEntry.IpAddress
  785. if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
  786. hostname = selectHostName(dialParams.TunnelProtocol, p)
  787. dialParams.MeekTransformedHostName = true
  788. }
  789. if serverEntry.MeekServerPort == 80 {
  790. dialParams.MeekHostHeader = hostname
  791. } else {
  792. dialParams.MeekHostHeader = net.JoinHostPort(
  793. hostname, strconv.Itoa(serverEntry.MeekServerPort))
  794. }
  795. } else if protocol.TunnelProtocolUsesQUIC(dialParams.TunnelProtocol) {
  796. dialParams.QUICDialSNIAddress = selectHostName(dialParams.TunnelProtocol, p)
  797. }
  798. }
  799. if (!isReplay || !replayQUICVersion) &&
  800. protocol.TunnelProtocolUsesQUIC(dialParams.TunnelProtocol) {
  801. isFronted := protocol.TunnelProtocolUsesFrontedMeekQUIC(dialParams.TunnelProtocol)
  802. isInproxy := protocol.TunnelProtocolUsesInproxy(dialParams.TunnelProtocol)
  803. dialParams.QUICVersion = selectQUICVersion(isFronted, isInproxy, serverEntry, p)
  804. // Due to potential tactics configurations, it may be that no QUIC
  805. // version is selected. Abort immediately, with no error, as in the
  806. // selectProtocol case. quic.Dial and quic.NewQUICTransporter will
  807. // check for a missing QUIC version, but at that later stage an
  808. // unnecessary failed_tunnel can be logged in this scenario.
  809. if dialParams.QUICVersion == "" {
  810. return nil, nil
  811. }
  812. if protocol.QUICVersionHasRandomizedClientHello(dialParams.QUICVersion) {
  813. dialParams.QUICClientHelloSeed, err = prng.NewSeed()
  814. if err != nil {
  815. return nil, errors.Trace(err)
  816. }
  817. }
  818. // Coin-flip for obfuscated PSK use for non-fronted QUIC.
  819. if !isFronted {
  820. dialParams.QUICUseObfuscatedPSK = p.WeightedCoinFlip(parameters.QUICObfuscatedPSKProbability)
  821. }
  822. dialParams.QUICDialEarly = p.WeightedCoinFlip(parameters.QUICDialEarlyProbability)
  823. dialParams.QUICDisablePathMTUDiscovery =
  824. protocol.QUICVersionUsesPathMTUDiscovery(dialParams.QUICVersion) &&
  825. p.WeightedCoinFlip(parameters.QUICDisableClientPathMTUDiscoveryProbability)
  826. }
  827. if quicTLSClientSessionCache != nil && protocol.TunnelProtocolUsesQUIC(dialParams.TunnelProtocol) {
  828. sessionKey, err := serverEntry.GetTLSSessionCacheKeyAddress(dialParams.TunnelProtocol)
  829. if err != nil {
  830. return nil, errors.Trace(err)
  831. }
  832. dialParams.quicTLSClientSessionCache = common.WrapClientSessionCache(
  833. quicTLSClientSessionCache,
  834. sessionKey)
  835. if !isReplay {
  836. // Remove the cache entry to make a fresh dial when !isReplay.
  837. dialParams.quicTLSClientSessionCache.RemoveCacheEntry()
  838. }
  839. }
  840. if (!isReplay || !replayObfuscatedQUIC) &&
  841. protocol.QUICVersionIsObfuscated(dialParams.QUICVersion) {
  842. dialParams.ObfuscatedQUICPaddingSeed, err = prng.NewSeed()
  843. if err != nil {
  844. return nil, errors.Trace(err)
  845. }
  846. }
  847. if protocol.QUICVersionIsObfuscated(dialParams.QUICVersion) {
  848. if serverEntry.DisableObfuscatedQUICTransforms {
  849. dialParams.ObfuscatedQUICNonceTransformerParameters = nil
  850. } else if !isReplay || !replayObfuscatedQUICNonceTransformer {
  851. params, err := makeSeedTransformerParameters(
  852. p,
  853. parameters.ObfuscatedQUICNonceTransformProbability,
  854. parameters.ObfuscatedQUICNonceTransformSpecs,
  855. parameters.ObfuscatedQUICNonceTransformScopedSpecNames)
  856. if err != nil {
  857. return nil, errors.Trace(err)
  858. }
  859. if params.TransformSpec != nil {
  860. dialParams.ObfuscatedQUICNonceTransformerParameters = params
  861. } else {
  862. dialParams.ObfuscatedQUICNonceTransformerParameters = nil
  863. }
  864. }
  865. }
  866. if !isReplay || !replayLivenessTest {
  867. // TODO: initialize only when LivenessTestMaxUp/DownstreamBytes > 0?
  868. dialParams.LivenessTestSeed, err = prng.NewSeed()
  869. if err != nil {
  870. return nil, errors.Trace(err)
  871. }
  872. }
  873. if !isReplay || !replayAPIRequestPadding {
  874. dialParams.APIRequestPaddingSeed, err = prng.NewSeed()
  875. if err != nil {
  876. return nil, errors.Trace(err)
  877. }
  878. }
  879. // Initialize dialParams.ResolveParameters for dials that will resolve
  880. // domain names, which currently includes fronted meek and Conjure API
  881. // registration, where the dial address is not an IP address.
  882. //
  883. // dialParams.ResolveParameters must be nil when the dial address is an IP
  884. // address to ensure that no DNS dial parameters are reported in metrics
  885. // or diagnostics when when no domain is resolved.
  886. //
  887. // No resolve parameters are initialized for in-proxy dials; broker and
  888. // STUN domain resolves use distinct ResolveParameters; and the proxy,
  889. // not the client, resolves any 2nd hop dial address domain.
  890. //
  891. // Limitation: DNSResolverPreresolvedIPAddressCIDRs could be applied by
  892. // the in-proxy client, and relayed to the proxy, enabling a preresolved
  893. // dial by the proxy, but this is currently not compatible with broker
  894. // dial destination verification.
  895. useResolver := (protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) ||
  896. dialParams.ConjureAPIRegistration) &&
  897. !protocol.TunnelProtocolUsesInproxy(dialParams.TunnelProtocol) &&
  898. net.ParseIP(dialParams.MeekFrontingDialAddress) == nil
  899. if (!isReplay || !replayResolveParameters) && useResolver {
  900. dialParams.ResolveParameters, err = dialParams.resolver.MakeResolveParameters(
  901. p, dialParams.FrontingProviderID, dialParams.MeekFrontingDialAddress)
  902. if err != nil {
  903. return nil, errors.Trace(err)
  904. }
  905. }
  906. if !isReplay || !replayHoldOffTunnel {
  907. var HoldOffTunnelProtocolDuration time.Duration
  908. var HoldOffFrontingTunnelDuration time.Duration
  909. var holdOffDirectTunnelDuration time.Duration
  910. var holdOffInproxyTunnelDuration time.Duration
  911. if common.Contains(
  912. p.TunnelProtocols(parameters.HoldOffTunnelProtocolNames), dialParams.TunnelProtocol) {
  913. if p.WeightedCoinFlip(parameters.HoldOffTunnelProtocolProbability) {
  914. HoldOffTunnelProtocolDuration = prng.Period(
  915. p.Duration(parameters.HoldOffTunnelProtocolMinDuration),
  916. p.Duration(parameters.HoldOffTunnelProtocolMaxDuration))
  917. }
  918. }
  919. if protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) &&
  920. common.Contains(
  921. p.Strings(parameters.HoldOffFrontingTunnelProviderIDs),
  922. dialParams.FrontingProviderID) {
  923. if p.WeightedCoinFlip(parameters.HoldOffFrontingTunnelProbability) {
  924. HoldOffFrontingTunnelDuration = prng.Period(
  925. p.Duration(parameters.HoldOffFrontingTunnelMinDuration),
  926. p.Duration(parameters.HoldOffFrontingTunnelMaxDuration))
  927. }
  928. }
  929. if protocol.TunnelProtocolIsDirect(dialParams.TunnelProtocol) &&
  930. common.ContainsAny(
  931. p.KeyStrings(
  932. parameters.HoldOffDirectTunnelProviderRegions,
  933. dialParams.ServerEntry.ProviderID),
  934. []string{"", serverEntry.Region}) {
  935. if p.WeightedCoinFlip(parameters.HoldOffDirectTunnelProbability) {
  936. holdOffDirectTunnelDuration = prng.Period(
  937. p.Duration(parameters.HoldOffDirectTunnelMinDuration),
  938. p.Duration(parameters.HoldOffDirectTunnelMaxDuration))
  939. }
  940. }
  941. if protocol.TunnelProtocolUsesInproxy(dialParams.TunnelProtocol) &&
  942. common.ContainsAny(
  943. p.KeyStrings(
  944. parameters.HoldOffInproxyTunnelProviderRegions,
  945. dialParams.ServerEntry.ProviderID),
  946. []string{"", serverEntry.Region}) {
  947. if p.WeightedCoinFlip(parameters.HoldOffInproxyTunnelProbability) {
  948. holdOffInproxyTunnelDuration = prng.Period(
  949. p.Duration(parameters.HoldOffInproxyTunnelMinDuration),
  950. p.Duration(parameters.HoldOffInproxyTunnelMaxDuration))
  951. }
  952. }
  953. // Use the longest hold off duration
  954. dialParams.HoldOffTunnelDuration = common.MaxDuration(
  955. HoldOffTunnelProtocolDuration,
  956. HoldOffFrontingTunnelDuration,
  957. holdOffDirectTunnelDuration,
  958. holdOffInproxyTunnelDuration)
  959. }
  960. // OSSH prefix and seed transform are applied only to the OSSH tunnel protocol,
  961. // and not to any other protocol layered over OSSH.
  962. if protocol.TunnelProtocolIsObfuscatedSSH(dialParams.TunnelProtocol) {
  963. // Limitation: in the case of in-proxy OSSH, the client will get and
  964. // apply tactics based on its geolocation, but any OSSH prefix is
  965. // visible on the wire only after the 2nd hop. Configuring an OSSH
  966. // prefix based on the in-proxy proxy geolocation would be preferable.
  967. if serverEntry.DisableOSSHTransforms {
  968. dialParams.OSSHObfuscatorSeedTransformerParameters = nil
  969. } else if !isReplay || !replayOSSHSeedTransformerParameters {
  970. params, err := makeSeedTransformerParameters(
  971. p,
  972. parameters.OSSHObfuscatorSeedTransformProbability,
  973. parameters.OSSHObfuscatorSeedTransformSpecs,
  974. parameters.OSSHObfuscatorSeedTransformScopedSpecNames)
  975. if err != nil {
  976. return nil, errors.Trace(err)
  977. }
  978. if params.TransformSpec != nil {
  979. dialParams.OSSHObfuscatorSeedTransformerParameters = params
  980. } else {
  981. dialParams.OSSHObfuscatorSeedTransformerParameters = nil
  982. }
  983. }
  984. if serverEntry.DisableOSSHPrefix {
  985. dialParams.OSSHPrefixSpec = nil
  986. dialParams.OSSHPrefixSplitConfig = nil
  987. } else if !isReplay || !replayOSSHPrefix {
  988. dialPortNumber, err := serverEntry.GetDialPortNumber(
  989. dialParams.TunnelProtocol)
  990. if err != nil {
  991. return nil, errors.Trace(err)
  992. }
  993. prefixSpec, err := makeOSSHPrefixSpecParameters(
  994. p, strconv.Itoa(dialPortNumber))
  995. if err != nil {
  996. return nil, errors.Trace(err)
  997. }
  998. splitConfig, err := makeOSSHPrefixSplitConfig(p)
  999. if err != nil {
  1000. return nil, errors.Trace(err)
  1001. }
  1002. if prefixSpec.Spec != nil {
  1003. dialParams.OSSHPrefixSpec = prefixSpec
  1004. dialParams.OSSHPrefixSplitConfig = splitConfig
  1005. } else {
  1006. dialParams.OSSHPrefixSpec = nil
  1007. dialParams.OSSHPrefixSplitConfig = nil
  1008. }
  1009. }
  1010. // OSSHPrefix supersedes OSSHObfuscatorSeedTransform.
  1011. // This ensures both tactics are not used simultaneously,
  1012. // until OSSHObfuscatorSeedTransform is removed.
  1013. if dialParams.OSSHPrefixSpec != nil {
  1014. dialParams.OSSHObfuscatorSeedTransformerParameters = nil
  1015. }
  1016. }
  1017. if protocol.TunnelProtocolUsesShadowsocks(dialParams.TunnelProtocol) {
  1018. if serverEntry.DisableShadowsocksPrefix {
  1019. dialParams.ShadowsocksPrefixSpec = nil
  1020. } else if !isReplay || !replayShadowsocksPrefix {
  1021. dialPortNumber, err := serverEntry.GetDialPortNumber(
  1022. dialParams.TunnelProtocol)
  1023. if err != nil {
  1024. return nil, errors.Trace(err)
  1025. }
  1026. prefixSpec, err := makeShadowsocksPrefixSpecParameters(
  1027. p, strconv.Itoa(dialPortNumber))
  1028. if err != nil {
  1029. return nil, errors.Trace(err)
  1030. }
  1031. if prefixSpec.Spec != nil {
  1032. dialParams.ShadowsocksPrefixSpec = prefixSpec
  1033. } else {
  1034. dialParams.ShadowsocksPrefixSpec = nil
  1035. }
  1036. }
  1037. }
  1038. if protocol.TunnelProtocolUsesMeekHTTP(dialParams.TunnelProtocol) {
  1039. if serverEntry.DisableHTTPTransforms {
  1040. dialParams.HTTPTransformerParameters = nil
  1041. } else if !isReplay || !replayHTTPTransformerParameters {
  1042. isFronted := protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol)
  1043. params, err := makeHTTPTransformerParameters(
  1044. p, serverEntry.FrontingProviderID, isFronted)
  1045. if err != nil {
  1046. return nil, errors.Trace(err)
  1047. }
  1048. if params.ProtocolTransformSpec != nil {
  1049. dialParams.HTTPTransformerParameters = params
  1050. } else {
  1051. dialParams.HTTPTransformerParameters = nil
  1052. }
  1053. }
  1054. }
  1055. // In-proxy dial configuration
  1056. // For untunneled tactics requests, meek servers running in-proxy tunnel
  1057. // protocols may be used, but the actual in-proxy 1st hop dial is skipped
  1058. // and the meek server is used directly.
  1059. if !isTactics && protocol.TunnelProtocolUsesInproxy(dialParams.TunnelProtocol) {
  1060. // Check for incompatible networks, such as running under a
  1061. // non-Psiphon VPN. While this check could be made before calling
  1062. // MakeDialParameters, such as in selectProtocol during iteration,
  1063. // checking here uses the network ID obtained in MakeDialParameters,
  1064. // and the logged warning is useful for diagnostics.
  1065. //
  1066. // This check is skipped when in-proxy protocols must be used.
  1067. if !config.IsInproxyClientPersonalPairingMode() &&
  1068. !p.TunnelProtocols(parameters.LimitTunnelProtocols).IsOnlyInproxyTunnelProtocols() {
  1069. incompatibleNetworkTypes := p.Strings(parameters.InproxyClientIncompatibleNetworkTypes)
  1070. compatibleNetwork := !common.Contains(
  1071. incompatibleNetworkTypes,
  1072. GetNetworkType(dialParams.NetworkID))
  1073. if !compatibleNetwork {
  1074. return nil, errors.TraceNew("inproxy protocols skipped on incompatible network")
  1075. }
  1076. }
  1077. // inproxyDialInitialized indicates that the inproxy dial was wired
  1078. // up, and this isn't an untunneled tactics request (isTactics).
  1079. dialParams.inproxyDialInitialized = true
  1080. // Store a reference to the current, shared in-proxy broker client.
  1081. //
  1082. // The broker client has its own, independent replay scheme and its
  1083. // own dial parameters which are reported for metrics.
  1084. dialParams.inproxyBrokerClient,
  1085. dialParams.inproxyBrokerDialParameters,
  1086. err = inproxyClientBrokerClientManager.GetBrokerClient(networkID)
  1087. if err != nil {
  1088. return nil, errors.Trace(err)
  1089. }
  1090. // Load the signed server entry to be presented to the broker as proof
  1091. // that the in-proxy destination is a Psiphon server. The original
  1092. // JSON server entry fields are loaded from the local data store
  1093. // (or from config.TargetServerEntry), since the signature may
  1094. // include fields, added after this client version, which are in the
  1095. // JSON but not in the protocol.ServerEntry.
  1096. var serverEntryFields protocol.ServerEntryFields
  1097. if serverEntry.LocalSource == protocol.SERVER_ENTRY_SOURCE_TARGET {
  1098. serverEntryFields, err = protocol.DecodeServerEntryFields(
  1099. config.TargetServerEntry, "", protocol.SERVER_ENTRY_SOURCE_TARGET)
  1100. if err != nil {
  1101. return nil, errors.Trace(err)
  1102. }
  1103. if serverEntryFields.GetIPAddress() != serverEntry.IpAddress {
  1104. return nil, errors.TraceNew("unexpected TargetServerEntry")
  1105. }
  1106. err = serverEntryFields.ToSignedFields()
  1107. if err != nil {
  1108. return nil, errors.Trace(err)
  1109. }
  1110. } else {
  1111. serverEntryFields, err = GetSignedServerEntryFields(serverEntry.IpAddress)
  1112. if err != nil {
  1113. return nil, errors.Trace(err)
  1114. }
  1115. }
  1116. // Verify the server entry signature locally to avoid a doomed broker
  1117. // round trip.
  1118. //
  1119. // Limitation: the broker still checks signatures, but it won't get to
  1120. // log an error in this case.
  1121. err = serverEntryFields.VerifySignature(config.ServerEntrySignaturePublicKey)
  1122. if err != nil {
  1123. return nil, errors.Trace(err)
  1124. }
  1125. packedServerEntryFields, err := protocol.EncodePackedServerEntryFields(serverEntryFields)
  1126. if err != nil {
  1127. return nil, errors.Trace(err)
  1128. }
  1129. dialParams.inproxyPackedSignedServerEntry, err = protocol.CBOREncoding.Marshal(packedServerEntryFields)
  1130. if err != nil {
  1131. return nil, errors.Trace(err)
  1132. }
  1133. dialParams.inproxyNATStateManager = inproxyClientNATStateManager
  1134. if !isReplay || !replayInproxySTUN {
  1135. isProxy := false
  1136. dialParams.InproxySTUNDialParameters, err = MakeInproxySTUNDialParameters(config, p, isProxy)
  1137. if err != nil {
  1138. return nil, errors.Trace(err)
  1139. }
  1140. } else if dialParams.InproxySTUNDialParameters != nil {
  1141. dialParams.InproxySTUNDialParameters.Prepare()
  1142. }
  1143. if !isReplay || !replayInproxyWebRTC {
  1144. dialParams.InproxyWebRTCDialParameters, err = MakeInproxyWebRTCDialParameters(p)
  1145. if err != nil {
  1146. return nil, errors.Trace(err)
  1147. }
  1148. }
  1149. if (!isReplay || !replayInproxyWebRTC) &&
  1150. protocol.TunnelProtocolUsesQUIC(dialParams.TunnelProtocol) &&
  1151. dialParams.InproxyWebRTCDialParameters.UseMediaStreams {
  1152. // In the in-proxy WebRTC media stream mode, QUIC packets are
  1153. // encapsulated in SRTP packet payloads, and the maximum QUIC
  1154. // packet size must be adjusted to fit. In addition, QUIC path
  1155. // MTU discovery is disabled, to avoid sending oversized packets.
  1156. dialParams.QUICMaxPacketSizeAdjustment = inproxy.GetQUICMaxPacketSizeAdjustment()
  1157. dialParams.QUICDisablePathMTUDiscovery = true
  1158. // Select a QUIC variant that is compatible with WebRTC media
  1159. // stream SRTP constraints. This selection overrides the previous
  1160. // selectQUICVersion. If a compatible QUIC variant cannot be
  1161. // selected, abort with no error, as is done in the previous
  1162. // selectQUICVersion case.
  1163. //
  1164. // Previous QUICUseObfuscatedPSK/QUICDialEarly parameter
  1165. // selections are retained, while parameters tied to the QUIC
  1166. // variant, including QUICClientHelloSeed and
  1167. // ObfuscatedQUICPaddingSeed/ObfuscatedQUICNonceTransformerParameters
  1168. // are set or cleared to match the new selection.
  1169. //
  1170. // Limitation: replayQUICVersion is ignored and
  1171. // replayInproxyWebRTC is used for this case, since
  1172. // UseMediaStreams is determined in the latter case.
  1173. dialParams.QUICVersion = selectWebRTCMediaStreamQUICVersion(serverEntry, p)
  1174. if dialParams.QUICVersion == "" {
  1175. return nil, nil
  1176. }
  1177. if protocol.QUICVersionHasRandomizedClientHello(dialParams.QUICVersion) {
  1178. dialParams.QUICClientHelloSeed, err = prng.NewSeed()
  1179. if err != nil {
  1180. return nil, errors.Trace(err)
  1181. }
  1182. }
  1183. if protocol.QUICVersionIsObfuscated(dialParams.QUICVersion) {
  1184. return nil, errors.TraceNew("unexpected obfuscated QUIC version")
  1185. }
  1186. dialParams.ObfuscatedQUICPaddingSeed = nil
  1187. dialParams.ObfuscatedQUICNonceTransformerParameters = nil
  1188. }
  1189. // dialParams.inproxyConn is left uninitialized until after the dial,
  1190. // and until then Load will return nil.
  1191. }
  1192. // Set dial address fields. This portion of configuration is
  1193. // deterministic, given the parameters established or replayed so far.
  1194. dialPortNumber, err := serverEntry.GetDialPortNumber(dialParams.TunnelProtocol)
  1195. if err != nil {
  1196. return nil, errors.Trace(err)
  1197. }
  1198. if dialPortNumber == 0 && p.Bool(parameters.ServerEntryPruneDialPortNumberZero) {
  1199. // Automatically prune any invalid server entry that has produced an
  1200. // invalid dial port number of 0. This case may arise due to missing
  1201. // port number fields in server entries. For older clients, this
  1202. // prune case is enforced in the server's status request
  1203. // failed_tunnel processing; see server.statusAPIRequestHandler.
  1204. PruneServerEntry(config, serverEntry.IpAddress)
  1205. return nil, errors.TraceNew("invalid dial port number")
  1206. }
  1207. dialParams.DialPortNumber = strconv.Itoa(dialPortNumber)
  1208. switch protocol.TunnelProtocolMinusInproxy(dialParams.TunnelProtocol) {
  1209. case protocol.TUNNEL_PROTOCOL_SSH,
  1210. protocol.TUNNEL_PROTOCOL_OBFUSCATED_SSH,
  1211. protocol.TUNNEL_PROTOCOL_TAPDANCE_OBFUSCATED_SSH,
  1212. protocol.TUNNEL_PROTOCOL_CONJURE_OBFUSCATED_SSH,
  1213. protocol.TUNNEL_PROTOCOL_QUIC_OBFUSCATED_SSH,
  1214. protocol.TUNNEL_PROTOCOL_TLS_OBFUSCATED_SSH,
  1215. protocol.TUNNEL_PROTOCOL_SHADOWSOCKS_OSSH:
  1216. dialParams.DirectDialAddress = net.JoinHostPort(serverEntry.IpAddress, dialParams.DialPortNumber)
  1217. case protocol.TUNNEL_PROTOCOL_FRONTED_MEEK,
  1218. protocol.TUNNEL_PROTOCOL_FRONTED_MEEK_QUIC_OBFUSCATED_SSH:
  1219. dialParams.MeekDialAddress = net.JoinHostPort(dialParams.MeekFrontingDialAddress, dialParams.DialPortNumber)
  1220. dialParams.MeekHostHeader = dialParams.MeekFrontingHost
  1221. if serverEntry.MeekFrontingDisableSNI {
  1222. dialParams.MeekSNIServerName = ""
  1223. // When SNI is omitted, the transformed host name is not used.
  1224. dialParams.MeekTransformedHostName = false
  1225. } else if !dialParams.MeekTransformedHostName {
  1226. dialParams.MeekSNIServerName = dialParams.MeekFrontingDialAddress
  1227. }
  1228. case protocol.TUNNEL_PROTOCOL_FRONTED_MEEK_HTTP:
  1229. dialParams.MeekDialAddress = net.JoinHostPort(dialParams.MeekFrontingDialAddress, dialParams.DialPortNumber)
  1230. dialParams.MeekHostHeader = dialParams.MeekFrontingHost
  1231. // For FRONTED HTTP, the Host header cannot be transformed.
  1232. dialParams.MeekTransformedHostName = false
  1233. case protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK:
  1234. dialParams.MeekDialAddress = net.JoinHostPort(serverEntry.IpAddress, dialParams.DialPortNumber)
  1235. case protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK_HTTPS,
  1236. protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK_SESSION_TICKET:
  1237. dialParams.MeekDialAddress = net.JoinHostPort(serverEntry.IpAddress, dialParams.DialPortNumber)
  1238. if !dialParams.MeekTransformedHostName {
  1239. // Note: IP address in SNI field will be omitted.
  1240. dialParams.MeekSNIServerName = serverEntry.IpAddress
  1241. }
  1242. default:
  1243. return nil, errors.Tracef(
  1244. "unknown tunnel protocol: %s", dialParams.TunnelProtocol)
  1245. }
  1246. if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) {
  1247. host, _, _ := net.SplitHostPort(dialParams.MeekDialAddress)
  1248. if p.Bool(parameters.MeekDialDomainsOnly) {
  1249. if net.ParseIP(host) != nil {
  1250. // No error, as this is a "not supported" case.
  1251. return nil, nil
  1252. }
  1253. }
  1254. // The underlying TLS implementation will automatically omit SNI for
  1255. // IP address server name values; we have this explicit check here so
  1256. // we record the correct value for stats.
  1257. if net.ParseIP(dialParams.MeekSNIServerName) != nil {
  1258. dialParams.MeekSNIServerName = ""
  1259. }
  1260. }
  1261. // TLS ClientHello fragmentation is applied only after the state
  1262. // of SNI is determined above.
  1263. if (!isReplay || !replayTLSFragmentClientHello) && usingTLS {
  1264. limitProtocols := p.TunnelProtocols(parameters.TLSFragmentClientHelloLimitProtocols)
  1265. if len(limitProtocols) == 0 || common.Contains(limitProtocols, dialParams.TunnelProtocol) {
  1266. // Note: The TLS stack automatically drops the SNI extension when
  1267. // the host is an IP address.
  1268. usingSNI := false
  1269. if dialParams.TLSOSSHSNIServerName != "" {
  1270. usingSNI = net.ParseIP(dialParams.TLSOSSHSNIServerName) == nil
  1271. } else if dialParams.MeekSNIServerName != "" {
  1272. usingSNI = net.ParseIP(dialParams.MeekSNIServerName) == nil
  1273. }
  1274. // TLS ClientHello fragmentor expects SNI to be present.
  1275. if usingSNI {
  1276. dialParams.TLSFragmentClientHello = p.WeightedCoinFlip(
  1277. parameters.TLSFragmentClientHelloProbability)
  1278. }
  1279. }
  1280. }
  1281. // Initialize upstream proxy.
  1282. if config.UseUpstreamProxy() {
  1283. // Note: UpstreamProxyURL will be validated in the dial
  1284. proxyURL, err := common.SafeParseURL(config.UpstreamProxyURL)
  1285. if err == nil {
  1286. dialParams.UpstreamProxyType = proxyURL.Scheme
  1287. }
  1288. }
  1289. // Initialize/replay User-Agent header for HTTP upstream proxy and meek protocols.
  1290. dialCustomHeaders := makeDialCustomHeaders(config, p)
  1291. if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) ||
  1292. dialParams.UpstreamProxyType == "http" ||
  1293. dialParams.ConjureAPIRegistration {
  1294. if !isReplay || !replayUserAgent {
  1295. dialParams.SelectedUserAgent, dialParams.UserAgent = selectUserAgentIfUnset(p, dialCustomHeaders)
  1296. }
  1297. if dialParams.SelectedUserAgent {
  1298. // Limitation: if config.CustomHeaders adds a User-Agent between
  1299. // replays, it may be ignored due to replaying a selected User-Agent.
  1300. dialCustomHeaders.Set("User-Agent", dialParams.UserAgent)
  1301. }
  1302. }
  1303. // UpstreamProxyCustomHeaderNames is a reported metric. Just the names and
  1304. // not the values are reported, in case the values are identifying.
  1305. if len(config.CustomHeaders) > 0 {
  1306. dialParams.UpstreamProxyCustomHeaderNames = make([]string, 0)
  1307. for name := range dialCustomHeaders {
  1308. if name == "User-Agent" && dialParams.SelectedUserAgent {
  1309. continue
  1310. }
  1311. dialParams.UpstreamProxyCustomHeaderNames = append(dialParams.UpstreamProxyCustomHeaderNames, name)
  1312. }
  1313. }
  1314. // Initialize Dial/MeekConfigs to be passed to the corresponding dialers.
  1315. var resolveIP func(ctx context.Context, hostname string) ([]net.IP, error)
  1316. // Determine whether to use a steering IP, and whether to indicate that
  1317. // this dial remains a replay or not.
  1318. //
  1319. // Steering IPs are used only for fronted tunnels and not lower-traffic
  1320. // tactics requests and signalling steps such as Conjure registration.
  1321. //
  1322. // The scope of the steering IP, and the corresponding cache key, is the
  1323. // fronting provider, tunnel protocol, and the current network ID.
  1324. //
  1325. // Currently, steering IPs are obtained and cached in the Psiphon API
  1326. // handshake response. A modest TTL is applied to cache entries, and, in
  1327. // the case of a failed tunnel, any corresponding cached steering IP is
  1328. // removed.
  1329. //
  1330. // DialParameters.SteeringIP is set and persisted, but is not used to dial
  1331. // in a replay case; it's used to determine whether this dial should be
  1332. // classified as a replay or not. A replay dial remains classified as
  1333. // replay if a steering IP is not used and no steering IP was used
  1334. // before; or when a steering IP is used and the same steering IP was
  1335. // used before.
  1336. //
  1337. // When a steering IP is used and none was used before, or vice versa,
  1338. // DialParameters.IsReplay is cleared so that is_replay is reported as
  1339. // false, since the dial may be very different in nature: using a
  1340. // different POP; skipping DNS; etc. Even if DialParameters.IsReplay was
  1341. // true and is cleared, this MakeDialParameters will have wired up all
  1342. // other dial parameters with replay values, so the benefit of those
  1343. // values is not lost.
  1344. var previousSteeringIP, currentSteeringIP string
  1345. if isReplay {
  1346. previousSteeringIP = dialParams.SteeringIP
  1347. }
  1348. dialParams.SteeringIP = ""
  1349. if !isTactics &&
  1350. protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) &&
  1351. dialParams.ServerEntry.FrontingProviderID != "" {
  1352. dialParams.steeringIPCacheKey = fmt.Sprintf("%s %s %s",
  1353. dialParams.NetworkID,
  1354. dialParams.ServerEntry.FrontingProviderID,
  1355. dialParams.TunnelProtocol)
  1356. steeringIPValue, ok := dialParams.steeringIPCache.Get(
  1357. dialParams.steeringIPCacheKey)
  1358. if ok {
  1359. currentSteeringIP = steeringIPValue.(string)
  1360. }
  1361. // A steering IP probability is applied and may be used to gradually
  1362. // apply steering IPs. The coin flip is made only to decide to start
  1363. // using a steering IP, avoiding flip flopping between dials. For any
  1364. // probability > 0.0, a long enough continuous session will
  1365. // eventually flip to true and then keep using steering IPs as long
  1366. // as they remain in the cache.
  1367. if previousSteeringIP == "" && currentSteeringIP != "" &&
  1368. !p.WeightedCoinFlip(parameters.SteeringIPProbability) {
  1369. currentSteeringIP = ""
  1370. }
  1371. }
  1372. if currentSteeringIP != "" {
  1373. IP := net.ParseIP(currentSteeringIP)
  1374. if IP == nil {
  1375. return nil, errors.TraceNew("invalid steering IP")
  1376. }
  1377. // Since tcpDial and NewUDPConn invoke ResolveIP unconditionally, even
  1378. // when the hostname is an IP address, a steering IP will be applied
  1379. // even in that case.
  1380. resolveIP = func(ctx context.Context, hostname string) ([]net.IP, error) {
  1381. return []net.IP{IP}, nil
  1382. }
  1383. // dialParams.SteeringIP will be used as the "previous" steering IP in
  1384. // the next replay.
  1385. dialParams.SteeringIP = currentSteeringIP
  1386. }
  1387. if currentSteeringIP != previousSteeringIP {
  1388. dialParams.IsReplay = false
  1389. }
  1390. // Custom ResolveParameters are set only when useResolver is true, but
  1391. // DialConfig.ResolveIP is required and wired up unconditionally. Any
  1392. // misconfigured or miscoded domain dial cases will use default
  1393. // ResolveParameters.
  1394. //
  1395. // ResolveIP will use the networkID obtained above, as it will be used
  1396. // almost immediately, instead of incurring the overhead of calling
  1397. // GetNetworkID again.
  1398. if resolveIP == nil {
  1399. resolveIP = func(ctx context.Context, hostname string) ([]net.IP, error) {
  1400. IPs, err := dialParams.resolver.ResolveIP(
  1401. ctx,
  1402. networkID,
  1403. dialParams.ResolveParameters,
  1404. hostname)
  1405. if err != nil {
  1406. return nil, errors.Trace(err)
  1407. }
  1408. return IPs, nil
  1409. }
  1410. }
  1411. // Fragmentor configuration.
  1412. // Note: fragmentorConfig is nil if fragmentor is disabled for prefixed OSSH.
  1413. //
  1414. // Limitation: when replaying and with replayIgnoreChangedConfigState set,
  1415. // fragmentor.NewUpstreamConfig may select a config using newer tactics
  1416. // parameters.
  1417. fragmentorConfig := fragmentor.NewUpstreamConfig(p, dialParams.TunnelProtocol, dialParams.FragmentorSeed)
  1418. if !p.Bool(parameters.OSSHPrefixEnableFragmentor) && dialParams.OSSHPrefixSpec != nil {
  1419. fragmentorConfig = nil
  1420. }
  1421. dialParams.dialConfig = &DialConfig{
  1422. DiagnosticID: serverEntry.GetDiagnosticID(),
  1423. UpstreamProxyURL: config.UpstreamProxyURL,
  1424. CustomHeaders: dialCustomHeaders,
  1425. BPFProgramInstructions: dialParams.BPFProgramInstructions,
  1426. DeviceBinder: config.deviceBinder,
  1427. IPv6Synthesizer: config.IPv6Synthesizer,
  1428. ResolveIP: resolveIP,
  1429. TrustedCACertificatesFilename: config.TrustedCACertificatesFilename,
  1430. FragmentorConfig: fragmentorConfig,
  1431. UpstreamProxyErrorCallback: upstreamProxyErrorCallback,
  1432. }
  1433. // Unconditionally initialize MeekResolvedIPAddress, so a valid string can
  1434. // always be read.
  1435. dialParams.MeekResolvedIPAddress.Store("")
  1436. if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) ||
  1437. dialParams.ConjureAPIRegistration {
  1438. // For tactics requests, AddPsiphonFrontingHeader is set when set for
  1439. // the related tunnel protocol. E.g., FRONTED-OSSH-MEEK for
  1440. // FRONTED-MEEK-TACTICS. AddPsiphonFrontingHeader is not replayed.
  1441. addFrontingHeader := addPsiphonFrontingHeader(
  1442. p,
  1443. dialParams.FrontingProviderID,
  1444. dialParams.TunnelProtocol,
  1445. dialParams.MeekDialAddress,
  1446. dialParams.ResolveParameters)
  1447. dialParams.meekConfig = &MeekConfig{
  1448. DiagnosticID: serverEntry.GetDiagnosticID(),
  1449. Parameters: config.GetParameters(),
  1450. DialAddress: dialParams.MeekDialAddress,
  1451. UseQUIC: protocol.TunnelProtocolUsesFrontedMeekQUIC(dialParams.TunnelProtocol),
  1452. QUICVersion: dialParams.QUICVersion,
  1453. QUICClientHelloSeed: dialParams.QUICClientHelloSeed,
  1454. QUICDialEarly: dialParams.QUICDialEarly,
  1455. QUICTLSClientSessionCache: dialParams.quicTLSClientSessionCache,
  1456. TLSClientSessionCache: dialParams.tlsClientSessionCache,
  1457. QUICDisablePathMTUDiscovery: dialParams.QUICDisablePathMTUDiscovery,
  1458. UseHTTPS: usingTLS,
  1459. TLSProfile: dialParams.TLSProfile,
  1460. TLSFragmentClientHello: dialParams.TLSFragmentClientHello,
  1461. LegacyPassthrough: serverEntry.ProtocolUsesLegacyPassthrough(dialParams.TunnelProtocol),
  1462. NoDefaultTLSSessionID: dialParams.NoDefaultTLSSessionID,
  1463. RandomizedTLSProfileSeed: dialParams.RandomizedTLSProfileSeed,
  1464. UseObfuscatedSessionTickets: dialParams.TunnelProtocol == protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK_SESSION_TICKET,
  1465. SNIServerName: dialParams.MeekSNIServerName,
  1466. AddPsiphonFrontingHeader: addFrontingHeader,
  1467. VerifyServerName: dialParams.MeekVerifyServerName,
  1468. VerifyPins: dialParams.MeekVerifyPins,
  1469. DisableSystemRootCAs: config.DisableSystemRootCAs,
  1470. HostHeader: dialParams.MeekHostHeader,
  1471. TransformedHostName: dialParams.MeekTransformedHostName,
  1472. ClientTunnelProtocol: dialParams.TunnelProtocol,
  1473. MeekCookieEncryptionPublicKey: serverEntry.MeekCookieEncryptionPublicKey,
  1474. MeekObfuscatedKey: serverEntry.MeekObfuscatedKey,
  1475. MeekObfuscatorPaddingSeed: dialParams.MeekObfuscatorPaddingSeed,
  1476. NetworkLatencyMultiplier: dialParams.NetworkLatencyMultiplier,
  1477. HTTPTransformerParameters: dialParams.HTTPTransformerParameters,
  1478. AdditionalHeaders: config.MeekAdditionalHeaders,
  1479. }
  1480. // Use an asynchronous callback to record the resolved IP address when
  1481. // dialing a domain name. Note that DialMeek doesn't immediately
  1482. // establish any HTTP connections, so the resolved IP address won't be
  1483. // reported in all cases until after SSH traffic is relayed or a
  1484. // endpoint request is made over the meek connection.
  1485. dialParams.dialConfig.ResolvedIPCallback = func(IPAddress string) {
  1486. dialParams.MeekResolvedIPAddress.Store(IPAddress)
  1487. }
  1488. if isTactics {
  1489. dialParams.meekConfig.Mode = MeekModeObfuscatedRoundTrip
  1490. } else if dialParams.ConjureAPIRegistration {
  1491. dialParams.meekConfig.Mode = MeekModePlaintextRoundTrip
  1492. } else {
  1493. dialParams.meekConfig.Mode = MeekModeRelay
  1494. }
  1495. }
  1496. if !isTactics &&
  1497. protocol.TunnelProtocolUsesInproxy(dialParams.TunnelProtocol) &&
  1498. protocol.TunnelProtocolUsesTCP(dialParams.TunnelProtocol) {
  1499. // Set DialConfig.CustomDialer to redirect all underlying TCP dials to use
  1500. // in-proxy as a 1st hop. Since QUIC doesn't use DialConfig or have its
  1501. // own CustomDialer, QUIC is handled with an explicit special case in
  1502. // dialTunnel.
  1503. dialParams.dialConfig.CustomDialer = makeInproxyTCPDialer(config, dialParams)
  1504. }
  1505. return dialParams, nil
  1506. }
  1507. func (dialParams *DialParameters) GetDialConfig() *DialConfig {
  1508. return dialParams.dialConfig
  1509. }
  1510. func (dialParams *DialParameters) GetMeekConfig() *MeekConfig {
  1511. return dialParams.meekConfig
  1512. }
  1513. func (dialParams *DialParameters) GetTLSOSSHConfig(config *Config) *TLSTunnelConfig {
  1514. p := config.GetParameters().Get()
  1515. useObfuscatedPSK := p.WeightedCoinFlip(parameters.TLSTunnelObfuscatedPSKProbability)
  1516. // TLSTunnelConfig isn't pre-created in MakeDialParameters to avoid holding a long
  1517. // term reference to TLSTunnelConfig.Parameters.
  1518. return &TLSTunnelConfig{
  1519. CustomTLSConfig: &CustomTLSConfig{
  1520. Parameters: config.GetParameters(),
  1521. DialAddr: dialParams.DirectDialAddress,
  1522. SNIServerName: dialParams.TLSOSSHSNIServerName,
  1523. SkipVerify: true,
  1524. VerifyServerName: "",
  1525. VerifyPins: nil,
  1526. TLSProfile: dialParams.TLSProfile,
  1527. NoDefaultTLSSessionID: &dialParams.NoDefaultTLSSessionID,
  1528. RandomizedTLSProfileSeed: dialParams.RandomizedTLSProfileSeed,
  1529. FragmentClientHello: dialParams.TLSFragmentClientHello,
  1530. ClientSessionCache: dialParams.tlsClientSessionCache,
  1531. },
  1532. UseObfuscatedSessionTickets: useObfuscatedPSK,
  1533. // Meek obfuscated key used to allow clients with legacy unfronted
  1534. // meek-https server entries, that have the passthrough capability, to
  1535. // connect with TLS-OSSH to the servers corresponding to those server
  1536. // entries, which now support TLS-OSSH by demultiplexing meek-https and
  1537. // TLS-OSSH over the meek-https port.
  1538. ObfuscatedKey: dialParams.ServerEntry.MeekObfuscatedKey,
  1539. ObfuscatorPaddingSeed: dialParams.TLSOSSHObfuscatorPaddingSeed,
  1540. }
  1541. }
  1542. func (dialParams *DialParameters) GetShadowsocksConfig() *ShadowsockConfig {
  1543. return &ShadowsockConfig{
  1544. dialAddr: dialParams.DirectDialAddress,
  1545. key: dialParams.ServerEntry.SshShadowsocksKey,
  1546. prefix: dialParams.ShadowsocksPrefixSpec,
  1547. }
  1548. }
  1549. func (dialParams *DialParameters) GetNetworkType() string {
  1550. return GetNetworkType(dialParams.NetworkID)
  1551. }
  1552. func (dialParams *DialParameters) GetTLSVersionForMetrics() string {
  1553. return getTLSVersionForMetrics(dialParams.TLSVersion, dialParams.NoDefaultTLSSessionID)
  1554. }
  1555. func getTLSVersionForMetrics(tlsVersion string, noDefaultTLSSessionID bool) string {
  1556. version := tlsVersion
  1557. if noDefaultTLSSessionID {
  1558. version += "-no_def_id"
  1559. }
  1560. return version
  1561. }
  1562. func (dialParams *DialParameters) GetInproxyMetrics() common.LogFields {
  1563. inproxyMetrics := common.LogFields{}
  1564. if !dialParams.inproxyDialInitialized {
  1565. // This was an untunneled tactics request using an in-proxy meek
  1566. // server, no there was no in-proxy dial or dial parameters.
  1567. return inproxyMetrics
  1568. }
  1569. inproxyMetrics.Add(dialParams.inproxyBrokerDialParameters.GetMetrics())
  1570. inproxyMetrics.Add(dialParams.InproxySTUNDialParameters.GetMetrics())
  1571. inproxyMetrics.Add(dialParams.InproxyWebRTCDialParameters.GetMetrics())
  1572. return inproxyMetrics
  1573. }
  1574. func (dialParams *DialParameters) Succeeded() {
  1575. // When TTL is 0, don't store dial parameters.
  1576. if dialParams.LastUsedTimestamp.IsZero() {
  1577. return
  1578. }
  1579. NoticeInfo("Set dial parameters for %s", dialParams.ServerEntry.GetDiagnosticID())
  1580. err := SetDialParameters(dialParams.ServerEntry.IpAddress, dialParams.NetworkID, dialParams)
  1581. if err != nil {
  1582. NoticeWarning("SetDialParameters failed: %s", err)
  1583. }
  1584. }
  1585. func (dialParams *DialParameters) Failed(config *Config, dialErr error) {
  1586. // When a tunnel fails, and the dial is a replay, clear the stored dial
  1587. // parameters which are now presumed to be blocked, impaired or otherwise
  1588. // no longer effective.
  1589. //
  1590. // It may be the case that a dial is not using stored dial parameters
  1591. // (!IsReplay), and in this case we retain those dial parameters since they
  1592. // were not exercised and may still be effective.
  1593. //
  1594. // Failed tunnel dial parameters may be retained with a configurable
  1595. // probability; this is intended to help mitigate false positive failures due
  1596. // to, e.g., temporary network disruptions or server load limiting.
  1597. // When dialing in-proxy tunnel protocols, replay is retained when the
  1598. // dial fails in the inproxyDial phase. This phase includes the broker
  1599. // request and the 1st hop WebRTC connection. The broker client has its
  1600. // own replay layer. The WebRTC peer is an ephemeral proxy which cannot
  1601. // be replayed and clearing replay for individual proxy failures unfairly
  1602. // deprioritizes in-proxy protocol selection overall. Any replay TTL
  1603. // remains in effect and will eventually clear the replay if there is a
  1604. // persistent issue with the in-proxy protocol. Replay is still cleared
  1605. // immediately for post-inproxyDial failures, as these can be due to more
  1606. // permanent conditions, such as a retired Psiphon server.
  1607. //
  1608. // Limitation: with this retention logic, InproxySTUNDialParameters and
  1609. // InproxyWebRTCDialParameters are retained and replayed, although it may
  1610. // be more optimal to replay in-proxy protocols while still reselecting
  1611. // different STUN servers and WebRTC properties.
  1612. p := config.GetParameters().Get()
  1613. var inproxyDialErr *inproxyDialFailedError
  1614. isInproxyDialErr := std_errors.As(dialErr, &inproxyDialErr)
  1615. if dialParams.IsReplay &&
  1616. !p.WeightedCoinFlip(parameters.ReplayRetainFailedProbability) &&
  1617. (!isInproxyDialErr || !p.WeightedCoinFlip(parameters.InproxyReplayRetainFailedProbability)) {
  1618. NoticeInfo("Delete dial parameters for %s", dialParams.ServerEntry.GetDiagnosticID())
  1619. err := DeleteDialParameters(dialParams.ServerEntry.IpAddress, dialParams.NetworkID)
  1620. if err != nil {
  1621. NoticeWarning("DeleteDialParameters failed: %s", err)
  1622. }
  1623. }
  1624. // Also clear the DSLPendingPrioritizeDial placeholder, to prevent
  1625. // subsequent move-to-front, with a configurable probability to retain it.
  1626. if dialParams.DSLPrioritizedDial && !dialParams.IsReplay &&
  1627. !p.WeightedCoinFlip(parameters.DSLPrioritizeDialRetainFailedProbability) {
  1628. NoticeInfo("Delete DSL prioritize dial for %s", dialParams.ServerEntry.GetDiagnosticID())
  1629. err := DeleteDialParameters(dialParams.ServerEntry.IpAddress, dialParams.NetworkID)
  1630. if err != nil {
  1631. NoticeWarning("DeleteDialParameters failed: %s", err)
  1632. }
  1633. }
  1634. // When a failed tunnel dialed with steering IP, remove the corresponding
  1635. // cache entry to avoid continuously redialing a potentially blocked or
  1636. // degraded POP.
  1637. //
  1638. // TODO: don't remove, but reduce the TTL to allow for one more dial?
  1639. if dialParams.steeringIPCacheKey != "" {
  1640. dialParams.steeringIPCache.Delete(dialParams.steeringIPCacheKey)
  1641. }
  1642. // Clear the TLS client session cache to avoid (potentially) reusing failed sessions for
  1643. // Meek, TLS-OSSH and QUIC connections.
  1644. if dialParams.quicTLSClientSessionCache != nil {
  1645. dialParams.quicTLSClientSessionCache.RemoveCacheEntry()
  1646. }
  1647. if dialParams.tlsClientSessionCache != nil {
  1648. dialParams.tlsClientSessionCache.RemoveCacheEntry()
  1649. }
  1650. }
  1651. // ExchangedDialParameters represents the subset of DialParameters that is
  1652. // shared in a client-to-client exchange of server connection info.
  1653. //
  1654. // The purpose of client-to-client exchange if for one user that can connect
  1655. // to help another user that cannot connect by sharing their connected
  1656. // configuration, including the server entry and dial parameters.
  1657. //
  1658. // There are two concerns regarding which dial parameter fields are safe to
  1659. // exchange:
  1660. //
  1661. // - Unlike signed server entries, there's no independent trust anchor
  1662. // that can certify that the exchange data is valid.
  1663. //
  1664. // - While users should only perform the exchange with trusted peers,
  1665. // the user's trust in their peer may be misplaced.
  1666. //
  1667. // This presents the possibility of attack such as the peer sending dial
  1668. // parameters that could be used to trace/monitor/flag the importer; or
  1669. // sending dial parameters, including dial address and SNI, to cause the peer
  1670. // to appear to connect to a banned service.
  1671. //
  1672. // To mitigate these risks, only a subset of dial parameters are exchanged.
  1673. // When exchanged dial parameters and imported and used, all unexchanged
  1674. // parameters are generated locally. At this time, only the tunnel protocol is
  1675. // exchanged. We consider tunnel protocol selection one of the key connection
  1676. // success factors.
  1677. //
  1678. // In addition, the exchange peers may not be on the same network with the
  1679. // same blocking and circumvention characteristics, which is another reason
  1680. // to limit exchanged dial parameter values to broadly applicable fields.
  1681. //
  1682. // Unlike the exchanged (and otherwise acquired) server entry,
  1683. // ExchangedDialParameters does not use the ServerEntry_Fields_ representation
  1684. // which allows older clients to receive and store new, unknown fields. Such a
  1685. // facility is less useful in this case, since exchanged dial parameters and
  1686. // used immediately and have a short lifespan.
  1687. //
  1688. // TODO: exchange more dial parameters, such as TLS profile, QUIC version, etc.
  1689. type ExchangedDialParameters struct {
  1690. TunnelProtocol string
  1691. }
  1692. // NewExchangedDialParameters creates a new ExchangedDialParameters from a
  1693. // DialParameters, including only the exchanged values.
  1694. // NewExchangedDialParameters assumes the input DialParameters has been
  1695. // initialized and populated by MakeDialParameters.
  1696. func NewExchangedDialParameters(dialParams *DialParameters) *ExchangedDialParameters {
  1697. return &ExchangedDialParameters{
  1698. TunnelProtocol: dialParams.TunnelProtocol,
  1699. }
  1700. }
  1701. // Validate checks that the ExchangedDialParameters contains only valid values
  1702. // and is compatible with the specified server entry.
  1703. func (dialParams *ExchangedDialParameters) Validate(serverEntry *protocol.ServerEntry) error {
  1704. if !common.Contains(protocol.SupportedTunnelProtocols, dialParams.TunnelProtocol) {
  1705. return errors.Tracef("unknown tunnel protocol: %s", dialParams.TunnelProtocol)
  1706. }
  1707. if !serverEntry.SupportsProtocol(dialParams.TunnelProtocol) {
  1708. return errors.Tracef("unsupported tunnel protocol: %s", dialParams.TunnelProtocol)
  1709. }
  1710. return nil
  1711. }
  1712. // MakeDialParameters creates a new, partially intitialized DialParameters
  1713. // from the values in ExchangedDialParameters. The returned DialParameters
  1714. // must not be used directly for dialing. It is intended to be stored, and
  1715. // then later fully initialized by MakeDialParameters.
  1716. func (dialParams *ExchangedDialParameters) MakeDialParameters(
  1717. config *Config,
  1718. p parameters.ParametersAccessor,
  1719. serverEntry *protocol.ServerEntry) *DialParameters {
  1720. configStateHash, serverEntryHash := getDialStateHashes(config, p, serverEntry)
  1721. return &DialParameters{
  1722. IsExchanged: true,
  1723. LastUsedTimestamp: time.Now(),
  1724. LastUsedConfigStateHash: configStateHash,
  1725. LastUsedServerEntryHash: serverEntryHash,
  1726. TunnelProtocol: dialParams.TunnelProtocol,
  1727. }
  1728. }
  1729. // getDialStateHashes returns two hashes: the config state hash reflects the
  1730. // config dial parameters and tactics tag used for a dial; and the server
  1731. // entry hash relects the server entry used for a dial.
  1732. //
  1733. // These hashes change if the input values change in a way that invalidates
  1734. // any stored dial parameters.
  1735. func getDialStateHashes(
  1736. config *Config,
  1737. p parameters.ParametersAccessor,
  1738. serverEntry *protocol.ServerEntry) ([]byte, []byte) {
  1739. // MD5 hash is used solely as a data checksum and not for any security
  1740. // purpose.
  1741. hash := md5.New()
  1742. // Add a hash of relevant dial parameter config fields. Config fields
  1743. // that change due to user preference changes, such as selected egress
  1744. // region, are not to be included in config.dialParametersHash.
  1745. //
  1746. // Limitation: the config hash may change even when tactics will override the
  1747. // changed config field.
  1748. hash.Write(config.dialParametersHash)
  1749. // Add the active tactics tag.
  1750. hash.Write([]byte(p.Tag()))
  1751. clientStateHash := hash.Sum(nil)
  1752. hash = md5.New()
  1753. // Add the server entry version and local timestamp, both of which should
  1754. // change when the server entry contents change and/or a new local copy is
  1755. // imported.
  1756. // TODO: marshal entire server entry?
  1757. var serverEntryConfigurationVersion [8]byte
  1758. binary.BigEndian.PutUint64(
  1759. serverEntryConfigurationVersion[:],
  1760. uint64(serverEntry.ConfigurationVersion))
  1761. hash.Write(serverEntryConfigurationVersion[:])
  1762. hash.Write([]byte(serverEntry.LocalTimestamp))
  1763. serverEntryHash := hash.Sum(nil)
  1764. return clientStateHash, serverEntryHash
  1765. }
  1766. func selectFrontingParameters(
  1767. serverEntry *protocol.ServerEntry) (string, string, error) {
  1768. frontingDialHost := ""
  1769. frontingHost := ""
  1770. if len(serverEntry.MeekFrontingAddressesRegex) > 0 {
  1771. // Generate a front address based on the regex.
  1772. var err error
  1773. frontingDialHost, err = regen.GenerateString(serverEntry.MeekFrontingAddressesRegex)
  1774. if err != nil {
  1775. return "", "", errors.Trace(err)
  1776. }
  1777. } else {
  1778. // Randomly select, for this connection attempt, one front address for
  1779. // fronting-capable servers.
  1780. if len(serverEntry.MeekFrontingAddresses) == 0 {
  1781. return "", "", errors.TraceNew("MeekFrontingAddresses is empty")
  1782. }
  1783. index := prng.Intn(len(serverEntry.MeekFrontingAddresses))
  1784. frontingDialHost = serverEntry.MeekFrontingAddresses[index]
  1785. }
  1786. if len(serverEntry.MeekFrontingHosts) > 0 {
  1787. index := prng.Intn(len(serverEntry.MeekFrontingHosts))
  1788. frontingHost = serverEntry.MeekFrontingHosts[index]
  1789. } else {
  1790. // Backwards compatibility case
  1791. frontingHost = serverEntry.MeekFrontingHost
  1792. }
  1793. return frontingDialHost, frontingHost, nil
  1794. }
  1795. func selectQUICVersion(
  1796. isFronted bool,
  1797. isInproxy bool,
  1798. serverEntry *protocol.ServerEntry,
  1799. p parameters.ParametersAccessor) string {
  1800. limitQUICVersions := p.QUICVersions(parameters.LimitQUICVersions)
  1801. var disableQUICVersions protocol.QUICVersions
  1802. if isFronted {
  1803. if serverEntry.FrontingProviderID == "" {
  1804. // Legacy server entry case
  1805. disableQUICVersions = protocol.QUICVersions{
  1806. protocol.QUIC_VERSION_V1,
  1807. protocol.QUIC_VERSION_RANDOMIZED_V1,
  1808. protocol.QUIC_VERSION_OBFUSCATED_V1,
  1809. protocol.QUIC_VERSION_DECOY_V1,
  1810. }
  1811. } else {
  1812. disableQUICVersions = p.LabeledQUICVersions(
  1813. parameters.DisableFrontingProviderQUICVersions,
  1814. serverEntry.FrontingProviderID)
  1815. }
  1816. }
  1817. quicVersions := make([]string, 0)
  1818. // Don't use gQUIC versions when the server entry specifies QUICv1-only.
  1819. //
  1820. // SupportedQUICVersions is specific to QUIC-OSSH and does not apply to
  1821. // in-proxy variants; all in-proxy QUIC is QUICv1-only.
  1822. supportedQUICVersions := protocol.SupportedQUICVersions
  1823. if isInproxy || serverEntry.SupportsOnlyQUICv1() {
  1824. supportedQUICVersions = protocol.SupportedQUICv1Versions
  1825. }
  1826. for _, quicVersion := range supportedQUICVersions {
  1827. if len(limitQUICVersions) > 0 &&
  1828. !common.Contains(limitQUICVersions, quicVersion) {
  1829. continue
  1830. }
  1831. // Both tactics and the server entry can specify LimitQUICVersions. In
  1832. // tactics, the parameter is intended to direct certain clients to
  1833. // use a successful protocol variant. In the server entry, the
  1834. // parameter may be used to direct all clients to send
  1835. // consistent-looking protocol variants to a particular server; e.g.,
  1836. // only regular QUIC, or only obfuscated QUIC.
  1837. //
  1838. // The isFronted/QUICVersionIsObfuscated logic predates
  1839. // ServerEntry.LimitQUICVersions; ServerEntry.LimitQUICVersions could
  1840. // now be used to achieve a similar outcome.
  1841. if len(serverEntry.LimitQUICVersions) > 0 &&
  1842. !common.Contains(serverEntry.LimitQUICVersions, quicVersion) {
  1843. continue
  1844. }
  1845. if isFronted &&
  1846. protocol.QUICVersionIsObfuscated(quicVersion) {
  1847. continue
  1848. }
  1849. if common.Contains(disableQUICVersions, quicVersion) {
  1850. continue
  1851. }
  1852. quicVersions = append(quicVersions, quicVersion)
  1853. }
  1854. if len(quicVersions) == 0 {
  1855. return ""
  1856. }
  1857. choice := prng.Intn(len(quicVersions))
  1858. return quicVersions[choice]
  1859. }
  1860. func selectWebRTCMediaStreamQUICVersion(
  1861. serverEntry *protocol.ServerEntry,
  1862. p parameters.ParametersAccessor) string {
  1863. // Based on selectQUICVersion. The only supported QUIC versions are the
  1864. // non-obfuscated IETF QUICv1 versions. Obfuscated versions do not meet
  1865. // the packet size constraints required for WebRTC SRTP.
  1866. limitQUICVersions := p.QUICVersions(parameters.LimitQUICVersions)
  1867. quicVersions := make([]string, 0)
  1868. supportedQUICVersions := protocol.QUICVersions{
  1869. protocol.QUIC_VERSION_V1,
  1870. protocol.QUIC_VERSION_RANDOMIZED_V1,
  1871. }
  1872. for _, quicVersion := range supportedQUICVersions {
  1873. if len(limitQUICVersions) > 0 &&
  1874. !common.Contains(limitQUICVersions, quicVersion) {
  1875. continue
  1876. }
  1877. if len(serverEntry.LimitQUICVersions) > 0 &&
  1878. !common.Contains(serverEntry.LimitQUICVersions, quicVersion) {
  1879. continue
  1880. }
  1881. quicVersions = append(quicVersions, quicVersion)
  1882. }
  1883. if len(quicVersions) == 0 {
  1884. return ""
  1885. }
  1886. choice := prng.Intn(len(quicVersions))
  1887. return quicVersions[choice]
  1888. }
  1889. // selectUserAgentIfUnset selects a User-Agent header if one is not set.
  1890. func selectUserAgentIfUnset(
  1891. p parameters.ParametersAccessor, headers http.Header) (bool, string) {
  1892. if _, ok := headers["User-Agent"]; !ok {
  1893. userAgent := ""
  1894. if p.WeightedCoinFlip(parameters.PickUserAgentProbability) {
  1895. userAgent = values.GetUserAgent()
  1896. }
  1897. return true, userAgent
  1898. }
  1899. return false, ""
  1900. }
  1901. func makeDialCustomHeaders(
  1902. config *Config,
  1903. p parameters.ParametersAccessor) http.Header {
  1904. dialCustomHeaders := make(http.Header)
  1905. if config.CustomHeaders != nil {
  1906. for k, v := range config.CustomHeaders {
  1907. dialCustomHeaders[k] = make([]string, len(v))
  1908. copy(dialCustomHeaders[k], v)
  1909. }
  1910. }
  1911. additionalCustomHeaders := p.HTTPHeaders(parameters.AdditionalCustomHeaders)
  1912. for k, v := range additionalCustomHeaders {
  1913. dialCustomHeaders[k] = make([]string, len(v))
  1914. copy(dialCustomHeaders[k], v)
  1915. }
  1916. return dialCustomHeaders
  1917. }
  1918. func selectHostName(
  1919. tunnelProtocol string, p parameters.ParametersAccessor) string {
  1920. limitProtocols := p.TunnelProtocols(parameters.CustomHostNameLimitProtocols)
  1921. if len(limitProtocols) > 0 && !common.Contains(limitProtocols, tunnelProtocol) {
  1922. return values.GetHostName()
  1923. }
  1924. if !p.WeightedCoinFlip(parameters.CustomHostNameProbability) {
  1925. return values.GetHostName()
  1926. }
  1927. regexStrings := p.RegexStrings(parameters.CustomHostNameRegexes)
  1928. if len(regexStrings) == 0 {
  1929. return values.GetHostName()
  1930. }
  1931. choice := prng.Intn(len(regexStrings))
  1932. hostName, err := regen.GenerateString(regexStrings[choice])
  1933. if err != nil {
  1934. NoticeWarning("selectHostName: regen.Generate failed: %v", errors.Trace(err))
  1935. return values.GetHostName()
  1936. }
  1937. return hostName
  1938. }
  1939. // makeHTTPTransformerParameters generates HTTPTransformerParameters using the
  1940. // input tactics parameters and optional frontingProviderID context.
  1941. func makeHTTPTransformerParameters(p parameters.ParametersAccessor,
  1942. frontingProviderID string, isFronted bool) (*transforms.HTTPTransformerParameters, error) {
  1943. params := transforms.HTTPTransformerParameters{}
  1944. // Select an HTTP transform. If the request is fronted, HTTP request
  1945. // transforms are "scoped" by fronting provider ID. Otherwise, a transform
  1946. // from the default scope (transforms.SCOPE_ANY == "") is selected.
  1947. var specsKey string
  1948. var scopedSpecsNamesKey string
  1949. useTransform := false
  1950. scope := transforms.SCOPE_ANY
  1951. if isFronted {
  1952. if p.WeightedCoinFlip(parameters.FrontedHTTPProtocolTransformProbability) {
  1953. useTransform = true
  1954. scope = frontingProviderID
  1955. specsKey = parameters.FrontedHTTPProtocolTransformSpecs
  1956. scopedSpecsNamesKey = parameters.FrontedHTTPProtocolTransformScopedSpecNames
  1957. }
  1958. } else {
  1959. // unfronted
  1960. if p.WeightedCoinFlip(parameters.DirectHTTPProtocolTransformProbability) {
  1961. useTransform = true
  1962. specsKey = parameters.DirectHTTPProtocolTransformSpecs
  1963. scopedSpecsNamesKey = parameters.DirectHTTPProtocolTransformScopedSpecNames
  1964. }
  1965. }
  1966. if useTransform {
  1967. specs := p.ProtocolTransformSpecs(
  1968. specsKey)
  1969. scopedSpecNames := p.ProtocolTransformScopedSpecNames(
  1970. scopedSpecsNamesKey)
  1971. name, spec := specs.Select(scope, scopedSpecNames)
  1972. if spec != nil {
  1973. params.ProtocolTransformName = name
  1974. params.ProtocolTransformSpec = spec
  1975. var err error
  1976. // transform seed generated
  1977. params.ProtocolTransformSeed, err = prng.NewSeed()
  1978. if err != nil {
  1979. return nil, errors.Trace(err)
  1980. }
  1981. }
  1982. }
  1983. return &params, nil
  1984. }
  1985. // makeSeedTransformerParameters generates ObfuscatorSeedTransformerParameters
  1986. // using the input tactics parameters.
  1987. func makeSeedTransformerParameters(p parameters.ParametersAccessor,
  1988. probabilityFieldName, specsKey, scopedSpecsKey string) (*transforms.ObfuscatorSeedTransformerParameters, error) {
  1989. if !p.WeightedCoinFlip(probabilityFieldName) {
  1990. return &transforms.ObfuscatorSeedTransformerParameters{}, nil
  1991. }
  1992. seed, err := prng.NewSeed()
  1993. if err != nil {
  1994. return nil, errors.Trace(err)
  1995. }
  1996. specs := p.ProtocolTransformSpecs(specsKey)
  1997. scopedSpecNames := p.ProtocolTransformScopedSpecNames(scopedSpecsKey)
  1998. name, spec := specs.Select(transforms.SCOPE_ANY, scopedSpecNames)
  1999. if spec == nil {
  2000. return &transforms.ObfuscatorSeedTransformerParameters{}, nil
  2001. } else {
  2002. return &transforms.ObfuscatorSeedTransformerParameters{
  2003. TransformName: name,
  2004. TransformSpec: spec,
  2005. TransformSeed: seed,
  2006. }, nil
  2007. }
  2008. }
  2009. func makeOSSHPrefixSpecParameters(
  2010. p parameters.ParametersAccessor,
  2011. dialPortNumber string) (*obfuscator.OSSHPrefixSpec, error) {
  2012. if !p.WeightedCoinFlip(parameters.OSSHPrefixProbability) {
  2013. return &obfuscator.OSSHPrefixSpec{}, nil
  2014. }
  2015. specs := p.ProtocolTransformSpecs(parameters.OSSHPrefixSpecs)
  2016. scopedSpecNames := p.ProtocolTransformScopedSpecNames(parameters.OSSHPrefixScopedSpecNames)
  2017. name, spec := specs.Select(dialPortNumber, scopedSpecNames)
  2018. if spec == nil {
  2019. return &obfuscator.OSSHPrefixSpec{}, nil
  2020. } else {
  2021. seed, err := prng.NewSeed()
  2022. if err != nil {
  2023. return nil, errors.Trace(err)
  2024. }
  2025. return &obfuscator.OSSHPrefixSpec{
  2026. Name: name,
  2027. Spec: spec,
  2028. Seed: seed,
  2029. }, nil
  2030. }
  2031. }
  2032. func makeOSSHPrefixSplitConfig(
  2033. p parameters.ParametersAccessor) (*obfuscator.OSSHPrefixSplitConfig, error) {
  2034. minDelay := p.Duration(parameters.OSSHPrefixSplitMinDelay)
  2035. maxDelay := p.Duration(parameters.OSSHPrefixSplitMaxDelay)
  2036. seed, err := prng.NewSeed()
  2037. if err != nil {
  2038. return nil, errors.Trace(err)
  2039. }
  2040. return &obfuscator.OSSHPrefixSplitConfig{
  2041. Seed: seed,
  2042. MinDelay: minDelay,
  2043. MaxDelay: maxDelay,
  2044. }, nil
  2045. }
  2046. func makeShadowsocksPrefixSpecParameters(
  2047. p parameters.ParametersAccessor,
  2048. dialPortNumber string) (*ShadowsocksPrefixSpec, error) {
  2049. if !p.WeightedCoinFlip(parameters.ShadowsocksPrefixProbability) {
  2050. return &ShadowsocksPrefixSpec{}, nil
  2051. }
  2052. specs := p.ProtocolTransformSpecs(parameters.ShadowsocksPrefixSpecs)
  2053. scopedSpecNames := p.ProtocolTransformScopedSpecNames(parameters.ShadowsocksPrefixScopedSpecNames)
  2054. name, spec := specs.Select(dialPortNumber, scopedSpecNames)
  2055. if spec == nil {
  2056. return &ShadowsocksPrefixSpec{}, nil
  2057. } else {
  2058. seed, err := prng.NewSeed()
  2059. if err != nil {
  2060. return nil, errors.Trace(err)
  2061. }
  2062. return &ShadowsocksPrefixSpec{
  2063. Name: name,
  2064. Spec: spec,
  2065. Seed: seed,
  2066. }, nil
  2067. }
  2068. }
  2069. func selectConjureTransport(
  2070. p parameters.ParametersAccessor) string {
  2071. limitConjureTransports := p.ConjureTransports(parameters.ConjureLimitTransports)
  2072. transports := make([]string, 0)
  2073. for _, transport := range protocol.SupportedConjureTransports {
  2074. if len(limitConjureTransports) > 0 &&
  2075. !common.Contains(limitConjureTransports, transport) {
  2076. continue
  2077. }
  2078. transports = append(transports, transport)
  2079. }
  2080. if len(transports) == 0 {
  2081. return ""
  2082. }
  2083. choice := prng.Intn(len(transports))
  2084. return transports[choice]
  2085. }
  2086. func addPsiphonFrontingHeader(
  2087. p parameters.ParametersAccessor,
  2088. frontingProviderID string,
  2089. tunnelProtocol string,
  2090. dialAddress string,
  2091. resolveParams *resolver.ResolveParameters) bool {
  2092. if frontingProviderID == "" {
  2093. return false
  2094. }
  2095. if resolveParams != nil &&
  2096. resolveParams.PreresolvedIPAddress != "" {
  2097. meekDialDomain, _, _ := net.SplitHostPort(dialAddress)
  2098. if resolveParams.PreresolvedDomain == meekDialDomain {
  2099. return false
  2100. }
  2101. }
  2102. return common.Contains(
  2103. p.LabeledTunnelProtocols(
  2104. parameters.AddFrontingProviderPsiphonFrontingHeader,
  2105. frontingProviderID),
  2106. tunnelProtocol)
  2107. }