dialParameters.go 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941
  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. "fmt"
  26. "net"
  27. "net/http"
  28. "strconv"
  29. "strings"
  30. "sync/atomic"
  31. "time"
  32. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  33. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  34. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/fragmentor"
  35. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
  37. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  38. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
  39. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/regen"
  40. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
  41. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/transforms"
  42. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
  43. lrucache "github.com/cognusion/go-cache-lru"
  44. "golang.org/x/net/bpf"
  45. )
  46. // DialParameters represents a selected protocol and all the related selected
  47. // protocol attributes, many chosen at random, for a tunnel dial attempt.
  48. //
  49. // DialParameters is used:
  50. // - to configure dialers
  51. // - as a persistent record to store successful dial parameters for replay
  52. // - to report dial stats in notices and Psiphon API calls.
  53. //
  54. // MeekResolvedIPAddress is set asynchronously, as it is not known until the
  55. // dial process has begun. The atomic.Value will contain a string, initialized
  56. // to "", and set to the resolved IP address once that part of the dial
  57. // process has completed.
  58. //
  59. // DialParameters is not safe for concurrent use.
  60. type DialParameters struct {
  61. ServerEntry *protocol.ServerEntry `json:"-"`
  62. NetworkID string `json:"-"`
  63. IsReplay bool `json:"-"`
  64. CandidateNumber int `json:"-"`
  65. EstablishedTunnelsCount int `json:"-"`
  66. IsExchanged bool
  67. LastUsedTimestamp time.Time
  68. LastUsedConfigStateHash []byte
  69. LastUsedServerEntryHash []byte
  70. NetworkLatencyMultiplier float64
  71. TunnelProtocol string
  72. DirectDialAddress string
  73. DialPortNumber string
  74. UpstreamProxyType string `json:"-"`
  75. UpstreamProxyCustomHeaderNames []string `json:"-"`
  76. BPFProgramName string
  77. BPFProgramInstructions []bpf.RawInstruction
  78. SelectedSSHClientVersion bool
  79. SSHClientVersion string
  80. SSHKEXSeed *prng.Seed
  81. ObfuscatorPaddingSeed *prng.Seed
  82. OSSHObfuscatorSeedTransformerParameters *transforms.ObfuscatorSeedTransformerParameters
  83. OSSHPrefixSpec *obfuscator.OSSHPrefixSpec
  84. OSSHPrefixSplitConfig *obfuscator.OSSHPrefixSplitConfig
  85. FragmentorSeed *prng.Seed
  86. FrontingProviderID string
  87. MeekFrontingDialAddress string
  88. MeekFrontingHost string
  89. MeekDialAddress string
  90. MeekTransformedHostName bool
  91. MeekSNIServerName string
  92. MeekVerifyServerName string
  93. MeekVerifyPins []string
  94. MeekHostHeader string
  95. MeekObfuscatorPaddingSeed *prng.Seed
  96. MeekTLSPaddingSize int
  97. MeekResolvedIPAddress atomic.Value `json:"-"`
  98. TLSOSSHTransformedSNIServerName bool
  99. TLSOSSHSNIServerName string
  100. TLSOSSHObfuscatorPaddingSeed *prng.Seed
  101. SelectedUserAgent bool
  102. UserAgent string
  103. SelectedTLSProfile bool
  104. TLSProfile string
  105. NoDefaultTLSSessionID bool
  106. TLSVersion string
  107. RandomizedTLSProfileSeed *prng.Seed
  108. TLSFragmentClientHello bool
  109. QUICVersion string
  110. QUICDialSNIAddress string
  111. QUICClientHelloSeed *prng.Seed
  112. ObfuscatedQUICPaddingSeed *prng.Seed
  113. ObfuscatedQUICNonceTransformerParameters *transforms.ObfuscatorSeedTransformerParameters
  114. QUICDisablePathMTUDiscovery bool
  115. ConjureCachedRegistrationTTL time.Duration
  116. ConjureAPIRegistration bool
  117. ConjureAPIRegistrarBidirectionalURL string
  118. ConjureAPIRegistrarDelay time.Duration
  119. ConjureDecoyRegistration bool
  120. ConjureDecoyRegistrarDelay time.Duration
  121. ConjureDecoyRegistrarWidth int
  122. ConjureTransport string
  123. ConjureSTUNServerAddress string
  124. ConjureDTLSEmptyInitialPacket bool
  125. LivenessTestSeed *prng.Seed
  126. APIRequestPaddingSeed *prng.Seed
  127. HoldOffTunnelDuration time.Duration
  128. DialConnMetrics common.MetricsSource `json:"-"`
  129. DialConnNoticeMetrics common.NoticeMetricsSource `json:"-"`
  130. ObfuscatedSSHConnMetrics common.MetricsSource `json:"-"`
  131. DialDuration time.Duration `json:"-"`
  132. resolver *resolver.Resolver `json:"-"`
  133. ResolveParameters *resolver.ResolveParameters
  134. HTTPTransformerParameters *transforms.HTTPTransformerParameters
  135. SteeringIP string
  136. steeringIPCache *lrucache.Cache `json:"-"`
  137. steeringIPCacheKey string `json:"-"`
  138. dialConfig *DialConfig `json:"-"`
  139. meekConfig *MeekConfig `json:"-"`
  140. }
  141. // MakeDialParameters creates a new DialParameters for the candidate server
  142. // entry, including selecting a protocol and all the various protocol
  143. // attributes. The input selectProtocol is used to comply with any active
  144. // protocol selection constraints.
  145. //
  146. // When stored dial parameters are available and may be used,
  147. // MakeDialParameters may replay previous dial parameters in an effort to
  148. // leverage "known working" values instead of always chosing at random from a
  149. // large space.
  150. //
  151. // MakeDialParameters will return nil/nil in cases where the candidate server
  152. // entry should be skipped.
  153. //
  154. // To support replay, the caller must call DialParameters.Succeeded when a
  155. // successful tunnel is established with the returned DialParameters; and must
  156. // call DialParameters.Failed when a tunnel dial or activation fails, except
  157. // when establishment is cancelled.
  158. func MakeDialParameters(
  159. config *Config,
  160. steeringIPCache *lrucache.Cache,
  161. upstreamProxyErrorCallback func(error),
  162. canReplay func(serverEntry *protocol.ServerEntry, replayProtocol string) bool,
  163. selectProtocol func(serverEntry *protocol.ServerEntry) (string, bool),
  164. serverEntry *protocol.ServerEntry,
  165. isTactics bool,
  166. candidateNumber int,
  167. establishedTunnelsCount int) (*DialParameters, error) {
  168. networkID := config.GetNetworkID()
  169. p := config.GetParameters().Get()
  170. ttl := p.Duration(parameters.ReplayDialParametersTTL)
  171. replayIgnoreChangedConfigState := p.Bool(parameters.ReplayIgnoreChangedConfigState)
  172. replayBPF := p.Bool(parameters.ReplayBPF)
  173. replaySSH := p.Bool(parameters.ReplaySSH)
  174. replayObfuscatorPadding := p.Bool(parameters.ReplayObfuscatorPadding)
  175. replayFragmentor := p.Bool(parameters.ReplayFragmentor)
  176. replayTLSProfile := p.Bool(parameters.ReplayTLSProfile)
  177. replayTLSFragmentClientHello := p.Bool(parameters.ReplayTLSFragmentClientHello)
  178. replayFronting := p.Bool(parameters.ReplayFronting)
  179. replayHostname := p.Bool(parameters.ReplayHostname)
  180. replayQUICVersion := p.Bool(parameters.ReplayQUICVersion)
  181. replayObfuscatedQUIC := p.Bool(parameters.ReplayObfuscatedQUIC)
  182. replayObfuscatedQUICNonceTransformer := p.Bool(parameters.ReplayObfuscatedQUICNonceTransformer)
  183. replayConjureRegistration := p.Bool(parameters.ReplayConjureRegistration)
  184. replayConjureTransport := p.Bool(parameters.ReplayConjureTransport)
  185. replayLivenessTest := p.Bool(parameters.ReplayLivenessTest)
  186. replayUserAgent := p.Bool(parameters.ReplayUserAgent)
  187. replayAPIRequestPadding := p.Bool(parameters.ReplayAPIRequestPadding)
  188. replayHoldOffTunnel := p.Bool(parameters.ReplayHoldOffTunnel)
  189. replayResolveParameters := p.Bool(parameters.ReplayResolveParameters)
  190. replayHTTPTransformerParameters := p.Bool(parameters.ReplayHTTPTransformerParameters)
  191. replayOSSHSeedTransformerParameters := p.Bool(parameters.ReplayOSSHSeedTransformerParameters)
  192. replayOSSHPrefix := p.Bool(parameters.ReplayOSSHPrefix)
  193. // Check for existing dial parameters for this server/network ID.
  194. dialParams, err := GetDialParameters(
  195. config, serverEntry.IpAddress, networkID)
  196. if err != nil {
  197. NoticeWarning("GetDialParameters failed: %s", err)
  198. dialParams = nil
  199. // Proceed, without existing dial parameters.
  200. }
  201. // Check if replay is permitted:
  202. // - TTL must be > 0 and existing dial parameters must not have expired
  203. // as indicated by LastUsedTimestamp + TTL.
  204. // - Config/tactics/server entry values must be unchanged from when
  205. // previous dial parameters were established.
  206. // - The protocol selection constraints must permit replay, as indicated
  207. // by canReplay.
  208. // - Must not be using an obsolete TLS profile that is no longer supported.
  209. // - Must be using the latest Conjure API URL.
  210. //
  211. // When existing dial parameters don't meet these conditions, dialParams
  212. // is reset to nil and new dial parameters will be generated.
  213. var currentTimestamp time.Time
  214. var configStateHash []byte
  215. var serverEntryHash []byte
  216. // When TTL is 0, replay is disabled; the timestamp remains 0 and the
  217. // output DialParameters will not be stored by Success.
  218. if ttl > 0 {
  219. currentTimestamp = time.Now()
  220. configStateHash, serverEntryHash = getDialStateHashes(config, p, serverEntry)
  221. }
  222. if dialParams != nil &&
  223. (ttl <= 0 ||
  224. dialParams.LastUsedTimestamp.Before(currentTimestamp.Add(-ttl)) ||
  225. // Replay is disabled when the current config state hash -- config
  226. // dial parameters and the current tactics tag -- have changed
  227. // since the last dial. This prioritizes applying any potential
  228. // tactics change over redialing with parameters that may have
  229. // changed in tactics.
  230. //
  231. // Because of this, frequent tactics changes may degrade replay
  232. // effectiveness. When ReplayIgnoreChangedConfigState is set,
  233. // differences in the config state hash are ignored.
  234. //
  235. // Limitation: some code which previously assumed that replay
  236. // always implied unchanged tactics parameters may now use newer
  237. // tactics parameters in replay cases when
  238. // ReplayIgnoreChangedConfigState is set. One case is the call
  239. // below to fragmentor.NewUpstreamConfig, made when initializing
  240. // dialParams.dialConfig.
  241. (!replayIgnoreChangedConfigState && !bytes.Equal(dialParams.LastUsedConfigStateHash, configStateHash)) ||
  242. // Replay is disabled when the server entry has changed.
  243. !bytes.Equal(dialParams.LastUsedServerEntryHash, serverEntryHash) ||
  244. (dialParams.TLSProfile != "" &&
  245. !common.Contains(protocol.SupportedTLSProfiles, dialParams.TLSProfile)) ||
  246. (dialParams.QUICVersion != "" &&
  247. !common.Contains(protocol.SupportedQUICVersions, dialParams.QUICVersion)) ||
  248. // Legacy clients use ConjureAPIRegistrarURL with
  249. // gotapdance.tapdance.APIRegistrar and new clients use
  250. // ConjureAPIRegistrarBidirectionalURL with
  251. // gotapdance.tapdance.APIRegistrarBidirectional. Updated clients
  252. // may have replay dial parameters with the old
  253. // ConjureAPIRegistrarURL field, which is now ignored. In this
  254. // case, ConjureAPIRegistrarBidirectionalURL will be blank. Reset
  255. // this replay.
  256. (dialParams.ConjureAPIRegistration && dialParams.ConjureAPIRegistrarBidirectionalURL == "")) {
  257. // In these cases, existing dial parameters are expired or no longer
  258. // match the config state and so are cleared to avoid rechecking them.
  259. err = DeleteDialParameters(serverEntry.IpAddress, networkID)
  260. if err != nil {
  261. NoticeWarning("DeleteDialParameters failed: %s", err)
  262. }
  263. dialParams = nil
  264. }
  265. if dialParams != nil {
  266. if config.DisableReplay ||
  267. !canReplay(serverEntry, dialParams.TunnelProtocol) {
  268. // In these ephemeral cases, existing dial parameters may still be valid
  269. // and used in future establishment phases, and so are retained.
  270. dialParams = nil
  271. }
  272. }
  273. // IsExchanged:
  274. //
  275. // Dial parameters received via client-to-client exchange are partially
  276. // initialized. Only the exchange fields are retained, and all other dial
  277. // parameters fields must be initialized. This is not considered or logged as
  278. // a replay. The exchange case is identified by the IsExchanged flag.
  279. //
  280. // When previously stored, IsExchanged dial parameters will have set the same
  281. // timestamp and state hash used for regular dial parameters and the same
  282. // logic above should invalidate expired or invalid exchanged dial
  283. // parameters.
  284. //
  285. // Limitation: metrics will indicate when an exchanged server entry is used
  286. // (source "EXCHANGED") but will not indicate when exchanged dial parameters
  287. // are used vs. a redial after discarding dial parameters.
  288. isReplay := (dialParams != nil)
  289. isExchanged := isReplay && dialParams.IsExchanged
  290. if !isReplay {
  291. dialParams = &DialParameters{}
  292. }
  293. if isExchanged {
  294. // Set isReplay to false to cause all non-exchanged values to be
  295. // initialized; this also causes the exchange case to not log as replay.
  296. isReplay = false
  297. }
  298. // Set IsExchanged such that full dial parameters are stored and replayed
  299. // upon success.
  300. dialParams.IsExchanged = false
  301. // Point to the current resolver to be used in dials.
  302. dialParams.resolver = config.GetResolver()
  303. if dialParams.resolver == nil {
  304. return nil, errors.TraceNew("missing resolver")
  305. }
  306. dialParams.steeringIPCache = steeringIPCache
  307. dialParams.ServerEntry = serverEntry
  308. dialParams.NetworkID = networkID
  309. dialParams.IsReplay = isReplay
  310. dialParams.CandidateNumber = candidateNumber
  311. dialParams.EstablishedTunnelsCount = establishedTunnelsCount
  312. // Even when replaying, LastUsedTimestamp is updated to extend the TTL of
  313. // replayed dial parameters which will be updated in the datastore upon
  314. // success.
  315. dialParams.LastUsedTimestamp = currentTimestamp
  316. dialParams.LastUsedConfigStateHash = configStateHash
  317. dialParams.LastUsedServerEntryHash = serverEntryHash
  318. // Initialize dial parameters.
  319. //
  320. // When not replaying, all required parameters are initialized. When
  321. // replaying, existing parameters are retained, subject to the replay-X
  322. // tactics flags.
  323. // Select a network latency multiplier for this dial. This allows clients to
  324. // explore and discover timeout values appropriate for the current network.
  325. // The selection applies per tunnel, to avoid delaying all establishment
  326. // candidates due to excessive timeouts. The random selection is bounded by a
  327. // min/max set in tactics and an exponential distribution is used so as to
  328. // heavily favor values close to the min, which should be set to the
  329. // singleton NetworkLatencyMultiplier tactics value.
  330. //
  331. // For NetworkLatencyMultiplierLambda close to 2.0, values near min are
  332. // very approximately 10x more likely to be selected than values near
  333. // max, while for NetworkLatencyMultiplierLambda close to 0.1, the
  334. // distribution is close to uniform.
  335. //
  336. // Not all existing, persisted DialParameters will have a custom
  337. // NetworkLatencyMultiplier value. Its zero value will cause the singleton
  338. // NetworkLatencyMultiplier tactics value to be used instead, which is
  339. // consistent with the pre-custom multiplier behavior in the older client
  340. // version which persisted that DialParameters.
  341. networkLatencyMultiplierMin := p.Float(parameters.NetworkLatencyMultiplierMin)
  342. networkLatencyMultiplierMax := p.Float(parameters.NetworkLatencyMultiplierMax)
  343. if !isReplay ||
  344. // Was selected...
  345. (dialParams.NetworkLatencyMultiplier != 0.0 &&
  346. // But is now outside tactics range...
  347. (dialParams.NetworkLatencyMultiplier < networkLatencyMultiplierMin ||
  348. dialParams.NetworkLatencyMultiplier > networkLatencyMultiplierMax)) {
  349. dialParams.NetworkLatencyMultiplier = prng.ExpFloat64Range(
  350. networkLatencyMultiplierMin,
  351. networkLatencyMultiplierMax,
  352. p.Float(parameters.NetworkLatencyMultiplierLambda))
  353. }
  354. // After this point, any tactics parameters that apply the network latency
  355. // multiplier will use this selected value.
  356. p = config.GetParameters().GetCustom(dialParams.NetworkLatencyMultiplier)
  357. if !isReplay && !isExchanged {
  358. // TODO: should there be a pre-check of selectProtocol before incurring
  359. // overhead of unmarshaling dial parameters? In may be that a server entry
  360. // is fully incapable of satisfying the current protocol selection
  361. // constraints.
  362. selectedProtocol, ok := selectProtocol(serverEntry)
  363. if !ok {
  364. return nil, nil
  365. }
  366. dialParams.TunnelProtocol = selectedProtocol
  367. }
  368. // Skip this candidate when the clients tactics restrict usage of the
  369. // provider ID. See the corresponding server-side enforcement comments in
  370. // server.TacticsListener.accept.
  371. if protocol.TunnelProtocolIsDirect(dialParams.TunnelProtocol) &&
  372. common.ContainsAny(
  373. p.KeyStrings(parameters.RestrictDirectProviderRegions, dialParams.ServerEntry.ProviderID), []string{"", serverEntry.Region}) {
  374. if p.WeightedCoinFlip(
  375. parameters.RestrictDirectProviderIDsClientProbability) {
  376. // When skipping, return nil/nil as no error should be logged.
  377. // NoticeSkipServerEntry emits each skip reason, regardless
  378. // of server entry, at most once per session.
  379. NoticeSkipServerEntry(
  380. "restricted provider ID: %s",
  381. dialParams.ServerEntry.ProviderID)
  382. return nil, nil
  383. }
  384. }
  385. // Skip this candidate when the clients tactics restrict usage of the
  386. // fronting provider ID. See the corresponding server-side enforcement
  387. // comments in server.MeekServer.getSessionOrEndpoint.
  388. if protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) &&
  389. common.Contains(
  390. p.Strings(parameters.RestrictFrontingProviderIDs),
  391. dialParams.ServerEntry.FrontingProviderID) {
  392. if p.WeightedCoinFlip(
  393. parameters.RestrictFrontingProviderIDsClientProbability) {
  394. // When skipping, return nil/nil as no error should be logged.
  395. // NoticeSkipServerEntry emits each skip reason, regardless
  396. // of server entry, at most once per session.
  397. NoticeSkipServerEntry(
  398. "restricted fronting provider ID: %s",
  399. dialParams.ServerEntry.FrontingProviderID)
  400. return nil, nil
  401. }
  402. }
  403. if config.UseUpstreamProxy() {
  404. // When UpstreamProxy is configured, ServerEntry.GetSupportedProtocols, when
  405. // called via selectProtocol, will filter out protocols such that will not
  406. // select a protocol incompatible with UpstreamProxy. This additional check
  407. // will catch cases where selectProtocol does not apply this filter.
  408. if !protocol.TunnelProtocolSupportsUpstreamProxy(dialParams.TunnelProtocol) {
  409. NoticeSkipServerEntry(
  410. "protocol does not support upstream proxy: %s",
  411. dialParams.TunnelProtocol)
  412. return nil, nil
  413. }
  414. // Skip this candidate when the server entry is not to be used with an
  415. // upstream proxy. By not exposing servers from sources that are
  416. // relatively hard to enumerate, this mechanism mitigates the risk of
  417. // a malicious upstream proxy enumerating Psiphon servers. Populate
  418. // the allowed sources with fronted servers to provide greater
  419. // blocking resistence for clients using upstream proxy clients that
  420. // are subject to blocking.
  421. source := dialParams.ServerEntry.LocalSource
  422. if !protocol.AllowServerEntrySourceWithUpstreamProxy(source) &&
  423. !p.Bool(parameters.UpstreamProxyAllowAllServerEntrySources) {
  424. NoticeSkipServerEntry(
  425. "server entry source disallowed with upstream proxy: %s",
  426. source)
  427. return nil, nil
  428. }
  429. }
  430. if (!isReplay || !replayBPF) &&
  431. ClientBPFEnabled() &&
  432. protocol.TunnelProtocolUsesTCP(dialParams.TunnelProtocol) {
  433. if p.WeightedCoinFlip(parameters.BPFClientTCPProbability) {
  434. dialParams.BPFProgramName = ""
  435. dialParams.BPFProgramInstructions = nil
  436. ok, name, rawInstructions := p.BPFProgram(parameters.BPFClientTCPProgram)
  437. if ok {
  438. dialParams.BPFProgramName = name
  439. dialParams.BPFProgramInstructions = rawInstructions
  440. }
  441. }
  442. }
  443. if !isReplay || !replaySSH {
  444. dialParams.SelectedSSHClientVersion = true
  445. dialParams.SSHClientVersion = values.GetSSHClientVersion()
  446. dialParams.SSHKEXSeed, err = prng.NewSeed()
  447. if err != nil {
  448. return nil, errors.Trace(err)
  449. }
  450. }
  451. if !isReplay || !replayObfuscatorPadding {
  452. dialParams.ObfuscatorPaddingSeed, err = prng.NewSeed()
  453. if err != nil {
  454. return nil, errors.Trace(err)
  455. }
  456. if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) {
  457. dialParams.MeekObfuscatorPaddingSeed, err = prng.NewSeed()
  458. if err != nil {
  459. return nil, errors.Trace(err)
  460. }
  461. } else if protocol.TunnelProtocolUsesTLSOSSH(dialParams.TunnelProtocol) {
  462. dialParams.TLSOSSHObfuscatorPaddingSeed, err = prng.NewSeed()
  463. if err != nil {
  464. return nil, errors.Trace(err)
  465. }
  466. }
  467. }
  468. if !isReplay || !replayFragmentor {
  469. dialParams.FragmentorSeed, err = prng.NewSeed()
  470. if err != nil {
  471. return nil, errors.Trace(err)
  472. }
  473. }
  474. if (!isReplay || !replayConjureRegistration) &&
  475. protocol.TunnelProtocolUsesConjure(dialParams.TunnelProtocol) {
  476. dialParams.ConjureCachedRegistrationTTL = p.Duration(parameters.ConjureCachedRegistrationTTL)
  477. apiURL := p.String(parameters.ConjureAPIRegistrarBidirectionalURL)
  478. decoyWidth := p.Int(parameters.ConjureDecoyRegistrarWidth)
  479. dialParams.ConjureAPIRegistration = apiURL != ""
  480. dialParams.ConjureDecoyRegistration = decoyWidth != 0
  481. // We select only one of API or decoy registration. When both are enabled,
  482. // ConjureDecoyRegistrarProbability determines the probability of using
  483. // decoy registration.
  484. //
  485. // In general, we disable retries in gotapdance and rely on Psiphon
  486. // establishment to try/retry different registration schemes. This allows us
  487. // to control the proportion of registration types attempted. And, in good
  488. // network conditions, individual candidates are most likely to be cancelled
  489. // before they exhaust their retry options.
  490. if dialParams.ConjureAPIRegistration && dialParams.ConjureDecoyRegistration {
  491. if p.WeightedCoinFlip(parameters.ConjureDecoyRegistrarProbability) {
  492. dialParams.ConjureAPIRegistration = false
  493. }
  494. }
  495. if dialParams.ConjureAPIRegistration {
  496. // While Conjure API registration uses MeekConn and specifies common meek
  497. // parameters, the meek address and SNI configuration is implemented in this
  498. // code block and not in common code blocks below. The exception is TLS
  499. // configuration.
  500. //
  501. // Accordingly, replayFronting/replayHostname have no effect on Conjure API
  502. // registration replay.
  503. dialParams.ConjureAPIRegistrarBidirectionalURL = apiURL
  504. frontingSpecs := p.FrontingSpecs(parameters.ConjureAPIRegistrarFrontingSpecs)
  505. dialParams.FrontingProviderID,
  506. dialParams.MeekFrontingDialAddress,
  507. dialParams.MeekSNIServerName,
  508. dialParams.MeekVerifyServerName,
  509. dialParams.MeekVerifyPins,
  510. dialParams.MeekFrontingHost,
  511. err = frontingSpecs.SelectParameters()
  512. if err != nil {
  513. return nil, errors.Trace(err)
  514. }
  515. if config.DisableSystemRootCAs {
  516. return nil, errors.TraceNew("TLS certificates must be verified in Conjure API registration")
  517. }
  518. dialParams.MeekDialAddress = net.JoinHostPort(dialParams.MeekFrontingDialAddress, "443")
  519. dialParams.MeekHostHeader = dialParams.MeekFrontingHost
  520. // For a FrontingSpec, an SNI value of "" indicates to disable/omit SNI, so
  521. // never transform in that case.
  522. if dialParams.MeekSNIServerName != "" {
  523. if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
  524. dialParams.MeekSNIServerName = selectHostName(dialParams.TunnelProtocol, p)
  525. dialParams.MeekTransformedHostName = true
  526. }
  527. }
  528. // The minimum delay value is determined by the Conjure station, which
  529. // performs an asynchronous "liveness test" against the selected phantom
  530. // IPs. The min/max range allows us to introduce some jitter so that we
  531. // don't present a trivial inter-flow fingerprint: CDN connection, fixed
  532. // delay, phantom dial.
  533. minDelay := p.Duration(parameters.ConjureAPIRegistrarMinDelay)
  534. maxDelay := p.Duration(parameters.ConjureAPIRegistrarMaxDelay)
  535. dialParams.ConjureAPIRegistrarDelay = prng.Period(minDelay, maxDelay)
  536. } else if dialParams.ConjureDecoyRegistration {
  537. dialParams.ConjureDecoyRegistrarWidth = decoyWidth
  538. minDelay := p.Duration(parameters.ConjureDecoyRegistrarMinDelay)
  539. maxDelay := p.Duration(parameters.ConjureDecoyRegistrarMaxDelay)
  540. dialParams.ConjureAPIRegistrarDelay = prng.Period(minDelay, maxDelay)
  541. } else {
  542. return nil, errors.TraceNew("no Conjure registrar configured")
  543. }
  544. }
  545. if (!isReplay || !replayConjureTransport) &&
  546. protocol.TunnelProtocolUsesConjure(dialParams.TunnelProtocol) {
  547. // None of ConjureEnableIPv6Dials, ConjureEnablePortRandomization, or
  548. // ConjureEnableRegistrationOverrides are set here for replay. The
  549. // current value of these flag parameters is always applied.
  550. dialParams.ConjureTransport = selectConjureTransport(p)
  551. if protocol.ConjureTransportUsesSTUN(dialParams.ConjureTransport) {
  552. stunServerAddresses := p.Strings(parameters.ConjureSTUNServerAddresses)
  553. if len(stunServerAddresses) == 0 {
  554. return nil, errors.Tracef(
  555. "no Conjure STUN servers addresses configured for transport %s", dialParams.ConjureTransport)
  556. }
  557. dialParams.ConjureSTUNServerAddress = stunServerAddresses[prng.Intn(len(stunServerAddresses))]
  558. dialParams.ConjureDTLSEmptyInitialPacket = p.WeightedCoinFlip(
  559. parameters.ConjureDTLSEmptyInitialPacketProbability)
  560. }
  561. }
  562. usingTLS := protocol.TunnelProtocolUsesMeekHTTPS(dialParams.TunnelProtocol) ||
  563. protocol.TunnelProtocolUsesTLSOSSH(dialParams.TunnelProtocol) ||
  564. dialParams.ConjureAPIRegistration
  565. if (!isReplay || !replayTLSProfile) && usingTLS {
  566. dialParams.SelectedTLSProfile = true
  567. requireTLS12SessionTickets := protocol.TunnelProtocolRequiresTLS12SessionTickets(
  568. dialParams.TunnelProtocol)
  569. requireTLS13Support := protocol.TunnelProtocolRequiresTLS13Support(dialParams.TunnelProtocol)
  570. isFronted := protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) ||
  571. dialParams.ConjureAPIRegistration
  572. dialParams.TLSProfile, dialParams.TLSVersion, dialParams.RandomizedTLSProfileSeed, err = SelectTLSProfile(
  573. requireTLS12SessionTickets, requireTLS13Support, isFronted, serverEntry.FrontingProviderID, p)
  574. if err != nil {
  575. return nil, errors.Trace(err)
  576. }
  577. if dialParams.TLSProfile == "" && (requireTLS12SessionTickets || requireTLS13Support) {
  578. return nil, errors.TraceNew("required TLS profile not found")
  579. }
  580. dialParams.NoDefaultTLSSessionID = p.WeightedCoinFlip(
  581. parameters.NoDefaultTLSSessionIDProbability)
  582. }
  583. if (!isReplay || !replayFronting) &&
  584. protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) {
  585. dialParams.FrontingProviderID = serverEntry.FrontingProviderID
  586. dialParams.MeekFrontingDialAddress, dialParams.MeekFrontingHost, err =
  587. selectFrontingParameters(serverEntry)
  588. if err != nil {
  589. return nil, errors.Trace(err)
  590. }
  591. }
  592. if !isReplay || !replayHostname {
  593. // Any MeekHostHeader selections made here will be overridden below,
  594. // as required, for fronting cases.
  595. if protocol.TunnelProtocolUsesMeekHTTPS(dialParams.TunnelProtocol) ||
  596. protocol.TunnelProtocolUsesFrontedMeekQUIC(dialParams.TunnelProtocol) {
  597. dialParams.MeekSNIServerName = ""
  598. hostname := ""
  599. if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
  600. dialParams.MeekSNIServerName = selectHostName(dialParams.TunnelProtocol, p)
  601. hostname = dialParams.MeekSNIServerName
  602. dialParams.MeekTransformedHostName = true
  603. } else {
  604. // Always select a hostname for the Host header in this case.
  605. // Unlike HTTP, the Host header isn't plaintext on the wire,
  606. // and so there's no anti-fingerprint benefit from presenting
  607. // the server IP address in the Host header. Omitting the
  608. // server IP here can prevent exposing it in certain
  609. // scenarios where the traffic is rerouted and arrives at a
  610. // different HTTPS server.
  611. hostname = selectHostName(dialParams.TunnelProtocol, p)
  612. }
  613. if serverEntry.MeekServerPort == 443 {
  614. dialParams.MeekHostHeader = hostname
  615. } else {
  616. dialParams.MeekHostHeader = net.JoinHostPort(
  617. hostname, strconv.Itoa(serverEntry.MeekServerPort))
  618. }
  619. } else if protocol.TunnelProtocolUsesTLSOSSH(dialParams.TunnelProtocol) {
  620. dialParams.TLSOSSHSNIServerName = ""
  621. if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
  622. dialParams.TLSOSSHSNIServerName = selectHostName(dialParams.TunnelProtocol, p)
  623. dialParams.TLSOSSHTransformedSNIServerName = true
  624. }
  625. } else if protocol.TunnelProtocolUsesMeekHTTP(dialParams.TunnelProtocol) {
  626. dialParams.MeekHostHeader = ""
  627. hostname := serverEntry.IpAddress
  628. if p.WeightedCoinFlip(parameters.TransformHostNameProbability) {
  629. hostname = selectHostName(dialParams.TunnelProtocol, p)
  630. dialParams.MeekTransformedHostName = true
  631. }
  632. if serverEntry.MeekServerPort == 80 {
  633. dialParams.MeekHostHeader = hostname
  634. } else {
  635. dialParams.MeekHostHeader = net.JoinHostPort(
  636. hostname, strconv.Itoa(serverEntry.MeekServerPort))
  637. }
  638. } else if protocol.TunnelProtocolUsesQUIC(dialParams.TunnelProtocol) {
  639. dialParams.QUICDialSNIAddress = selectHostName(dialParams.TunnelProtocol, p)
  640. }
  641. }
  642. if (!isReplay || !replayQUICVersion) &&
  643. protocol.TunnelProtocolUsesQUIC(dialParams.TunnelProtocol) {
  644. isFronted := protocol.TunnelProtocolUsesFrontedMeekQUIC(dialParams.TunnelProtocol)
  645. dialParams.QUICVersion = selectQUICVersion(isFronted, serverEntry, p)
  646. // Due to potential tactics configurations, it may be that no QUIC
  647. // version is selected. Abort immediately, with no error, as in the
  648. // selectProtocol case. quic.Dial and quic.NewQUICTransporter will
  649. // check for a missing QUIC version, but at that later stage an
  650. // unnecessary failed_tunnel can be logged in this scenario.
  651. if dialParams.QUICVersion == "" {
  652. return nil, nil
  653. }
  654. if protocol.QUICVersionHasRandomizedClientHello(dialParams.QUICVersion) {
  655. dialParams.QUICClientHelloSeed, err = prng.NewSeed()
  656. if err != nil {
  657. return nil, errors.Trace(err)
  658. }
  659. }
  660. dialParams.QUICDisablePathMTUDiscovery =
  661. protocol.QUICVersionUsesPathMTUDiscovery(dialParams.QUICVersion) &&
  662. p.WeightedCoinFlip(parameters.QUICDisableClientPathMTUDiscoveryProbability)
  663. }
  664. if (!isReplay || !replayObfuscatedQUIC) &&
  665. protocol.QUICVersionIsObfuscated(dialParams.QUICVersion) {
  666. dialParams.ObfuscatedQUICPaddingSeed, err = prng.NewSeed()
  667. if err != nil {
  668. return nil, errors.Trace(err)
  669. }
  670. }
  671. if protocol.QUICVersionIsObfuscated(dialParams.QUICVersion) {
  672. if serverEntry.DisableObfuscatedQUICTransforms {
  673. dialParams.ObfuscatedQUICNonceTransformerParameters = nil
  674. } else if !isReplay || !replayObfuscatedQUICNonceTransformer {
  675. params, err := makeSeedTransformerParameters(
  676. p,
  677. parameters.ObfuscatedQUICNonceTransformProbability,
  678. parameters.ObfuscatedQUICNonceTransformSpecs,
  679. parameters.ObfuscatedQUICNonceTransformScopedSpecNames)
  680. if err != nil {
  681. return nil, errors.Trace(err)
  682. }
  683. if params.TransformSpec != nil {
  684. dialParams.ObfuscatedQUICNonceTransformerParameters = params
  685. } else {
  686. dialParams.ObfuscatedQUICNonceTransformerParameters = nil
  687. }
  688. }
  689. }
  690. if !isReplay || !replayLivenessTest {
  691. // TODO: initialize only when LivenessTestMaxUp/DownstreamBytes > 0?
  692. dialParams.LivenessTestSeed, err = prng.NewSeed()
  693. if err != nil {
  694. return nil, errors.Trace(err)
  695. }
  696. }
  697. if !isReplay || !replayAPIRequestPadding {
  698. dialParams.APIRequestPaddingSeed, err = prng.NewSeed()
  699. if err != nil {
  700. return nil, errors.Trace(err)
  701. }
  702. }
  703. // Initialize dialParams.ResolveParameters for dials that will resolve
  704. // domain names, which currently includes fronted meek and Conjure API
  705. // registration, where the dial address is not an IP address.
  706. //
  707. // dialParams.ResolveParameters must be nil when the dial address is an IP
  708. // address to ensure that no DNS dial parameters are reported in metrics
  709. // or diagnostics when when no domain is resolved.
  710. useResolver := (protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) ||
  711. dialParams.ConjureAPIRegistration) &&
  712. net.ParseIP(dialParams.MeekFrontingDialAddress) == nil
  713. if (!isReplay || !replayResolveParameters) && useResolver {
  714. dialParams.ResolveParameters, err = dialParams.resolver.MakeResolveParameters(
  715. p, dialParams.FrontingProviderID, dialParams.MeekFrontingDialAddress)
  716. if err != nil {
  717. return nil, errors.Trace(err)
  718. }
  719. }
  720. if !isReplay || !replayHoldOffTunnel {
  721. var holdOffTunnelDuration time.Duration
  722. var holdOffDirectTunnelDuration time.Duration
  723. if common.Contains(
  724. p.TunnelProtocols(parameters.HoldOffTunnelProtocols), dialParams.TunnelProtocol) ||
  725. (protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) &&
  726. common.Contains(
  727. p.Strings(parameters.HoldOffTunnelFrontingProviderIDs),
  728. dialParams.FrontingProviderID)) {
  729. if p.WeightedCoinFlip(parameters.HoldOffTunnelProbability) {
  730. holdOffTunnelDuration = prng.Period(
  731. p.Duration(parameters.HoldOffTunnelMinDuration),
  732. p.Duration(parameters.HoldOffTunnelMaxDuration))
  733. }
  734. }
  735. if protocol.TunnelProtocolIsDirect(dialParams.TunnelProtocol) &&
  736. common.ContainsAny(
  737. p.KeyStrings(parameters.HoldOffDirectTunnelProviderRegions, dialParams.ServerEntry.ProviderID), []string{"", serverEntry.Region}) {
  738. if p.WeightedCoinFlip(parameters.HoldOffDirectTunnelProbability) {
  739. holdOffDirectTunnelDuration = prng.Period(
  740. p.Duration(parameters.HoldOffDirectTunnelMinDuration),
  741. p.Duration(parameters.HoldOffDirectTunnelMaxDuration))
  742. }
  743. }
  744. // Use the longest hold off duration
  745. if holdOffTunnelDuration >= holdOffDirectTunnelDuration {
  746. dialParams.HoldOffTunnelDuration = holdOffTunnelDuration
  747. } else {
  748. dialParams.HoldOffTunnelDuration = holdOffDirectTunnelDuration
  749. }
  750. }
  751. // OSSH prefix and seed transform are applied only to the OSSH tunnel protocol,
  752. // and not to any other protocol layered over OSSH.
  753. if dialParams.TunnelProtocol == protocol.TUNNEL_PROTOCOL_OBFUSCATED_SSH {
  754. if serverEntry.DisableOSSHTransforms {
  755. dialParams.OSSHObfuscatorSeedTransformerParameters = nil
  756. } else if !isReplay || !replayOSSHSeedTransformerParameters {
  757. params, err := makeSeedTransformerParameters(
  758. p,
  759. parameters.OSSHObfuscatorSeedTransformProbability,
  760. parameters.OSSHObfuscatorSeedTransformSpecs,
  761. parameters.OSSHObfuscatorSeedTransformScopedSpecNames)
  762. if err != nil {
  763. return nil, errors.Trace(err)
  764. }
  765. if params.TransformSpec != nil {
  766. dialParams.OSSHObfuscatorSeedTransformerParameters = params
  767. } else {
  768. dialParams.OSSHObfuscatorSeedTransformerParameters = nil
  769. }
  770. }
  771. if serverEntry.DisableOSSHPrefix {
  772. dialParams.OSSHPrefixSpec = nil
  773. dialParams.OSSHPrefixSplitConfig = nil
  774. } else if !isReplay || !replayOSSHPrefix {
  775. dialPortNumber, err := serverEntry.GetDialPortNumber(dialParams.TunnelProtocol)
  776. if err != nil {
  777. return nil, errors.Trace(err)
  778. }
  779. prefixSpec, err := makeOSSHPrefixSpecParameters(p, strconv.Itoa(dialPortNumber))
  780. if err != nil {
  781. return nil, errors.Trace(err)
  782. }
  783. splitConfig, err := makeOSSHPrefixSplitConfig(p)
  784. if err != nil {
  785. return nil, errors.Trace(err)
  786. }
  787. if prefixSpec.Spec != nil {
  788. dialParams.OSSHPrefixSpec = prefixSpec
  789. dialParams.OSSHPrefixSplitConfig = splitConfig
  790. } else {
  791. dialParams.OSSHPrefixSpec = nil
  792. dialParams.OSSHPrefixSplitConfig = nil
  793. }
  794. }
  795. // OSSHPrefix supersedes OSSHObfuscatorSeedTransform.
  796. // This ensures both tactics are not used simultaneously,
  797. // until OSSHObfuscatorSeedTransform is removed.
  798. if dialParams.OSSHPrefixSpec != nil {
  799. dialParams.OSSHObfuscatorSeedTransformerParameters = nil
  800. }
  801. }
  802. if protocol.TunnelProtocolUsesMeekHTTP(dialParams.TunnelProtocol) {
  803. if serverEntry.DisableHTTPTransforms {
  804. dialParams.HTTPTransformerParameters = nil
  805. } else if !isReplay || !replayHTTPTransformerParameters {
  806. isFronted := protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol)
  807. params, err := makeHTTPTransformerParameters(config.GetParameters().Get(), serverEntry.FrontingProviderID, isFronted)
  808. if err != nil {
  809. return nil, errors.Trace(err)
  810. }
  811. if params.ProtocolTransformSpec != nil {
  812. dialParams.HTTPTransformerParameters = params
  813. } else {
  814. dialParams.HTTPTransformerParameters = nil
  815. }
  816. }
  817. }
  818. // Set dial address fields. This portion of configuration is
  819. // deterministic, given the parameters established or replayed so far.
  820. dialPortNumber, err := serverEntry.GetDialPortNumber(dialParams.TunnelProtocol)
  821. if err != nil {
  822. return nil, errors.Trace(err)
  823. }
  824. dialParams.DialPortNumber = strconv.Itoa(dialPortNumber)
  825. switch dialParams.TunnelProtocol {
  826. case protocol.TUNNEL_PROTOCOL_SSH,
  827. protocol.TUNNEL_PROTOCOL_OBFUSCATED_SSH,
  828. protocol.TUNNEL_PROTOCOL_TAPDANCE_OBFUSCATED_SSH,
  829. protocol.TUNNEL_PROTOCOL_CONJURE_OBFUSCATED_SSH,
  830. protocol.TUNNEL_PROTOCOL_QUIC_OBFUSCATED_SSH,
  831. protocol.TUNNEL_PROTOCOL_TLS_OBFUSCATED_SSH:
  832. dialParams.DirectDialAddress = net.JoinHostPort(serverEntry.IpAddress, dialParams.DialPortNumber)
  833. case protocol.TUNNEL_PROTOCOL_FRONTED_MEEK,
  834. protocol.TUNNEL_PROTOCOL_FRONTED_MEEK_QUIC_OBFUSCATED_SSH:
  835. dialParams.MeekDialAddress = net.JoinHostPort(dialParams.MeekFrontingDialAddress, dialParams.DialPortNumber)
  836. dialParams.MeekHostHeader = dialParams.MeekFrontingHost
  837. if serverEntry.MeekFrontingDisableSNI {
  838. dialParams.MeekSNIServerName = ""
  839. // When SNI is omitted, the transformed host name is not used.
  840. dialParams.MeekTransformedHostName = false
  841. } else if !dialParams.MeekTransformedHostName {
  842. dialParams.MeekSNIServerName = dialParams.MeekFrontingDialAddress
  843. }
  844. case protocol.TUNNEL_PROTOCOL_FRONTED_MEEK_HTTP:
  845. dialParams.MeekDialAddress = net.JoinHostPort(dialParams.MeekFrontingDialAddress, dialParams.DialPortNumber)
  846. dialParams.MeekHostHeader = dialParams.MeekFrontingHost
  847. // For FRONTED HTTP, the Host header cannot be transformed.
  848. dialParams.MeekTransformedHostName = false
  849. case protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK:
  850. dialParams.MeekDialAddress = net.JoinHostPort(serverEntry.IpAddress, dialParams.DialPortNumber)
  851. case protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK_HTTPS,
  852. protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK_SESSION_TICKET:
  853. dialParams.MeekDialAddress = net.JoinHostPort(serverEntry.IpAddress, dialParams.DialPortNumber)
  854. if !dialParams.MeekTransformedHostName {
  855. // Note: IP address in SNI field will be omitted.
  856. dialParams.MeekSNIServerName = serverEntry.IpAddress
  857. }
  858. default:
  859. return nil, errors.Tracef(
  860. "unknown tunnel protocol: %s", dialParams.TunnelProtocol)
  861. }
  862. if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) {
  863. host, _, _ := net.SplitHostPort(dialParams.MeekDialAddress)
  864. if p.Bool(parameters.MeekDialDomainsOnly) {
  865. if net.ParseIP(host) != nil {
  866. // No error, as this is a "not supported" case.
  867. return nil, nil
  868. }
  869. }
  870. // The underlying TLS implementation will automatically omit SNI for
  871. // IP address server name values; we have this explicit check here so
  872. // we record the correct value for stats.
  873. if net.ParseIP(dialParams.MeekSNIServerName) != nil {
  874. dialParams.MeekSNIServerName = ""
  875. }
  876. }
  877. // TLS ClientHello fragmentation is applied only after the state
  878. // of SNI is determined above.
  879. if (!isReplay || !replayTLSFragmentClientHello) && usingTLS {
  880. limitProtocols := p.TunnelProtocols(parameters.TLSFragmentClientHelloLimitProtocols)
  881. if len(limitProtocols) == 0 || common.Contains(limitProtocols, dialParams.TunnelProtocol) {
  882. // Note: The TLS stack automatically drops the SNI extension when
  883. // the host is an IP address.
  884. usingSNI := false
  885. if dialParams.TLSOSSHSNIServerName != "" {
  886. usingSNI = net.ParseIP(dialParams.TLSOSSHSNIServerName) == nil
  887. } else if dialParams.MeekSNIServerName != "" {
  888. usingSNI = net.ParseIP(dialParams.MeekSNIServerName) == nil
  889. }
  890. // TLS ClientHello fragmentor expects SNI to be present.
  891. if usingSNI {
  892. dialParams.TLSFragmentClientHello = p.WeightedCoinFlip(
  893. parameters.TLSFragmentClientHelloProbability)
  894. }
  895. }
  896. }
  897. // Initialize/replay User-Agent header for HTTP upstream proxy and meek protocols.
  898. if config.UseUpstreamProxy() {
  899. // Note: UpstreamProxyURL will be validated in the dial
  900. proxyURL, err := common.SafeParseURL(config.UpstreamProxyURL)
  901. if err == nil {
  902. dialParams.UpstreamProxyType = proxyURL.Scheme
  903. }
  904. }
  905. dialCustomHeaders := makeDialCustomHeaders(config, p)
  906. if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) ||
  907. dialParams.UpstreamProxyType == "http" ||
  908. dialParams.ConjureAPIRegistration {
  909. if !isReplay || !replayUserAgent {
  910. dialParams.SelectedUserAgent, dialParams.UserAgent = selectUserAgentIfUnset(p, dialCustomHeaders)
  911. }
  912. if dialParams.SelectedUserAgent {
  913. dialCustomHeaders.Set("User-Agent", dialParams.UserAgent)
  914. }
  915. }
  916. // UpstreamProxyCustomHeaderNames is a reported metric. Just the names and
  917. // not the values are reported, in case the values are identifying.
  918. if len(config.CustomHeaders) > 0 {
  919. dialParams.UpstreamProxyCustomHeaderNames = make([]string, 0)
  920. for name := range dialCustomHeaders {
  921. if name == "User-Agent" && dialParams.SelectedUserAgent {
  922. continue
  923. }
  924. dialParams.UpstreamProxyCustomHeaderNames = append(dialParams.UpstreamProxyCustomHeaderNames, name)
  925. }
  926. }
  927. // Initialize Dial/MeekConfigs to be passed to the corresponding dialers.
  928. var resolveIP func(ctx context.Context, hostname string) ([]net.IP, error)
  929. // Determine whether to use a steering IP, and whether to indicate that
  930. // this dial remains a replay or not.
  931. //
  932. // Steering IPs are used only for fronted tunnels and not lower-traffic
  933. // tactics requests and signalling steps such as Conjure registration.
  934. //
  935. // The scope of the steering IP, and the corresponding cache key, is the
  936. // fronting provider, tunnel protocol, and the current network ID.
  937. //
  938. // Currently, steering IPs are obtained and cached in the Psiphon API
  939. // handshake response. A modest TTL is applied to cache entries, and, in
  940. // the case of a failed tunnel, any corresponding cached steering IP is
  941. // removed.
  942. //
  943. // DialParameters.SteeringIP is set and persisted, but is not used to dial
  944. // in a replay case; it's used to determine whether this dial should be
  945. // classified as a replay or not. A replay dial remains classified as
  946. // replay if a steering IP is not used and no steering IP was used
  947. // before; or when a steering IP is used and the same steering IP was
  948. // used before.
  949. //
  950. // When a steering IP is used and none was used before, or vice versa,
  951. // DialParameters.IsReplay is cleared so that is_replay is reported as
  952. // false, since the dial may be very different in nature: using a
  953. // different POP; skipping DNS; etc. Even if DialParameters.IsReplay was
  954. // true and is cleared, this MakeDialParameters will have wired up all
  955. // other dial parameters with replay values, so the benefit of those
  956. // values is not lost.
  957. var previousSteeringIP, currentSteeringIP string
  958. if isReplay {
  959. previousSteeringIP = dialParams.SteeringIP
  960. }
  961. dialParams.SteeringIP = ""
  962. if !isTactics &&
  963. protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol) &&
  964. dialParams.ServerEntry.FrontingProviderID != "" {
  965. dialParams.steeringIPCacheKey = fmt.Sprintf("%s %s %s",
  966. dialParams.NetworkID,
  967. dialParams.ServerEntry.FrontingProviderID,
  968. dialParams.TunnelProtocol)
  969. steeringIPValue, ok := dialParams.steeringIPCache.Get(
  970. dialParams.steeringIPCacheKey)
  971. if ok {
  972. currentSteeringIP = steeringIPValue.(string)
  973. }
  974. // A steering IP probability is applied and may be used to gradually
  975. // apply steering IPs. The coin flip is made only to decide to start
  976. // using a steering IP, avoiding flip flopping between dials. For any
  977. // probability > 0.0, a long enough continuous session will
  978. // eventually flip to true and then keep using steering IPs as long
  979. // as they remain in the cache.
  980. if previousSteeringIP == "" && currentSteeringIP != "" &&
  981. !p.WeightedCoinFlip(parameters.SteeringIPProbability) {
  982. currentSteeringIP = ""
  983. }
  984. }
  985. if currentSteeringIP != "" {
  986. IP := net.ParseIP(currentSteeringIP)
  987. if IP == nil {
  988. return nil, errors.TraceNew("invalid steering IP")
  989. }
  990. // Since tcpDial and NewUDPConn invoke ResolveIP unconditionally, even
  991. // when the hostname is an IP address, a steering IP will be applied
  992. // even in that case.
  993. resolveIP = func(ctx context.Context, hostname string) ([]net.IP, error) {
  994. return []net.IP{IP}, nil
  995. }
  996. // dialParams.SteeringIP will be used as the "previous" steering IP in
  997. // the next replay.
  998. dialParams.SteeringIP = currentSteeringIP
  999. }
  1000. if currentSteeringIP != previousSteeringIP {
  1001. dialParams.IsReplay = false
  1002. }
  1003. // Custom ResolveParameters are set only when useResolver is true, but
  1004. // DialConfig.ResolveIP is required and wired up unconditionally. Any
  1005. // misconfigured or miscoded domain dial cases will use default
  1006. // ResolveParameters.
  1007. //
  1008. // ResolveIP will use the networkID obtained above, as it will be used
  1009. // almost immediately, instead of incurring the overhead of calling
  1010. // GetNetworkID again.
  1011. if resolveIP == nil {
  1012. resolveIP = func(ctx context.Context, hostname string) ([]net.IP, error) {
  1013. IPs, err := dialParams.resolver.ResolveIP(
  1014. ctx,
  1015. networkID,
  1016. dialParams.ResolveParameters,
  1017. hostname)
  1018. if err != nil {
  1019. return nil, errors.Trace(err)
  1020. }
  1021. return IPs, nil
  1022. }
  1023. }
  1024. // Fragmentor configuration.
  1025. // Note: fragmentorConfig is nil if fragmentor is disabled for prefixed OSSH.
  1026. //
  1027. // Limitation: when replaying and with ReplayIgnoreChangedConfigState set,
  1028. // fragmentor.NewUpstreamConfig may select a config using newer tactics
  1029. // parameters.
  1030. fragmentorConfig := fragmentor.NewUpstreamConfig(p, dialParams.TunnelProtocol, dialParams.FragmentorSeed)
  1031. if !p.Bool(parameters.OSSHPrefixEnableFragmentor) && dialParams.OSSHPrefixSpec != nil {
  1032. fragmentorConfig = nil
  1033. }
  1034. dialParams.dialConfig = &DialConfig{
  1035. DiagnosticID: serverEntry.GetDiagnosticID(),
  1036. UpstreamProxyURL: config.UpstreamProxyURL,
  1037. CustomHeaders: dialCustomHeaders,
  1038. BPFProgramInstructions: dialParams.BPFProgramInstructions,
  1039. DeviceBinder: config.deviceBinder,
  1040. IPv6Synthesizer: config.IPv6Synthesizer,
  1041. ResolveIP: resolveIP,
  1042. TrustedCACertificatesFilename: config.TrustedCACertificatesFilename,
  1043. FragmentorConfig: fragmentorConfig,
  1044. UpstreamProxyErrorCallback: upstreamProxyErrorCallback,
  1045. }
  1046. // Unconditionally initialize MeekResolvedIPAddress, so a valid string can
  1047. // always be read.
  1048. dialParams.MeekResolvedIPAddress.Store("")
  1049. if protocol.TunnelProtocolUsesMeek(dialParams.TunnelProtocol) ||
  1050. dialParams.ConjureAPIRegistration {
  1051. // For tactics requests, AddPsiphonFrontingHeader is set when set for
  1052. // the related tunnel protocol. E.g., FRONTED-OSSH-MEEK for
  1053. // FRONTED-MEEK-TACTICS. AddPsiphonFrontingHeader is not replayed.
  1054. addPsiphonFrontingHeader := false
  1055. if dialParams.FrontingProviderID != "" {
  1056. addPsiphonFrontingHeader = common.Contains(
  1057. p.LabeledTunnelProtocols(
  1058. parameters.AddFrontingProviderPsiphonFrontingHeader, dialParams.FrontingProviderID),
  1059. dialParams.TunnelProtocol)
  1060. }
  1061. dialParams.meekConfig = &MeekConfig{
  1062. DiagnosticID: serverEntry.GetDiagnosticID(),
  1063. Parameters: config.GetParameters(),
  1064. DialAddress: dialParams.MeekDialAddress,
  1065. UseQUIC: protocol.TunnelProtocolUsesFrontedMeekQUIC(dialParams.TunnelProtocol),
  1066. QUICVersion: dialParams.QUICVersion,
  1067. QUICClientHelloSeed: dialParams.QUICClientHelloSeed,
  1068. QUICDisablePathMTUDiscovery: dialParams.QUICDisablePathMTUDiscovery,
  1069. UseHTTPS: usingTLS,
  1070. TLSProfile: dialParams.TLSProfile,
  1071. TLSFragmentClientHello: dialParams.TLSFragmentClientHello,
  1072. LegacyPassthrough: serverEntry.ProtocolUsesLegacyPassthrough(dialParams.TunnelProtocol),
  1073. NoDefaultTLSSessionID: dialParams.NoDefaultTLSSessionID,
  1074. RandomizedTLSProfileSeed: dialParams.RandomizedTLSProfileSeed,
  1075. UseObfuscatedSessionTickets: dialParams.TunnelProtocol == protocol.TUNNEL_PROTOCOL_UNFRONTED_MEEK_SESSION_TICKET,
  1076. SNIServerName: dialParams.MeekSNIServerName,
  1077. AddPsiphonFrontingHeader: addPsiphonFrontingHeader,
  1078. VerifyServerName: dialParams.MeekVerifyServerName,
  1079. VerifyPins: dialParams.MeekVerifyPins,
  1080. DisableSystemRootCAs: config.DisableSystemRootCAs,
  1081. HostHeader: dialParams.MeekHostHeader,
  1082. TransformedHostName: dialParams.MeekTransformedHostName,
  1083. ClientTunnelProtocol: dialParams.TunnelProtocol,
  1084. MeekCookieEncryptionPublicKey: serverEntry.MeekCookieEncryptionPublicKey,
  1085. MeekObfuscatedKey: serverEntry.MeekObfuscatedKey,
  1086. MeekObfuscatorPaddingSeed: dialParams.MeekObfuscatorPaddingSeed,
  1087. NetworkLatencyMultiplier: dialParams.NetworkLatencyMultiplier,
  1088. HTTPTransformerParameters: dialParams.HTTPTransformerParameters,
  1089. AdditionalHeaders: config.MeekAdditionalHeaders,
  1090. }
  1091. // Use an asynchronous callback to record the resolved IP address when
  1092. // dialing a domain name. Note that DialMeek doesn't immediately
  1093. // establish any HTTP connections, so the resolved IP address won't be
  1094. // reported in all cases until after SSH traffic is relayed or a
  1095. // endpoint request is made over the meek connection.
  1096. dialParams.dialConfig.ResolvedIPCallback = func(IPAddress string) {
  1097. dialParams.MeekResolvedIPAddress.Store(IPAddress)
  1098. }
  1099. if isTactics {
  1100. dialParams.meekConfig.Mode = MeekModeObfuscatedRoundTrip
  1101. } else if dialParams.ConjureAPIRegistration {
  1102. dialParams.meekConfig.Mode = MeekModePlaintextRoundTrip
  1103. } else {
  1104. dialParams.meekConfig.Mode = MeekModeRelay
  1105. }
  1106. }
  1107. return dialParams, nil
  1108. }
  1109. func (dialParams *DialParameters) GetDialConfig() *DialConfig {
  1110. return dialParams.dialConfig
  1111. }
  1112. func (dialParams *DialParameters) GetTLSOSSHConfig(config *Config) *TLSTunnelConfig {
  1113. return &TLSTunnelConfig{
  1114. CustomTLSConfig: &CustomTLSConfig{
  1115. Parameters: config.GetParameters(),
  1116. DialAddr: dialParams.DirectDialAddress,
  1117. SNIServerName: dialParams.TLSOSSHSNIServerName,
  1118. SkipVerify: true,
  1119. VerifyServerName: "",
  1120. VerifyPins: nil,
  1121. TLSProfile: dialParams.TLSProfile,
  1122. NoDefaultTLSSessionID: &dialParams.NoDefaultTLSSessionID,
  1123. RandomizedTLSProfileSeed: dialParams.RandomizedTLSProfileSeed,
  1124. FragmentClientHello: dialParams.TLSFragmentClientHello,
  1125. },
  1126. // Obfuscated session tickets are not used because TLS-OSSH uses TLS 1.3.
  1127. UseObfuscatedSessionTickets: false,
  1128. // Meek obfuscated key used to allow clients with legacy unfronted
  1129. // meek-https server entries, that have the passthrough capability, to
  1130. // connect with TLS-OSSH to the servers corresponding to those server
  1131. // entries, which now support TLS-OSSH by demultiplexing meek-https and
  1132. // TLS-OSSH over the meek-https port.
  1133. ObfuscatedKey: dialParams.ServerEntry.MeekObfuscatedKey,
  1134. ObfuscatorPaddingSeed: dialParams.TLSOSSHObfuscatorPaddingSeed,
  1135. }
  1136. }
  1137. func (dialParams *DialParameters) GetMeekConfig() *MeekConfig {
  1138. return dialParams.meekConfig
  1139. }
  1140. // GetNetworkType returns a network type name, suitable for metrics, which is
  1141. // derived from the network ID.
  1142. func (dialParams *DialParameters) GetNetworkType() string {
  1143. // Unlike the logic in loggingNetworkIDGetter.GetNetworkID, we don't take the
  1144. // arbitrary text before the first "-" since some platforms without network
  1145. // detection support stub in random values to enable tactics. Instead we
  1146. // check for and use the common network type prefixes currently used in
  1147. // NetworkIDGetter implementations.
  1148. if strings.HasPrefix(dialParams.NetworkID, "VPN") {
  1149. return "VPN"
  1150. }
  1151. if strings.HasPrefix(dialParams.NetworkID, "WIFI") {
  1152. return "WIFI"
  1153. }
  1154. if strings.HasPrefix(dialParams.NetworkID, "MOBILE") {
  1155. return "MOBILE"
  1156. }
  1157. return "UNKNOWN"
  1158. }
  1159. func (dialParams *DialParameters) Succeeded() {
  1160. // When TTL is 0, don't store dial parameters.
  1161. if dialParams.LastUsedTimestamp.IsZero() {
  1162. return
  1163. }
  1164. NoticeInfo("Set dial parameters for %s", dialParams.ServerEntry.GetDiagnosticID())
  1165. err := SetDialParameters(dialParams.ServerEntry.IpAddress, dialParams.NetworkID, dialParams)
  1166. if err != nil {
  1167. NoticeWarning("SetDialParameters failed: %s", err)
  1168. }
  1169. }
  1170. func (dialParams *DialParameters) Failed(config *Config) {
  1171. // When a tunnel fails, and the dial is a replay, clear the stored dial
  1172. // parameters which are now presumed to be blocked, impaired or otherwise
  1173. // no longer effective.
  1174. //
  1175. // It may be the case that a dial is not using stored dial parameters
  1176. // (!IsReplay), and in this case we retain those dial parameters since they
  1177. // were not exercised and may still be effective.
  1178. //
  1179. // Failed tunnel dial parameters may be retained with a configurable
  1180. // probability; this is intended to help mitigate false positive failures due
  1181. // to, e.g., temporary network disruptions or server load limiting.
  1182. if dialParams.IsReplay &&
  1183. !config.GetParameters().Get().WeightedCoinFlip(
  1184. parameters.ReplayRetainFailedProbability) {
  1185. NoticeInfo("Delete dial parameters for %s", dialParams.ServerEntry.GetDiagnosticID())
  1186. err := DeleteDialParameters(dialParams.ServerEntry.IpAddress, dialParams.NetworkID)
  1187. if err != nil {
  1188. NoticeWarning("DeleteDialParameters failed: %s", err)
  1189. }
  1190. }
  1191. // When a failed tunnel dialed with steering IP, remove the corresponding
  1192. // cache entry to avoid continuously redialing a potentially blocked or
  1193. // degraded POP.
  1194. //
  1195. // TODO: don't remove, but reduce the TTL to allow for one more dial?
  1196. if dialParams.steeringIPCacheKey != "" {
  1197. dialParams.steeringIPCache.Delete(dialParams.steeringIPCacheKey)
  1198. }
  1199. }
  1200. func (dialParams *DialParameters) GetTLSVersionForMetrics() string {
  1201. return getTLSVersionForMetrics(dialParams.TLSVersion, dialParams.NoDefaultTLSSessionID)
  1202. }
  1203. func getTLSVersionForMetrics(tlsVersion string, noDefaultTLSSessionID bool) string {
  1204. version := tlsVersion
  1205. if noDefaultTLSSessionID {
  1206. version += "-no_def_id"
  1207. }
  1208. return version
  1209. }
  1210. // ExchangedDialParameters represents the subset of DialParameters that is
  1211. // shared in a client-to-client exchange of server connection info.
  1212. //
  1213. // The purpose of client-to-client exchange if for one user that can connect
  1214. // to help another user that cannot connect by sharing their connected
  1215. // configuration, including the server entry and dial parameters.
  1216. //
  1217. // There are two concerns regarding which dial parameter fields are safe to
  1218. // exchange:
  1219. //
  1220. // - Unlike signed server entries, there's no independent trust anchor
  1221. // that can certify that the exchange data is valid.
  1222. //
  1223. // - While users should only perform the exchange with trusted peers,
  1224. // the user's trust in their peer may be misplaced.
  1225. //
  1226. // This presents the possibility of attack such as the peer sending dial
  1227. // parameters that could be used to trace/monitor/flag the importer; or
  1228. // sending dial parameters, including dial address and SNI, to cause the peer
  1229. // to appear to connect to a banned service.
  1230. //
  1231. // To mitigate these risks, only a subset of dial parameters are exchanged.
  1232. // When exchanged dial parameters and imported and used, all unexchanged
  1233. // parameters are generated locally. At this time, only the tunnel protocol is
  1234. // exchanged. We consider tunnel protocol selection one of the key connection
  1235. // success factors.
  1236. //
  1237. // In addition, the exchange peers may not be on the same network with the
  1238. // same blocking and circumvention characteristics, which is another reason
  1239. // to limit exchanged dial parameter values to broadly applicable fields.
  1240. //
  1241. // Unlike the exchanged (and otherwise acquired) server entry,
  1242. // ExchangedDialParameters does not use the ServerEntry_Fields_ representation
  1243. // which allows older clients to receive and store new, unknown fields. Such a
  1244. // facility is less useful in this case, since exchanged dial parameters and
  1245. // used immediately and have a short lifespan.
  1246. //
  1247. // TODO: exchange more dial parameters, such as TLS profile, QUIC version, etc.
  1248. type ExchangedDialParameters struct {
  1249. TunnelProtocol string
  1250. }
  1251. // NewExchangedDialParameters creates a new ExchangedDialParameters from a
  1252. // DialParameters, including only the exchanged values.
  1253. // NewExchangedDialParameters assumes the input DialParameters has been
  1254. // initialized and populated by MakeDialParameters.
  1255. func NewExchangedDialParameters(dialParams *DialParameters) *ExchangedDialParameters {
  1256. return &ExchangedDialParameters{
  1257. TunnelProtocol: dialParams.TunnelProtocol,
  1258. }
  1259. }
  1260. // Validate checks that the ExchangedDialParameters contains only valid values
  1261. // and is compatible with the specified server entry.
  1262. func (dialParams *ExchangedDialParameters) Validate(serverEntry *protocol.ServerEntry) error {
  1263. if !common.Contains(protocol.SupportedTunnelProtocols, dialParams.TunnelProtocol) {
  1264. return errors.Tracef("unknown tunnel protocol: %s", dialParams.TunnelProtocol)
  1265. }
  1266. if !serverEntry.SupportsProtocol(dialParams.TunnelProtocol) {
  1267. return errors.Tracef("unsupported tunnel protocol: %s", dialParams.TunnelProtocol)
  1268. }
  1269. return nil
  1270. }
  1271. // MakeDialParameters creates a new, partially intitialized DialParameters
  1272. // from the values in ExchangedDialParameters. The returned DialParameters
  1273. // must not be used directly for dialing. It is intended to be stored, and
  1274. // then later fully initialized by MakeDialParameters.
  1275. func (dialParams *ExchangedDialParameters) MakeDialParameters(
  1276. config *Config,
  1277. p parameters.ParametersAccessor,
  1278. serverEntry *protocol.ServerEntry) *DialParameters {
  1279. configStateHash, serverEntryHash := getDialStateHashes(config, p, serverEntry)
  1280. return &DialParameters{
  1281. IsExchanged: true,
  1282. LastUsedTimestamp: time.Now(),
  1283. LastUsedConfigStateHash: configStateHash,
  1284. LastUsedServerEntryHash: serverEntryHash,
  1285. TunnelProtocol: dialParams.TunnelProtocol,
  1286. }
  1287. }
  1288. // getDialStateHashes returns two hashes: the config state hash reflects the
  1289. // config dial parameters and tactics tag used for a dial; and the server
  1290. // entry hash relects the server entry used for a dial.
  1291. //
  1292. // These hashes change if the input values change in a way that invalidates
  1293. // any stored dial parameters.
  1294. func getDialStateHashes(
  1295. config *Config,
  1296. p parameters.ParametersAccessor,
  1297. serverEntry *protocol.ServerEntry) ([]byte, []byte) {
  1298. // MD5 hash is used solely as a data checksum and not for any security
  1299. // purpose.
  1300. hash := md5.New()
  1301. // Add a hash of relevant dial parameter config fields. Config fields
  1302. // that change due to user preference changes, such as selected egress
  1303. // region, are not to be included in config.dialParametersHash.
  1304. //
  1305. // Limitation: the config hash may change even when tactics will override the
  1306. // changed config field.
  1307. hash.Write(config.dialParametersHash)
  1308. // Add the active tactics tag.
  1309. hash.Write([]byte(p.Tag()))
  1310. clientStateHash := hash.Sum(nil)
  1311. hash = md5.New()
  1312. // Add the server entry version and local timestamp, both of which should
  1313. // change when the server entry contents change and/or a new local copy is
  1314. // imported.
  1315. // TODO: marshal entire server entry?
  1316. var serverEntryConfigurationVersion [8]byte
  1317. binary.BigEndian.PutUint64(
  1318. serverEntryConfigurationVersion[:],
  1319. uint64(serverEntry.ConfigurationVersion))
  1320. hash.Write(serverEntryConfigurationVersion[:])
  1321. hash.Write([]byte(serverEntry.LocalTimestamp))
  1322. serverEntryHash := hash.Sum(nil)
  1323. return clientStateHash, serverEntryHash
  1324. }
  1325. func selectFrontingParameters(
  1326. serverEntry *protocol.ServerEntry) (string, string, error) {
  1327. frontingDialHost := ""
  1328. frontingHost := ""
  1329. if len(serverEntry.MeekFrontingAddressesRegex) > 0 {
  1330. // Generate a front address based on the regex.
  1331. var err error
  1332. frontingDialHost, err = regen.GenerateString(serverEntry.MeekFrontingAddressesRegex)
  1333. if err != nil {
  1334. return "", "", errors.Trace(err)
  1335. }
  1336. } else {
  1337. // Randomly select, for this connection attempt, one front address for
  1338. // fronting-capable servers.
  1339. if len(serverEntry.MeekFrontingAddresses) == 0 {
  1340. return "", "", errors.TraceNew("MeekFrontingAddresses is empty")
  1341. }
  1342. index := prng.Intn(len(serverEntry.MeekFrontingAddresses))
  1343. frontingDialHost = serverEntry.MeekFrontingAddresses[index]
  1344. }
  1345. if len(serverEntry.MeekFrontingHosts) > 0 {
  1346. index := prng.Intn(len(serverEntry.MeekFrontingHosts))
  1347. frontingHost = serverEntry.MeekFrontingHosts[index]
  1348. } else {
  1349. // Backwards compatibility case
  1350. frontingHost = serverEntry.MeekFrontingHost
  1351. }
  1352. return frontingDialHost, frontingHost, nil
  1353. }
  1354. func selectQUICVersion(
  1355. isFronted bool,
  1356. serverEntry *protocol.ServerEntry,
  1357. p parameters.ParametersAccessor) string {
  1358. limitQUICVersions := p.QUICVersions(parameters.LimitQUICVersions)
  1359. var disableQUICVersions protocol.QUICVersions
  1360. if isFronted {
  1361. if serverEntry.FrontingProviderID == "" {
  1362. // Legacy server entry case
  1363. disableQUICVersions = protocol.QUICVersions{
  1364. protocol.QUIC_VERSION_V1,
  1365. protocol.QUIC_VERSION_RANDOMIZED_V1,
  1366. protocol.QUIC_VERSION_OBFUSCATED_V1,
  1367. protocol.QUIC_VERSION_DECOY_V1,
  1368. }
  1369. } else {
  1370. disableQUICVersions = p.LabeledQUICVersions(
  1371. parameters.DisableFrontingProviderQUICVersions,
  1372. serverEntry.FrontingProviderID)
  1373. }
  1374. }
  1375. quicVersions := make([]string, 0)
  1376. // Don't use gQUIC versions when the server entry specifies QUICv1-only.
  1377. supportedQUICVersions := protocol.SupportedQUICVersions
  1378. if serverEntry.SupportsOnlyQUICv1() {
  1379. supportedQUICVersions = protocol.SupportedQUICv1Versions
  1380. }
  1381. for _, quicVersion := range supportedQUICVersions {
  1382. if len(limitQUICVersions) > 0 &&
  1383. !common.Contains(limitQUICVersions, quicVersion) {
  1384. continue
  1385. }
  1386. // Both tactics and the server entry can specify LimitQUICVersions. In
  1387. // tactics, the parameter is intended to direct certain clients to
  1388. // use a successful protocol variant. In the server entry, the
  1389. // parameter may be used to direct all clients to send
  1390. // consistent-looking protocol variants to a particular server; e.g.,
  1391. // only regular QUIC, or only obfuscated QUIC.
  1392. //
  1393. // The isFronted/QUICVersionIsObfuscated logic predates
  1394. // ServerEntry.LimitQUICVersions; ServerEntry.LimitQUICVersions could
  1395. // now be used to achieve a similar outcome.
  1396. if len(serverEntry.LimitQUICVersions) > 0 &&
  1397. !common.Contains(serverEntry.LimitQUICVersions, quicVersion) {
  1398. continue
  1399. }
  1400. if isFronted &&
  1401. protocol.QUICVersionIsObfuscated(quicVersion) {
  1402. continue
  1403. }
  1404. if common.Contains(disableQUICVersions, quicVersion) {
  1405. continue
  1406. }
  1407. quicVersions = append(quicVersions, quicVersion)
  1408. }
  1409. if len(quicVersions) == 0 {
  1410. return ""
  1411. }
  1412. choice := prng.Intn(len(quicVersions))
  1413. return quicVersions[choice]
  1414. }
  1415. // selectUserAgentIfUnset selects a User-Agent header if one is not set.
  1416. func selectUserAgentIfUnset(
  1417. p parameters.ParametersAccessor, headers http.Header) (bool, string) {
  1418. if _, ok := headers["User-Agent"]; !ok {
  1419. userAgent := ""
  1420. if p.WeightedCoinFlip(parameters.PickUserAgentProbability) {
  1421. userAgent = values.GetUserAgent()
  1422. }
  1423. return true, userAgent
  1424. }
  1425. return false, ""
  1426. }
  1427. func makeDialCustomHeaders(
  1428. config *Config,
  1429. p parameters.ParametersAccessor) http.Header {
  1430. dialCustomHeaders := make(http.Header)
  1431. if config.CustomHeaders != nil {
  1432. for k, v := range config.CustomHeaders {
  1433. dialCustomHeaders[k] = make([]string, len(v))
  1434. copy(dialCustomHeaders[k], v)
  1435. }
  1436. }
  1437. additionalCustomHeaders := p.HTTPHeaders(parameters.AdditionalCustomHeaders)
  1438. for k, v := range additionalCustomHeaders {
  1439. dialCustomHeaders[k] = make([]string, len(v))
  1440. copy(dialCustomHeaders[k], v)
  1441. }
  1442. return dialCustomHeaders
  1443. }
  1444. func selectHostName(
  1445. tunnelProtocol string, p parameters.ParametersAccessor) string {
  1446. limitProtocols := p.TunnelProtocols(parameters.CustomHostNameLimitProtocols)
  1447. if len(limitProtocols) > 0 && !common.Contains(limitProtocols, tunnelProtocol) {
  1448. return values.GetHostName()
  1449. }
  1450. if !p.WeightedCoinFlip(parameters.CustomHostNameProbability) {
  1451. return values.GetHostName()
  1452. }
  1453. regexStrings := p.RegexStrings(parameters.CustomHostNameRegexes)
  1454. if len(regexStrings) == 0 {
  1455. return values.GetHostName()
  1456. }
  1457. choice := prng.Intn(len(regexStrings))
  1458. hostName, err := regen.GenerateString(regexStrings[choice])
  1459. if err != nil {
  1460. NoticeWarning("selectHostName: regen.Generate failed: %v", errors.Trace(err))
  1461. return values.GetHostName()
  1462. }
  1463. return hostName
  1464. }
  1465. // makeHTTPTransformerParameters generates HTTPTransformerParameters using the
  1466. // input tactics parameters and optional frontingProviderID context.
  1467. func makeHTTPTransformerParameters(p parameters.ParametersAccessor,
  1468. frontingProviderID string, isFronted bool) (*transforms.HTTPTransformerParameters, error) {
  1469. params := transforms.HTTPTransformerParameters{}
  1470. // Select an HTTP transform. If the request is fronted, HTTP request
  1471. // transforms are "scoped" by fronting provider ID. Otherwise, a transform
  1472. // from the default scope (transforms.SCOPE_ANY == "") is selected.
  1473. var specsKey string
  1474. var scopedSpecsNamesKey string
  1475. useTransform := false
  1476. scope := transforms.SCOPE_ANY
  1477. if isFronted {
  1478. if p.WeightedCoinFlip(parameters.FrontedHTTPProtocolTransformProbability) {
  1479. useTransform = true
  1480. scope = frontingProviderID
  1481. specsKey = parameters.FrontedHTTPProtocolTransformSpecs
  1482. scopedSpecsNamesKey = parameters.FrontedHTTPProtocolTransformScopedSpecNames
  1483. }
  1484. } else {
  1485. // unfronted
  1486. if p.WeightedCoinFlip(parameters.DirectHTTPProtocolTransformProbability) {
  1487. useTransform = true
  1488. specsKey = parameters.DirectHTTPProtocolTransformSpecs
  1489. scopedSpecsNamesKey = parameters.DirectHTTPProtocolTransformScopedSpecNames
  1490. }
  1491. }
  1492. if useTransform {
  1493. specs := p.ProtocolTransformSpecs(
  1494. specsKey)
  1495. scopedSpecNames := p.ProtocolTransformScopedSpecNames(
  1496. scopedSpecsNamesKey)
  1497. name, spec := specs.Select(scope, scopedSpecNames)
  1498. if spec != nil {
  1499. params.ProtocolTransformName = name
  1500. params.ProtocolTransformSpec = spec
  1501. var err error
  1502. // transform seed generated
  1503. params.ProtocolTransformSeed, err = prng.NewSeed()
  1504. if err != nil {
  1505. return nil, errors.Trace(err)
  1506. }
  1507. }
  1508. }
  1509. return &params, nil
  1510. }
  1511. // makeSeedTransformerParameters generates ObfuscatorSeedTransformerParameters
  1512. // using the input tactics parameters.
  1513. func makeSeedTransformerParameters(p parameters.ParametersAccessor,
  1514. probabilityFieldName, specsKey, scopedSpecsKey string) (*transforms.ObfuscatorSeedTransformerParameters, error) {
  1515. if !p.WeightedCoinFlip(probabilityFieldName) {
  1516. return &transforms.ObfuscatorSeedTransformerParameters{}, nil
  1517. }
  1518. seed, err := prng.NewSeed()
  1519. if err != nil {
  1520. return nil, errors.Trace(err)
  1521. }
  1522. specs := p.ProtocolTransformSpecs(specsKey)
  1523. scopedSpecNames := p.ProtocolTransformScopedSpecNames(scopedSpecsKey)
  1524. name, spec := specs.Select(transforms.SCOPE_ANY, scopedSpecNames)
  1525. if spec == nil {
  1526. return &transforms.ObfuscatorSeedTransformerParameters{}, nil
  1527. } else {
  1528. return &transforms.ObfuscatorSeedTransformerParameters{
  1529. TransformName: name,
  1530. TransformSpec: spec,
  1531. TransformSeed: seed,
  1532. }, nil
  1533. }
  1534. }
  1535. func makeOSSHPrefixSpecParameters(
  1536. p parameters.ParametersAccessor,
  1537. dialPortNumber string) (*obfuscator.OSSHPrefixSpec, error) {
  1538. if !p.WeightedCoinFlip(parameters.OSSHPrefixProbability) {
  1539. return &obfuscator.OSSHPrefixSpec{}, nil
  1540. }
  1541. specs := p.ProtocolTransformSpecs(parameters.OSSHPrefixSpecs)
  1542. scopedSpecNames := p.ProtocolTransformScopedSpecNames(parameters.OSSHPrefixScopedSpecNames)
  1543. name, spec := specs.Select(dialPortNumber, scopedSpecNames)
  1544. if spec == nil {
  1545. return &obfuscator.OSSHPrefixSpec{}, nil
  1546. } else {
  1547. seed, err := prng.NewSeed()
  1548. if err != nil {
  1549. return nil, errors.Trace(err)
  1550. }
  1551. return &obfuscator.OSSHPrefixSpec{
  1552. Name: name,
  1553. Spec: spec,
  1554. Seed: seed,
  1555. }, nil
  1556. }
  1557. }
  1558. func makeOSSHPrefixSplitConfig(p parameters.ParametersAccessor) (*obfuscator.OSSHPrefixSplitConfig, error) {
  1559. minDelay := p.Duration(parameters.OSSHPrefixSplitMinDelay)
  1560. maxDelay := p.Duration(parameters.OSSHPrefixSplitMaxDelay)
  1561. seed, err := prng.NewSeed()
  1562. if err != nil {
  1563. return nil, errors.Trace(err)
  1564. }
  1565. return &obfuscator.OSSHPrefixSplitConfig{
  1566. Seed: seed,
  1567. MinDelay: minDelay,
  1568. MaxDelay: maxDelay,
  1569. }, nil
  1570. }
  1571. func selectConjureTransport(
  1572. p parameters.ParametersAccessor) string {
  1573. limitConjureTransports := p.ConjureTransports(parameters.ConjureLimitTransports)
  1574. transports := make([]string, 0)
  1575. for _, transport := range protocol.SupportedConjureTransports {
  1576. if len(limitConjureTransports) > 0 &&
  1577. !common.Contains(limitConjureTransports, transport) {
  1578. continue
  1579. }
  1580. transports = append(transports, transport)
  1581. }
  1582. if len(transports) == 0 {
  1583. return ""
  1584. }
  1585. choice := prng.Intn(len(transports))
  1586. return transports[choice]
  1587. }