dialParameters.go 91 KB

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