| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086 |
- /*
- * Copyright (c) 2015, Psiphon Inc.
- * All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- package psiphon
- import (
- "crypto/md5"
- "encoding/base64"
- "encoding/binary"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
- "os"
- "path/filepath"
- "reflect"
- "regexp"
- "strconv"
- "strings"
- "sync"
- "sync/atomic"
- "time"
- "unicode"
- "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
- "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
- "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy"
- "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/networkid"
- "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
- "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
- "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
- "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/transforms"
- "golang.org/x/crypto/nacl/secretbox"
- )
- const (
- TUNNEL_POOL_SIZE = 1
- MAX_TUNNEL_POOL_SIZE = 32
- // Psiphon data directory name, relative to config.DataRootDirectory.
- // See config.GetPsiphonDataDirectory().
- PsiphonDataDirectoryName = "ca.psiphon.PsiphonTunnel.tunnel-core"
- // Filename constants, all relative to config.GetPsiphonDataDirectory().
- HomepageFilename = "homepage"
- NoticesFilename = "notices"
- OldNoticesFilename = "notices.1"
- UpgradeDownloadFilename = "upgrade"
- )
- // Config is the Psiphon configuration specified by the application. This
- // configuration controls the behavior of the core tunnel functionality.
- //
- // To distinguish omitted timeout params from explicit 0 value timeout params,
- // corresponding fields are int pointers. nil means no value was supplied and
- // to use the default; a non-nil pointer to 0 means no timeout.
- type Config struct {
- // DataRootDirectory is the directory in which to store persistent files,
- // which contain information such as server entries. By default, current
- // working directory.
- //
- // Psiphon will assume full control of files under this directory. They may
- // be deleted, moved or overwritten.
- DataRootDirectory string
- // UseNoticeFiles configures notice files for writing. If set, homepages
- // will be written to a file created at config.GetHomePageFilename()
- // and notices will be written to a file created at
- // config.GetNoticesFilename().
- //
- // The homepage file may be read after the Tunnels notice with count of 1.
- //
- // The value of UseNoticeFiles sets the size and frequency at which the
- // notices file, config.GetNoticesFilename(), will be rotated. See the
- // comment for UseNoticeFiles for more details. One rotated older file,
- // config.GetOldNoticesFilename(), is retained.
- //
- // The notice files may be may be read at any time; and should be opened
- // read-only for reading. Diagnostic notices are omitted from the notice
- // files.
- //
- // See comment for setNoticeFiles in notice.go for further details.
- UseNoticeFiles *UseNoticeFiles
- // PropagationChannelId is a string identifier which indicates how the
- // Psiphon client was distributed. This parameter is required. This value
- // is supplied by and depends on the Psiphon Network, and is typically
- // embedded in the client binary.
- PropagationChannelId string
- // SponsorId is a string identifier which indicates who is sponsoring this
- // Psiphon client. One purpose of this value is to determine the home
- // pages for display. This parameter is required. This value is supplied
- // by and depends on the Psiphon Network, and is typically embedded in the
- // client binary.
- SponsorId string
- // ClientVersion is the client version number that the client reports to
- // the server. The version number refers to the host client application,
- // not the core tunnel library. One purpose of this value is to enable
- // automatic updates. This value is supplied by and depends on the Psiphon
- // Network, and is typically embedded in the client binary.
- //
- // Note that sending a ClientPlatform string which includes "windows"
- // (case insensitive) and a ClientVersion of <= 44 will cause an error in
- // processing the response to DoConnectedRequest calls.
- ClientVersion string
- // ClientPlatform is the client platform ("Windows", "Android", etc.) that
- // the client reports to the server.
- ClientPlatform string
- // ClientAPILevel is the client API or SDK level, such as
- // Build.VERSION.SDK_INT on Android. This value is used for local
- // configuration, as required, and not reported to the server.
- // ClientAPILevel is ignored when 0.
- ClientAPILevel int
- // ClientFeatures is a list of feature names denoting enabled application
- // features. Clients report enabled features to the server for stats
- // purposes.
- ClientFeatures []string
- // EgressRegion is a ISO 3166-1 alpha-2 country code which indicates which
- // country to egress from. For the default, "", the best performing server
- // in any country is selected.
- EgressRegion string
- // SplitTunnelOwnRegion enables split tunnel mode for the client's own
- // country. When enabled, TCP port forward destinations that resolve to
- // the same GeoIP country as the client are connected to directly,
- // untunneled.
- SplitTunnelOwnRegion bool
- // SplitTunnelRegions enables selected split tunnel mode in which the
- // client specifies a list of ISO 3166-1 alpha-2 country codes for which
- // traffic should be untunneled. TCP port forwards destined to any
- // country specified in SplitTunnelRegions will be untunneled, regardless
- // of whether SplitTunnelOwnRegion is on or off.
- SplitTunnelRegions []string
- // ListenInterface specifies which interface to listen on. If no
- // interface is provided then listen on 127.0.0.1. If 'any' is provided
- // then use 0.0.0.0. If there are multiple IP addresses on an interface
- // use the first IPv4 address.
- ListenInterface string
- // DisableLocalSocksProxy disables running the local SOCKS proxy.
- DisableLocalSocksProxy bool
- // LocalSocksProxyPort specifies a port number for the local SOCKS proxy
- // running at 127.0.0.1. For the default value, 0, the system selects a
- // free port (a notice reporting the selected port is emitted).
- LocalSocksProxyPort int
- // LocalHttpProxyPort specifies a port number for the local HTTP proxy
- // running at 127.0.0.1. For the default value, 0, the system selects a
- // free port (a notice reporting the selected port is emitted).
- LocalHttpProxyPort int
- // DisableLocalHTTPProxy disables running the local HTTP proxy.
- DisableLocalHTTPProxy bool
- // NetworkLatencyMultiplier is a multiplier that is to be applied to
- // default network event timeouts. Set this to tune performance for
- // slow networks.
- // When set, must be >= 1.0.
- NetworkLatencyMultiplier float64
- // LimitTunnelProtocols indicates which protocols to use. Valid values
- // include: "SSH", "OSSH", "TLS-OSSH", "UNFRONTED-MEEK-OSSH",
- // "UNFRONTED-MEEK-HTTPS-OSSH", "UNFRONTED-MEEK-SESSION-TICKET-OSSH",
- // "FRONTED-MEEK-OSSH", "FRONTED-MEEK-HTTP-OSSH", "QUIC-OSSH",
- // "FRONTED-MEEK-QUIC-OSSH", "TAPDANCE-OSSH", "CONJURE-OSSH", and
- // "SHADOWSOCKS-OSSH".
- // For the default, an empty list, all protocols are used.
- LimitTunnelProtocols []string
- // InitialLimitTunnelProtocols is an optional initial phase of limited
- // protocols for the first InitialLimitTunnelProtocolsCandidateCount
- // candidates; after these candidates, LimitTunnelProtocols applies.
- //
- // For the default, an empty list, InitialLimitTunnelProtocols is off.
- InitialLimitTunnelProtocols []string
- // InitialLimitTunnelProtocolsCandidateCount is the number of candidates
- // to which InitialLimitTunnelProtocols is applied instead of
- // LimitTunnelProtocols.
- //
- // For the default, 0, InitialLimitTunnelProtocols is off.
- InitialLimitTunnelProtocolsCandidateCount int
- // LimitTLSProfiles indicates which TLS profiles to select from. Valid
- // values are listed in protocols.SupportedTLSProfiles.
- // For the default, an empty list, all profiles are candidates for
- // selection.
- LimitTLSProfiles []string
- // LimitQUICVersions indicates which QUIC versions to select from. Valid
- // values are listed in protocols.SupportedQUICVersions.
- // For the default, an empty list, all versions are candidates for
- // selection.
- LimitQUICVersions []string
- // EstablishTunnelTimeoutSeconds specifies a time limit after which to
- // halt the core tunnel controller if no tunnel has been established. The
- // default is parameters.EstablishTunnelTimeout.
- EstablishTunnelTimeoutSeconds *int
- // EstablishTunnelPausePeriodSeconds specifies the delay between attempts
- // to establish tunnels. Briefly pausing allows for network conditions to
- // improve and for asynchronous operations such as fetch remote server
- // list to complete. If omitted, a default value is used. This value is
- // typical overridden for testing.
- EstablishTunnelPausePeriodSeconds *int
- // EstablishTunnelPausePeriodSeconds specifies the grace period, or head
- // start, provided to the affinity server candidate when establishing. The
- // affinity server is the server used for the last established tunnel.
- EstablishTunnelServerAffinityGracePeriodMilliseconds *int
- // ConnectionWorkerPoolSize specifies how many connection attempts to
- // attempt in parallel. If omitted or when 0, a default is used; this is
- // recommended.
- ConnectionWorkerPoolSize int
- // TunnelPoolSize specifies how many tunnels to run in parallel. Port
- // forwards are multiplexed over multiple tunnels. If omitted or when 0,
- // the default is TUNNEL_POOL_SIZE, which is recommended. Any value over
- // MAX_TUNNEL_POOL_SIZE is treated as MAX_TUNNEL_POOL_SIZE.
- TunnelPoolSize int
- // StaggerConnectionWorkersMilliseconds adds a specified delay before
- // making each server candidate available to connection workers. This
- // option is enabled when StaggerConnectionWorkersMilliseconds > 0.
- StaggerConnectionWorkersMilliseconds int
- // LimitIntensiveConnectionWorkers limits the number of concurrent
- // connection workers attempting connections with resource intensive
- // protocols. This option is enabled when LimitIntensiveConnectionWorkers
- // > 0.
- LimitIntensiveConnectionWorkers int
- // LimitMeekBufferSizes selects smaller buffers for meek protocols.
- LimitMeekBufferSizes bool
- // LimitCPUThreads minimizes the number of CPU threads -- and associated
- // overhead -- the are used.
- LimitCPUThreads bool
- // LimitRelayBufferSizes selects smaller buffers for port forward relaying.
- LimitRelayBufferSizes bool
- // IgnoreHandshakeStatsRegexps skips compiling and using stats regexes.
- IgnoreHandshakeStatsRegexps bool
- // UpstreamProxyURL is a URL specifying an upstream proxy to use for all
- // outbound connections. The URL should include proxy type and
- // authentication information, as required. See example URLs here:
- // https://github.com/Psiphon-Labs/psiphon-tunnel-core/tree/master/psiphon/upstreamproxy
- UpstreamProxyURL string
- // CustomHeaders is a set of additional arbitrary HTTP headers that are
- // added to all plaintext HTTP requests and requests made through an HTTP
- // upstream proxy when specified by UpstreamProxyURL.
- CustomHeaders http.Header
- // MeekAdditionalHeaders is a set of additional arbitrary HTTP headers
- // that are added to all meek HTTP requests. An additional header is
- // ignored when the header name is already present in a meek request.
- MeekAdditionalHeaders http.Header
- // NetworkConnectivityChecker is an interface that enables tunnel-core to
- // call into the host application to check for network connectivity. See:
- // NetworkConnectivityChecker doc.
- NetworkConnectivityChecker NetworkConnectivityChecker
- // DeviceBinder is an interface that enables tunnel-core to call into the
- // host application to bind sockets to specific devices. See: DeviceBinder
- // doc.
- //
- // When DeviceBinder is set, the "VPN" feature name is automatically added
- // when reporting ClientFeatures.
- DeviceBinder DeviceBinder
- // AllowDefaultDNSResolverWithBindToDevice indicates that it's safe to use
- // the default resolver when DeviceBinder is configured, as the host OS
- // will automatically exclude DNS requests from the VPN.
- AllowDefaultDNSResolverWithBindToDevice bool
- // IPv6Synthesizer is an interface that allows tunnel-core to call into
- // the host application to synthesize IPv6 addresses. See: IPv6Synthesizer
- // doc.
- IPv6Synthesizer IPv6Synthesizer
- // HasIPv6RouteGetter is an interface that allows tunnel-core to call into
- // the host application to determine if the host has an IPv6 route. See:
- // HasIPv6RouteGetter doc.
- HasIPv6RouteGetter HasIPv6RouteGetter
- // DNSServerGetter is an interface that enables tunnel-core to call into
- // the host application to discover the native network DNS server
- // settings. See: DNSServerGetter doc.
- DNSServerGetter DNSServerGetter
- // NetworkIDGetter in an interface that enables tunnel-core to call into
- // the host application to get an identifier for the host's current active
- // network. See: NetworkIDGetter doc.
- NetworkIDGetter NetworkIDGetter
- // NetworkID, when not blank, is used as the identifier for the host's
- // current active network.
- // NetworkID is ignored when NetworkIDGetter is set, or when
- // common/networkid is enabled.
- NetworkID string
- // DisableTactics disables tactics operations including requests, payload
- // handling, and application of parameters.
- DisableTactics bool
- // DisableReplay causes any persisted dial parameters to be ignored when
- // they would otherwise be used for replay.
- DisableReplay bool
- // TargetServerEntry is an encoded server entry. When specified, this
- // server entry is used exclusively and all other known servers are
- // ignored; also, when set, ConnectionWorkerPoolSize is ignored and
- // the pool size is 1.
- TargetServerEntry string
- // DisableApi disables Psiphon server API calls including handshake,
- // connected, status, etc. This is used for special case temporary tunnels
- // (Windows VPN mode).
- DisableApi bool
- // TargetAPIProtocol specifies whether to force use of "ssh" or "web" API
- // protocol. When blank, the default, the optimal API protocol is used.
- // Note that this capability check is not applied before the
- // "CandidateServers" count is emitted.
- //
- // This parameter is intended for testing and debugging only. Not all
- // parameters are supported in the legacy "web" API protocol, including
- // speed test samples.
- TargetAPIProtocol string
- // TargetAPIProtocol specifies whether to use "json" or "cbor" API
- // protocol parameter encodings. When blank, the default is to use "cbor"
- // where supported.
- TargetAPIEncoding string
- // RemoteServerListURLs is list of URLs which specify locations to fetch
- // out-of-band server entries. This facility is used when a tunnel cannot
- // be established to known servers. This value is supplied by and depends
- // on the Psiphon Network, and is typically embedded in the client binary.
- // All URLs must point to the same entity with the same ETag. At least one
- // TransferURL must have OnlyAfterAttempts = 0.
- RemoteServerListURLs parameters.TransferURLs
- // RemoteServerListSignaturePublicKey specifies a public key that's used
- // to authenticate the remote server list payload. This value is supplied
- // by and depends on the Psiphon Network, and is typically embedded in the
- // client binary.
- RemoteServerListSignaturePublicKey string
- // DisableRemoteServerListFetcher disables fetching remote server lists.
- // This is used for special case temporary tunnels.
- DisableRemoteServerListFetcher bool
- // FetchRemoteServerListRetryPeriodMilliseconds specifies the delay before
- // resuming a remote server list download after a failure. If omitted, a
- // default value is used. This value is typical overridden for testing.
- FetchRemoteServerListRetryPeriodMilliseconds *int
- // ObfuscatedServerListRootURLs is a list of URLs which specify root
- // locations from which to fetch obfuscated server list files. This value
- // is supplied by and depends on the Psiphon Network, and is typically
- // embedded in the client binary. All URLs must point to the same entity
- // with the same ETag. At least one DownloadURL must have
- // OnlyAfterAttempts = 0.
- ObfuscatedServerListRootURLs parameters.TransferURLs
- // EnableUpgradeDownload indicates whether to check for and download
- // upgrades. When set, UpgradeDownloadURLs and
- // UpgradeDownloadClientVersionHeader must also be set. ClientPlatform
- // and ClientVersion should also be set.
- EnableUpgradeDownload bool
- // UpgradeDownloadURLs is list of URLs which specify locations from which
- // to download a host client upgrade file, when one is available. The core
- // tunnel controller provides a resumable download facility which
- // downloads this resource and emits a notice when complete. This value is
- // supplied by and depends on the Psiphon Network, and is typically
- // embedded in the client binary. All URLs must point to the same entity
- // with the same ETag. At least one DownloadURL must have
- // OnlyAfterAttempts = 0.
- UpgradeDownloadURLs parameters.TransferURLs
- // UpgradeDownloadClientVersionHeader specifies the HTTP header name for
- // the entity at UpgradeDownloadURLs which specifies the client version
- // (an integer value). A HEAD request may be made to check the version
- // number available at UpgradeDownloadURLs.
- // UpgradeDownloadClientVersionHeader is required when UpgradeDownloadURLs
- // is specified.
- UpgradeDownloadClientVersionHeader string
- // FetchUpgradeRetryPeriodMilliseconds specifies the delay before resuming
- // a client upgrade download after a failure. If omitted, a default value
- // is used. This value is typical overridden for testing.
- FetchUpgradeRetryPeriodMilliseconds *int
- // EnableFeedbackUpload indicates whether to enable uploading feedback
- // data. When set, FeedbackUploadURLs and FeedbackEncryptionPublicKey
- // must also be set.
- EnableFeedbackUpload bool
- // FeedbackUploadURLs is a list of SecureTransferURLs which specify
- // locations where feedback data can be uploaded, pairing with each
- // location a public key with which to encrypt the feedback data. This
- // value is supplied by and depends on the Psiphon Network, and is
- // typically embedded in the client binary. At least one TransferURL must
- // have OnlyAfterAttempts = 0.
- FeedbackUploadURLs parameters.TransferURLs
- // FeedbackEncryptionPublicKey is a default base64-encoded, RSA public key
- // value used to encrypt feedback data. Used when uploading feedback with a
- // TransferURL which has no public key value configured, i.e.
- // B64EncodedPublicKey = "".
- FeedbackEncryptionPublicKey string
- // TrustedCACertificatesFilename specifies a file containing trusted CA
- // certs. When set, this toggles use of the trusted CA certs, specified in
- // TrustedCACertificatesFilename, for tunneled TLS connections that expect
- // server certificates signed with public certificate authorities
- // (currently, only upgrade downloads). This option is used with stock Go
- // TLS in cases where Go may fail to obtain a list of root CAs from the
- // operating system.
- TrustedCACertificatesFilename string
- // DisableSystemRootCAs, when true, disables loading system root CAs when
- // verifying TLS certificates for all remote server list downloads, upgrade
- // downloads, and feedback uploads. Each of these transfers has additional
- // security at the payload level. Verifying TLS certificates is preferred,
- // as an additional security and circumvention layer; set
- // DisableSystemRootCAs only in cases where system root CAs cannot be
- // loaded; for example, if unsupported (iOS < 12) or insufficient memory
- // (VPN extension on iOS < 15).
- DisableSystemRootCAs bool
- // DisablePeriodicSshKeepAlive indicates whether to send an SSH keepalive
- // every 1-2 minutes, when the tunnel is idle. If the SSH keepalive times
- // out, the tunnel is considered to have failed.
- DisablePeriodicSshKeepAlive bool
- // DeviceLocation is the optional, reported location the host device is
- // running in. This input value should be a string representing location
- // geohash. The device location is reported to the server in the connected
- // request and recorded for Psiphon stats.
- DeviceLocation string
- // DeviceRegion is the optional, reported region the host device is
- // running in. This input value should be a ISO 3166-1 alpha-2 country
- // code. The device region is reported to the server in the connected
- // request and recorded for Psiphon stats.
- //
- // When provided, this value may be used, pre-connection, to select
- // performance or circumvention optimization strategies for the given
- // region.
- DeviceRegion string
- // EmitDiagnosticNotices indicates whether to output notices containing
- // detailed information about the Psiphon session. As these notices may
- // contain sensitive information, they should not be insecurely distributed
- // or displayed to users. Default is off.
- EmitDiagnosticNotices bool
- // EmitDiagnosticNetworkParameters indicates whether to include network
- // parameters in diagnostic notices. As these parameters are sensitive
- // circumvention network information, they should not be insecurely
- // distributed or displayed to users. Default is off.
- EmitDiagnosticNetworkParameters bool
- // EmitBytesTransferred indicates whether to emit frequent notices showing
- // bytes sent and received.
- EmitBytesTransferred bool
- // EmitSLOKs indicates whether to emit notices for each seeded SLOK. As
- // this could reveal user browsing activity, it's intended for debugging
- // and testing only.
- EmitSLOKs bool
- // EmitRefractionNetworkingLogs indicates whether to emit gotapdance log
- // messages to stdout. Note that gotapdance log messages do not conform to
- // the Notice format standard. Default is off.
- EmitRefractionNetworkingLogs bool
- // EmitServerAlerts indicates whether to emit notices for server alerts.
- EmitServerAlerts bool
- // EmitClientAddress indicates whether to emit the client's public network
- // address, IP and port, as seen by the server.
- EmitClientAddress bool
- // RateLimits specify throttling configuration for the tunnel.
- RateLimits common.RateLimits
- // PacketTunnelTunDeviceFileDescriptor specifies a tun device file
- // descriptor to use for running a packet tunnel. When this value is > 0,
- // a packet tunnel is established through the server and packets are
- // relayed via the tun device file descriptor. The file descriptor is
- // duped in NewController. When PacketTunnelTunDeviceFileDescriptor is
- // set, TunnelPoolSize must be 1.
- PacketTunnelTunFileDescriptor int
- // PacketTunnelTransparentDNSIPv4Address is the IPv4 address of the DNS
- // server configured by a VPN using a packet tunnel. All DNS packets
- // destined to this DNS server are transparently redirected to the
- // Psiphon server DNS.
- PacketTunnelTransparentDNSIPv4Address string
- // PacketTunnelTransparentDNSIPv6Address is the IPv6 address of the DNS
- // server configured by a VPN using a packet tunnel. All DNS packets
- // destined to this DNS server are transparently redirected to the
- // Psiphon server DNS.
- PacketTunnelTransparentDNSIPv6Address string
- // SessionID specifies a client session ID to use in the Psiphon API. The
- // session ID should be a randomly generated value that is used only for a
- // single session, which is defined as the period between a user starting
- // a Psiphon client and stopping the client.
- //
- // A session ID must be 32 hex digits (lower case). When blank, a random
- // session ID is automatically generated. Supply a session ID when a
- // single client session will cross multiple Controller instances.
- SessionID string
- // Authorizations is a list of encoded, signed access control
- // authorizations that the client has obtained and will present to the
- // server.
- Authorizations []string
- // ServerEntrySignaturePublicKey is a base64-encoded, ed25519 public
- // key value used to verify individual server entry signatures. This value
- // is supplied by and depends on the Psiphon Network, and is typically
- // embedded in the client binary.
- ServerEntrySignaturePublicKey string
- // ExchangeObfuscationKey is a base64-encoded, NaCl secretbox key used to
- // obfuscate server info exchanges between clients.
- // Required for the exchange functionality.
- ExchangeObfuscationKey string
- // MigrateHomepageNoticesFilename migrates a homepage file from the path
- // previously configured with setNoticeFiles to the new path for homepage
- // files under the data root directory. The file specified by this config
- // value will be moved to config.GetHomePageFilename().
- //
- // Note: see comment for config.Commit() for a description of how file
- // migrations are performed.
- //
- // If not set, no migration operation will be performed.
- MigrateHomepageNoticesFilename string
- // MigrateRotatingNoticesFilename migrates notice files from the path
- // previously configured with setNoticeFiles to the new path for notice
- // files under the data root directory.
- //
- // MigrateRotatingNoticesFilename will be moved to
- // config.GetNoticesFilename().
- //
- // MigrateRotatingNoticesFilename.1 will be moved to
- // config.GetOldNoticesFilename().
- //
- // Note: see comment for config.Commit() for a description of how file
- // migrations are performed.
- //
- // If not set, no migration operation will be performed.
- MigrateRotatingNoticesFilename string
- // MigrateDataStoreDirectory indicates the location of the datastore
- // directory, as previously configured with the deprecated
- // DataStoreDirectory config field. Datastore files found in the specified
- // directory will be moved under the data root directory.
- //
- // Note: see comment for config.Commit() for a description of how file
- // migrations are performed.
- MigrateDataStoreDirectory string
- // MigrateRemoteServerListDownloadFilename indicates the location of
- // remote server list download files. The remote server list files found at
- // the specified path will be moved under the data root directory.
- //
- // Note: see comment for config.Commit() for a description of how file
- // migrations are performed.
- MigrateRemoteServerListDownloadFilename string
- // MigrateObfuscatedServerListDownloadDirectory indicates the location of
- // the obfuscated server list downloads directory, as previously configured
- // with ObfuscatedServerListDownloadDirectory. Obfuscated server list
- // download files found in the specified directory will be moved under the
- // data root directory.
- //
- // Warning: if the directory is empty after obfuscated server
- // list files are moved, then it will be deleted.
- //
- // Note: see comment for config.Commit() for a description of how file
- // migrations are performed.
- MigrateObfuscatedServerListDownloadDirectory string
- // MigrateUpgradeDownloadFilename indicates the location of downloaded
- // application upgrade files. Downloaded upgrade files found at the
- // specified path will be moved under the data root directory.
- //
- // Note: see comment for config.Commit() for a description of how file
- // migrations are performed.
- MigrateUpgradeDownloadFilename string
- // DisableTunnels disables establishing a client tunnel. Set
- // DisableTunnels when running a stand-alone in-proxy proxy.
- DisableTunnels bool
- // InproxyEnableProxy enables running an in-proxy proxy.
- InproxyEnableProxy bool
- // InproxyProxySessionPrivateKey specifies a long-term in-proxy proxy
- // private key and corresponding, derived proxy ID to use. If blank, an
- // ephemeral key will be generated.
- InproxyProxySessionPrivateKey string
- // InproxyMaxClients specifies the maximum number of in-proxy clients to
- // be proxied concurrently. Must be > 0 when InproxyEnableProxy is set.
- InproxyMaxClients int
- // InproxyLimitUpstreamBytesPerSecond specifies the upstream byte transfer
- // rate limit for each proxied client. When 0, there is no limit.
- InproxyLimitUpstreamBytesPerSecond int
- // InproxyLimitDownstreamBytesPerSecond specifies the downstream byte
- // transfer rate limit for each proxied client. When 0, there is no limit.
- InproxyLimitDownstreamBytesPerSecond int
- // InproxyProxyPersonalCompartmentID specifies the personal compartment
- // ID used by an in-proxy proxy. Personal compartment IDs are
- // distributed from proxy operators to client users out-of-band and
- // provide a mechanism to allow only certain clients to use a proxy.
- InproxyProxyPersonalCompartmentID string
- // InproxyClientPersonalCompartmentID specifies the personal compartment
- // ID used by an in-proxy client. Personal compartment IDs are
- // distributed from proxy operators to client users out-of-band and
- // provide a mechanism to ensure a client uses only a certain proxy for
- // all tunnels connections.
- //
- // When an InproxyClientPersonalCompartmentID is set, the client will use
- // only in-proxy protocols, ensuring that all connections go through the
- // proxy or proxies with the same personal compartment ID.
- InproxyClientPersonalCompartmentID string
- // InproxyPersonalPairingConnectionWorkerPoolSize specifies the value for
- // ConnectionWorkerPoolSize in personal pairing mode. If omitted or when
- // 0, a default is used; this is recommended.
- InproxyPersonalPairingConnectionWorkerPoolSize int
- // EmitInproxyProxyActivity indicates whether to emit frequent notices
- // showing proxy connection information and bytes transferred.
- EmitInproxyProxyActivity bool
- // ShutdownGoroutineProfileDeadlineSeconds is the number of seconds to
- // await shutdown in Controller.Run before dumping a goroutine profile to
- // diagnostics. Specify 0 to disable. When not specified, the default is
- // 60 seconds.
- ShutdownGoroutineProfileDeadlineSeconds *int
- //
- // The following parameters are deprecated.
- //
- // DataStoreDirectory is the directory in which to store the persistent
- // database, which contains information such as server entries. By
- // default, current working directory.
- //
- // Deprecated:
- // Use MigrateDataStoreDirectory. When MigrateDataStoreDirectory
- // is set, this parameter is ignored.
- //
- // DataStoreDirectory has been subsumed by the new data root directory,
- // which is configured with DataRootDirectory. If set, datastore files
- // found in the specified directory will be moved under the data root
- // directory.
- DataStoreDirectory string
- // RemoteServerListDownloadFilename specifies a target filename for
- // storing the remote server list download. Data is stored in co-located
- // files (RemoteServerListDownloadFilename.part*) to allow for resumable
- // downloading.
- //
- // Deprecated:
- // Use MigrateRemoteServerListDownloadFilename. When
- // MigrateRemoteServerListDownloadFilename is set, this parameter is
- // ignored.
- //
- // If set, remote server list download files found at the specified path
- // will be moved under the data root directory.
- RemoteServerListDownloadFilename string
- // ObfuscatedServerListDownloadDirectory specifies a target directory for
- // storing the obfuscated remote server list downloads. Data is stored in
- // co-located files (<OSL filename>.part*) to allow for resumable
- // downloading.
- //
- // Deprecated:
- // Use MigrateObfuscatedServerListDownloadDirectory. When
- // MigrateObfuscatedServerListDownloadDirectory is set, this parameter is
- // ignored.
- //
- // If set, obfuscated server list download files found at the specified path
- // will be moved under the data root directory.
- ObfuscatedServerListDownloadDirectory string
- // UpgradeDownloadFilename is the local target filename for an upgrade
- // download. This parameter is required when UpgradeDownloadURLs (or
- // UpgradeDownloadUrl) is specified. Data is stored in co-located files
- // (UpgradeDownloadFilename.part*) to allow for resumable downloading.
- //
- // Deprecated:
- // Use MigrateUpgradeDownloadFilename. When MigrateUpgradeDownloadFilename
- // is set, this parameter is ignored.
- //
- // If set, upgrade download files found at the specified path will be moved
- // under the data root directory.
- UpgradeDownloadFilename string
- // TunnelProtocol indicates which protocol to use. For the default, "",
- // all protocols are used.
- //
- // Deprecated: Use LimitTunnelProtocols. When LimitTunnelProtocols is not
- // nil, this parameter is ignored.
- TunnelProtocol string
- // Deprecated: Use CustomHeaders. When CustomHeaders is not nil, this
- // parameter is ignored.
- UpstreamProxyCustomHeaders http.Header
- // RemoteServerListUrl is a URL which specifies a location to fetch out-
- // of-band server entries. This facility is used when a tunnel cannot be
- // established to known servers. This value is supplied by and depends on
- // the Psiphon Network, and is typically embedded in the client binary.
- //
- // Deprecated: Use RemoteServerListURLs. When RemoteServerListURLs is not
- // nil, this parameter is ignored.
- RemoteServerListUrl string
- // ObfuscatedServerListRootURL is a URL which specifies the root location
- // from which to fetch obfuscated server list files. This value is
- // supplied by and depends on the Psiphon Network, and is typically
- // embedded in the client binary.
- //
- // Deprecated: Use ObfuscatedServerListRootURLs. When
- // ObfuscatedServerListRootURLs is not nil, this parameter is ignored.
- ObfuscatedServerListRootURL string
- // UpgradeDownloadUrl specifies a URL from which to download a host client
- // upgrade file, when one is available. The core tunnel controller
- // provides a resumable download facility which downloads this resource
- // and emits a notice when complete. This value is supplied by and depends
- // on the Psiphon Network, and is typically embedded in the client binary.
- //
- // Deprecated: Use UpgradeDownloadURLs. When UpgradeDownloadURLs is not
- // nil, this parameter is ignored.
- UpgradeDownloadUrl string
- //
- // The following parameters are for testing purposes.
- //
- // TransformHostNameProbability is for testing purposes.
- TransformHostNameProbability *float64
- // FragmentorProbability and associated Fragmentor fields are for testing
- // purposes.
- FragmentorProbability *float64
- FragmentorLimitProtocols []string
- FragmentorMinTotalBytes *int
- FragmentorMaxTotalBytes *int
- FragmentorMinWriteBytes *int
- FragmentorMaxWriteBytes *int
- FragmentorMinDelayMicroseconds *int
- FragmentorMaxDelayMicroseconds *int
- // MeekTrafficShapingProbability and associated fields are for testing
- // purposes.
- MeekTrafficShapingProbability *float64
- MeekTrafficShapingLimitProtocols []string
- MeekMinTLSPadding *int
- MeekMaxTLSPadding *int
- MeekMinLimitRequestPayloadLength *int
- MeekMaxLimitRequestPayloadLength *int
- MeekRedialTLSProbability *float64
- MeekAlternateCookieNameProbability *float64
- MeekAlternateContentTypeProbability *float64
- // ObfuscatedSSHAlgorithms and associated ObfuscatedSSH fields are for
- // testing purposes. If specified, ObfuscatedSSHAlgorithms must have 4 SSH
- // KEX elements in order: the kex algorithm, cipher, MAC, and server host
- // key algorithm.
- ObfuscatedSSHAlgorithms []string
- ObfuscatedSSHMinPadding *int
- ObfuscatedSSHMaxPadding *int
- // LivenessTestMinUpstreamBytes and other LivenessTest fields are for
- // testing purposes.
- InitialLivenessTest parameters.LivenessTestSpecs
- LivenessTest parameters.LivenessTestSpecs
- LivenessTestMinUpstreamBytes *int
- LivenessTestMaxUpstreamBytes *int
- LivenessTestMinDownstreamBytes *int
- LivenessTestMaxDownstreamBytes *int
- // ReplayCandidateCount and other Replay fields are for testing purposes.
- ReplayCandidateCount *int
- ReplayDialParametersTTLSeconds *int
- ReplayTargetUpstreamBytes *int
- ReplayTargetDownstreamBytes *int
- ReplayTargetTunnelDurationSeconds *int
- ReplayLaterRoundMoveToFrontProbability *float64
- ReplayRetainFailedProbability *float64
- ReplayIgnoreChangedConfigState *bool
- // NetworkLatencyMultiplierMin and other NetworkLatencyMultiplier fields are
- // for testing purposes.
- NetworkLatencyMultiplierMin float64
- NetworkLatencyMultiplierMax float64
- NetworkLatencyMultiplierLambda float64
- // UseOnlyCustomTLSProfiles and other TLS configuration fields are for
- // testing purposes.
- UseOnlyCustomTLSProfiles *bool
- CustomTLSProfiles protocol.CustomTLSProfiles
- SelectRandomizedTLSProfileProbability *float64
- NoDefaultTLSSessionIDProbability *float64
- DisableFrontingProviderTLSProfiles protocol.LabeledTLSProfiles
- // ClientBurstUpstreamTargetBytes and other burst metric fields are for
- // testing purposes.
- ClientBurstUpstreamTargetBytes *int
- ClientBurstUpstreamDeadlineMilliseconds *int
- ClientBurstDownstreamTargetBytes *int
- ClientBurstDownstreamDeadlineMilliseconds *int
- // ApplicationParameters is for testing purposes.
- ApplicationParameters parameters.KeyValues
- // CustomHostNameRegexes and other custom host name fields are for testing
- // purposes.
- CustomHostNameRegexes []string
- CustomHostNameProbability *float64
- CustomHostNameLimitProtocols []string
- // ConjureCachedRegistrationTTLSeconds and other Conjure fields are for
- // testing purposes.
- ConjureCachedRegistrationTTLSeconds *int
- ConjureAPIRegistrarBidirectionalURL string
- ConjureAPIRegistrarFrontingSpecs parameters.FrontingSpecs
- ConjureAPIRegistrarMinDelayMilliseconds *int
- ConjureAPIRegistrarMaxDelayMilliseconds *int
- ConjureDecoyRegistrarProbability *float64
- ConjureDecoyRegistrarWidth *int
- ConjureDecoyRegistrarMinDelayMilliseconds *int
- ConjureDecoyRegistrarMaxDelayMilliseconds *int
- ConjureEnableIPv6Dials *bool
- ConjureEnablePortRandomization *bool
- ConjureEnableRegistrationOverrides *bool
- ConjureLimitTransports protocol.ConjureTransports
- ConjureSTUNServerAddresses []string
- ConjureDTLSEmptyInitialPacketProbability *float64
- // HoldOffTunnelProtocolMinDurationMilliseconds and other
- // HoldOffTunnelProtocol fields are for testing purposes.
- HoldOffTunnelProtocolMinDurationMilliseconds *int
- HoldOffTunnelProtocolMaxDurationMilliseconds *int
- HoldOffTunnelProtocolNames []string
- HoldOffTunnelProtocolProbability *float64
- // HoldOffFrontingTunnelMinDurationMilliseconds and other
- // HoldOffFrontingTunnel fields are for testing purposes.
- HoldOffFrontingTunnelMinDurationMilliseconds *int
- HoldOffFrontingTunnelMaxDurationMilliseconds *int
- HoldOffFrontingTunnelProviderIDs []string
- HoldOffFrontingTunnelProbability *float64
- // RestrictFrontingProviderIDs and other RestrictFrontingProviderIDs fields
- // are for testing purposes.
- RestrictFrontingProviderIDs []string
- RestrictFrontingProviderIDsClientProbability *float64
- // HoldOffDirectTunnelMinDurationMilliseconds and other HoldOffDirect
- // fields are for testing purposes.
- HoldOffDirectTunnelMinDurationMilliseconds *int
- HoldOffDirectTunnelMaxDurationMilliseconds *int
- HoldOffDirectTunnelProviderRegions map[string][]string
- HoldOffDirectTunnelProbability *float64
- // RestrictDirectProviderRegions and other RestrictDirect fields are for
- // testing purposes.
- RestrictDirectProviderRegions map[string][]string
- RestrictDirectProviderIDsClientProbability *float64
- // HoldOffInproxyTunnelMinDurationMilliseconds and other HoldOffInproxy
- // fields are for testing purposes.
- HoldOffInproxyTunnelMinDurationMilliseconds *int
- HoldOffInproxyTunnelMaxDurationMilliseconds *int
- HoldOffInproxyTunnelProviderRegions map[string][]string
- HoldOffInproxyTunnelProbability *float64
- // RestrictInproxyProviderRegions and other RestrictInproxy fields are for
- // testing purposes.
- RestrictInproxyProviderRegions map[string][]string
- RestrictInproxyProviderIDsClientProbability *float64
- // UpstreamProxyAllowAllServerEntrySources is for testing purposes.
- UpstreamProxyAllowAllServerEntrySources *bool
- // LimitTunnelDialPortNumbers is for testing purposes.
- LimitTunnelDialPortNumbers parameters.TunnelProtocolPortLists
- // QUICDialEarlyProbability is for testing purposes.
- QUICDialEarlyProbability *float64
- // QUICObfuscatedPSKProbability is for testing purposes.
- QUICObfuscatedPSKProbability *float64
- // QUICDisablePathMTUDiscoveryProbability is for testing purposes.
- QUICDisablePathMTUDiscoveryProbability *float64
- // DNSResolverAttemptsPerServer and other DNSResolver fields are for
- // testing purposes.
- DNSResolverAttemptsPerServer *int
- DNSResolverAttemptsPerPreferredServer *int
- DNSResolverRequestTimeoutMilliseconds *int
- DNSResolverAwaitTimeoutMilliseconds *int
- DNSResolverPreresolvedIPAddressCIDRs parameters.LabeledCIDRs
- DNSResolverPreresolvedIPAddressProbability *float64
- DNSResolverAlternateServers []string
- DNSResolverPreferredAlternateServers []string
- DNSResolverPreferAlternateServerProbability *float64
- DNSResolverProtocolTransformSpecs transforms.Specs
- DNSResolverProtocolTransformScopedSpecNames transforms.ScopedSpecNames
- DNSResolverProtocolTransformProbability *float64
- DNSResolverQNameRandomizeCasingProbability *float64
- DNSResolverQNameMustMatchProbability *float64
- DNSResolverIncludeEDNS0Probability *float64
- DNSResolverCacheExtensionInitialTTLMilliseconds *int
- DNSResolverCacheExtensionVerifiedTTLMilliseconds *int
- DirectHTTPProtocolTransformSpecs transforms.Specs
- DirectHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames
- DirectHTTPProtocolTransformProbability *float64
- FrontedHTTPProtocolTransformSpecs transforms.Specs
- FrontedHTTPProtocolTransformScopedSpecNames transforms.ScopedSpecNames
- FrontedHTTPProtocolTransformProbability *float64
- OSSHObfuscatorSeedTransformSpecs transforms.Specs
- OSSHObfuscatorSeedTransformScopedSpecNames transforms.ScopedSpecNames
- OSSHObfuscatorSeedTransformProbability *float64
- ObfuscatedQUICNonceTransformSpecs transforms.Specs
- ObfuscatedQUICNonceTransformScopedSpecNames transforms.ScopedSpecNames
- ObfuscatedQUICNonceTransformProbability *float64
- // OSSHPrefix parameters are for testing purposes only.
- OSSHPrefixSpecs transforms.Specs
- OSSHPrefixScopedSpecNames transforms.ScopedSpecNames
- OSSHPrefixProbability *float64
- OSSHPrefixSplitMinDelayMilliseconds *int
- OSSHPrefixSplitMaxDelayMilliseconds *int
- OSSHPrefixEnableFragmentor *bool
- // ShadowsocksPrefix parameters are for testing purposes only.
- ShadowsocksPrefixSpecs transforms.Specs
- ShadowsocksPrefixScopedSpecNames transforms.ScopedSpecNames
- ShadowsocksPrefixProbability *float64
- // TLSTunnelTrafficShapingProbability and associated fields are for testing.
- TLSTunnelObfuscatedPSKProbability *float64
- TLSTunnelTrafficShapingProbability *float64
- TLSTunnelMinTLSPadding *int
- TLSTunnelMaxTLSPadding *int
- // TLSFragmentClientHello fields are for testing purposes only.
- TLSFragmentClientHelloProbability *float64
- TLSFragmentClientHelloLimitProtocols []string
- // AdditionalParameters is used for testing.
- AdditionalParameters string
- // SteeringIP fields are for testing purposes only.
- SteeringIPCacheTTLSeconds *int
- SteeringIPCacheMaxEntries *int
- SteeringIPProbability *float64
- // FrontedHTTPClientReplayDialParametersTTL and other FrontedHTTPClient
- // fields are for testing purposes only.
- FrontedHTTPClientReplayDialParametersTTLSeconds *int
- FrontedHTTPClientReplayUpdateFrequencySeconds *int
- FrontedHTTPClientReplayDialParametersProbability *float64
- FrontedHTTPClientReplayRetainFailedProbability *float64
- // The following in-proxy fields are for testing purposes only.
- InproxyAllowProxy *bool
- InproxyAllowClient *bool
- InproxyTunnelProtocolSelectionProbability *float64
- InproxyBrokerSpecs parameters.InproxyBrokerSpecsValue
- InproxyPersonalPairingBrokerSpecs parameters.InproxyBrokerSpecsValue
- InproxyProxyBrokerSpecs parameters.InproxyBrokerSpecsValue
- InproxyProxyPersonalPairingBrokerSpecs parameters.InproxyBrokerSpecsValue
- InproxyClientBrokerSpecs parameters.InproxyBrokerSpecsValue
- InproxyClientPersonalPairingBrokerSpecs parameters.InproxyBrokerSpecsValue
- InproxyReplayBrokerDialParametersTTLSeconds *int
- InproxyReplayBrokerUpdateFrequencySeconds *int
- InproxyReplayBrokerDialParametersProbability *float64
- InproxyReplayBrokerRetainFailedProbability *float64
- InproxyCommonCompartmentIDs parameters.InproxyCompartmentIDsValue
- InproxyMaxCompartmentIDListLength *int
- InproxyProxyAnnounceRequestTimeoutMilliseconds *int
- InproxyProxyAnnounceDelayMilliseconds *int
- InproxyProxyAnnounceMaxBackoffDelayMilliseconds *int
- InproxyProxyAnnounceDelayJitter *float64
- InproxyProxyAnswerRequestTimeoutMilliseconds *int
- InproxyClientOfferRequestTimeoutMilliseconds *int
- InproxyClientOfferRequestPersonalTimeoutMilliseconds *int
- InproxyClientOfferRetryDelayMilliseconds *int
- InproxyClientOfferRetryJitter *float64
- InproxyClientRelayedPacketRequestTimeoutMilliseconds *int
- InproxyDTLSRandomizationProbability *float64
- InproxyWebRTCMediaStreamsProbability *float64
- InproxyWebRTCDataChannelTrafficShapingProbability *float64
- InproxyWebRTCDataChannelTrafficShapingParameters *parameters.InproxyTrafficShapingParametersValue
- InproxyWebRTCMediaStreamsTrafficShapingProbability *float64
- InproxyWebRTCMediaStreamsTrafficShapingParameters *parameters.InproxyTrafficShapingParametersValue
- InproxySTUNServerAddresses []string
- InproxySTUNServerAddressesRFC5780 []string
- InproxyProxySTUNServerAddresses []string
- InproxyProxySTUNServerAddressesRFC5780 []string
- InproxyClientSTUNServerAddresses []string
- InproxyClientSTUNServerAddressesRFC5780 []string
- InproxyClientDiscoverNATProbability *float64
- InproxyDisableSTUN *bool
- InproxyDisablePortMapping *bool
- InproxyDisableInboundForMobileNetworks *bool
- InproxyDisableIPv6ICECandidates *bool
- InproxyProxyDisableSTUN *bool
- InproxyProxyDisablePortMapping *bool
- InproxyProxyDisableInboundForMobileNetworks *bool
- InproxyProxyDisableIPv6ICECandidates *bool
- InproxyClientDisableSTUN *bool
- InproxyClientDisablePortMapping *bool
- InproxyClientDisableInboundForMobileNetworks *bool
- InproxyClientDisableIPv6ICECandidates *bool
- InproxyProxyDiscoverNATTimeoutMilliseconds *int
- InproxyClientDiscoverNATTimeoutMilliseconds *int
- InproxyWebRTCAnswerTimeoutMilliseconds *int
- InproxyProxyWebRTCAwaitReadyToProxyTimeoutMilliseconds *int
- InproxyClientWebRTCAwaitReadyToProxyTimeoutMilliseconds *int
- InproxyProxyDestinationDialTimeoutMilliseconds *int
- InproxyPsiphonAPIRequestTimeoutMilliseconds *int
- InproxyProxyTotalActivityNoticePeriodMilliseconds *int
- InproxyClientDialRateLimitQuantity *int
- InproxyClientDialRateLimitIntervalMilliseconds *int
- InproxyClientNoMatchFailoverProbability *float64
- InproxyClientNoMatchFailoverPersonalProbability *float64
- InproxyFrontingProviderClientMaxRequestTimeouts map[string]string
- InproxyProxyOnBrokerClientFailedRetryPeriodMilliseconds *int
- InproxyProxyIncompatibleNetworkTypes []string
- InproxyClientIncompatibleNetworkTypes []string
- InproxyReplayRetainFailedProbability *float64
- InproxyProxyDisableWaitToShareSession *bool
- InproxyClientDisableWaitToShareSession *bool
- InproxyTunnelProtocolPreferProbability *float64
- InproxyTunnelProtocolForceSelectionCount *int
- InproxySkipAwaitFullyConnected bool
- InproxyEnableWebRTCDebugLogging bool
- NetworkIDCacheTTLMilliseconds *int
- // params is the active parameters.Parameters with defaults, config values,
- // and, optionally, tactics applied.
- //
- // New tactics must be applied by calling Config.SetParameters; calling
- // params.Set directly will fail to add config values.
- paramsMutex sync.Mutex
- params *parameters.Parameters
- dialParametersHash []byte
- dynamicConfigMutex sync.Mutex
- sponsorID string
- authorizations []string
- deviceBinder DeviceBinder
- networkIDGetter *cachingNetworkIDGetter
- clientFeatures []string
- resolverMutex sync.Mutex
- resolver *resolver.Resolver
- committed bool
- loadTimestamp string
- tacticsAppliedReceiversMutex sync.Mutex
- tacticsAppliedReceivers []TacticsAppliedReceiver
- signalComponentFailure atomic.Value
- inproxyMustUpgradePosted int32
- }
- // TacticsAppliedReceiver specifies the interface for a component that is
- // signaled when tactics are applied. TacticsApplied is invoked when any
- // tactics are applied after initial start up, and then whenever new tactics
- // are received and applied while running.
- type TacticsAppliedReceiver interface {
- TacticsApplied() error
- }
- // Config field which specifies if notice files should be used and at which
- // frequency and size they should be rotated.
- //
- // If either RotatingFileSize or RotatingSyncFrequency are <= 0, default values
- // are used.
- //
- // See comment for setNoticeFiles in notice.go for further details.
- type UseNoticeFiles struct {
- RotatingFileSize int
- RotatingSyncFrequency int
- }
- // LoadConfig parses a JSON format Psiphon config JSON string and returns a
- // Config struct populated with config values.
- //
- // The Config struct may then be programmatically populated with additional
- // values, including callbacks such as DeviceBinder.
- //
- // Before using the Config, Commit must be called, which will perform further
- // validation and initialize internal data structures.
- func LoadConfig(configJson []byte) (*Config, error) {
- var config Config
- err := json.Unmarshal(configJson, &config)
- if err != nil {
- return nil, errors.Trace(err)
- }
- config.loadTimestamp = common.TruncateTimestampToHour(
- common.GetCurrentTimestamp())
- config.signalComponentFailure.Store(func() {})
- return &config, nil
- }
- // IsCommitted checks if Commit was called.
- func (config *Config) IsCommitted() bool {
- return config.committed
- }
- // Commit validates Config fields finalizes initialization.
- //
- // Config fields should not be set after calling Config, as any changes may
- // not be reflected in internal data structures.
- //
- // If migrateFromLegacyFields is set to true, then an attempt to migrate from
- // legacy fields is made.
- //
- // Migration from legacy fields:
- // Config fields of the naming Migrate* (e.g. MigrateDataStoreDirectory) specify
- // a file migration operation which should be performed. These fields correspond
- // to deprecated fields, which previously could be used to specify where Psiphon
- // stored different sets of persistent files (e.g. MigrateDataStoreDirectory
- // corresponds to the deprecated field DataStoreDirectory).
- //
- // Psiphon now stores all persistent data under the configurable
- // DataRootDirectory (see Config.DataRootDirectory). The deprecated fields, and
- // corresponding Migrate* fields, are now used to specify the file or directory
- // path where, or under which, persistent files and directories created by
- // previous versions of Psiphon exist, so they can be moved under the
- // DataRootDirectory.
- //
- // For each migration operation:
- // - In the case of directories that could have defaulted to the current working
- // directory, persistent files and directories created by Psiphon are
- // precisely targeted to avoid moving files which were not created by Psiphon.
- // - If no file is found at the specified path, or an error is encountered while
- // migrating the file, then an error is logged and execution continues
- // normally.
- //
- // A sentinel file which signals that file migration has been completed, and
- // should not be attempted again, is created under DataRootDirectory after one
- // full pass through Commit(), regardless of whether file migration succeeds or
- // fails. It is better to not endlessly retry file migrations on each Commit()
- // because file system errors are expected to be rare and persistent files will
- // be re-populated over time.
- func (config *Config) Commit(migrateFromLegacyFields bool) error {
- // Apply any additional parameters first
- additionalParametersInfoMsgs, err := config.applyAdditionalParameters()
- if err != nil {
- return errors.TraceMsg(err, "failed to apply additional parameters")
- }
- // Do SetEmitDiagnosticNotices first, to ensure config file errors are
- // emitted.
- if config.EmitDiagnosticNotices {
- SetEmitDiagnosticNotices(
- true, config.EmitDiagnosticNetworkParameters)
- }
- // Migrate and set notice files before any operations that may emit an
- // error. This is to ensure config file errors are written to file when
- // notice files are configured with config.UseNoticeFiles.
- //
- // Note:
- // Errors encountered while configuring the data directory cannot be written
- // to notice files. This is because notices files are created within the
- // data directory.
- if config.DataRootDirectory == "" {
- wd, err := os.Getwd()
- if err != nil {
- return errors.Trace(common.RedactFilePathsError(err))
- }
- config.DataRootDirectory = wd
- }
- // Create root directory
- dataDirectoryPath := config.GetPsiphonDataDirectory()
- if !common.FileExists(dataDirectoryPath) {
- err := os.Mkdir(dataDirectoryPath, os.ModePerm)
- if err != nil {
- return errors.Tracef(
- "failed to create datastore directory with error: %s",
- common.RedactFilePathsError(err, dataDirectoryPath))
- }
- }
- // Check if the migration from legacy config fields has already been
- // completed. See the Migrate* config fields for more details.
- migrationCompleteFilePath := filepath.Join(config.GetPsiphonDataDirectory(), "migration_complete")
- needMigration := !common.FileExists(migrationCompleteFilePath)
- // Collect notices to emit them after notice files are set
- var noticeMigrationAlertMsgs []string
- var noticeMigrationInfoMsgs []string
- // Migrate notices first to ensure notice files are used for notices if
- // UseNoticeFiles is set.
- homepageFilePath := config.GetHomePageFilename()
- noticesFilePath := config.GetNoticesFilename()
- if migrateFromLegacyFields {
- if needMigration {
- // Move notice files that exist at legacy file paths under the data root
- // directory.
- noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, "Config migration: need migration")
- noticeMigrations := migrationsFromLegacyNoticeFilePaths(config)
- successfulMigrations := 0
- for _, migration := range noticeMigrations {
- err := DoFileMigration(migration)
- if err != nil {
- alertMsg := fmt.Sprintf("Config migration: %s", errors.Trace(err))
- noticeMigrationAlertMsgs = append(noticeMigrationAlertMsgs, alertMsg)
- } else {
- successfulMigrations += 1
- }
- }
- infoMsg := fmt.Sprintf("Config migration: %d/%d notice files successfully migrated", successfulMigrations, len(noticeMigrations))
- noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, infoMsg)
- } else {
- noticeMigrationInfoMsgs = append(noticeMigrationInfoMsgs, "Config migration: migration already completed")
- }
- }
- if config.UseNoticeFiles != nil {
- err := setNoticeFiles(
- homepageFilePath,
- noticesFilePath,
- config.UseNoticeFiles.RotatingFileSize,
- config.UseNoticeFiles.RotatingSyncFrequency)
- if err != nil {
- return errors.Trace(err)
- }
- }
- // Emit notices now that notice files are set if configured
- for _, msg := range additionalParametersInfoMsgs {
- NoticeInfo(msg)
- }
- for _, msg := range noticeMigrationAlertMsgs {
- NoticeWarning(msg)
- }
- for _, msg := range noticeMigrationInfoMsgs {
- NoticeInfo(msg)
- }
- // Promote legacy fields.
- if config.CustomHeaders == nil {
- config.CustomHeaders = config.UpstreamProxyCustomHeaders
- config.UpstreamProxyCustomHeaders = nil
- }
- if config.RemoteServerListUrl != "" && config.RemoteServerListURLs == nil {
- config.RemoteServerListURLs = promoteLegacyTransferURL(config.RemoteServerListUrl)
- }
- if config.ObfuscatedServerListRootURL != "" && config.ObfuscatedServerListRootURLs == nil {
- config.ObfuscatedServerListRootURLs = promoteLegacyTransferURL(config.ObfuscatedServerListRootURL)
- }
- if config.UpgradeDownloadUrl != "" && config.UpgradeDownloadURLs == nil {
- config.UpgradeDownloadURLs = promoteLegacyTransferURL(config.UpgradeDownloadUrl)
- }
- if config.TunnelProtocol != "" && len(config.LimitTunnelProtocols) == 0 {
- config.LimitTunnelProtocols = []string{config.TunnelProtocol}
- }
- if config.DataStoreDirectory != "" && config.MigrateDataStoreDirectory == "" {
- config.MigrateDataStoreDirectory = config.DataStoreDirectory
- }
- if config.RemoteServerListDownloadFilename != "" && config.MigrateRemoteServerListDownloadFilename == "" {
- config.MigrateRemoteServerListDownloadFilename = config.RemoteServerListDownloadFilename
- }
- if config.ObfuscatedServerListDownloadDirectory != "" && config.MigrateObfuscatedServerListDownloadDirectory == "" {
- config.MigrateObfuscatedServerListDownloadDirectory = config.ObfuscatedServerListDownloadDirectory
- }
- if config.UpgradeDownloadFilename != "" && config.MigrateUpgradeDownloadFilename == "" {
- config.MigrateUpgradeDownloadFilename = config.UpgradeDownloadFilename
- }
- // Supply default values.
- // Create datastore directory.
- dataStoreDirectoryPath := config.GetDataStoreDirectory()
- if !common.FileExists(dataStoreDirectoryPath) {
- err := os.Mkdir(dataStoreDirectoryPath, os.ModePerm)
- if err != nil {
- return errors.Tracef(
- "failed to create datastore directory with error: %s",
- common.RedactFilePathsError(err, dataStoreDirectoryPath))
- }
- }
- // Create OSL directory.
- oslDirectoryPath := config.GetObfuscatedServerListDownloadDirectory()
- if !common.FileExists(oslDirectoryPath) {
- err := os.Mkdir(oslDirectoryPath, os.ModePerm)
- if err != nil {
- return errors.Tracef(
- "failed to create osl directory with error: %s",
- common.RedactFilePathsError(err, oslDirectoryPath))
- }
- }
- if config.ClientVersion == "" {
- config.ClientVersion = "0"
- }
- if config.TunnelPoolSize == 0 {
- config.TunnelPoolSize = TUNNEL_POOL_SIZE
- }
- // Validate config fields.
- if !common.FileExists(config.DataRootDirectory) {
- return errors.TraceNew("DataRootDirectory does not exist")
- }
- if config.PropagationChannelId == "" {
- return errors.TraceNew("propagation channel ID is missing from the configuration file")
- }
- if config.SponsorId == "" {
- return errors.TraceNew("sponsor ID is missing from the configuration file")
- }
- _, err = strconv.Atoi(config.ClientVersion)
- if err != nil {
- return errors.Tracef("invalid client version: %s", err)
- }
- if config.TargetAPIProtocol != "" &&
- !protocol.PsiphonAPIProtocolIsValid(config.TargetAPIProtocol) {
- return errors.TraceNew("invalid TargetAPIProtocol")
- }
- if config.TargetAPIEncoding != "" &&
- !protocol.PsiphonAPIEncodingIsValid(config.TargetAPIEncoding) {
- return errors.TraceNew("invalid TargetAPIEncoding")
- }
- if !config.DisableRemoteServerListFetcher {
- if config.RemoteServerListURLs != nil {
- if config.RemoteServerListSignaturePublicKey == "" {
- return errors.TraceNew("missing RemoteServerListSignaturePublicKey")
- }
- }
- if config.ObfuscatedServerListRootURLs != nil {
- if config.RemoteServerListSignaturePublicKey == "" {
- return errors.TraceNew("missing RemoteServerListSignaturePublicKey")
- }
- }
- }
- if config.EnableUpgradeDownload {
- if len(config.UpgradeDownloadURLs) == 0 {
- return errors.TraceNew("missing UpgradeDownloadURLs")
- }
- if config.UpgradeDownloadClientVersionHeader == "" {
- return errors.TraceNew("missing UpgradeDownloadClientVersionHeader")
- }
- }
- if config.EnableFeedbackUpload {
- if len(config.FeedbackUploadURLs) == 0 {
- return errors.TraceNew("missing FeedbackUploadURLs")
- }
- if config.FeedbackEncryptionPublicKey == "" {
- return errors.TraceNew("missing FeedbackEncryptionPublicKey")
- }
- }
- if config.ObfuscatedSSHAlgorithms != nil &&
- len(config.ObfuscatedSSHAlgorithms) != 4 {
- // TODO: validate each algorithm?
- return errors.TraceNew("invalid ObfuscatedSSHAlgorithms")
- }
- if config.InproxyEnableProxy && config.InproxyMaxClients <= 0 {
- return errors.TraceNew("invalid InproxyMaxClients")
- }
- if !config.DisableTunnels &&
- config.InproxyEnableProxy &&
- !GetAllowOverlappingPersonalCompartmentIDs() &&
- len(config.InproxyProxyPersonalCompartmentID) > 0 &&
- config.InproxyProxyPersonalCompartmentID ==
- config.InproxyClientPersonalCompartmentID {
- // Don't allow an in-proxy client and proxy run in the same app to match.
- return errors.TraceNew("invalid overlapping personal compartment IDs")
- }
- if len(config.InproxyProxyPersonalCompartmentID) > 0 &&
- !inproxy.Enabled() {
- // When in-proxy personal pairing mode is on, fail if the build was
- // made without the PSIPHON_ENABLE_INPROXY build tag.
- //
- // Note that this check could also be enforced in the case of a
- // LimitTunnelProtocols.IsOnlyInproxyTunnelProtocols configuration,
- // but that can be overridden by tactics so we allow it.
- return errors.TraceNew("build does not enable required in-proxy functionality")
- }
- // This constraint is expected by logic in Controller.runTunnels().
- if config.PacketTunnelTunFileDescriptor > 0 && config.TunnelPoolSize != 1 {
- return errors.TraceNew("packet tunnel mode requires TunnelPoolSize to be 1")
- }
- // SessionID must be PSIPHON_API_CLIENT_SESSION_ID_LENGTH lowercase hex-encoded bytes.
- if config.SessionID == "" {
- sessionID, err := MakeSessionId()
- if err != nil {
- return errors.Trace(err)
- }
- config.SessionID = sessionID
- }
- if len(config.SessionID) != 2*protocol.PSIPHON_API_CLIENT_SESSION_ID_LENGTH ||
- -1 != strings.IndexFunc(config.SessionID, func(c rune) bool {
- return !unicode.Is(unicode.ASCII_Hex_Digit, c) || unicode.IsUpper(c)
- }) {
- return errors.TraceNew("invalid SessionID")
- }
- config.paramsMutex.Lock()
- config.params, err = parameters.NewParameters(
- func(err error) {
- NoticeWarning("Parameters getValue failed: %s", err)
- })
- config.paramsMutex.Unlock()
- if err != nil {
- return errors.Trace(err)
- }
- // parametersParameters.Set will validate the config fields applied to
- // parametersParameters.
- err = config.SetParameters("", false, nil)
- if err != nil {
- return errors.Trace(err)
- }
- // Calculate and set the dial parameters hash. After this point, related
- // config fields must not change.
- config.setDialParametersHash()
- // Set defaults for dynamic config fields.
- config.SetDynamicConfig(config.SponsorId, config.Authorizations)
- // Initialize config.deviceBinder and config.config.networkIDGetter. These
- // wrap config.DeviceBinder and config.NetworkIDGetter/NetworkID with
- // loggers.
- //
- // The network ID getter is further wrapped with a cache (see
- // cachingNetworkIDGetter doc).
- //
- // New variables are set to avoid mutating input config fields.
- // Internally, code must use config.deviceBinder and
- // config.networkIDGetter and not the input/exported fields.
- if config.DeviceBinder != nil {
- config.deviceBinder = newLoggingDeviceBinder(config.DeviceBinder)
- }
- networkIDGetter := config.NetworkIDGetter
- if networkIDGetter == nil {
- if networkid.Enabled() {
- networkIDGetter = newCommonNetworkIDGetter()
- } else {
- // Limitation: unlike NetworkIDGetter, which calls back to platform APIs
- // this method of network identification is not dynamic and will not reflect
- // network changes that occur while running.
- if config.NetworkID != "" {
- networkIDGetter = newStaticNetworkIDGetter(config.NetworkID)
- } else {
- networkIDGetter = newStaticNetworkIDGetter(unknownNetworkID)
- }
- }
- }
- config.networkIDGetter = newCachingNetworkIDGetter(
- config,
- newLoggingNetworkIDGetter(networkIDGetter))
- // Initialize config.clientFeatures, which adds feature names on top of
- // those specified by the host application in config.ClientFeatures.
- config.clientFeatures = config.ClientFeatures
- feature := "VPN"
- if config.DeviceBinder != nil && !common.Contains(config.clientFeatures, feature) {
- config.clientFeatures = append(config.clientFeatures, feature)
- }
- // Migrate from old config fields. This results in files being moved under
- // a config specified data root directory.
- if migrateFromLegacyFields && needMigration {
- // If unset, set MigrateDataStoreDirectory to the previous default value for
- // DataStoreDirectory to ensure that datastore files are migrated.
- if config.MigrateDataStoreDirectory == "" {
- wd, err := os.Getwd()
- if err != nil {
- return errors.Trace(err)
- }
- NoticeInfo("MigrateDataStoreDirectory unset, using working directory")
- config.MigrateDataStoreDirectory = wd
- }
- // Move files that exist at legacy file paths under the data root
- // directory.
- migrations, err := migrationsFromLegacyFilePaths(config)
- if err != nil {
- return errors.Trace(err)
- }
- // Do migrations
- successfulMigrations := 0
- for _, migration := range migrations {
- err := DoFileMigration(migration)
- if err != nil {
- NoticeWarning("Config migration: %s", errors.Trace(err))
- } else {
- successfulMigrations += 1
- }
- }
- NoticeInfo(fmt.Sprintf(
- "Config migration: %d/%d legacy files successfully migrated",
- successfulMigrations, len(migrations)))
- // Remove OSL directory if empty
- if config.MigrateObfuscatedServerListDownloadDirectory != "" {
- files, err := ioutil.ReadDir(config.MigrateObfuscatedServerListDownloadDirectory)
- if err != nil {
- NoticeWarning(
- "Error reading OSL directory: %s",
- errors.Trace(common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory)))
- } else if len(files) == 0 {
- err := os.Remove(config.MigrateObfuscatedServerListDownloadDirectory)
- if err != nil {
- NoticeWarning(
- "Error deleting empty OSL directory: %s",
- errors.Trace(common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory)))
- }
- }
- }
- f, err := os.Create(migrationCompleteFilePath)
- if err != nil {
- NoticeWarning(
- "Config migration: failed to create migration completed file with error %s",
- errors.Trace(common.RedactFilePathsError(err, migrationCompleteFilePath)))
- } else {
- NoticeInfo("Config migration: completed")
- f.Close()
- }
- }
- config.committed = true
- return nil
- }
- // GetParameters returns the current parameters.Parameters.
- func (config *Config) GetParameters() *parameters.Parameters {
- config.paramsMutex.Lock()
- defer config.paramsMutex.Unlock()
- return config.params
- }
- // SetParameters resets the parameters.Parameters to the default values,
- // applies any config file values, and then applies the input parameters (from
- // tactics, etc.)
- //
- // Set skipOnError to false when initially applying only config values, as
- // this will validate the values and should fail. Set skipOnError to true when
- // applying tactics to ignore invalid or unknown parameter values from tactics.
- //
- // In the case of applying tactics, do not call Config.parameters.Set
- // directly as this will not first apply config values.
- //
- // If there is an error, the existing Config.parameters are left
- // entirely unmodified.
- func (config *Config) SetParameters(tag string, skipOnError bool, applyParameters map[string]interface{}) error {
- setParameters := []map[string]interface{}{config.makeConfigParameters()}
- if applyParameters != nil {
- setParameters = append(setParameters, applyParameters)
- }
- // Don't hold the lock on config.paramsMutex when signalling
- // GetTacticsAppliedReceivers, or else GetParameters will deadlock.
- // Releasing the lock early here also ensures we don't hold the lock when
- // posting notices.
- config.paramsMutex.Lock()
- tagUnchanged := tag != "" && tag == config.params.Get().Tag()
- validationFlags := 0
- if skipOnError {
- validationFlags |= parameters.ValidationSkipOnError
- }
- counts, err := config.params.Set(tag, validationFlags, setParameters...)
- if err != nil {
- config.paramsMutex.Unlock()
- return errors.Trace(err)
- }
- p := config.params.Get()
- config.paramsMutex.Unlock()
- // Skip emitting notices and invoking GetTacticsAppliedReceivers when the
- // tactics tag is unchanged. The notices are redundant, and the receivers
- // will unnecessarily reset components such as in-proxy broker clients.
- //
- // At this time, the GetTactics call in launchEstablishing can result in
- // redundant SetParameters calls with an unchanged tag.
- //
- // As a fail safe, and since there should not be any unwanted side
- // effects, the above params.Set is still executed even for unchanged tags.
- if tagUnchanged {
- return nil
- }
- NoticeInfo("applied %v parameters with tag '%s'", counts, tag)
- // Emit certain individual parameter values for quick reference in diagnostics.
- NoticeInfo(
- "NetworkLatencyMultiplier Min/Max/Lambda: %f/%f/%f",
- p.Float(parameters.NetworkLatencyMultiplierMin),
- p.Float(parameters.NetworkLatencyMultiplierMax),
- p.Float(parameters.NetworkLatencyMultiplierLambda))
- // Application Parameters are feature flags/config info, delivered as Client
- // Parameters via tactics/etc., to be communicated to the outer application.
- // Emit these now, as notices.
- if p.WeightedCoinFlip(parameters.ApplicationParametersProbability) {
- NoticeApplicationParameters(p.KeyValues(parameters.ApplicationParameters))
- } else {
- // The front end may persist Application Parameters, so clear any previously
- // persisted values.
- NoticeApplicationParameters(parameters.KeyValues{})
- }
- // Signal all registered TacticsAppliedReceivers that new tactics have
- // been applied. Each receiver is responsible for checking if its
- // individual tactics parameters have actually changed.
- for _, receiver := range config.GetTacticsAppliedReceivers() {
- err := receiver.TacticsApplied()
- if err != nil {
- NoticeError("TacticsApplied failed: %v", errors.Trace(err))
- // Log and continue running.
- }
- }
- return nil
- }
- // SetResolver sets the current resolver.
- func (config *Config) SetResolver(resolver *resolver.Resolver) {
- config.resolverMutex.Lock()
- defer config.resolverMutex.Unlock()
- config.resolver = resolver
- }
- // GetResolver returns the current resolver. May return nil.
- func (config *Config) GetResolver() *resolver.Resolver {
- config.resolverMutex.Lock()
- defer config.resolverMutex.Unlock()
- return config.resolver
- }
- // SetTacticsAppliedReceivers registers the list of TacticsAppliedReceivers.
- func (config *Config) SetTacticsAppliedReceivers(receivers []TacticsAppliedReceiver) {
- config.tacticsAppliedReceiversMutex.Lock()
- defer config.tacticsAppliedReceiversMutex.Unlock()
- config.tacticsAppliedReceivers = receivers
- }
- // GetTacticsAppliedReceivers gets the list of registered
- // TacticsAppliedReceivers.
- func (config *Config) GetTacticsAppliedReceivers() []TacticsAppliedReceiver {
- config.tacticsAppliedReceiversMutex.Lock()
- defer config.tacticsAppliedReceiversMutex.Unlock()
- return config.tacticsAppliedReceivers
- }
- // SetDynamicConfig sets the current client sponsor ID and authorizations.
- // Invalid values for sponsor ID are ignored. The caller must not modify the
- // input authorizations slice.
- func (config *Config) SetDynamicConfig(sponsorID string, authorizations []string) {
- config.dynamicConfigMutex.Lock()
- defer config.dynamicConfigMutex.Unlock()
- if sponsorID != "" {
- config.sponsorID = sponsorID
- }
- config.authorizations = authorizations
- }
- // GetSponsorID returns the current client sponsor ID.
- func (config *Config) GetSponsorID() string {
- config.dynamicConfigMutex.Lock()
- defer config.dynamicConfigMutex.Unlock()
- return config.sponsorID
- }
- // IsSplitTunnelEnabled indicates if split tunnel mode is enabled, either for
- // the client's own country, a specified list of countries, or both.
- func (config *Config) IsSplitTunnelEnabled() bool {
- return config.SplitTunnelOwnRegion || len(config.SplitTunnelRegions) > 0
- }
- // GetAuthorizations returns the current client authorizations.
- // The caller must not modify the returned slice.
- func (config *Config) GetAuthorizations() []string {
- config.dynamicConfigMutex.Lock()
- defer config.dynamicConfigMutex.Unlock()
- return config.authorizations
- }
- // GetPsiphonDataDirectory returns the directory under which all persistent
- // files should be stored. This directory is created under
- // config.DataRootDirectory. The motivation for an additional directory is that
- // config.DataRootDirectory defaults to the current working directory, which may
- // include non-tunnel-core files that should be excluded from directory-spanning
- // operations (e.g. excluding all tunnel-core files from backup).
- func (config *Config) GetPsiphonDataDirectory() string {
- return filepath.Join(config.DataRootDirectory, PsiphonDataDirectoryName)
- }
- // GetHomePageFilename the path where the homepage notices file will be created.
- func (config *Config) GetHomePageFilename() string {
- return filepath.Join(config.GetPsiphonDataDirectory(), HomepageFilename)
- }
- // GetNoticesFilename returns the path where the notices file will be created.
- // When the file is rotated it will be moved to config.GetOldNoticesFilename().
- func (config *Config) GetNoticesFilename() string {
- return filepath.Join(config.GetPsiphonDataDirectory(), NoticesFilename)
- }
- // GetOldNoticeFilename returns the path where the rotated notices file will be
- // created.
- func (config *Config) GetOldNoticesFilename() string {
- return filepath.Join(config.GetPsiphonDataDirectory(), OldNoticesFilename)
- }
- // GetDataStoreDirectory returns the directory in which the persistent database
- // will be stored. Created in Config.Commit(). The persistent database contains
- // information such as server entries.
- func (config *Config) GetDataStoreDirectory() string {
- return filepath.Join(config.GetPsiphonDataDirectory(), "datastore")
- }
- // GetObfuscatedServerListDownloadDirectory returns the directory in which
- // obfuscated remote server list downloads will be stored. Created in
- // Config.Commit().
- func (config *Config) GetObfuscatedServerListDownloadDirectory() string {
- return filepath.Join(config.GetPsiphonDataDirectory(), "osl")
- }
- // GetRemoteServerListDownloadFilename returns the filename where the remote
- // server list download will be stored. Data is stored in co-located files
- // (RemoteServerListDownloadFilename.part*) to allow for resumable downloading.
- func (config *Config) GetRemoteServerListDownloadFilename() string {
- return filepath.Join(config.GetPsiphonDataDirectory(), "remote_server_list")
- }
- // GetUpgradeDownloadFilename specifies the filename where upgrade downloads
- // will be stored. This filename is valid when UpgradeDownloadURLs
- // (or UpgradeDownloadUrl) is specified. Data is stored in co-located files
- // (UpgradeDownloadFilename.part*) to allow for resumable downloading.
- func (config *Config) GetUpgradeDownloadFilename() string {
- return filepath.Join(config.GetPsiphonDataDirectory(), UpgradeDownloadFilename)
- }
- // UseUpstreamProxy indicates if an upstream proxy has been
- // configured.
- func (config *Config) UseUpstreamProxy() bool {
- return config.UpstreamProxyURL != ""
- }
- // GetNetworkID returns the current network ID. When NetworkIDGetter
- // is set, this calls into the host application; otherwise, a default
- // value is returned.
- func (config *Config) GetNetworkID() string {
- return config.networkIDGetter.GetNetworkID()
- }
- func (config *Config) SetSignalComponentFailure(signalComponentFailure func()) {
- config.signalComponentFailure.Store(signalComponentFailure)
- }
- // IsInproxyClientPersonalPairingMode indicates that the client is in in-proxy
- // personal pairing mode, where connections are made only through in-proxy
- // proxies with the corresponding personal compartment ID.
- func (config *Config) IsInproxyClientPersonalPairingMode() bool {
- return len(config.InproxyClientPersonalCompartmentID) > 0
- }
- // IsInproxyProxyPersonalPairingMode indicates that the proxy is in in-proxy
- // personal pairing mode, where connections are made only with in-proxy
- // clients with the corresponding personal compartment ID.
- func (config *Config) IsInproxyProxyPersonalPairingMode() bool {
- return len(config.InproxyProxyPersonalCompartmentID) > 0
- }
- // OnInproxyMustUpgrade is invoked when the in-proxy broker returns the
- // MustUpgrade response. When either running a proxy, or when running a
- // client in personal-pairing mode -- two states that require in-proxy
- // functionality -- onInproxyMustUpgrade initiates a shutdown after emitting
- // the InproxyMustUpgrade notice.
- func (config *Config) OnInproxyMustUpgrade() {
- // TODO: check if LimitTunnelProtocols is set to allow only INPROXY tunnel
- // protocols; this is another case where in-proxy functionality is
- // required.
- if config.InproxyEnableProxy || config.IsInproxyClientPersonalPairingMode() {
- if atomic.CompareAndSwapInt32(&config.inproxyMustUpgradePosted, 0, 1) {
- NoticeInproxyMustUpgrade()
- }
- config.signalComponentFailure.Load().(func())()
- }
- }
- func (config *Config) makeConfigParameters() map[string]interface{} {
- // Build set of config values to apply to parameters.
- //
- // Note: names of some config fields such as
- // StaggerConnectionWorkersMilliseconds and LimitMeekBufferSizes have
- // changed in the parameters. The existing config fields are retained for
- // backwards compatibility.
- applyParameters := make(map[string]interface{})
- // To support platform clients that configure NetworkLatencyMultiplier, set
- // the NetworkLatencyMultiplierMin/NetworkLatencyMultiplierMax range to the
- // specified value. Also set the older NetworkLatencyMultiplier tactic, since
- // that will be used in the case of replaying with dial parameters persisted
- // by an older client version.
- if config.NetworkLatencyMultiplier > 0.0 {
- applyParameters[parameters.NetworkLatencyMultiplier] = config.NetworkLatencyMultiplier
- applyParameters[parameters.NetworkLatencyMultiplierMin] = config.NetworkLatencyMultiplier
- applyParameters[parameters.NetworkLatencyMultiplierMax] = config.NetworkLatencyMultiplier
- }
- if config.NetworkLatencyMultiplierMin > 0.0 {
- applyParameters[parameters.NetworkLatencyMultiplierMin] = config.NetworkLatencyMultiplierMin
- }
- if config.NetworkLatencyMultiplierMax > 0.0 {
- applyParameters[parameters.NetworkLatencyMultiplierMax] = config.NetworkLatencyMultiplierMax
- }
- if config.NetworkLatencyMultiplierLambda > 0.0 {
- applyParameters[parameters.NetworkLatencyMultiplierLambda] = config.NetworkLatencyMultiplierLambda
- }
- if len(config.LimitTunnelProtocols) > 0 {
- applyParameters[parameters.LimitTunnelProtocols] = protocol.TunnelProtocols(config.LimitTunnelProtocols)
- }
- if len(config.InitialLimitTunnelProtocols) > 0 && config.InitialLimitTunnelProtocolsCandidateCount > 0 {
- applyParameters[parameters.InitialLimitTunnelProtocols] = protocol.TunnelProtocols(config.InitialLimitTunnelProtocols)
- applyParameters[parameters.InitialLimitTunnelProtocolsCandidateCount] = config.InitialLimitTunnelProtocolsCandidateCount
- }
- if len(config.LimitTLSProfiles) > 0 {
- applyParameters[parameters.LimitTLSProfiles] = protocol.TunnelProtocols(config.LimitTLSProfiles)
- }
- if len(config.LimitQUICVersions) > 0 {
- applyParameters[parameters.LimitQUICVersions] = protocol.QUICVersions(config.LimitQUICVersions)
- }
- if config.EstablishTunnelTimeoutSeconds != nil {
- applyParameters[parameters.EstablishTunnelTimeout] = fmt.Sprintf("%ds", *config.EstablishTunnelTimeoutSeconds)
- }
- if config.EstablishTunnelServerAffinityGracePeriodMilliseconds != nil {
- applyParameters[parameters.EstablishTunnelServerAffinityGracePeriod] = fmt.Sprintf("%dms", *config.EstablishTunnelServerAffinityGracePeriodMilliseconds)
- }
- if config.EstablishTunnelPausePeriodSeconds != nil {
- applyParameters[parameters.EstablishTunnelPausePeriod] = fmt.Sprintf("%ds", *config.EstablishTunnelPausePeriodSeconds)
- }
- if config.ConnectionWorkerPoolSize != 0 {
- applyParameters[parameters.ConnectionWorkerPoolSize] = config.ConnectionWorkerPoolSize
- }
- if config.TunnelPoolSize != 0 {
- applyParameters[parameters.TunnelPoolSize] = config.TunnelPoolSize
- }
- if config.StaggerConnectionWorkersMilliseconds > 0 {
- applyParameters[parameters.StaggerConnectionWorkersPeriod] = fmt.Sprintf("%dms", config.StaggerConnectionWorkersMilliseconds)
- }
- if config.LimitIntensiveConnectionWorkers > 0 {
- applyParameters[parameters.LimitIntensiveConnectionWorkers] = config.LimitIntensiveConnectionWorkers
- }
- applyParameters[parameters.MeekLimitBufferSizes] = config.LimitMeekBufferSizes
- applyParameters[parameters.IgnoreHandshakeStatsRegexps] = config.IgnoreHandshakeStatsRegexps
- if config.EstablishTunnelTimeoutSeconds != nil {
- applyParameters[parameters.EstablishTunnelTimeout] = fmt.Sprintf("%ds", *config.EstablishTunnelTimeoutSeconds)
- }
- if config.FetchRemoteServerListRetryPeriodMilliseconds != nil {
- applyParameters[parameters.FetchRemoteServerListRetryPeriod] = fmt.Sprintf("%dms", *config.FetchRemoteServerListRetryPeriodMilliseconds)
- }
- if config.FetchUpgradeRetryPeriodMilliseconds != nil {
- applyParameters[parameters.FetchUpgradeRetryPeriod] = fmt.Sprintf("%dms", *config.FetchUpgradeRetryPeriodMilliseconds)
- }
- if !config.DisableRemoteServerListFetcher {
- if config.RemoteServerListURLs != nil {
- applyParameters[parameters.RemoteServerListSignaturePublicKey] = config.RemoteServerListSignaturePublicKey
- applyParameters[parameters.RemoteServerListURLs] = config.RemoteServerListURLs
- }
- if config.ObfuscatedServerListRootURLs != nil {
- applyParameters[parameters.RemoteServerListSignaturePublicKey] = config.RemoteServerListSignaturePublicKey
- applyParameters[parameters.ObfuscatedServerListRootURLs] = config.ObfuscatedServerListRootURLs
- }
- }
- if config.EnableUpgradeDownload {
- applyParameters[parameters.UpgradeDownloadURLs] = config.UpgradeDownloadURLs
- applyParameters[parameters.UpgradeDownloadClientVersionHeader] = config.UpgradeDownloadClientVersionHeader
- }
- if config.EnableFeedbackUpload {
- applyParameters[parameters.FeedbackUploadURLs] = config.FeedbackUploadURLs
- applyParameters[parameters.FeedbackEncryptionPublicKey] = config.FeedbackEncryptionPublicKey
- }
- applyParameters[parameters.TunnelRateLimits] = config.RateLimits
- if config.TransformHostNameProbability != nil {
- applyParameters[parameters.TransformHostNameProbability] = *config.TransformHostNameProbability
- }
- if config.FragmentorProbability != nil {
- applyParameters[parameters.FragmentorProbability] = *config.FragmentorProbability
- }
- if len(config.FragmentorLimitProtocols) > 0 {
- applyParameters[parameters.FragmentorLimitProtocols] = protocol.TunnelProtocols(config.FragmentorLimitProtocols)
- }
- if config.FragmentorMinTotalBytes != nil {
- applyParameters[parameters.FragmentorMinTotalBytes] = *config.FragmentorMinTotalBytes
- }
- if config.FragmentorMaxTotalBytes != nil {
- applyParameters[parameters.FragmentorMaxTotalBytes] = *config.FragmentorMaxTotalBytes
- }
- if config.FragmentorMinWriteBytes != nil {
- applyParameters[parameters.FragmentorMinWriteBytes] = *config.FragmentorMinWriteBytes
- }
- if config.FragmentorMaxWriteBytes != nil {
- applyParameters[parameters.FragmentorMaxWriteBytes] = *config.FragmentorMaxWriteBytes
- }
- if config.FragmentorMinDelayMicroseconds != nil {
- applyParameters[parameters.FragmentorMinDelay] = fmt.Sprintf("%dus", *config.FragmentorMinDelayMicroseconds)
- }
- if config.FragmentorMaxDelayMicroseconds != nil {
- applyParameters[parameters.FragmentorMaxDelay] = fmt.Sprintf("%dus", *config.FragmentorMaxDelayMicroseconds)
- }
- if config.MeekTrafficShapingProbability != nil {
- applyParameters[parameters.MeekTrafficShapingProbability] = *config.MeekTrafficShapingProbability
- }
- if len(config.MeekTrafficShapingLimitProtocols) > 0 {
- applyParameters[parameters.MeekTrafficShapingLimitProtocols] = protocol.TunnelProtocols(config.MeekTrafficShapingLimitProtocols)
- }
- if config.MeekMinTLSPadding != nil {
- applyParameters[parameters.MeekMinTLSPadding] = *config.MeekMinTLSPadding
- }
- if config.MeekMaxTLSPadding != nil {
- applyParameters[parameters.MeekMaxTLSPadding] = *config.MeekMaxTLSPadding
- }
- if config.MeekMinLimitRequestPayloadLength != nil {
- applyParameters[parameters.MeekMinLimitRequestPayloadLength] = *config.MeekMinLimitRequestPayloadLength
- }
- if config.MeekMaxLimitRequestPayloadLength != nil {
- applyParameters[parameters.MeekMaxLimitRequestPayloadLength] = *config.MeekMaxLimitRequestPayloadLength
- }
- if config.MeekRedialTLSProbability != nil {
- applyParameters[parameters.MeekRedialTLSProbability] = *config.MeekRedialTLSProbability
- }
- if config.MeekAlternateCookieNameProbability != nil {
- applyParameters[parameters.MeekAlternateCookieNameProbability] = *config.MeekAlternateCookieNameProbability
- }
- if config.MeekAlternateContentTypeProbability != nil {
- applyParameters[parameters.MeekAlternateContentTypeProbability] = *config.MeekAlternateContentTypeProbability
- }
- if config.ObfuscatedSSHMinPadding != nil {
- applyParameters[parameters.ObfuscatedSSHMinPadding] = *config.ObfuscatedSSHMinPadding
- }
- if config.ObfuscatedSSHMaxPadding != nil {
- applyParameters[parameters.ObfuscatedSSHMaxPadding] = *config.ObfuscatedSSHMaxPadding
- }
- if len(config.InitialLivenessTest) > 0 {
- applyParameters[parameters.InitialLivenessTest] = config.InitialLivenessTest
- }
- if len(config.LivenessTest) > 0 {
- applyParameters[parameters.LivenessTest] = config.LivenessTest
- }
- if config.LivenessTestMinUpstreamBytes != nil {
- applyParameters[parameters.LivenessTestMinUpstreamBytes] = *config.LivenessTestMinUpstreamBytes
- }
- if config.LivenessTestMaxUpstreamBytes != nil {
- applyParameters[parameters.LivenessTestMaxUpstreamBytes] = *config.LivenessTestMaxUpstreamBytes
- }
- if config.LivenessTestMinDownstreamBytes != nil {
- applyParameters[parameters.LivenessTestMinDownstreamBytes] = *config.LivenessTestMinDownstreamBytes
- }
- if config.LivenessTestMaxDownstreamBytes != nil {
- applyParameters[parameters.LivenessTestMaxDownstreamBytes] = *config.LivenessTestMaxDownstreamBytes
- }
- if config.ReplayCandidateCount != nil {
- applyParameters[parameters.ReplayCandidateCount] = *config.ReplayCandidateCount
- }
- if config.ReplayDialParametersTTLSeconds != nil {
- applyParameters[parameters.ReplayDialParametersTTL] = fmt.Sprintf("%ds", *config.ReplayDialParametersTTLSeconds)
- }
- if config.ReplayTargetUpstreamBytes != nil {
- applyParameters[parameters.ReplayTargetUpstreamBytes] = *config.ReplayTargetUpstreamBytes
- }
- if config.ReplayTargetDownstreamBytes != nil {
- applyParameters[parameters.ReplayTargetDownstreamBytes] = *config.ReplayTargetDownstreamBytes
- }
- if config.ReplayTargetTunnelDurationSeconds != nil {
- applyParameters[parameters.ReplayTargetTunnelDuration] = fmt.Sprintf("%ds", *config.ReplayTargetTunnelDurationSeconds)
- }
- if config.ReplayLaterRoundMoveToFrontProbability != nil {
- applyParameters[parameters.ReplayLaterRoundMoveToFrontProbability] = *config.ReplayLaterRoundMoveToFrontProbability
- }
- if config.ReplayRetainFailedProbability != nil {
- applyParameters[parameters.ReplayRetainFailedProbability] = *config.ReplayRetainFailedProbability
- }
- if config.ReplayIgnoreChangedConfigState != nil {
- applyParameters[parameters.ReplayIgnoreChangedConfigState] = *config.ReplayIgnoreChangedConfigState
- }
- if config.UseOnlyCustomTLSProfiles != nil {
- applyParameters[parameters.UseOnlyCustomTLSProfiles] = *config.UseOnlyCustomTLSProfiles
- }
- if len(config.CustomTLSProfiles) > 0 {
- applyParameters[parameters.CustomTLSProfiles] = config.CustomTLSProfiles
- }
- if config.SelectRandomizedTLSProfileProbability != nil {
- applyParameters[parameters.SelectRandomizedTLSProfileProbability] = *config.SelectRandomizedTLSProfileProbability
- }
- if config.NoDefaultTLSSessionIDProbability != nil {
- applyParameters[parameters.NoDefaultTLSSessionIDProbability] = *config.NoDefaultTLSSessionIDProbability
- }
- if len(config.DisableFrontingProviderTLSProfiles) > 0 {
- applyParameters[parameters.DisableFrontingProviderTLSProfiles] = config.DisableFrontingProviderTLSProfiles
- }
- if config.ClientBurstUpstreamTargetBytes != nil {
- applyParameters[parameters.ClientBurstUpstreamTargetBytes] = *config.ClientBurstUpstreamTargetBytes
- }
- if config.ClientBurstUpstreamDeadlineMilliseconds != nil {
- applyParameters[parameters.ClientBurstUpstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstUpstreamDeadlineMilliseconds)
- }
- if config.ClientBurstDownstreamTargetBytes != nil {
- applyParameters[parameters.ClientBurstDownstreamTargetBytes] = *config.ClientBurstDownstreamTargetBytes
- }
- if config.ClientBurstDownstreamDeadlineMilliseconds != nil {
- applyParameters[parameters.ClientBurstDownstreamDeadline] = fmt.Sprintf("%dms", *config.ClientBurstDownstreamDeadlineMilliseconds)
- }
- if config.ApplicationParameters != nil {
- applyParameters[parameters.ApplicationParameters] = config.ApplicationParameters
- }
- if config.CustomHostNameRegexes != nil {
- applyParameters[parameters.CustomHostNameRegexes] = parameters.RegexStrings(config.CustomHostNameRegexes)
- }
- if config.CustomHostNameProbability != nil {
- applyParameters[parameters.CustomHostNameProbability] = *config.CustomHostNameProbability
- }
- if config.CustomHostNameLimitProtocols != nil {
- applyParameters[parameters.CustomHostNameLimitProtocols] = protocol.TunnelProtocols(config.CustomHostNameLimitProtocols)
- }
- if config.ConjureCachedRegistrationTTLSeconds != nil {
- applyParameters[parameters.ConjureCachedRegistrationTTL] = fmt.Sprintf("%ds", *config.ConjureCachedRegistrationTTLSeconds)
- }
- if config.ConjureAPIRegistrarBidirectionalURL != "" {
- applyParameters[parameters.ConjureAPIRegistrarBidirectionalURL] = config.ConjureAPIRegistrarBidirectionalURL
- }
- if len(config.ConjureAPIRegistrarFrontingSpecs) > 0 {
- applyParameters[parameters.ConjureAPIRegistrarFrontingSpecs] = config.ConjureAPIRegistrarFrontingSpecs
- }
- if config.ConjureAPIRegistrarMinDelayMilliseconds != nil {
- applyParameters[parameters.ConjureAPIRegistrarMinDelay] = fmt.Sprintf("%dms", *config.ConjureAPIRegistrarMinDelayMilliseconds)
- }
- if config.ConjureAPIRegistrarMaxDelayMilliseconds != nil {
- applyParameters[parameters.ConjureAPIRegistrarMaxDelay] = fmt.Sprintf("%dms", *config.ConjureAPIRegistrarMaxDelayMilliseconds)
- }
- if config.ConjureDecoyRegistrarProbability != nil {
- applyParameters[parameters.ConjureDecoyRegistrarProbability] = *config.ConjureDecoyRegistrarProbability
- }
- if config.ConjureDecoyRegistrarWidth != nil {
- applyParameters[parameters.ConjureDecoyRegistrarWidth] = *config.ConjureDecoyRegistrarWidth
- }
- if config.ConjureDecoyRegistrarMinDelayMilliseconds != nil {
- applyParameters[parameters.ConjureDecoyRegistrarMinDelay] = fmt.Sprintf("%dms", *config.ConjureDecoyRegistrarMinDelayMilliseconds)
- }
- if config.ConjureDecoyRegistrarMaxDelayMilliseconds != nil {
- applyParameters[parameters.ConjureDecoyRegistrarMaxDelay] = fmt.Sprintf("%dms", *config.ConjureDecoyRegistrarMaxDelayMilliseconds)
- }
- if config.ConjureEnableIPv6Dials != nil {
- applyParameters[parameters.ConjureEnableIPv6Dials] = *config.ConjureEnableIPv6Dials
- }
- if config.ConjureEnablePortRandomization != nil {
- applyParameters[parameters.ConjureEnablePortRandomization] = *config.ConjureEnablePortRandomization
- }
- if config.ConjureEnableRegistrationOverrides != nil {
- applyParameters[parameters.ConjureEnableRegistrationOverrides] = *config.ConjureEnableRegistrationOverrides
- }
- if config.ConjureLimitTransports != nil {
- applyParameters[parameters.ConjureLimitTransports] = config.ConjureLimitTransports
- }
- if config.ConjureSTUNServerAddresses != nil {
- applyParameters[parameters.ConjureSTUNServerAddresses] = config.ConjureSTUNServerAddresses
- }
- if config.ConjureDTLSEmptyInitialPacketProbability != nil {
- applyParameters[parameters.ConjureDTLSEmptyInitialPacketProbability] = *config.ConjureDTLSEmptyInitialPacketProbability
- }
- if config.HoldOffTunnelProtocolMinDurationMilliseconds != nil {
- applyParameters[parameters.HoldOffTunnelProtocolMinDuration] = fmt.Sprintf("%dms", *config.HoldOffTunnelProtocolMinDurationMilliseconds)
- }
- if config.HoldOffTunnelProtocolMaxDurationMilliseconds != nil {
- applyParameters[parameters.HoldOffTunnelProtocolMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffTunnelProtocolMaxDurationMilliseconds)
- }
- if len(config.HoldOffTunnelProtocolNames) > 0 {
- applyParameters[parameters.HoldOffTunnelProtocolNames] = protocol.TunnelProtocols(config.HoldOffTunnelProtocolNames)
- }
- if config.HoldOffTunnelProtocolProbability != nil {
- applyParameters[parameters.HoldOffTunnelProtocolProbability] = *config.HoldOffTunnelProtocolProbability
- }
- if config.HoldOffFrontingTunnelMinDurationMilliseconds != nil {
- applyParameters[parameters.HoldOffFrontingTunnelMinDuration] = fmt.Sprintf("%dms", *config.HoldOffFrontingTunnelMinDurationMilliseconds)
- }
- if config.HoldOffFrontingTunnelMaxDurationMilliseconds != nil {
- applyParameters[parameters.HoldOffFrontingTunnelMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffFrontingTunnelMaxDurationMilliseconds)
- }
- if len(config.HoldOffFrontingTunnelProviderIDs) > 0 {
- applyParameters[parameters.HoldOffFrontingTunnelProviderIDs] = config.HoldOffFrontingTunnelProviderIDs
- }
- if config.HoldOffFrontingTunnelProbability != nil {
- applyParameters[parameters.HoldOffFrontingTunnelProbability] = *config.HoldOffFrontingTunnelProbability
- }
- if config.HoldOffDirectTunnelMinDurationMilliseconds != nil {
- applyParameters[parameters.HoldOffDirectTunnelMinDuration] = fmt.Sprintf("%dms", *config.HoldOffDirectTunnelMinDurationMilliseconds)
- }
- if config.HoldOffDirectTunnelMaxDurationMilliseconds != nil {
- applyParameters[parameters.HoldOffDirectTunnelMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffDirectTunnelMaxDurationMilliseconds)
- }
- if len(config.HoldOffDirectTunnelProviderRegions) > 0 {
- applyParameters[parameters.HoldOffDirectTunnelProviderRegions] = parameters.KeyStrings(config.HoldOffDirectTunnelProviderRegions)
- }
- if config.HoldOffDirectTunnelProbability != nil {
- applyParameters[parameters.HoldOffDirectTunnelProbability] = *config.HoldOffDirectTunnelProbability
- }
- if len(config.RestrictDirectProviderRegions) > 0 {
- applyParameters[parameters.RestrictDirectProviderRegions] = parameters.KeyStrings(config.RestrictDirectProviderRegions)
- }
- if config.RestrictDirectProviderIDsClientProbability != nil {
- applyParameters[parameters.RestrictDirectProviderIDsClientProbability] = *config.RestrictDirectProviderIDsClientProbability
- }
- if len(config.RestrictFrontingProviderIDs) > 0 {
- applyParameters[parameters.RestrictFrontingProviderIDs] = config.RestrictFrontingProviderIDs
- }
- if config.RestrictFrontingProviderIDsClientProbability != nil {
- applyParameters[parameters.RestrictFrontingProviderIDsClientProbability] = *config.RestrictFrontingProviderIDsClientProbability
- }
- if config.HoldOffInproxyTunnelMinDurationMilliseconds != nil {
- applyParameters[parameters.HoldOffInproxyTunnelMinDuration] = fmt.Sprintf("%dms", *config.HoldOffInproxyTunnelMinDurationMilliseconds)
- }
- if config.HoldOffInproxyTunnelMaxDurationMilliseconds != nil {
- applyParameters[parameters.HoldOffInproxyTunnelMaxDuration] = fmt.Sprintf("%dms", *config.HoldOffInproxyTunnelMaxDurationMilliseconds)
- }
- if len(config.HoldOffInproxyTunnelProviderRegions) > 0 {
- applyParameters[parameters.HoldOffInproxyTunnelProviderRegions] = parameters.KeyStrings(config.HoldOffInproxyTunnelProviderRegions)
- }
- if config.HoldOffInproxyTunnelProbability != nil {
- applyParameters[parameters.HoldOffInproxyTunnelProbability] = *config.HoldOffInproxyTunnelProbability
- }
- if config.UpstreamProxyAllowAllServerEntrySources != nil {
- applyParameters[parameters.UpstreamProxyAllowAllServerEntrySources] = *config.UpstreamProxyAllowAllServerEntrySources
- }
- if len(config.LimitTunnelDialPortNumbers) > 0 {
- applyParameters[parameters.LimitTunnelDialPortNumbers] = config.LimitTunnelDialPortNumbers
- }
- if config.QUICDialEarlyProbability != nil {
- applyParameters[parameters.QUICDialEarlyProbability] = *config.QUICDialEarlyProbability
- }
- if config.QUICObfuscatedPSKProbability != nil {
- applyParameters[parameters.QUICObfuscatedPSKProbability] = *config.QUICObfuscatedPSKProbability
- }
- if config.QUICDisablePathMTUDiscoveryProbability != nil {
- applyParameters[parameters.QUICDisableClientPathMTUDiscoveryProbability] = *config.QUICDisablePathMTUDiscoveryProbability
- }
- if config.DNSResolverAttemptsPerServer != nil {
- applyParameters[parameters.DNSResolverAttemptsPerServer] = *config.DNSResolverAttemptsPerServer
- }
- if config.DNSResolverAttemptsPerPreferredServer != nil {
- applyParameters[parameters.DNSResolverAttemptsPerPreferredServer] = *config.DNSResolverAttemptsPerPreferredServer
- }
- if config.DNSResolverRequestTimeoutMilliseconds != nil {
- applyParameters[parameters.DNSResolverRequestTimeout] = fmt.Sprintf("%dms", *config.DNSResolverRequestTimeoutMilliseconds)
- }
- if config.DNSResolverAwaitTimeoutMilliseconds != nil {
- applyParameters[parameters.DNSResolverAwaitTimeout] = fmt.Sprintf("%dms", *config.DNSResolverAwaitTimeoutMilliseconds)
- }
- if config.DNSResolverPreresolvedIPAddressProbability != nil {
- applyParameters[parameters.DNSResolverPreresolvedIPAddressProbability] = *config.DNSResolverPreresolvedIPAddressProbability
- }
- if config.DNSResolverPreresolvedIPAddressCIDRs != nil {
- applyParameters[parameters.DNSResolverPreresolvedIPAddressCIDRs] = config.DNSResolverPreresolvedIPAddressCIDRs
- }
- if config.DNSResolverAlternateServers != nil {
- applyParameters[parameters.DNSResolverAlternateServers] = config.DNSResolverAlternateServers
- }
- if config.DNSResolverPreferredAlternateServers != nil {
- applyParameters[parameters.DNSResolverPreferredAlternateServers] = config.DNSResolverPreferredAlternateServers
- }
- if config.DNSResolverPreferAlternateServerProbability != nil {
- applyParameters[parameters.DNSResolverPreferAlternateServerProbability] = *config.DNSResolverPreferAlternateServerProbability
- }
- if config.DNSResolverProtocolTransformSpecs != nil {
- applyParameters[parameters.DNSResolverProtocolTransformSpecs] = config.DNSResolverProtocolTransformSpecs
- }
- if config.DNSResolverProtocolTransformScopedSpecNames != nil {
- applyParameters[parameters.DNSResolverProtocolTransformScopedSpecNames] = config.DNSResolverProtocolTransformScopedSpecNames
- }
- if config.DNSResolverProtocolTransformProbability != nil {
- applyParameters[parameters.DNSResolverProtocolTransformProbability] = *config.DNSResolverProtocolTransformProbability
- }
- if config.DNSResolverQNameRandomizeCasingProbability != nil {
- applyParameters[parameters.DNSResolverQNameRandomizeCasingProbability] = *config.DNSResolverQNameRandomizeCasingProbability
- }
- if config.DNSResolverQNameMustMatchProbability != nil {
- applyParameters[parameters.DNSResolverQNameMustMatchProbability] = *config.DNSResolverQNameMustMatchProbability
- }
- if config.DNSResolverIncludeEDNS0Probability != nil {
- applyParameters[parameters.DNSResolverIncludeEDNS0Probability] = *config.DNSResolverIncludeEDNS0Probability
- }
- if config.DNSResolverCacheExtensionInitialTTLMilliseconds != nil {
- applyParameters[parameters.DNSResolverCacheExtensionInitialTTL] = fmt.Sprintf("%dms", *config.DNSResolverCacheExtensionInitialTTLMilliseconds)
- }
- if config.DNSResolverCacheExtensionVerifiedTTLMilliseconds != nil {
- applyParameters[parameters.DNSResolverCacheExtensionVerifiedTTL] = fmt.Sprintf("%dms", *config.DNSResolverCacheExtensionVerifiedTTLMilliseconds)
- }
- if config.DirectHTTPProtocolTransformSpecs != nil {
- applyParameters[parameters.DirectHTTPProtocolTransformSpecs] = config.DirectHTTPProtocolTransformSpecs
- }
- if config.DirectHTTPProtocolTransformScopedSpecNames != nil {
- applyParameters[parameters.DirectHTTPProtocolTransformScopedSpecNames] = config.DirectHTTPProtocolTransformScopedSpecNames
- }
- if config.DirectHTTPProtocolTransformProbability != nil {
- applyParameters[parameters.DirectHTTPProtocolTransformProbability] = *config.DirectHTTPProtocolTransformProbability
- }
- if config.FrontedHTTPProtocolTransformSpecs != nil {
- applyParameters[parameters.FrontedHTTPProtocolTransformSpecs] = config.FrontedHTTPProtocolTransformSpecs
- }
- if config.FrontedHTTPProtocolTransformScopedSpecNames != nil {
- applyParameters[parameters.FrontedHTTPProtocolTransformScopedSpecNames] = config.FrontedHTTPProtocolTransformScopedSpecNames
- }
- if config.FrontedHTTPProtocolTransformProbability != nil {
- applyParameters[parameters.FrontedHTTPProtocolTransformProbability] = *config.FrontedHTTPProtocolTransformProbability
- }
- if config.OSSHObfuscatorSeedTransformSpecs != nil {
- applyParameters[parameters.OSSHObfuscatorSeedTransformSpecs] = config.OSSHObfuscatorSeedTransformSpecs
- }
- if config.OSSHObfuscatorSeedTransformScopedSpecNames != nil {
- applyParameters[parameters.OSSHObfuscatorSeedTransformScopedSpecNames] = config.OSSHObfuscatorSeedTransformScopedSpecNames
- }
- if config.OSSHObfuscatorSeedTransformProbability != nil {
- applyParameters[parameters.OSSHObfuscatorSeedTransformProbability] = *config.OSSHObfuscatorSeedTransformProbability
- }
- if config.ObfuscatedQUICNonceTransformSpecs != nil {
- applyParameters[parameters.ObfuscatedQUICNonceTransformSpecs] = config.ObfuscatedQUICNonceTransformSpecs
- }
- if config.ObfuscatedQUICNonceTransformScopedSpecNames != nil {
- applyParameters[parameters.ObfuscatedQUICNonceTransformScopedSpecNames] = config.ObfuscatedQUICNonceTransformScopedSpecNames
- }
- if config.ObfuscatedQUICNonceTransformProbability != nil {
- applyParameters[parameters.ObfuscatedQUICNonceTransformProbability] = *config.ObfuscatedQUICNonceTransformProbability
- }
- if config.OSSHPrefixSpecs != nil {
- applyParameters[parameters.OSSHPrefixSpecs] = config.OSSHPrefixSpecs
- }
- if config.OSSHPrefixScopedSpecNames != nil {
- applyParameters[parameters.OSSHPrefixScopedSpecNames] = config.OSSHPrefixScopedSpecNames
- }
- if config.OSSHPrefixProbability != nil {
- applyParameters[parameters.OSSHPrefixProbability] = *config.OSSHPrefixProbability
- }
- if config.OSSHPrefixSplitMinDelayMilliseconds != nil {
- applyParameters[parameters.OSSHPrefixSplitMinDelay] = fmt.Sprintf("%dms", *config.OSSHPrefixSplitMinDelayMilliseconds)
- }
- if config.OSSHPrefixSplitMaxDelayMilliseconds != nil {
- applyParameters[parameters.OSSHPrefixSplitMaxDelay] = fmt.Sprintf("%dms", *config.OSSHPrefixSplitMaxDelayMilliseconds)
- }
- if config.OSSHPrefixEnableFragmentor != nil {
- applyParameters[parameters.OSSHPrefixEnableFragmentor] = *config.OSSHPrefixEnableFragmentor
- }
- if config.ShadowsocksPrefixSpecs != nil {
- applyParameters[parameters.ShadowsocksPrefixSpecs] = config.ShadowsocksPrefixSpecs
- }
- if config.ShadowsocksPrefixScopedSpecNames != nil {
- applyParameters[parameters.ShadowsocksPrefixScopedSpecNames] = config.ShadowsocksPrefixScopedSpecNames
- }
- if config.ShadowsocksPrefixProbability != nil {
- applyParameters[parameters.ShadowsocksPrefixProbability] = *config.ShadowsocksPrefixProbability
- }
- if config.TLSTunnelObfuscatedPSKProbability != nil {
- applyParameters[parameters.TLSTunnelObfuscatedPSKProbability] = *config.TLSTunnelObfuscatedPSKProbability
- }
- if config.TLSTunnelTrafficShapingProbability != nil {
- applyParameters[parameters.TLSTunnelTrafficShapingProbability] = *config.TLSTunnelTrafficShapingProbability
- }
- if config.TLSTunnelMinTLSPadding != nil {
- applyParameters[parameters.TLSTunnelMinTLSPadding] = *config.TLSTunnelMinTLSPadding
- }
- if config.TLSTunnelMaxTLSPadding != nil {
- applyParameters[parameters.TLSTunnelMaxTLSPadding] = *config.TLSTunnelMaxTLSPadding
- }
- if config.TLSFragmentClientHelloProbability != nil {
- applyParameters[parameters.TLSFragmentClientHelloProbability] = *config.TLSFragmentClientHelloProbability
- }
- if len(config.TLSFragmentClientHelloLimitProtocols) > 0 {
- applyParameters[parameters.TLSFragmentClientHelloLimitProtocols] = protocol.TunnelProtocols(config.TLSFragmentClientHelloLimitProtocols)
- }
- if config.SteeringIPCacheTTLSeconds != nil {
- applyParameters[parameters.SteeringIPCacheTTL] = fmt.Sprintf("%ds", *config.SteeringIPCacheTTLSeconds)
- }
- if config.SteeringIPCacheMaxEntries != nil {
- applyParameters[parameters.SteeringIPCacheMaxEntries] = *config.SteeringIPCacheMaxEntries
- }
- if config.SteeringIPProbability != nil {
- applyParameters[parameters.SteeringIPProbability] = *config.SteeringIPProbability
- }
- if config.FrontedHTTPClientReplayDialParametersTTLSeconds != nil {
- applyParameters[parameters.FrontedHTTPClientReplayDialParametersTTL] = fmt.Sprintf("%ds", *config.FrontedHTTPClientReplayDialParametersTTLSeconds)
- }
- if config.FrontedHTTPClientReplayUpdateFrequencySeconds != nil {
- applyParameters[parameters.FrontedHTTPClientReplayUpdateFrequency] = fmt.Sprintf("%ds", *config.FrontedHTTPClientReplayUpdateFrequencySeconds)
- }
- if config.FrontedHTTPClientReplayDialParametersProbability != nil {
- applyParameters[parameters.FrontedHTTPClientReplayDialParametersProbability] = *config.FrontedHTTPClientReplayDialParametersProbability
- }
- if config.FrontedHTTPClientReplayRetainFailedProbability != nil {
- applyParameters[parameters.FrontedHTTPClientReplayRetainFailedProbability] = *config.FrontedHTTPClientReplayRetainFailedProbability
- }
- if config.InproxyPersonalPairingConnectionWorkerPoolSize != 0 {
- applyParameters[parameters.InproxyPersonalPairingConnectionWorkerPoolSize] = config.InproxyPersonalPairingConnectionWorkerPoolSize
- }
- if config.InproxyAllowProxy != nil {
- applyParameters[parameters.InproxyAllowProxy] = *config.InproxyAllowProxy
- }
- if config.InproxyAllowClient != nil {
- applyParameters[parameters.InproxyAllowClient] = *config.InproxyAllowClient
- }
- if config.InproxyTunnelProtocolSelectionProbability != nil {
- applyParameters[parameters.InproxyTunnelProtocolSelectionProbability] = *config.InproxyTunnelProtocolSelectionProbability
- }
- if len(config.InproxyBrokerSpecs) > 0 {
- applyParameters[parameters.InproxyBrokerSpecs] = config.InproxyBrokerSpecs
- }
- if len(config.InproxyPersonalPairingBrokerSpecs) > 0 {
- applyParameters[parameters.InproxyPersonalPairingBrokerSpecs] = config.InproxyPersonalPairingBrokerSpecs
- }
- if len(config.InproxyProxyBrokerSpecs) > 0 {
- applyParameters[parameters.InproxyProxyBrokerSpecs] = config.InproxyProxyBrokerSpecs
- }
- if len(config.InproxyProxyPersonalPairingBrokerSpecs) > 0 {
- applyParameters[parameters.InproxyProxyPersonalPairingBrokerSpecs] = config.InproxyProxyPersonalPairingBrokerSpecs
- }
- if len(config.InproxyClientBrokerSpecs) > 0 {
- applyParameters[parameters.InproxyClientBrokerSpecs] = config.InproxyClientBrokerSpecs
- }
- if len(config.InproxyClientPersonalPairingBrokerSpecs) > 0 {
- applyParameters[parameters.InproxyClientPersonalPairingBrokerSpecs] = config.InproxyClientPersonalPairingBrokerSpecs
- }
- if config.InproxyReplayBrokerDialParametersTTLSeconds != nil {
- applyParameters[parameters.InproxyReplayBrokerDialParametersTTL] = fmt.Sprintf("%ds", *config.InproxyReplayBrokerDialParametersTTLSeconds)
- }
- if config.InproxyReplayBrokerUpdateFrequencySeconds != nil {
- applyParameters[parameters.InproxyReplayBrokerUpdateFrequency] = fmt.Sprintf("%ds", *config.InproxyReplayBrokerUpdateFrequencySeconds)
- }
- if config.InproxyReplayBrokerDialParametersProbability != nil {
- applyParameters[parameters.InproxyReplayBrokerDialParametersProbability] = *config.InproxyReplayBrokerDialParametersProbability
- }
- if config.InproxyReplayBrokerRetainFailedProbability != nil {
- applyParameters[parameters.InproxyReplayBrokerRetainFailedProbability] = *config.InproxyReplayBrokerRetainFailedProbability
- }
- if len(config.InproxyCommonCompartmentIDs) > 0 {
- applyParameters[parameters.InproxyCommonCompartmentIDs] = config.InproxyCommonCompartmentIDs
- }
- if config.InproxyMaxCompartmentIDListLength != nil {
- applyParameters[parameters.InproxyMaxCompartmentIDListLength] = *config.InproxyMaxCompartmentIDListLength
- }
- if config.InproxyProxyAnnounceRequestTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyProxyAnnounceRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyAnnounceRequestTimeoutMilliseconds)
- }
- if config.InproxyProxyAnnounceDelayMilliseconds != nil {
- applyParameters[parameters.InproxyProxyAnnounceDelay] = fmt.Sprintf("%dms", *config.InproxyProxyAnnounceDelayMilliseconds)
- }
- if config.InproxyProxyAnnounceMaxBackoffDelayMilliseconds != nil {
- applyParameters[parameters.InproxyProxyAnnounceMaxBackoffDelay] = fmt.Sprintf("%dms", *config.InproxyProxyAnnounceMaxBackoffDelayMilliseconds)
- }
- if config.InproxyProxyAnnounceDelayJitter != nil {
- applyParameters[parameters.InproxyProxyAnnounceDelayJitter] = *config.InproxyProxyAnnounceDelayJitter
- }
- if config.InproxyProxyAnswerRequestTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyProxyAnswerRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyAnswerRequestTimeoutMilliseconds)
- }
- if config.InproxyClientOfferRequestTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyClientOfferRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyClientOfferRequestTimeoutMilliseconds)
- }
- if config.InproxyClientOfferRequestPersonalTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyClientOfferRequestPersonalTimeout] = fmt.Sprintf("%dms", *config.InproxyClientOfferRequestPersonalTimeoutMilliseconds)
- }
- if config.InproxyClientOfferRetryDelayMilliseconds != nil {
- applyParameters[parameters.InproxyClientOfferRetryDelay] = fmt.Sprintf("%dms", *config.InproxyClientOfferRetryDelayMilliseconds)
- }
- if config.InproxyClientOfferRetryJitter != nil {
- applyParameters[parameters.InproxyClientOfferRetryJitter] = *config.InproxyClientOfferRetryJitter
- }
- if config.InproxyClientRelayedPacketRequestTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyClientRelayedPacketRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyClientRelayedPacketRequestTimeoutMilliseconds)
- }
- if config.InproxyDTLSRandomizationProbability != nil {
- applyParameters[parameters.InproxyDTLSRandomizationProbability] = *config.InproxyDTLSRandomizationProbability
- }
- if config.InproxyWebRTCMediaStreamsProbability != nil {
- applyParameters[parameters.InproxyWebRTCMediaStreamsProbability] = *config.InproxyWebRTCMediaStreamsProbability
- }
- if config.InproxyWebRTCDataChannelTrafficShapingProbability != nil {
- applyParameters[parameters.InproxyWebRTCDataChannelTrafficShapingProbability] = *config.InproxyWebRTCDataChannelTrafficShapingProbability
- }
- if config.InproxyWebRTCDataChannelTrafficShapingParameters != nil {
- applyParameters[parameters.InproxyWebRTCDataChannelTrafficShapingParameters] = *config.InproxyWebRTCDataChannelTrafficShapingParameters
- }
- if config.InproxyWebRTCMediaStreamsTrafficShapingProbability != nil {
- applyParameters[parameters.InproxyWebRTCMediaStreamsTrafficShapingProbability] = *config.InproxyWebRTCMediaStreamsTrafficShapingProbability
- }
- if config.InproxyWebRTCMediaStreamsTrafficShapingParameters != nil {
- applyParameters[parameters.InproxyWebRTCMediaStreamsTrafficShapingParameters] = *config.InproxyWebRTCMediaStreamsTrafficShapingParameters
- }
- if len(config.InproxySTUNServerAddresses) > 0 {
- applyParameters[parameters.InproxySTUNServerAddresses] = config.InproxySTUNServerAddresses
- }
- if len(config.InproxySTUNServerAddressesRFC5780) > 0 {
- applyParameters[parameters.InproxySTUNServerAddressesRFC5780] = config.InproxySTUNServerAddressesRFC5780
- }
- if len(config.InproxyProxySTUNServerAddresses) > 0 {
- applyParameters[parameters.InproxyProxySTUNServerAddresses] = config.InproxyProxySTUNServerAddresses
- }
- if len(config.InproxyProxySTUNServerAddressesRFC5780) > 0 {
- applyParameters[parameters.InproxyProxySTUNServerAddressesRFC5780] = config.InproxyProxySTUNServerAddressesRFC5780
- }
- if len(config.InproxyClientSTUNServerAddresses) > 0 {
- applyParameters[parameters.InproxyClientSTUNServerAddresses] = config.InproxyClientSTUNServerAddresses
- }
- if len(config.InproxyClientSTUNServerAddressesRFC5780) > 0 {
- applyParameters[parameters.InproxyClientSTUNServerAddressesRFC5780] = config.InproxyClientSTUNServerAddressesRFC5780
- }
- if config.InproxyClientDiscoverNATProbability != nil {
- applyParameters[parameters.InproxyClientDiscoverNATProbability] = *config.InproxyClientDiscoverNATProbability
- }
- if config.InproxyDisableSTUN != nil {
- applyParameters[parameters.InproxyDisableSTUN] = *config.InproxyDisableSTUN
- }
- if config.InproxyDisablePortMapping != nil {
- applyParameters[parameters.InproxyDisablePortMapping] = *config.InproxyDisablePortMapping
- }
- if config.InproxyDisableInboundForMobileNetworks != nil {
- applyParameters[parameters.InproxyDisableInboundForMobileNetworks] = *config.InproxyDisableInboundForMobileNetworks
- }
- if config.InproxyDisableIPv6ICECandidates != nil {
- applyParameters[parameters.InproxyDisableIPv6ICECandidates] = *config.InproxyDisableIPv6ICECandidates
- }
- if config.InproxyProxyDisableSTUN != nil {
- applyParameters[parameters.InproxyProxyDisableSTUN] = *config.InproxyProxyDisableSTUN
- }
- if config.InproxyProxyDisablePortMapping != nil {
- applyParameters[parameters.InproxyProxyDisablePortMapping] = *config.InproxyProxyDisablePortMapping
- }
- if config.InproxyProxyDisableInboundForMobileNetworks != nil {
- applyParameters[parameters.InproxyProxyDisableInboundForMobileNetworks] = *config.InproxyProxyDisableInboundForMobileNetworks
- }
- if config.InproxyProxyDisableIPv6ICECandidates != nil {
- applyParameters[parameters.InproxyProxyDisableIPv6ICECandidates] = *config.InproxyProxyDisableIPv6ICECandidates
- }
- if config.InproxyClientDisableSTUN != nil {
- applyParameters[parameters.InproxyClientDisableSTUN] = *config.InproxyClientDisableSTUN
- }
- if config.InproxyClientDisablePortMapping != nil {
- applyParameters[parameters.InproxyClientDisablePortMapping] = *config.InproxyClientDisablePortMapping
- }
- if config.InproxyClientDisableInboundForMobileNetworks != nil {
- applyParameters[parameters.InproxyClientDisableInboundForMobileNetworks] = *config.InproxyClientDisableInboundForMobileNetworks
- }
- if config.InproxyClientDisableIPv6ICECandidates != nil {
- applyParameters[parameters.InproxyClientDisableIPv6ICECandidates] = *config.InproxyClientDisableIPv6ICECandidates
- }
- if config.InproxyProxyDiscoverNATTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyProxyDiscoverNATTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyDiscoverNATTimeoutMilliseconds)
- }
- if config.InproxyClientDiscoverNATTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyClientDiscoverNATTimeout] = fmt.Sprintf("%dms", *config.InproxyClientDiscoverNATTimeoutMilliseconds)
- }
- if config.InproxyWebRTCAnswerTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyWebRTCAnswerTimeout] = fmt.Sprintf("%dms", *config.InproxyWebRTCAnswerTimeoutMilliseconds)
- }
- if config.InproxyProxyWebRTCAwaitReadyToProxyTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyProxyWebRTCAwaitReadyToProxyTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyWebRTCAwaitReadyToProxyTimeoutMilliseconds)
- }
- if config.InproxyClientWebRTCAwaitReadyToProxyTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyClientWebRTCAwaitReadyToProxyTimeout] = fmt.Sprintf("%dms", *config.InproxyClientWebRTCAwaitReadyToProxyTimeoutMilliseconds)
- }
- if config.InproxyProxyDestinationDialTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyProxyDestinationDialTimeout] = fmt.Sprintf("%dms", *config.InproxyProxyDestinationDialTimeoutMilliseconds)
- }
- if config.InproxyPsiphonAPIRequestTimeoutMilliseconds != nil {
- applyParameters[parameters.InproxyPsiphonAPIRequestTimeout] = fmt.Sprintf("%dms", *config.InproxyPsiphonAPIRequestTimeoutMilliseconds)
- }
- if config.InproxyProxyTotalActivityNoticePeriodMilliseconds != nil {
- applyParameters[parameters.InproxyProxyTotalActivityNoticePeriod] = fmt.Sprintf("%dms", *config.InproxyProxyTotalActivityNoticePeriodMilliseconds)
- }
- if config.InproxyClientDialRateLimitQuantity != nil {
- applyParameters[parameters.InproxyClientDialRateLimitQuantity] = *config.InproxyClientDialRateLimitQuantity
- }
- if config.InproxyClientDialRateLimitIntervalMilliseconds != nil {
- applyParameters[parameters.InproxyClientDialRateLimitInterval] = fmt.Sprintf("%dms", *config.InproxyClientDialRateLimitIntervalMilliseconds)
- }
- if config.InproxyClientNoMatchFailoverProbability != nil {
- applyParameters[parameters.InproxyClientNoMatchFailoverProbability] = *config.InproxyClientNoMatchFailoverProbability
- }
- if config.InproxyClientNoMatchFailoverPersonalProbability != nil {
- applyParameters[parameters.InproxyClientNoMatchFailoverPersonalProbability] = *config.InproxyClientNoMatchFailoverPersonalProbability
- }
- if config.InproxyFrontingProviderClientMaxRequestTimeouts != nil {
- applyParameters[parameters.InproxyFrontingProviderClientMaxRequestTimeouts] = config.InproxyFrontingProviderClientMaxRequestTimeouts
- }
- if config.InproxyProxyOnBrokerClientFailedRetryPeriodMilliseconds != nil {
- applyParameters[parameters.InproxyProxyOnBrokerClientFailedRetryPeriod] = fmt.Sprintf("%dms", *config.InproxyProxyOnBrokerClientFailedRetryPeriodMilliseconds)
- }
- if len(config.InproxyProxyIncompatibleNetworkTypes) > 0 {
- applyParameters[parameters.InproxyProxyIncompatibleNetworkTypes] = config.InproxyProxyIncompatibleNetworkTypes
- }
- if len(config.InproxyClientIncompatibleNetworkTypes) > 0 {
- applyParameters[parameters.InproxyClientIncompatibleNetworkTypes] = config.InproxyClientIncompatibleNetworkTypes
- }
- if config.InproxyReplayRetainFailedProbability != nil {
- applyParameters[parameters.InproxyReplayRetainFailedProbability] = *config.InproxyReplayRetainFailedProbability
- }
- if config.InproxyProxyDisableWaitToShareSession != nil {
- applyParameters[parameters.InproxyProxyDisableWaitToShareSession] = *config.InproxyProxyDisableWaitToShareSession
- }
- if config.InproxyClientDisableWaitToShareSession != nil {
- applyParameters[parameters.InproxyClientDisableWaitToShareSession] = *config.InproxyClientDisableWaitToShareSession
- }
- if config.InproxyTunnelProtocolPreferProbability != nil {
- applyParameters[parameters.InproxyTunnelProtocolPreferProbability] = *config.InproxyTunnelProtocolPreferProbability
- }
- if config.InproxyTunnelProtocolForceSelectionCount != nil {
- applyParameters[parameters.InproxyTunnelProtocolForceSelectionCount] = *config.InproxyTunnelProtocolForceSelectionCount
- }
- if config.NetworkIDCacheTTLMilliseconds != nil {
- applyParameters[parameters.NetworkIDCacheTTL] = fmt.Sprintf("%dms", *config.NetworkIDCacheTTLMilliseconds)
- }
- // When adding new config dial parameters that may override tactics, also
- // update setDialParametersHash.
- return applyParameters
- }
- func (config *Config) setDialParametersHash() {
- // Calculate and store a hash of the config values that may impact
- // dial parameters. This hash is used as part of the dial parameters
- // replay mechanism to detect when persisted dial parameters should
- // be discarded due to conflicting config changes.
- //
- // With a couple of minor exceptions, configuring dial parameters via the
- // config is intended for testing only, and so these parameters are expected
- // to be present in test runs only. It remains an important case to discard
- // replay dial parameters when test config parameters are varied.
- //
- // Hashing the parameter names detects some ambiguous hash cases, such as two
- // consecutive int64 parameters, one omitted and one not, that are flipped.
- // The serialization is not completely unambiguous, and the format is
- // currently limited by legacy cases (not invalidating replay dial parameters
- // for production clients is more important than invalidating for test runs).
- // We cannot hash the entire config JSON as it contains non-dial parameter
- // fields which may frequently change across runs.
- //
- // MD5 hash is used solely as a data checksum and not for any security
- // purpose.
- hash := md5.New()
- if len(config.LimitTunnelProtocols) > 0 {
- hash.Write([]byte("LimitTunnelProtocols"))
- for _, protocol := range config.LimitTunnelProtocols {
- hash.Write([]byte(protocol))
- }
- }
- if len(config.InitialLimitTunnelProtocols) > 0 && config.InitialLimitTunnelProtocolsCandidateCount > 0 {
- hash.Write([]byte("InitialLimitTunnelProtocols"))
- for _, protocol := range config.InitialLimitTunnelProtocols {
- hash.Write([]byte(protocol))
- }
- binary.Write(hash, binary.LittleEndian, int64(config.InitialLimitTunnelProtocolsCandidateCount))
- }
- if len(config.LimitTLSProfiles) > 0 {
- hash.Write([]byte("LimitTLSProfiles"))
- for _, profile := range config.LimitTLSProfiles {
- hash.Write([]byte(profile))
- }
- }
- if len(config.LimitQUICVersions) > 0 {
- hash.Write([]byte("LimitQUICVersions"))
- for _, version := range config.LimitQUICVersions {
- hash.Write([]byte(version))
- }
- }
- // Whether a custom User-Agent is specified is a binary flag: when not set,
- // the replay dial parameters value applies. When set, external
- // considerations apply.
- if _, ok := config.CustomHeaders["User-Agent"]; ok {
- hash.Write([]byte("CustomHeaders User-Agent"))
- hash.Write([]byte{1})
- }
- if config.UpstreamProxyURL != "" {
- hash.Write([]byte("UpstreamProxyURL"))
- hash.Write([]byte(config.UpstreamProxyURL))
- }
- if config.TransformHostNameProbability != nil {
- hash.Write([]byte("TransformHostNameProbability"))
- binary.Write(hash, binary.LittleEndian, *config.TransformHostNameProbability)
- }
- if config.FragmentorProbability != nil {
- hash.Write([]byte("FragmentorProbability"))
- binary.Write(hash, binary.LittleEndian, *config.FragmentorProbability)
- }
- if len(config.FragmentorLimitProtocols) > 0 {
- hash.Write([]byte("FragmentorLimitProtocols"))
- for _, protocol := range config.FragmentorLimitProtocols {
- hash.Write([]byte(protocol))
- }
- }
- if config.FragmentorMinTotalBytes != nil {
- hash.Write([]byte("FragmentorMinTotalBytes"))
- binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinTotalBytes))
- }
- if config.FragmentorMaxTotalBytes != nil {
- hash.Write([]byte("FragmentorMaxTotalBytes"))
- binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxTotalBytes))
- }
- if config.FragmentorMinWriteBytes != nil {
- hash.Write([]byte("FragmentorMinWriteBytes"))
- binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinWriteBytes))
- }
- if config.FragmentorMaxWriteBytes != nil {
- hash.Write([]byte("FragmentorMaxWriteBytes"))
- binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxWriteBytes))
- }
- if config.FragmentorMinDelayMicroseconds != nil {
- hash.Write([]byte("FragmentorMinDelayMicroseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMinDelayMicroseconds))
- }
- if config.FragmentorMaxDelayMicroseconds != nil {
- hash.Write([]byte("FragmentorMaxDelayMicroseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.FragmentorMaxDelayMicroseconds))
- }
- if config.MeekTrafficShapingProbability != nil {
- hash.Write([]byte("MeekTrafficShapingProbability"))
- binary.Write(hash, binary.LittleEndian, *config.MeekTrafficShapingProbability)
- }
- if len(config.MeekTrafficShapingLimitProtocols) > 0 {
- hash.Write([]byte("MeekTrafficShapingLimitProtocols"))
- for _, protocol := range config.MeekTrafficShapingLimitProtocols {
- hash.Write([]byte(protocol))
- }
- }
- if config.MeekMinLimitRequestPayloadLength != nil {
- hash.Write([]byte("MeekMinLimitRequestPayloadLength"))
- binary.Write(hash, binary.LittleEndian, int64(*config.MeekMinLimitRequestPayloadLength))
- }
- if config.MeekMaxLimitRequestPayloadLength != nil {
- hash.Write([]byte("MeekMaxLimitRequestPayloadLength"))
- binary.Write(hash, binary.LittleEndian, int64(*config.MeekMaxLimitRequestPayloadLength))
- }
- if config.MeekRedialTLSProbability != nil {
- hash.Write([]byte("MeekRedialTLSProbability"))
- binary.Write(hash, binary.LittleEndian, *config.MeekRedialTLSProbability)
- }
- if config.ObfuscatedSSHMinPadding != nil {
- hash.Write([]byte("ObfuscatedSSHMinPadding"))
- binary.Write(hash, binary.LittleEndian, int64(*config.ObfuscatedSSHMinPadding))
- }
- if config.ObfuscatedSSHMaxPadding != nil {
- hash.Write([]byte("ObfuscatedSSHMaxPadding"))
- binary.Write(hash, binary.LittleEndian, int64(*config.ObfuscatedSSHMaxPadding))
- }
- if config.LivenessTestMinUpstreamBytes != nil {
- hash.Write([]byte("LivenessTestMinUpstreamBytes"))
- binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMinUpstreamBytes))
- }
- if config.LivenessTestMaxUpstreamBytes != nil {
- hash.Write([]byte("LivenessTestMaxUpstreamBytes"))
- binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMaxUpstreamBytes))
- }
- if config.LivenessTestMinDownstreamBytes != nil {
- hash.Write([]byte("LivenessTestMinDownstreamBytes"))
- binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMinDownstreamBytes))
- }
- if config.LivenessTestMaxDownstreamBytes != nil {
- hash.Write([]byte("LivenessTestMaxDownstreamBytes"))
- binary.Write(hash, binary.LittleEndian, int64(*config.LivenessTestMaxDownstreamBytes))
- }
- // Legacy case: these parameters are included in the hash unconditionally,
- // and so will impact almost all production clients. These parameter names
- // are not hashed since that would invalidate all replay dial parameters for
- // existing clients whose hashes predate the inclusion of parameter names.
- binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierMin)
- binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierMax)
- binary.Write(hash, binary.LittleEndian, config.NetworkLatencyMultiplierLambda)
- if config.UseOnlyCustomTLSProfiles != nil {
- hash.Write([]byte("UseOnlyCustomTLSProfiles"))
- binary.Write(hash, binary.LittleEndian, *config.UseOnlyCustomTLSProfiles)
- }
- if len(config.CustomTLSProfiles) > 0 {
- hash.Write([]byte("CustomTLSProfiles"))
- for _, customTLSProfile := range config.CustomTLSProfiles {
- encodedCustomTLSProofile, _ := json.Marshal(customTLSProfile)
- hash.Write(encodedCustomTLSProofile)
- }
- }
- if config.SelectRandomizedTLSProfileProbability != nil {
- hash.Write([]byte("SelectRandomizedTLSProfileProbability"))
- binary.Write(hash, binary.LittleEndian, *config.SelectRandomizedTLSProfileProbability)
- }
- if config.NoDefaultTLSSessionIDProbability != nil {
- hash.Write([]byte("NoDefaultTLSSessionIDProbability"))
- binary.Write(hash, binary.LittleEndian, *config.NoDefaultTLSSessionIDProbability)
- }
- if len(config.DisableFrontingProviderTLSProfiles) > 0 {
- hash.Write([]byte("DisableFrontingProviderTLSProfiles"))
- encodedDisableFrontingProviderTLSProfiles, _ :=
- json.Marshal(config.DisableFrontingProviderTLSProfiles)
- hash.Write(encodedDisableFrontingProviderTLSProfiles)
- }
- if len(config.CustomHostNameRegexes) > 0 {
- hash.Write([]byte("CustomHostNameRegexes"))
- for _, customHostNameRegex := range config.CustomHostNameRegexes {
- hash.Write([]byte(customHostNameRegex))
- }
- }
- if config.CustomHostNameProbability != nil {
- hash.Write([]byte("CustomHostNameProbability"))
- binary.Write(hash, binary.LittleEndian, *config.CustomHostNameProbability)
- }
- if len(config.CustomHostNameLimitProtocols) > 0 {
- hash.Write([]byte("CustomHostNameLimitProtocols"))
- for _, protocol := range config.CustomHostNameLimitProtocols {
- hash.Write([]byte(protocol))
- }
- }
- if config.ConjureCachedRegistrationTTLSeconds != nil {
- hash.Write([]byte("ConjureCachedRegistrationTTLSeconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.ConjureCachedRegistrationTTLSeconds))
- }
- if config.ConjureAPIRegistrarBidirectionalURL != "" {
- hash.Write([]byte("ConjureAPIRegistrarBidirectionalURL"))
- hash.Write([]byte(config.ConjureAPIRegistrarBidirectionalURL))
- }
- if len(config.ConjureAPIRegistrarFrontingSpecs) > 0 {
- hash.Write([]byte("ConjureAPIRegistrarFrontingSpecs"))
- for _, frontingSpec := range config.ConjureAPIRegistrarFrontingSpecs {
- encodedFrontSpec, _ := json.Marshal(frontingSpec)
- hash.Write(encodedFrontSpec)
- }
- }
- if config.ConjureAPIRegistrarMinDelayMilliseconds != nil {
- hash.Write([]byte("ConjureAPIRegistrarMinDelayMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.ConjureAPIRegistrarMinDelayMilliseconds))
- }
- if config.ConjureAPIRegistrarMaxDelayMilliseconds != nil {
- hash.Write([]byte("ConjureAPIRegistrarMaxDelayMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.ConjureAPIRegistrarMaxDelayMilliseconds))
- }
- if config.ConjureDecoyRegistrarWidth != nil {
- hash.Write([]byte("ConjureDecoyRegistrarWidth"))
- binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarWidth))
- }
- if config.ConjureDecoyRegistrarMinDelayMilliseconds != nil {
- hash.Write([]byte("ConjureDecoyRegistrarMinDelayMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarMinDelayMilliseconds))
- }
- if config.ConjureDecoyRegistrarMaxDelayMilliseconds != nil {
- hash.Write([]byte("ConjureDecoyRegistrarMaxDelayMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.ConjureDecoyRegistrarMaxDelayMilliseconds))
- }
- if config.ConjureLimitTransports != nil {
- hash.Write([]byte("ConjureLimitTransports"))
- for _, transport := range config.ConjureLimitTransports {
- hash.Write([]byte(transport))
- }
- }
- if config.ConjureSTUNServerAddresses != nil {
- hash.Write([]byte("ConjureSTUNServerAddresses"))
- for _, address := range config.ConjureSTUNServerAddresses {
- hash.Write([]byte(address))
- }
- }
- if config.HoldOffTunnelProtocolMinDurationMilliseconds != nil {
- hash.Write([]byte("HoldOffTunnelProtocolMinDurationMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffTunnelProtocolMinDurationMilliseconds))
- }
- if config.HoldOffTunnelProtocolMaxDurationMilliseconds != nil {
- hash.Write([]byte("HoldOffTunnelProtocolMaxDurationMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffTunnelProtocolMaxDurationMilliseconds))
- }
- if len(config.HoldOffTunnelProtocolNames) > 0 {
- hash.Write([]byte("HoldOffTunnelProtocolNames"))
- for _, protocol := range config.HoldOffTunnelProtocolNames {
- hash.Write([]byte(protocol))
- }
- }
- if config.HoldOffTunnelProtocolProbability != nil {
- hash.Write([]byte("HoldOffTunnelProtocolProbability"))
- binary.Write(hash, binary.LittleEndian, *config.HoldOffTunnelProtocolProbability)
- }
- if config.HoldOffFrontingTunnelMinDurationMilliseconds != nil {
- hash.Write([]byte("HoldOffFrontingTunnelMinDurationMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffFrontingTunnelMinDurationMilliseconds))
- }
- if config.HoldOffFrontingTunnelMaxDurationMilliseconds != nil {
- hash.Write([]byte("HoldOffFrontingTunnelMaxDurationMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffFrontingTunnelMaxDurationMilliseconds))
- }
- if len(config.HoldOffFrontingTunnelProviderIDs) > 0 {
- hash.Write([]byte("HoldOffFrontingTunnelProviderIDs"))
- for _, providerID := range config.HoldOffFrontingTunnelProviderIDs {
- hash.Write([]byte(providerID))
- }
- }
- if config.HoldOffFrontingTunnelProbability != nil {
- hash.Write([]byte("HoldOffFrontingTunnelProbability"))
- binary.Write(hash, binary.LittleEndian, *config.HoldOffFrontingTunnelProbability)
- }
- if config.HoldOffDirectTunnelProbability != nil {
- hash.Write([]byte("HoldOffDirectTunnelProbability"))
- binary.Write(hash, binary.LittleEndian, *config.HoldOffDirectTunnelProbability)
- }
- if config.HoldOffDirectTunnelMinDurationMilliseconds != nil {
- hash.Write([]byte("HoldOffDirectTunnelMinDurationMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffDirectTunnelMinDurationMilliseconds))
- }
- if config.HoldOffDirectTunnelMaxDurationMilliseconds != nil {
- hash.Write([]byte("HoldOffDirectTunnelMaxDurationMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffDirectTunnelMaxDurationMilliseconds))
- }
- if len(config.HoldOffDirectTunnelProviderRegions) > 0 {
- hash.Write([]byte("HoldOffDirectTunnelProviderRegions"))
- for providerID, regions := range config.HoldOffDirectTunnelProviderRegions {
- hash.Write([]byte(providerID))
- for _, region := range regions {
- hash.Write([]byte(region))
- }
- }
- }
- if len(config.RestrictDirectProviderRegions) > 0 {
- hash.Write([]byte("RestrictDirectProviderRegions"))
- for providerID, regions := range config.RestrictDirectProviderRegions {
- hash.Write([]byte(providerID))
- for _, region := range regions {
- hash.Write([]byte(region))
- }
- }
- }
- if config.RestrictDirectProviderIDsClientProbability != nil {
- hash.Write([]byte("RestrictDirectProviderIDsClientProbability"))
- binary.Write(hash, binary.LittleEndian, *config.RestrictDirectProviderIDsClientProbability)
- }
- if len(config.RestrictFrontingProviderIDs) > 0 {
- hash.Write([]byte("RestrictFrontingProviderIDs"))
- for _, providerID := range config.RestrictFrontingProviderIDs {
- hash.Write([]byte(providerID))
- }
- }
- if config.RestrictFrontingProviderIDsClientProbability != nil {
- hash.Write([]byte("RestrictFrontingProviderIDsClientProbability"))
- binary.Write(hash, binary.LittleEndian, *config.RestrictFrontingProviderIDsClientProbability)
- }
- if config.HoldOffInproxyTunnelProbability != nil {
- hash.Write([]byte("HoldOffInproxyTunnelProbability"))
- binary.Write(hash, binary.LittleEndian, *config.HoldOffInproxyTunnelProbability)
- }
- if config.HoldOffInproxyTunnelMinDurationMilliseconds != nil {
- hash.Write([]byte("HoldOffInproxyTunnelMinDurationMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffInproxyTunnelMinDurationMilliseconds))
- }
- if config.HoldOffInproxyTunnelMaxDurationMilliseconds != nil {
- hash.Write([]byte("HoldOffInproxyTunnelMaxDurationMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.HoldOffInproxyTunnelMaxDurationMilliseconds))
- }
- if len(config.HoldOffInproxyTunnelProviderRegions) > 0 {
- hash.Write([]byte("HoldOffInproxyTunnelProviderRegions"))
- for providerID, regions := range config.HoldOffInproxyTunnelProviderRegions {
- hash.Write([]byte(providerID))
- for _, region := range regions {
- hash.Write([]byte(region))
- }
- }
- }
- if len(config.RestrictInproxyProviderRegions) > 0 {
- hash.Write([]byte("RestrictInproxyProviderRegions"))
- for providerID, regions := range config.RestrictInproxyProviderRegions {
- hash.Write([]byte(providerID))
- for _, region := range regions {
- hash.Write([]byte(region))
- }
- }
- }
- if config.RestrictInproxyProviderIDsClientProbability != nil {
- hash.Write([]byte("RestrictInproxyProviderIDsClientProbability"))
- binary.Write(hash, binary.LittleEndian, *config.RestrictInproxyProviderIDsClientProbability)
- }
- if config.UpstreamProxyAllowAllServerEntrySources != nil {
- hash.Write([]byte("UpstreamProxyAllowAllServerEntrySources"))
- binary.Write(hash, binary.LittleEndian, *config.UpstreamProxyAllowAllServerEntrySources)
- }
- if len(config.LimitTunnelDialPortNumbers) > 0 {
- hash.Write([]byte("LimitTunnelDialPortNumbers"))
- encodedLimitTunnelDialPortNumbers, _ :=
- json.Marshal(config.LimitTunnelDialPortNumbers)
- hash.Write(encodedLimitTunnelDialPortNumbers)
- }
- if config.QUICDialEarlyProbability != nil {
- hash.Write([]byte("QUICDialEarlyProbability"))
- binary.Write(hash, binary.LittleEndian, *config.QUICDialEarlyProbability)
- }
- if config.QUICObfuscatedPSKProbability != nil {
- hash.Write([]byte("QUICObfuscatedPSKProbability"))
- binary.Write(hash, binary.LittleEndian, *config.QUICObfuscatedPSKProbability)
- }
- if config.QUICDisablePathMTUDiscoveryProbability != nil {
- hash.Write([]byte("QUICDisablePathMTUDiscoveryProbability"))
- binary.Write(hash, binary.LittleEndian, *config.QUICDisablePathMTUDiscoveryProbability)
- }
- if config.DNSResolverAttemptsPerServer != nil {
- hash.Write([]byte("DNSResolverAttemptsPerServer"))
- binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverAttemptsPerServer))
- }
- if config.DNSResolverRequestTimeoutMilliseconds != nil {
- hash.Write([]byte("DNSResolverRequestTimeoutMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverRequestTimeoutMilliseconds))
- }
- if config.DNSResolverAwaitTimeoutMilliseconds != nil {
- hash.Write([]byte("DNSResolverAwaitTimeoutMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverAwaitTimeoutMilliseconds))
- }
- if config.DNSResolverPreresolvedIPAddressCIDRs != nil {
- hash.Write([]byte("DNSResolverPreresolvedIPAddressCIDRs"))
- encodedDNSResolverPreresolvedIPAddressCIDRs, _ :=
- json.Marshal(config.DNSResolverPreresolvedIPAddressCIDRs)
- hash.Write(encodedDNSResolverPreresolvedIPAddressCIDRs)
- }
- if config.DNSResolverPreresolvedIPAddressProbability != nil {
- hash.Write([]byte("DNSResolverPreresolvedIPAddressProbability"))
- binary.Write(hash, binary.LittleEndian, *config.DNSResolverPreresolvedIPAddressProbability)
- }
- if config.DNSResolverAlternateServers != nil {
- hash.Write([]byte("DNSResolverAlternateServers"))
- for _, server := range config.DNSResolverAlternateServers {
- hash.Write([]byte(server))
- }
- }
- if config.DNSResolverPreferAlternateServerProbability != nil {
- hash.Write([]byte("DNSResolverPreferAlternateServerProbability"))
- binary.Write(hash, binary.LittleEndian, *config.DNSResolverPreferAlternateServerProbability)
- }
- if config.DNSResolverProtocolTransformSpecs != nil {
- hash.Write([]byte("DNSResolverProtocolTransformSpecs"))
- encodedDNSResolverProtocolTransformSpecs, _ :=
- json.Marshal(config.DNSResolverProtocolTransformSpecs)
- hash.Write(encodedDNSResolverProtocolTransformSpecs)
- }
- if config.DNSResolverProtocolTransformScopedSpecNames != nil {
- hash.Write([]byte("DNSResolverProtocolTransformScopedSpecNames"))
- encodedDNSResolverProtocolTransformScopedSpecNames, _ :=
- json.Marshal(config.DNSResolverProtocolTransformScopedSpecNames)
- hash.Write(encodedDNSResolverProtocolTransformScopedSpecNames)
- }
- if config.DNSResolverProtocolTransformProbability != nil {
- hash.Write([]byte("DNSResolverProtocolTransformProbability"))
- binary.Write(hash, binary.LittleEndian, *config.DNSResolverProtocolTransformProbability)
- }
- if config.DNSResolverQNameRandomizeCasingProbability != nil {
- hash.Write([]byte("DNSResolverQNameRandomizeCasingProbability"))
- binary.Write(hash, binary.LittleEndian, *config.DNSResolverQNameRandomizeCasingProbability)
- }
- if config.DNSResolverQNameMustMatchProbability != nil {
- hash.Write([]byte("DNSResolverQNameMustMatchProbability"))
- binary.Write(hash, binary.LittleEndian, *config.DNSResolverQNameMustMatchProbability)
- }
- if config.DNSResolverIncludeEDNS0Probability != nil {
- hash.Write([]byte("DNSResolverIncludeEDNS0Probability"))
- binary.Write(hash, binary.LittleEndian, *config.DNSResolverIncludeEDNS0Probability)
- }
- if config.DNSResolverCacheExtensionInitialTTLMilliseconds != nil {
- hash.Write([]byte("DNSResolverCacheExtensionInitialTTLMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverCacheExtensionInitialTTLMilliseconds))
- }
- if config.DNSResolverCacheExtensionVerifiedTTLMilliseconds != nil {
- hash.Write([]byte("DNSResolverCacheExtensionVerifiedTTLMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.DNSResolverCacheExtensionVerifiedTTLMilliseconds))
- }
- if config.DirectHTTPProtocolTransformSpecs != nil {
- hash.Write([]byte("DirectHTTPProtocolTransformSpecs"))
- encodedDirectHTTPProtocolTransformSpecs, _ :=
- json.Marshal(config.DirectHTTPProtocolTransformSpecs)
- hash.Write(encodedDirectHTTPProtocolTransformSpecs)
- }
- if config.DirectHTTPProtocolTransformScopedSpecNames != nil {
- hash.Write([]byte("DirectHTTPProtocolTransformScopedSpecNames"))
- encodedDirectHTTPProtocolTransformScopedSpecNames, _ :=
- json.Marshal(config.DirectHTTPProtocolTransformScopedSpecNames)
- hash.Write(encodedDirectHTTPProtocolTransformScopedSpecNames)
- }
- if config.DirectHTTPProtocolTransformProbability != nil {
- hash.Write([]byte("DirectHTTPProtocolTransformProbability"))
- binary.Write(hash, binary.LittleEndian, *config.DirectHTTPProtocolTransformProbability)
- }
- if config.FrontedHTTPProtocolTransformSpecs != nil {
- hash.Write([]byte("FrontedHTTPProtocolTransformSpecs"))
- encodedFrontedHTTPProtocolTransformSpecs, _ :=
- json.Marshal(config.FrontedHTTPProtocolTransformSpecs)
- hash.Write(encodedFrontedHTTPProtocolTransformSpecs)
- }
- if config.FrontedHTTPProtocolTransformScopedSpecNames != nil {
- hash.Write([]byte("FrontedHTTPProtocolTransformScopedSpecNames"))
- encodedFrontedHTTPProtocolTransformScopedSpecNames, _ :=
- json.Marshal(config.FrontedHTTPProtocolTransformScopedSpecNames)
- hash.Write(encodedFrontedHTTPProtocolTransformScopedSpecNames)
- }
- if config.FrontedHTTPProtocolTransformProbability != nil {
- hash.Write([]byte("FrontedHTTPProtocolTransformProbability"))
- binary.Write(hash, binary.LittleEndian, *config.FrontedHTTPProtocolTransformProbability)
- }
- if config.OSSHObfuscatorSeedTransformSpecs != nil {
- hash.Write([]byte("OSSHObfuscatorSeedTransformSpecs"))
- encodedOSSHObfuscatorSeedTransformSpecs, _ :=
- json.Marshal(config.OSSHObfuscatorSeedTransformSpecs)
- hash.Write(encodedOSSHObfuscatorSeedTransformSpecs)
- }
- if config.OSSHObfuscatorSeedTransformScopedSpecNames != nil {
- hash.Write([]byte("OSSHObfuscatorSeedTransformScopedSpecNames"))
- encodedOSSHObfuscatorSeedTransformScopedSpecNames, _ :=
- json.Marshal(config.OSSHObfuscatorSeedTransformScopedSpecNames)
- hash.Write(encodedOSSHObfuscatorSeedTransformScopedSpecNames)
- }
- if config.OSSHObfuscatorSeedTransformProbability != nil {
- hash.Write([]byte("OSSHObfuscatorSeedTransformProbability"))
- binary.Write(hash, binary.LittleEndian, *config.OSSHObfuscatorSeedTransformProbability)
- }
- if config.ObfuscatedQUICNonceTransformSpecs != nil {
- hash.Write([]byte("ObfuscatedQUICNonceTransformSpecs"))
- encodedObfuscatedQUICNonceTransformSpecs, _ :=
- json.Marshal(config.ObfuscatedQUICNonceTransformSpecs)
- hash.Write(encodedObfuscatedQUICNonceTransformSpecs)
- }
- if config.ObfuscatedQUICNonceTransformScopedSpecNames != nil {
- hash.Write([]byte("ObfuscatedQUICNonceTransformScopedSpecNames"))
- encodedObfuscatedQUICNonceTransformScopedSpecNames, _ :=
- json.Marshal(config.ObfuscatedQUICNonceTransformScopedSpecNames)
- hash.Write(encodedObfuscatedQUICNonceTransformScopedSpecNames)
- }
- if config.ObfuscatedQUICNonceTransformProbability != nil {
- hash.Write([]byte("ObfuscatedQUICNonceTransformProbability"))
- binary.Write(hash, binary.LittleEndian, *config.ObfuscatedQUICNonceTransformProbability)
- }
- if config.OSSHPrefixSpecs != nil {
- hash.Write([]byte("OSSHPrefixSpecs"))
- encodedOSSHPrefixSpecs, _ := json.Marshal(config.OSSHPrefixSpecs)
- hash.Write(encodedOSSHPrefixSpecs)
- }
- if config.OSSHPrefixScopedSpecNames != nil {
- hash.Write([]byte("OSSHPrefixScopedSpecNames"))
- encodedOSSHPrefixScopedSpecNames, _ := json.Marshal(config.OSSHPrefixScopedSpecNames)
- hash.Write(encodedOSSHPrefixScopedSpecNames)
- }
- if config.OSSHPrefixProbability != nil {
- hash.Write([]byte("OSSHPrefixProbability"))
- binary.Write(hash, binary.LittleEndian, *config.OSSHPrefixProbability)
- }
- if config.OSSHPrefixSplitMinDelayMilliseconds != nil {
- hash.Write([]byte("OSSHPrefixSplitMinDelayMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.OSSHPrefixSplitMinDelayMilliseconds))
- }
- if config.OSSHPrefixSplitMaxDelayMilliseconds != nil {
- hash.Write([]byte("OSSHPrefixSplitMaxDelayMilliseconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.OSSHPrefixSplitMaxDelayMilliseconds))
- }
- if config.OSSHPrefixEnableFragmentor != nil {
- hash.Write([]byte("OSSHPrefixEnableFragmentor"))
- binary.Write(hash, binary.LittleEndian, *config.OSSHPrefixEnableFragmentor)
- }
- if config.ShadowsocksPrefixSpecs != nil {
- hash.Write([]byte("ShadowsocksPrefixSpecs"))
- encodedShadowsocksPrefixSpecs, _ := json.Marshal(config.ShadowsocksPrefixSpecs)
- hash.Write(encodedShadowsocksPrefixSpecs)
- }
- if config.ShadowsocksPrefixScopedSpecNames != nil {
- hash.Write([]byte("ShadowsocksPrefixScopedSpecNames"))
- encodedShadowsocksPrefixScopedSpecNames, _ := json.Marshal(config.ShadowsocksPrefixScopedSpecNames)
- hash.Write(encodedShadowsocksPrefixScopedSpecNames)
- }
- if config.ShadowsocksPrefixProbability != nil {
- hash.Write([]byte("ShadowsocksPrefixProbability"))
- binary.Write(hash, binary.LittleEndian, *config.ShadowsocksPrefixProbability)
- }
- if config.TLSTunnelObfuscatedPSKProbability != nil {
- hash.Write([]byte("TLSTunnelObfuscatedPSKProbability"))
- binary.Write(hash, binary.LittleEndian, *config.TLSTunnelObfuscatedPSKProbability)
- }
- if config.TLSTunnelTrafficShapingProbability != nil {
- hash.Write([]byte("TLSTunnelTrafficShapingProbability"))
- binary.Write(hash, binary.LittleEndian, *config.TLSTunnelTrafficShapingProbability)
- }
- if config.TLSTunnelMinTLSPadding != nil {
- hash.Write([]byte("TLSTunnelMinTLSPadding"))
- binary.Write(hash, binary.LittleEndian, int64(*config.TLSTunnelMinTLSPadding))
- }
- if config.TLSTunnelMaxTLSPadding != nil {
- hash.Write([]byte("TLSTunnelMaxTLSPadding"))
- binary.Write(hash, binary.LittleEndian, int64(*config.TLSTunnelMaxTLSPadding))
- }
- if config.TLSFragmentClientHelloProbability != nil {
- hash.Write([]byte("TLSFragmentClientHelloProbability"))
- binary.Write(hash, binary.LittleEndian, *config.TLSFragmentClientHelloProbability)
- }
- if len(config.TLSFragmentClientHelloLimitProtocols) > 0 {
- hash.Write([]byte("TLSFragmentClientHelloLimitProtocols"))
- for _, protocol := range config.TLSFragmentClientHelloLimitProtocols {
- hash.Write([]byte(protocol))
- }
- }
- // Steering IPs are ephemeral and not replayed, so steering IP parameters
- // are excluded here.
- if config.InproxyTunnelProtocolSelectionProbability != nil {
- hash.Write([]byte("InproxyTunnelProtocolSelectionProbability"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyTunnelProtocolSelectionProbability)
- }
- if len(config.InproxyBrokerSpecs) > 0 {
- hash.Write([]byte("InproxyBrokerSpecs"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyBrokerSpecs)))
- }
- if len(config.InproxyPersonalPairingBrokerSpecs) > 0 {
- hash.Write([]byte("InproxyPersonalPairingBrokerSpecs"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyPersonalPairingBrokerSpecs)))
- }
- if len(config.InproxyProxyBrokerSpecs) > 0 {
- hash.Write([]byte("InproxyProxyBrokerSpecs"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxyBrokerSpecs)))
- }
- if len(config.InproxyProxyPersonalPairingBrokerSpecs) > 0 {
- hash.Write([]byte("InproxyProxyPersonalPairingBrokerSpecs"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxyPersonalPairingBrokerSpecs)))
- }
- if len(config.InproxyClientBrokerSpecs) > 0 {
- hash.Write([]byte("InproxyClientBrokerSpecs"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyClientBrokerSpecs)))
- }
- if len(config.InproxyClientPersonalPairingBrokerSpecs) > 0 {
- hash.Write([]byte("InproxyClientPersonalPairingBrokerSpecs"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyClientPersonalPairingBrokerSpecs)))
- }
- if config.InproxyReplayBrokerDialParametersTTLSeconds != nil {
- hash.Write([]byte("InproxyReplayBrokerDialParametersTTLSeconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.InproxyReplayBrokerDialParametersTTLSeconds))
- }
- if config.InproxyReplayBrokerUpdateFrequencySeconds != nil {
- hash.Write([]byte("InproxyReplayBrokerUpdateFrequencySeconds"))
- binary.Write(hash, binary.LittleEndian, int64(*config.InproxyReplayBrokerUpdateFrequencySeconds))
- }
- if config.InproxyReplayBrokerDialParametersProbability != nil {
- hash.Write([]byte("InproxyReplayBrokerDialParametersProbability"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyReplayBrokerDialParametersProbability)
- }
- if config.InproxyReplayBrokerRetainFailedProbability != nil {
- hash.Write([]byte("InproxyReplayBrokerRetainFailedProbability"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyReplayBrokerRetainFailedProbability)
- }
- if len(config.InproxyCommonCompartmentIDs) > 0 {
- hash.Write([]byte("InproxyCommonCompartmentIDs"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyCommonCompartmentIDs)))
- }
- if config.InproxyMaxCompartmentIDListLength != nil {
- hash.Write([]byte("InproxyMaxCompartmentIDListLength"))
- binary.Write(hash, binary.LittleEndian, int64(*config.InproxyMaxCompartmentIDListLength))
- }
- if config.InproxyDTLSRandomizationProbability != nil {
- hash.Write([]byte("InproxyDTLSRandomizationProbability"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyDTLSRandomizationProbability)
- }
- if config.InproxyWebRTCMediaStreamsProbability != nil {
- hash.Write([]byte("InproxyWebRTCMediaStreamsProbability"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyWebRTCMediaStreamsProbability)
- }
- if config.InproxyWebRTCDataChannelTrafficShapingProbability != nil {
- hash.Write([]byte("InproxyWebRTCDataChannelTrafficShapingProbability"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyWebRTCDataChannelTrafficShapingProbability)
- }
- if config.InproxyWebRTCDataChannelTrafficShapingParameters != nil {
- hash.Write([]byte("InproxyWebRTCDataChannelTrafficShapingParameters"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyWebRTCDataChannelTrafficShapingParameters)))
- }
- if config.InproxyWebRTCMediaStreamsTrafficShapingProbability != nil {
- hash.Write([]byte("InproxyWebRTCMediaStreamsTrafficShapingProbability"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyWebRTCMediaStreamsTrafficShapingProbability)
- }
- if config.InproxyWebRTCMediaStreamsTrafficShapingParameters != nil {
- hash.Write([]byte("InproxyWebRTCMediaStreamsTrafficShapingParameters"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyWebRTCMediaStreamsTrafficShapingParameters)))
- }
- if config.InproxySTUNServerAddresses != nil {
- hash.Write([]byte("InproxySTUNServerAddresses"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxySTUNServerAddresses)))
- }
- if config.InproxySTUNServerAddressesRFC5780 != nil {
- hash.Write([]byte("InproxySTUNServerAddressesRFC5780"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxySTUNServerAddressesRFC5780)))
- }
- if config.InproxyProxySTUNServerAddresses != nil {
- hash.Write([]byte("InproxyProxySTUNServerAddresses"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxySTUNServerAddresses)))
- }
- if config.InproxyProxySTUNServerAddressesRFC5780 != nil {
- hash.Write([]byte("InproxyProxySTUNServerAddressesRFC5780"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyProxySTUNServerAddressesRFC5780)))
- }
- if config.InproxyClientSTUNServerAddresses != nil {
- hash.Write([]byte("InproxyClientSTUNServerAddresses"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyClientSTUNServerAddresses)))
- }
- if config.InproxyClientSTUNServerAddressesRFC5780 != nil {
- hash.Write([]byte("InproxyClientSTUNServerAddressesRFC5780"))
- hash.Write([]byte(fmt.Sprintf("%+v", config.InproxyClientSTUNServerAddressesRFC5780)))
- }
- if config.InproxyClientDiscoverNATProbability != nil {
- hash.Write([]byte("InproxyClientDiscoverNATProbability"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyClientDiscoverNATProbability)
- }
- if config.InproxyDisableSTUN != nil {
- hash.Write([]byte("InproxyDisableSTUN"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyDisableSTUN)
- }
- if config.InproxyDisablePortMapping != nil {
- hash.Write([]byte("InproxyDisablePortMapping"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyDisablePortMapping)
- }
- if config.InproxyDisableInboundForMobileNetworks != nil {
- hash.Write([]byte("InproxyDisableInboundForMobileNetworks"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyDisableInboundForMobileNetworks)
- }
- if config.InproxyDisableIPv6ICECandidates != nil {
- hash.Write([]byte("InproxyDisableIPv6ICECandidates"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyDisableIPv6ICECandidates)
- }
- if config.InproxyProxyDisableSTUN != nil {
- hash.Write([]byte("InproxyProxyDisableSTUN"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyProxyDisableSTUN)
- }
- if config.InproxyProxyDisablePortMapping != nil {
- hash.Write([]byte("InproxyProxyDisablePortMapping"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyProxyDisablePortMapping)
- }
- if config.InproxyProxyDisableInboundForMobileNetworks != nil {
- hash.Write([]byte("InproxyProxyDisableInboundForMobileNetworks"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyProxyDisableInboundForMobileNetworks)
- }
- if config.InproxyProxyDisableIPv6ICECandidates != nil {
- hash.Write([]byte("InproxyProxyDisableIPv6ICECandidates"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyProxyDisableIPv6ICECandidates)
- }
- if config.InproxyClientDisableSTUN != nil {
- hash.Write([]byte("InproxyClientDisableSTUN"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyClientDisableSTUN)
- }
- if config.InproxyClientDisablePortMapping != nil {
- hash.Write([]byte("InproxyClientDisablePortMapping"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyClientDisablePortMapping)
- }
- if config.InproxyClientDisableInboundForMobileNetworks != nil {
- hash.Write([]byte("InproxyClientDisableInboundForMobileNetworks"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyClientDisableInboundForMobileNetworks)
- }
- if config.InproxyClientDisableIPv6ICECandidates != nil {
- hash.Write([]byte("InproxyClientDisableIPv6ICECandidates"))
- binary.Write(hash, binary.LittleEndian, *config.InproxyClientDisableIPv6ICECandidates)
- }
- config.dialParametersHash = hash.Sum(nil)
- }
- // applyAdditionalParameters decodes and applies any additional parameters
- // stored in config.AdditionalParameter to the Config and returns an array
- // of notices which should be logged at the info level. If there is no error,
- // then config.AdditionalParameter is set to "" to conserve memory and further
- // calls will do nothing. This function should only be called once.
- //
- // If there is an error, the existing Config is left entirely unmodified.
- func (config *Config) applyAdditionalParameters() ([]string, error) {
- if config.AdditionalParameters == "" {
- return nil, nil
- }
- b, err := base64.StdEncoding.DecodeString(config.AdditionalParameters)
- if err != nil {
- return nil, errors.Trace(err)
- }
- if len(b) < 32 {
- return nil, errors.Tracef("invalid length, len(b) == %d", len(b))
- }
- var key [32]byte
- copy(key[:], b[:32])
- decrypted, ok := secretbox.Open(nil, b[32:], &[24]byte{}, &key)
- if !ok {
- return nil, errors.TraceNew("secretbox.Open failed")
- }
- var additionalParameters Config
- err = json.Unmarshal(decrypted, &additionalParameters)
- if err != nil {
- return nil, errors.Trace(err)
- }
- src := reflect.ValueOf(&additionalParameters).Elem()
- dest := reflect.ValueOf(config).Elem()
- var infoNotices []string
- for i := 0; i < src.NumField(); i++ {
- if !src.Field(i).IsZero() {
- dest.Field(i).Set(src.Field(i))
- infoNotice := fmt.Sprintf("%s overridden by AdditionalParameters", dest.Type().Field(i).Name)
- infoNotices = append(infoNotices, infoNotice)
- }
- }
- // Reset field to conserve memory since this is a one-time operation.
- config.AdditionalParameters = ""
- return infoNotices, nil
- }
- func promoteLegacyTransferURL(URL string) parameters.TransferURLs {
- transferURLs := make(parameters.TransferURLs, 1)
- transferURLs[0] = ¶meters.TransferURL{
- URL: base64.StdEncoding.EncodeToString([]byte(URL)),
- SkipVerify: false,
- OnlyAfterAttempts: 0,
- }
- return transferURLs
- }
- type loggingDeviceBinder struct {
- d DeviceBinder
- }
- func newLoggingDeviceBinder(d DeviceBinder) *loggingDeviceBinder {
- return &loggingDeviceBinder{d: d}
- }
- func (d *loggingDeviceBinder) BindToDevice(fileDescriptor int) (string, error) {
- deviceInfo, err := d.d.BindToDevice(fileDescriptor)
- if err == nil && deviceInfo != "" {
- NoticeBindToDevice(deviceInfo)
- }
- return deviceInfo, err
- }
- const unknownNetworkID = "UNKNOWN"
- type staticNetworkIDGetter struct {
- networkID string
- }
- func newStaticNetworkIDGetter(networkID string) *staticNetworkIDGetter {
- return &staticNetworkIDGetter{networkID: networkID}
- }
- func (n *staticNetworkIDGetter) GetNetworkID() string {
- return n.networkID
- }
- type commonNetworkIDGetter struct {
- }
- func newCommonNetworkIDGetter() *commonNetworkIDGetter {
- return &commonNetworkIDGetter{}
- }
- func (n *commonNetworkIDGetter) GetNetworkID() string {
- networkID, err := networkid.Get()
- if err != nil {
- NoticeError("networkid.Get failed: %v", errors.Trace(err))
- return unknownNetworkID
- }
- return networkID
- }
- type loggingNetworkIDGetter struct {
- n NetworkIDGetter
- }
- func newLoggingNetworkIDGetter(n NetworkIDGetter) *loggingNetworkIDGetter {
- return &loggingNetworkIDGetter{n: n}
- }
- func (n *loggingNetworkIDGetter) GetNetworkID() string {
- networkID := n.n.GetNetworkID()
- // All PII must appear after the initial "-"
- // See: https://godoc.org/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon#NetworkIDGetter
- logNetworkID := networkID
- index := strings.Index(logNetworkID, "-")
- if index != -1 {
- logNetworkID = logNetworkID[:index]
- }
- if len(logNetworkID)+1 < len(networkID) {
- // Indicate when additional network info was present after the first "-".
- logNetworkID += "+[redacted]"
- }
- NoticeNetworkID(logNetworkID)
- return networkID
- }
- // cachingNetworkIDGetter caches the GetNetworkID result from the underlying
- // network ID getter. The current GetNetworkID implementations take in the
- // range of 1-7ms (Android); 2-3ms (iOS); ~3.5ms (Windows) to execute, on
- // modern devices. To minimize delaying dials and other operations that start
- // with fetching the current network ID, the return values are cached for a
- // short time. On platforms that invoke NetworkChanged, the cache is flushed
- // immediately upon a network change.
- type cachingNetworkIDGetter struct {
- config *Config
- n NetworkIDGetter
- mutex sync.Mutex
- cachedNetworkID string
- cacheExpiry time.Time
- }
- func newCachingNetworkIDGetter(
- config *Config, n NetworkIDGetter) *cachingNetworkIDGetter {
- return &cachingNetworkIDGetter{
- config: config,
- n: n,
- }
- }
- func (n *cachingNetworkIDGetter) GetNetworkID() string {
- n.mutex.Lock()
- defer n.mutex.Unlock()
- if n.cachedNetworkID != "" && n.cacheExpiry.After(time.Now()) {
- return n.cachedNetworkID
- }
- networkID := n.n.GetNetworkID()
- p := n.config.GetParameters().Get()
- ttl := p.Duration(parameters.NetworkIDCacheTTL)
- if ttl > 0 {
- n.cachedNetworkID = networkID
- n.cacheExpiry = time.Now().Add(ttl)
- }
- return networkID
- }
- func (n *cachingNetworkIDGetter) FlushCache() {
- n.mutex.Lock()
- defer n.mutex.Unlock()
- n.cachedNetworkID = ""
- n.cacheExpiry = time.Time{}
- }
- // migrationsFromLegacyNoticeFilePaths returns the file migrations which must be
- // performed to move notice files from legacy file paths, which were configured
- // with the legacy config fields HomepageNoticesFilename and
- // RotatingNoticesFilename, to the new file paths used by Psiphon which exist
- // under the data root directory.
- func migrationsFromLegacyNoticeFilePaths(config *Config) []FileMigration {
- var noticeMigrations []FileMigration
- if config.MigrateHomepageNoticesFilename != "" {
- noticeMigrations = append(noticeMigrations, FileMigration{
- Name: "hompage",
- OldPath: config.MigrateHomepageNoticesFilename,
- NewPath: config.GetHomePageFilename(),
- })
- }
- if config.MigrateRotatingNoticesFilename != "" {
- migrations := []FileMigration{
- {
- Name: "notices",
- OldPath: config.MigrateRotatingNoticesFilename,
- NewPath: config.GetNoticesFilename(),
- IsDir: false,
- },
- {
- Name: "notices.1",
- OldPath: config.MigrateRotatingNoticesFilename + ".1",
- NewPath: config.GetNoticesFilename() + ".1",
- },
- }
- noticeMigrations = append(noticeMigrations, migrations...)
- }
- return noticeMigrations
- }
- // migrationsFromLegacyFilePaths returns the file migrations which must be
- // performed to move files from legacy file paths, which were configured with
- // legacy config fields, to the new file paths used by Psiphon which exist
- // under the data root directory.
- // Note: an attempt is made to redact any file paths from the returned error.
- func migrationsFromLegacyFilePaths(config *Config) ([]FileMigration, error) {
- migrations := []FileMigration{
- {
- Name: "psiphon.boltdb",
- OldPath: filepath.Join(config.MigrateDataStoreDirectory, "psiphon.boltdb"),
- NewPath: filepath.Join(config.GetDataStoreDirectory(), "psiphon.boltdb"),
- },
- {
- Name: "psiphon.boltdb.lock",
- OldPath: filepath.Join(config.MigrateDataStoreDirectory, "psiphon.boltdb.lock"),
- NewPath: filepath.Join(config.GetDataStoreDirectory(), "psiphon.boltdb.lock"),
- },
- }
- if config.MigrateRemoteServerListDownloadFilename != "" {
- // Migrate remote server list files
- rslMigrations := []FileMigration{
- {
- Name: "remote_server_list",
- OldPath: config.MigrateRemoteServerListDownloadFilename,
- NewPath: config.GetRemoteServerListDownloadFilename(),
- },
- {
- Name: "remote_server_list.part",
- OldPath: config.MigrateRemoteServerListDownloadFilename + ".part",
- NewPath: config.GetRemoteServerListDownloadFilename() + ".part",
- },
- {
- Name: "remote_server_list.part.etag",
- OldPath: config.MigrateRemoteServerListDownloadFilename + ".part.etag",
- NewPath: config.GetRemoteServerListDownloadFilename() + ".part.etag",
- },
- }
- migrations = append(migrations, rslMigrations...)
- }
- if config.MigrateObfuscatedServerListDownloadDirectory != "" {
- // Migrate OSL registry file and downloads
- oslFileRegex, err := regexp.Compile(`^osl-.+$`)
- if err != nil {
- return nil, errors.TraceMsg(err, "failed to compile regex for osl files")
- }
- files, err := ioutil.ReadDir(config.MigrateObfuscatedServerListDownloadDirectory)
- if err != nil {
- NoticeWarning(
- "Migration: failed to read OSL download directory with error %s",
- common.RedactFilePathsError(err, config.MigrateObfuscatedServerListDownloadDirectory))
- } else {
- for _, file := range files {
- if oslFileRegex.MatchString(file.Name()) {
- fileMigration := FileMigration{
- Name: "osl",
- OldPath: filepath.Join(config.MigrateObfuscatedServerListDownloadDirectory, file.Name()),
- NewPath: filepath.Join(config.GetObfuscatedServerListDownloadDirectory(), file.Name()),
- }
- migrations = append(migrations, fileMigration)
- }
- }
- }
- }
- if config.MigrateUpgradeDownloadFilename != "" {
- // Migrate downloaded upgrade files
- oldUpgradeDownloadFilename := filepath.Base(config.MigrateUpgradeDownloadFilename)
- // Create regex for:
- // <old_upgrade_download_filename>
- // <old_upgrade_download_filename>.<client_version_number>
- // <old_upgrade_download_filename>.<client_version_number>.part
- // <old_upgrade_download_filename>.<client_version_number>.part.etag
- upgradeDownloadFileRegex, err := regexp.Compile(`^` + oldUpgradeDownloadFilename + `(\.\d+(\.part(\.etag)?)?)?$`)
- if err != nil {
- return nil, errors.TraceMsg(err, "failed to compile regex for upgrade files")
- }
- upgradeDownloadDir := filepath.Dir(config.MigrateUpgradeDownloadFilename)
- files, err := ioutil.ReadDir(upgradeDownloadDir)
- if err != nil {
- NoticeWarning(
- "Migration: failed to read upgrade download directory with error %s",
- common.RedactFilePathsError(err, upgradeDownloadDir))
- } else {
- for _, file := range files {
- if upgradeDownloadFileRegex.MatchString(file.Name()) {
- oldFileSuffix := strings.TrimPrefix(file.Name(), oldUpgradeDownloadFilename)
- fileMigration := FileMigration{
- Name: "upgrade",
- OldPath: filepath.Join(upgradeDownloadDir, file.Name()),
- NewPath: config.GetUpgradeDownloadFilename() + oldFileSuffix,
- }
- migrations = append(migrations, fileMigration)
- }
- }
- }
- }
- return migrations, nil
- }
|