webrtc.go 109 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432
  1. //go:build PSIPHON_ENABLE_INPROXY
  2. /*
  3. * Copyright (c) 2023, Psiphon Inc.
  4. * All rights reserved.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. package inproxy
  21. import (
  22. "bytes"
  23. "context"
  24. "encoding/binary"
  25. std_errors "errors"
  26. "fmt"
  27. "io"
  28. "math"
  29. "net"
  30. "strconv"
  31. "strings"
  32. "sync"
  33. "sync/atomic"
  34. "time"
  35. tls "github.com/Psiphon-Labs/psiphon-tls"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  37. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  38. inproxy_dtls "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy/dtls"
  39. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  40. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic"
  41. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/stacktrace"
  42. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values"
  43. quic_go "github.com/Psiphon-Labs/quic-go"
  44. "github.com/pion/datachannel"
  45. "github.com/pion/dtls/v2"
  46. "github.com/pion/ice/v2"
  47. "github.com/pion/interceptor"
  48. pion_logging "github.com/pion/logging"
  49. "github.com/pion/rtp"
  50. "github.com/pion/sdp/v3"
  51. "github.com/pion/stun"
  52. "github.com/pion/transport/v2"
  53. "github.com/pion/webrtc/v3"
  54. "github.com/wlynxg/anet"
  55. )
  56. const (
  57. portMappingAwaitTimeout = 2 * time.Second
  58. readyToProxyAwaitTimeout = 20 * time.Second
  59. dataChannelBufferedAmountLowThreshold uint64 = 512 * 1024
  60. dataChannelMaxBufferedAmount uint64 = 1024 * 1024
  61. dataChannelMaxMessageSize = 65536
  62. dataChannelMaxLabelLength = 256
  63. mediaTrackMaxUDPPayloadLength = 1200
  64. mediaTrackRTPPacketOverhead = 12 + 16 + 1 // RTP header, SRTP encryption, and Psiphon padding header
  65. mediaTrackMaxRTPPayloadLength = mediaTrackMaxUDPPayloadLength - mediaTrackRTPPacketOverhead
  66. mediaTrackMaxIDLength = 256
  67. // Psiphon uses a fork of github.com/pion/dtls/v2, selected with go mod
  68. // replace, which has an idential API apart from dtls.IsPsiphon. If
  69. // dtls.IsPsiphon is undefined, the build is not using the fork.
  70. //
  71. // Limitation: this doesn't check that the vendored code is exactly the
  72. // same code as the fork.
  73. assertDTLSFork = dtls.IsPsiphon
  74. // Similarly, check for the fork of github.com/pion/ice/v2.
  75. assertICEFork = ice.IsPsiphon
  76. // Note that Psiphon also uses a fork of github.com/pion/webrtc/v3, but it
  77. // has an API change which will cause builds to fail when not present.
  78. )
  79. // webRTCConn is a WebRTC connection between two peers, with a data channel
  80. // used to relay streams or packets between them. WebRTCConn implements the
  81. // net.Conn interface.
  82. type webRTCConn struct {
  83. config *webRTCConfig
  84. isOffer bool
  85. mutex sync.Mutex
  86. udpConn net.PacketConn
  87. portMapper *portMapper
  88. isClosed bool
  89. closedSignal chan struct{}
  90. readyToProxySignal chan struct{}
  91. readyToProxyOnce sync.Once
  92. peerConnection *webrtc.PeerConnection
  93. dataChannel *webrtc.DataChannel
  94. dataChannelConn datachannel.ReadWriteCloser
  95. dataChannelWriteBufferSignal chan struct{}
  96. sendMediaTrack *webrtc.TrackLocalStaticRTP
  97. sendMediaTrackRTP *webrtc.RTPTransceiver
  98. receiveMediaTrack *webrtc.TrackRemote
  99. receiveMediaTrackOpenedSignal chan struct{}
  100. mediaTrackReliabilityLayer *reliableConn
  101. iceCandidatePairMetrics common.LogFields
  102. readMutex sync.Mutex
  103. readBuffer []byte
  104. readOffset int
  105. readLength int
  106. readError error
  107. peerPaddingDone bool
  108. receiveMediaTrackPacket *rtp.Packet
  109. writeMutex sync.Mutex
  110. trafficShapingPRNG *prng.PRNG
  111. trafficShapingBuffer *bytes.Buffer
  112. paddedMessageCount int
  113. decoyMessageCount int
  114. trafficShapingDone bool
  115. sendMediaTrackPacket *rtp.Packet
  116. sendMediaTrackSequencer rtp.Sequencer
  117. sendMediaTrackTimestampTick int
  118. sendMediaTrackFrameSizeRange [2]int
  119. sendMediaTrackRemainingFrameSize int
  120. decoyDone atomic.Bool
  121. paddedMessagesSent int32
  122. paddedMessagesReceived int32
  123. decoyMessagesSent int32
  124. decoyMessagesReceived int32
  125. }
  126. // webRTCConfig specifies the configuration for a WebRTC dial.
  127. type webRTCConfig struct {
  128. // Logger is used to log events.
  129. Logger common.Logger
  130. // EnableDebugLogging indicates whether to log pion/webrtc debug and trace
  131. // events. When enabled, these events will be logged to the specified
  132. // Logger at a Debug log level.
  133. EnableDebugLogging bool
  134. // WebRTCDialCoordinator specifies specific WebRTC dial strategies and
  135. // settings; WebRTCDialCoordinator also facilities dial replay by
  136. // receiving callbacks when individual dial steps succeed or fail.
  137. WebRTCDialCoordinator WebRTCDialCoordinator
  138. // ClientRootObfuscationSecret is generated (or replayed) by the client
  139. // and sent to the proxy and used to drive obfuscation operations.
  140. ClientRootObfuscationSecret ObfuscationSecret
  141. // DoDTLSRandomization indicates whether to perform DTLS randomization.
  142. DoDTLSRandomization bool
  143. // UseMediaStreams indicates whether to use WebRTC media streams to tunnel
  144. // traffic. When false, a WebRTC data channel is used to tunnel traffic.
  145. UseMediaStreams bool
  146. // TrafficShapingParameters indicates whether and how to perform data
  147. // channel or media track traffic shaping.
  148. TrafficShapingParameters *TrafficShapingParameters
  149. // ReliableTransport indicates whether to configure the WebRTC data
  150. // channel to use reliable transport. Set ReliableTransport when proxying
  151. // a TCP stream, and unset it when proxying a UDP packets flow with its
  152. // own reliability later, such as QUIC.
  153. ReliableTransport bool
  154. }
  155. // newWebRTCConnWithOffer initiates a new WebRTC connection. An offer SDP is
  156. // returned, to be sent to the peer. After the offer SDP is forwarded and an
  157. // answer SDP received in response, call SetRemoteSDP with the answer SDP and
  158. // then call AwaitInitialDataChannel to await the eventual WebRTC connection
  159. // establishment.
  160. func newWebRTCConnForOffer(
  161. ctx context.Context,
  162. config *webRTCConfig,
  163. hasPersonalCompartmentIDs bool) (
  164. *webRTCConn, WebRTCSessionDescription, *webRTCSDPMetrics, error) {
  165. conn, SDP, metrics, err := newWebRTCConn(
  166. ctx, config, nil, hasPersonalCompartmentIDs)
  167. if err != nil {
  168. return nil, WebRTCSessionDescription{}, nil, errors.Trace(err)
  169. }
  170. return conn, *SDP, metrics, nil
  171. }
  172. // newWebRTCConnWithAnswer creates a new WebRTC connection initiated by a peer
  173. // that provided an offer SDP. An answer SDP is returned to be sent to the
  174. // peer. After the answer SDP is forwarded, call AwaitInitialDataChannel to
  175. // await the eventual WebRTC connection establishment.
  176. func newWebRTCConnForAnswer(
  177. ctx context.Context,
  178. config *webRTCConfig,
  179. peerSDP WebRTCSessionDescription,
  180. hasPersonalCompartmentIDs bool) (
  181. *webRTCConn, WebRTCSessionDescription, *webRTCSDPMetrics, error) {
  182. conn, SDP, metrics, err := newWebRTCConn(
  183. ctx, config, &peerSDP, hasPersonalCompartmentIDs)
  184. if err != nil {
  185. return nil, WebRTCSessionDescription{}, nil, errors.Trace(err)
  186. }
  187. return conn, *SDP, metrics, nil
  188. }
  189. func newWebRTCConn(
  190. ctx context.Context,
  191. config *webRTCConfig,
  192. peerSDP *WebRTCSessionDescription,
  193. hasPersonalCompartmentIDs bool) (
  194. retconn *webRTCConn,
  195. retSDP *WebRTCSessionDescription,
  196. retMetrics *webRTCSDPMetrics,
  197. retErr error) {
  198. isOffer := peerSDP == nil
  199. udpConn, err := config.WebRTCDialCoordinator.UDPListen(ctx)
  200. if err != nil {
  201. return nil, nil, nil, errors.Trace(err)
  202. }
  203. // Initialize WebRTC
  204. // There is no explicit anti-probing measures for the proxy side of the
  205. // WebRTC connection, since each proxy "listener" is ephemeral, and since
  206. // the WebRTC data channel protocol authenticates peers with
  207. // certificates, so even if a probe were to find an ephemeral proxy
  208. // listener, the listener can respond the same as a normal WebRTC end
  209. // point would respond to a peer that doesn't have the correct credentials.
  210. //
  211. // pion's Mux API is used, as it enables providing a pre-created UDP
  212. // socket which is configured with necessary BindToDevice settings. We do
  213. // not actually multiplex multiple client connections on a single proxy
  214. // connection. As a proxy creates a new UDP socket and Mux for each
  215. // client, this currently open issue should not impact our
  216. // implementation: "Listener doesn't process parallel handshakes",
  217. // https://github.com/pion/dtls/issues/279.
  218. //
  219. // We detach data channels in order to use the standard Read/Write APIs.
  220. // As detaching avoids using the pion DataChannel read loop, this
  221. // currently open issue should not impact our
  222. // implementation: "DataChannel.readLoop goroutine leak",
  223. // https://github.com/pion/webrtc/issues/2098.
  224. // UDPMux Limitations:
  225. //
  226. // For Psiphon, WebRTCDialCoordinator.UDPListen will call
  227. // https://pkg.go.dev/net#ListenUDP with an unspecified IP address, in
  228. // order to listen on all available interfaces, both IPv4 and IPv6.
  229. // However, using webrtc.NewICEUDPMux and a UDP conn with an unspecified
  230. // IP address results in this log warning: "UDPMuxDefault should not
  231. // listening on unspecified address, use NewMultiUDPMuxFromPort instead".
  232. //
  233. // With NewICEUDPMux and an unspecified IP address, pion currently
  234. // enumerates local, active interfaces and derives a list of listening
  235. // addresses, combining each interface's IP addresses with the assigned
  236. // port:
  237. // https://github.com/pion/ice/blob/8c5b0991ef3bb070e47afda96faf090e8bf94be6/net.go#L35.
  238. // While this works ok in many cases, this PR,
  239. // https://github.com/pion/ice/pull/475, indicates the nature of the
  240. // issue with UDPMuxDefault:
  241. //
  242. // > When we have multiple host candidates and been mux to a single port,
  243. // > if these candidates share a same conn (either tcp or udp), they
  244. // > might read other's [messages causing failure].
  245. //
  246. // This PR, https://github.com/pion/ice/pull/473, also describes the issue:
  247. //
  248. // > When using UDPMux and UniversalUDPMux, it is possible that a
  249. // > registerConnForAddress() could be called twice or more for the same
  250. // > remote candidate (endpoint) by different candidates. E.g., when
  251. // > different HOST candidates ping the same remote candidate, the
  252. // > udpMuxedConn gets stored once. The second candidate will never
  253. // > receive a response. This is also the case when a single socket is
  254. // > used for gathering SRFLX and HOST candidates.
  255. //
  256. // PR 475 introduced MultiUDPMuxDefault to address the issue. However, at
  257. // this time, https://github.com/pion/ice/releases/tag/v2.3.6, there's an
  258. // open bug with MultiUDPMuxDefault
  259. // https://github.com/pion/ice/issues/507: "Multi UDP Mux can't works
  260. // when remote also enables Multi UDP Mux". Running the test program
  261. // attached to the bug confirms that no data channel is established;
  262. // while switching the test code to use NewICEUDPMux results in a
  263. // successful data channel connection. Since we need to use a Mux API on
  264. // both clients and proxies, we can't yet use MultiUDPMux.
  265. //
  266. // We patch pion/webrtc to add the SetICEUDPMuxSrflx functionality from
  267. // the currently unmerged https://github.com/pion/webrtc/pull/2298.
  268. // Without SetICEUDPMuxSrflx, STUN operations don't use the mux.
  269. //
  270. // We patch pion/ice gatherCandidatesSrflxUDPMux vendor patch to include
  271. // only the correct network type (IPv4 or IPv6) address candidates.
  272. // Without this patch, we observed up to 2x duplicate/redundant STUN
  273. // candidates.
  274. //
  275. // TODO: implement and try using transport.Net UDP dial functions in place
  276. // of NewICEUDPMux and pre-dialed UDP conn; track all dialed UDP
  277. // connections to close on WebRTCConn.Close; this approach would require
  278. // an alternative approach to injecting port mapping candidates, which
  279. // currently depends on the mux UDP socket being available outside of pion.
  280. // Another limitation and issue with NewICEUDPMux is that its enumeration
  281. // of all local interfaces and IPs includes many IPv6 addresses for
  282. // certain interfaces. For example, on macOS,
  283. // https://apple.stackexchange.com/a/371661, there are "secured" IPv6
  284. // addresses and many "temporary" IPv6 addresses, with all but one
  285. // temporary address being "deprecated". Instead of a full enumeration,
  286. // we should select only the non-deprecated temporary IPv6 address --
  287. // both for performance (avoid excess STUN requests) and privacy.
  288. //
  289. // Go has a proposal to expose the necessary IPv6 address information:
  290. // https://github.com/golang/go/issues/42694. However, as of Android SDK
  291. // 30, Go's net.InterfaceAddrs doesn't work at all:
  292. // https://github.com/pion/transport/issues/228,
  293. // https://github.com/golang/go/issues/40569.
  294. //
  295. // Note that it's not currently possible to
  296. // webrtc.SettingEngine.SetIPFilter to limit IPv6 selection to a single
  297. // candidate; that IP filter is not passed through to localInterfaces in
  298. // the NewUDPMuxDefault case. And even if it were, there's no guarantee
  299. // that the the first IPv6 address passed to the filter would be the
  300. // non-deprecated temporary address.
  301. //
  302. // To workaround net.Interface issues, we use SettingEngine.SetNet to plug
  303. // in an alternative implementation of net.Interface which selects only
  304. // one IPv4 and one IPv6 active interface and IP address and uses the
  305. // anet package for Android. See pionNetwork for more details.
  306. deadline, _ := ctx.Deadline()
  307. TTL := time.Until(deadline)
  308. pionLoggerFactory := newPionLoggerFactory(
  309. config.Logger,
  310. func() bool { return ctx.Err() != nil },
  311. config.EnableDebugLogging)
  312. pionNetwork := newPionNetwork(
  313. ctx, pionLoggerFactory.NewLogger("net"), config.WebRTCDialCoordinator)
  314. udpMux := webrtc.NewICEUniversalUDPMux(
  315. pionLoggerFactory.NewLogger("mux"), udpConn, TTL, pionNetwork)
  316. settingEngine := webrtc.SettingEngine{
  317. LoggerFactory: pionLoggerFactory,
  318. }
  319. settingEngine.SetNet(pionNetwork)
  320. settingEngine.DetachDataChannels()
  321. settingEngine.SetICEMulticastDNSMode(ice.MulticastDNSModeDisabled)
  322. settingEngine.SetICEUDPMux(udpMux)
  323. settingEngine.SetICEUDPMuxSrflx(udpMux)
  324. // Set this behavior to look like common web browser WebRTC stacks.
  325. settingEngine.SetDTLSInsecureSkipHelloVerify(true)
  326. settingEngine.EnableSCTPZeroChecksum(true)
  327. // Timeout, retry, and delay adjustments
  328. //
  329. // - Add some jitter to timed operations to avoid a trivial pion timing
  330. // fingerprint.
  331. //
  332. // - Reduce the wait time for STUN and peer reflexive candidates from the
  333. // default 500ms and 1s.
  334. //
  335. // - Reduce keepalives from the default 2s to +/-15s and increase
  336. // disconnect timeout from the default 5s to 3x15s.
  337. //
  338. // TODO:
  339. //
  340. // - Configuration via tactics.
  341. //
  342. // - While the RFC,
  343. // https://datatracker.ietf.org/doc/html/rfc5245#section-10, calls for
  344. // keep alives no less than 15s, implementations such as Chrome send
  345. // keep alives much more frequently,
  346. // https://issues.webrtc.org/issues/42221718.
  347. //
  348. // - Varying the period bewteen each keepalive, as is done with SSH via
  349. // SSHKeepAlivePeriodMin/Max, requires changes to pion/dtls.
  350. //
  351. // - Some traffic-related timeouts are not yet exposed via settingEngine,
  352. // including ice.defaultSTUNGatherTimeout, ice.maxBindingRequestTimeout.
  353. settingEngine.SetDTLSRetransmissionInterval(prng.JitterDuration(100*time.Millisecond, 0.1))
  354. settingEngine.SetHostAcceptanceMinWait(0)
  355. settingEngine.SetSrflxAcceptanceMinWait(prng.JitterDuration(100*time.Millisecond, 0.1))
  356. settingEngine.SetPrflxAcceptanceMinWait(prng.JitterDuration(200*time.Millisecond, 0.1))
  357. settingEngine.SetICETimeouts(45*time.Second, 0, prng.JitterDuration(15*time.Second, 0.2))
  358. settingEngine.SetICEMaxBindingRequests(10)
  359. // Initialize data channel or media streams obfuscation
  360. config.Logger.WithTraceFields(common.LogFields{
  361. "dtls_randomization": config.DoDTLSRandomization,
  362. "data_channel_traffic_shaping": config.TrafficShapingParameters != nil,
  363. "use_media_streams": config.UseMediaStreams,
  364. }).Info("webrtc_obfuscation")
  365. // Facilitate DTLS Client/ServerHello randomization. The client decides
  366. // whether to do DTLS randomization and generates and the proxy receives
  367. // ClientRootObfuscationSecret, so the client can orchestrate replay on
  368. // both ends of the connection by reusing an obfuscation secret. Derive a
  369. // secret specific to DTLS. SetDTLSSeed will futher derive a secure PRNG
  370. // seed specific to either the client or proxy end of the connection
  371. // (so each peer's randomization will be distinct).
  372. //
  373. // To avoid forking many pion repos in order to pass the seed through to
  374. // the DTLS implementation, SetDTLSSeed attaches the seed to the DTLS
  375. // dial context.
  376. //
  377. // Either SetDTLSSeed or SetNoDTLSSeed should be set for each conn, as the
  378. // pion/dtl fork treats no-seed as an error, as a check against the
  379. // context value mechanism.
  380. var dtlsCtx context.Context
  381. if config.DoDTLSRandomization {
  382. dtlsObfuscationSecret, err := deriveObfuscationSecret(
  383. config.ClientRootObfuscationSecret, "in-proxy-DTLS-seed")
  384. if err != nil {
  385. return nil, nil, nil, errors.Trace(err)
  386. }
  387. baseSeed := prng.Seed(dtlsObfuscationSecret)
  388. dtlsCtx, err = inproxy_dtls.SetDTLSSeed(ctx, &baseSeed, isOffer)
  389. if err != nil {
  390. return nil, nil, nil, errors.Trace(err)
  391. }
  392. } else {
  393. dtlsCtx = inproxy_dtls.SetNoDTLSSeed(ctx)
  394. }
  395. settingEngine.SetDTLSConnectContextMaker(func() (context.Context, func()) {
  396. return context.WithCancel(dtlsCtx)
  397. })
  398. // Configure traffic shaping, which adds random padding and decoy messages
  399. // to data channel message or media track packet flows.
  400. var trafficShapingPRNG *prng.PRNG
  401. trafficShapingBuffer := new(bytes.Buffer)
  402. paddedMessageCount := 0
  403. decoyMessageCount := 0
  404. if config.TrafficShapingParameters != nil {
  405. // TODO: also use pion/dtls.Config.PaddingLengthGenerator?
  406. trafficShapingContext := "in-proxy-traffic-shaping-offer"
  407. if !isOffer {
  408. trafficShapingContext = "in-proxy-traffic-shaping-answer"
  409. }
  410. trafficShapingObfuscationSecret, err := deriveObfuscationSecret(
  411. config.ClientRootObfuscationSecret, trafficShapingContext)
  412. if err != nil {
  413. return nil, nil, nil, errors.Trace(err)
  414. }
  415. seed := prng.Seed(trafficShapingObfuscationSecret)
  416. trafficShapingPRNG = prng.NewPRNGWithSeed(&seed)
  417. paddedMessageCount = trafficShapingPRNG.Range(
  418. config.TrafficShapingParameters.MinPaddedMessages,
  419. config.TrafficShapingParameters.MaxPaddedMessages)
  420. decoyMessageCount = trafficShapingPRNG.Range(
  421. config.TrafficShapingParameters.MinDecoyMessages,
  422. config.TrafficShapingParameters.MaxDecoyMessages)
  423. }
  424. // NAT traversal setup
  425. // When DisableInboundForMobileNetworks is set, skip both STUN and port
  426. // mapping for mobile networks. Most mobile networks use CGNAT and
  427. // neither STUN nor port mapping will be effective. It's faster to not
  428. // wait for something that ultimately won't work.
  429. disableInbound := config.WebRTCDialCoordinator.DisableInboundForMobileNetworks() &&
  430. config.WebRTCDialCoordinator.NetworkType() == NetworkTypeMobile
  431. // Try to establish a port mapping (UPnP-IGD, PCP, or NAT-PMP), using port
  432. // mapping services previously found and recorded in PortMappingProbe.
  433. // Note that portMapper may perform additional probes. portMapper.start
  434. // launches the process of creating a new port mapping and does not
  435. // block. Port mappings are not part of the WebRTC standard, or supported
  436. // by pion/webrtc. Instead, if a port mapping is established, it's edited
  437. // into the SDP as a new host-type ICE candidate.
  438. portMappingProbe := config.WebRTCDialCoordinator.PortMappingProbe()
  439. doPortMapping := !disableInbound &&
  440. !config.WebRTCDialCoordinator.DisablePortMapping() &&
  441. portMappingProbe != nil
  442. var portMapper *portMapper
  443. if doPortMapping {
  444. localPort := udpConn.LocalAddr().(*net.UDPAddr).Port
  445. portMapper, err = newPortMapper(config.Logger, portMappingProbe, localPort)
  446. if err != nil {
  447. config.Logger.WithTraceFields(common.LogFields{
  448. "error": err,
  449. }).Warning("newPortMapper failed")
  450. // Continue without port mapper
  451. } else {
  452. portMapper.start()
  453. // On early return, portMapper will be closed by the following
  454. // deferred conn.Close.
  455. }
  456. }
  457. // Select a STUN server for ICE hole punching. The STUN server to be used
  458. // needs only support bind and not full RFC5780 NAT discovery.
  459. //
  460. // Each dial trys only one STUN server; in Psiphon tunnel establishment,
  461. // other, concurrent in-proxy dials may select alternative STUN servers
  462. // via WebRTCDialCoordinator. When the STUN server operation is successful,
  463. // WebRTCDialCoordinator will be signaled so that it may configure the STUN
  464. // server selection for replay.
  465. //
  466. // The STUN server will observe proxy IP addresses. Enumeration is
  467. // mitigated by using various public STUN servers, including Psiphon STUN
  468. // servers for proxies in non-censored regions. Proxies are also more
  469. // ephemeral than Psiphon servers.
  470. RFC5780 := false
  471. stunServerAddress := config.WebRTCDialCoordinator.STUNServerAddress(RFC5780)
  472. // Proceed even when stunServerAddress is "" and !DisableSTUN, as ICE may
  473. // find other host candidates.
  474. doSTUN := stunServerAddress != "" && !disableInbound && !config.WebRTCDialCoordinator.DisableSTUN()
  475. var ICEServers []webrtc.ICEServer
  476. if doSTUN {
  477. // stunServerAddress domain names are resolved with the Psiphon custom
  478. // resolver via pionNetwork.ResolveUDPAddr
  479. ICEServers = []webrtc.ICEServer{{URLs: []string{"stun:" + stunServerAddress}}}
  480. }
  481. conn := &webRTCConn{
  482. config: config,
  483. isOffer: isOffer,
  484. udpConn: udpConn,
  485. portMapper: portMapper,
  486. closedSignal: make(chan struct{}),
  487. readyToProxySignal: make(chan struct{}),
  488. dataChannelWriteBufferSignal: make(chan struct{}, 1),
  489. // A data channel uses SCTP and is message oriented. The maximum
  490. // message size supported by pion/webrtc is 65536:
  491. // https://github.com/pion/webrtc/blob/dce970438344727af9c9965f88d958c55d32e64d/datachannel.go#L19.
  492. // This read buffer must be as large as the maximum message size or
  493. // else a read may fail with io.ErrShortBuffer.
  494. //
  495. // For media streams, the largest media track RTP packet payload is
  496. // no more than mediaTrackMaxRTPPayloadLength.
  497. readBuffer: make([]byte, max(dataChannelMaxMessageSize, mediaTrackMaxRTPPayloadLength)),
  498. trafficShapingPRNG: trafficShapingPRNG,
  499. trafficShapingBuffer: trafficShapingBuffer,
  500. paddedMessageCount: paddedMessageCount,
  501. decoyMessageCount: decoyMessageCount,
  502. }
  503. defer func() {
  504. if retErr != nil {
  505. // Cleanup on early return
  506. conn.Close()
  507. // Notify the WebRTCDialCoordinator that the operation failed so
  508. // that it can clear replay for that STUN server selection.
  509. //
  510. // Limitation: the error here may be due to failures unrelated to
  511. // the STUN server.
  512. if ctx.Err() == nil && doSTUN {
  513. config.WebRTCDialCoordinator.STUNServerAddressFailed(RFC5780, stunServerAddress)
  514. }
  515. }
  516. }()
  517. settingEngine.SetICEBindingRequestHandler(conn.onICEBindingRequest)
  518. // All settingEngine configuration must be done before calling NewAPI.
  519. var webRTCAPI *webrtc.API
  520. if !config.UseMediaStreams {
  521. webRTCAPI = webrtc.NewAPI(webrtc.WithSettingEngine(settingEngine))
  522. } else {
  523. // Additional webRTCAPI setup for media streams support.
  524. mediaEngine := &webrtc.MediaEngine{}
  525. err := mediaEngine.RegisterDefaultCodecs()
  526. if err != nil {
  527. return nil, nil, nil, errors.Trace(err)
  528. }
  529. // pion/webrtc interceptors monitor RTP and send additional traffic
  530. // including NACKs and RTCP. Enable interceptors for the potential
  531. // obfuscation benefit from exhibiting this additional traffic.
  532. // webrtc.RegisterDefaultInterceptors calls ConfigureNack,
  533. // ConfigureRTCPReports, ConfigureTWCCSender. At this time we skip
  534. // ConfigureNack as this appears to generate excess "duplicated
  535. // packet" logs and connection instability. From a connection
  536. // reliability stand point, the underlying QUIC layer provides any
  537. // necessary resends.
  538. interceptors := &interceptor.Registry{}
  539. err = webrtc.ConfigureRTCPReports(interceptors)
  540. if err != nil {
  541. return nil, nil, nil, errors.Trace(err)
  542. }
  543. err = webrtc.ConfigureTWCCSender(mediaEngine, interceptors)
  544. if err != nil {
  545. return nil, nil, nil, errors.Trace(err)
  546. }
  547. webRTCAPI = webrtc.NewAPI(
  548. webrtc.WithSettingEngine(settingEngine),
  549. webrtc.WithMediaEngine(mediaEngine),
  550. webrtc.WithInterceptorRegistry(interceptors))
  551. }
  552. conn.peerConnection, err = webRTCAPI.NewPeerConnection(
  553. webrtc.Configuration{
  554. ICEServers: ICEServers,
  555. })
  556. if err != nil {
  557. return nil, nil, nil, errors.Trace(err)
  558. }
  559. conn.peerConnection.OnConnectionStateChange(conn.onConnectionStateChange)
  560. conn.peerConnection.OnICECandidate(conn.onICECandidate)
  561. conn.peerConnection.OnICEConnectionStateChange(conn.onICEConnectionStateChange)
  562. conn.peerConnection.OnICEGatheringStateChange(conn.onICEGatheringStateChange)
  563. conn.peerConnection.OnNegotiationNeeded(conn.onNegotiationNeeded)
  564. conn.peerConnection.OnSignalingStateChange(conn.onSignalingStateChange)
  565. conn.peerConnection.OnDataChannel(conn.onDataChannel)
  566. if !config.UseMediaStreams && isOffer {
  567. // Use a data channel to proxy traffic. The client offer sets the data
  568. // channel configuration.
  569. dataChannelInit := &webrtc.DataChannelInit{}
  570. if !config.ReliableTransport {
  571. ordered := false
  572. dataChannelInit.Ordered = &ordered
  573. maxRetransmits := uint16(0)
  574. dataChannelInit.MaxRetransmits = &maxRetransmits
  575. }
  576. // Generate a random length label, to vary the DATA_CHANNEL_OPEN
  577. // message length. This length/value is not replayed.
  578. dataChannelLabel := prng.HexString(prng.Range(1, dataChannelMaxLabelLength))
  579. dataChannel, err := conn.peerConnection.CreateDataChannel(
  580. dataChannelLabel, dataChannelInit)
  581. if err != nil {
  582. return nil, nil, nil, errors.Trace(err)
  583. }
  584. conn.setDataChannel(dataChannel)
  585. }
  586. if config.UseMediaStreams {
  587. // Use media streams to proxy traffic. Each peer configures one
  588. // unidirectional media stream track to send its proxied traffic. In
  589. // WebRTC, a media stream consists of a set of tracks. Configure and
  590. // use a single video track.
  591. //
  592. // This implementation is intended to circumvent the WebRTC data
  593. // channel blocking described in "Differential Degradation
  594. // Vulnerabilities in Censorship Circumvention Systems",
  595. // https://arxiv.org/html/2409.06247v1, section 5.2.
  596. // Select the media track attributes, which are observable, in
  597. // plaintext, in the RTP header. Attributes include the payload
  598. // type/codec and codec timestamp inputs. Attempt to mimic common
  599. // WebRTC media stream traffic by selecting common codecs and video
  600. // frame sizes and timestamp ticks. Each peer's track has its own
  601. // attributes, which is not unusual. This is a basic effort to avoid
  602. // trivial, stateless or minimal state DPI blocking, unlike more
  603. // advanced schemes which replace bytes in actual video streams. The
  604. // client drives attribute selection and replay by specifying
  605. // ClientRootObfuscationSecret.
  606. propertiesContext := "in-proxy-media-track-properties-offer"
  607. if !isOffer {
  608. propertiesContext = "in-proxy-media-track-properties-answer"
  609. }
  610. propertiesObfuscationSecret, err := deriveObfuscationSecret(
  611. config.ClientRootObfuscationSecret, propertiesContext)
  612. if err != nil {
  613. return nil, nil, nil, errors.Trace(err)
  614. }
  615. seed := prng.Seed(propertiesObfuscationSecret)
  616. propertiesPRNG := prng.NewPRNGWithSeed(&seed)
  617. // Omit webrtc.MimeTypeH265, which results in the error:
  618. // "SetRemoteSDP: unable to start track, codec is not supported by remote".
  619. mimeTypes := []string{webrtc.MimeTypeH264, webrtc.MimeTypeVP8, webrtc.MimeTypeVP9, webrtc.MimeTypeAV1}
  620. clockRate := 90000 // Standard 90kHz
  621. frameRates := []int{25, 30, 60} // Common frame rates
  622. // Select frame sizes from common video modes. Each frame size is
  623. // selected at random from the given range, and the codec timestamp
  624. // is advanced when the resulting "frame size" number of proxied
  625. // bytes is sent.
  626. //
  627. // - Low-resolution video (e.g., QCIF): 1–10 KB per frame.
  628. // - Standard-definition video (480p): 50–200 KB per frame.
  629. // - High-definition video (720p): 100–500 KB per frame.
  630. // - Full HD video (1080p): 300 KB – 1 MB per frame.
  631. // - 4K video: 1–4 MB per frame.
  632. KB := 1024
  633. MB := 1024 * 1024
  634. frameSizeRanges := [][2]int{
  635. {1 * KB, 10 * KB},
  636. {50 * KB, 200 * KB},
  637. {100 * KB, 500 * KB},
  638. {300 * KB, 1 * MB},
  639. {1 * MB, 4 * MB}}
  640. mimeType := mimeTypes[propertiesPRNG.Intn(len(mimeTypes))]
  641. frameRate := frameRates[propertiesPRNG.Intn(len(frameRates))]
  642. frameSizeRange := frameSizeRanges[propertiesPRNG.Intn(len(frameSizeRanges))]
  643. conn.sendMediaTrackTimestampTick = clockRate / frameRate
  644. conn.sendMediaTrackFrameSizeRange = frameSizeRange
  645. // Initialize the first frame size. The random frame sizes are not
  646. // replayed.
  647. conn.sendMediaTrackRemainingFrameSize = prng.Range(
  648. conn.sendMediaTrackFrameSizeRange[0], conn.sendMediaTrackFrameSizeRange[1])
  649. // Generate random IDs, to vary the resulting SDP entry size message
  650. // length. These lengths/values are not replayed.
  651. trackID := prng.HexString(prng.Range(1, mediaTrackMaxIDLength))
  652. trackStreamID := prng.HexString(prng.Range(1, mediaTrackMaxIDLength))
  653. // Initialize a reusable rtp.Packet struct to avoid an allocation per
  654. // write. In SRTP, the packet payload is encrypted while the RTP
  655. // header remains plaintext.
  656. //
  657. // Plaintext RTP header fields:
  658. //
  659. // - Version is always 2.
  660. //
  661. // - Timestamp is initialized here to a random value, as is common,
  662. // and incremented, after writes, for the next video "frame".
  663. // Limitation: in states of low tunnel traffic, the video frame and
  664. // timestamp progression won't look realistic.
  665. //
  666. // - PayloadType is the codec and is auto-populated by pion.
  667. //
  668. // - SequenceNumber is a packet sequence number and populated by
  669. // pion's rtp.NewRandomSequencer, which uses the same logic as
  670. // Chrome's WebRTC implementation.
  671. //
  672. // - SSRC a random stream identifier, distinct from the track/stream
  673. // ID, and is auto-populated by pion.
  674. conn.sendMediaTrackPacket = &rtp.Packet{
  675. Header: rtp.Header{
  676. Version: 2,
  677. Timestamp: uint32(prng.Int63n(int64(1) << 32)),
  678. }}
  679. conn.sendMediaTrackSequencer = rtp.NewRandomSequencer()
  680. // Add the outbound media track to the SDP that is sent to the peer.
  681. conn.sendMediaTrack, err = webrtc.NewTrackLocalStaticRTP(
  682. webrtc.RTPCodecCapability{
  683. MimeType: mimeType,
  684. ClockRate: uint32(clockRate),
  685. },
  686. trackID,
  687. trackStreamID)
  688. if err != nil {
  689. return nil, nil, nil, errors.Trace(err)
  690. }
  691. conn.sendMediaTrackRTP, err = conn.peerConnection.AddTransceiverFromTrack(
  692. conn.sendMediaTrack,
  693. webrtc.RTPTransceiverInit{Direction: webrtc.RTPTransceiverDirectionSendrecv})
  694. if err != nil {
  695. return nil, nil, nil, errors.Trace(err)
  696. }
  697. for _, rtpSender := range conn.peerConnection.GetSenders() {
  698. // Read incoming packets for this outbound RTP stream. Streams are
  699. // unidirectional for media payload, but there will be incoming
  700. // packets, from the peer, for RTCP, NACK, and other control
  701. // mechanisms. Interceptors are implicitly invoked and the
  702. // packets are then discarded.
  703. go func(rtpSender *webrtc.RTPSender) {
  704. var buffer [1500]byte
  705. for {
  706. _, _, err := conn.sendMediaTrackRTP.Sender().Read(buffer[:])
  707. if err != nil {
  708. // TODO: log error?
  709. select {
  710. case <-conn.closedSignal:
  711. return
  712. default:
  713. }
  714. }
  715. }
  716. }(rtpSender)
  717. }
  718. // Initialize the callback that is invoked once we receive an inbound
  719. // packet from the peer's media stream.
  720. //
  721. // Unlike data channels, where webrtc.DataChannel.OnOpen is symmetric
  722. // and invoked on both peers for a single, bidirectional channel,
  723. // webrtc.PeerConnection.OnTrack is unidirectional. And, unlike
  724. // DataChannel.OnOpen, if both peers await OnTrack before proxying,
  725. // the tunnel will hang. One side must start sending data in order
  726. // for OnTrack to be invoked on the other side.
  727. // See: https://github.com/pion/webrtc/issues/989#issuecomment-580424615.
  728. //
  729. // This has implications for AwaitReadyToProxy: in the media stream
  730. // mode, and when not using the media track reliability layer,
  731. // AwaitReadyToProxy returns when the DTLS handshake has completed,
  732. // but before any SRTP packets have been received from the peer.
  733. conn.receiveMediaTrackOpenedSignal = make(chan struct{})
  734. conn.receiveMediaTrackPacket = &rtp.Packet{}
  735. conn.peerConnection.OnTrack(conn.onMediaTrack)
  736. }
  737. // Prepare to await full ICE completion, including STUN candidates.
  738. // Trickle ICE is not used, simplifying the broker API. It's expected
  739. // that most clients and proxies will be behind a NAT, and not have
  740. // publicly addressable host candidates. TURN is not used. So most
  741. // candidates will be STUN, or server-reflexive, candidates.
  742. //
  743. // Later, the first to complete out of ICE or port mapping is used.
  744. //
  745. // TODO: stop waiting if an IPv6 host candidate is found?
  746. iceComplete := webrtc.GatheringCompletePromise(conn.peerConnection)
  747. // Create an offer, or input a peer's offer to create an answer.
  748. if isOffer {
  749. offer, err := conn.peerConnection.CreateOffer(nil)
  750. if err != nil {
  751. return nil, nil, nil, errors.Trace(err)
  752. }
  753. err = conn.peerConnection.SetLocalDescription(offer)
  754. if err != nil {
  755. return nil, nil, nil, errors.Trace(err)
  756. }
  757. } else {
  758. SDP := peerSDP.SDP
  759. if hasPersonalCompartmentIDs {
  760. // In personal pairing mode, the peer SDP may include private IP
  761. // addresses. To avoid unnecessary network traffic, filter out
  762. // any peer private IP addresses for which there is no
  763. // corresponding local, active interface.
  764. errorOnNoCandidates := false
  765. allowPrivateIPAddressCandidates := true
  766. filterPrivateIPAddressCandidates := true
  767. adjustedSDP, _, err := filterSDPAddresses(
  768. []byte(peerSDP.SDP),
  769. errorOnNoCandidates,
  770. nil,
  771. common.GeoIPData{},
  772. allowPrivateIPAddressCandidates,
  773. filterPrivateIPAddressCandidates)
  774. if err != nil {
  775. return nil, nil, nil, errors.Trace(err)
  776. }
  777. SDP = string(adjustedSDP)
  778. }
  779. pionSessionDescription := webrtc.SessionDescription{
  780. Type: webrtc.SDPType(peerSDP.Type),
  781. SDP: SDP,
  782. }
  783. err = conn.peerConnection.SetRemoteDescription(pionSessionDescription)
  784. if err != nil {
  785. return nil, nil, nil, errors.Trace(err)
  786. }
  787. answer, err := conn.peerConnection.CreateAnswer(nil)
  788. if err != nil {
  789. return nil, nil, nil, errors.Trace(err)
  790. }
  791. err = conn.peerConnection.SetLocalDescription(answer)
  792. if err != nil {
  793. return nil, nil, nil, errors.Trace(err)
  794. }
  795. }
  796. // Await either ICE or port mapping completion.
  797. // As a future enhancement, track which of ICE or port mapping succeeds
  798. // and is then followed by a failed WebRTC dial; stop trying the method
  799. // that often fails.
  800. iceCompleted := false
  801. portMappingExternalAddr := ""
  802. if portMapper == nil {
  803. select {
  804. case <-iceComplete:
  805. iceCompleted = true
  806. case <-ctx.Done():
  807. return nil, nil, nil, errors.Trace(ctx.Err())
  808. }
  809. } else {
  810. select {
  811. case <-iceComplete:
  812. iceCompleted = true
  813. case portMappingExternalAddr = <-portMapper.portMappingExternalAddress():
  814. case <-ctx.Done():
  815. return nil, nil, nil, errors.Trace(ctx.Err())
  816. }
  817. // When STUN is skipped and a port mapping is expected to be
  818. // available, await a port mapping for a short period. In this
  819. // scenario, pion ICE gathering may complete first, since it's only
  820. // gathering local host candidates.
  821. //
  822. // It remains possible that these local candidates are sufficient, if
  823. // they are public IPs or private IPs on the same LAN as the peer in
  824. // the case of personal pairing. For that reason, the await timeout
  825. // should be no more than a couple of seconds.
  826. //
  827. // TODO: also await port mappings when doSTUN, in case there are no
  828. // STUN candidates; see hasServerReflexive check below; as it stands,
  829. // in this case, it's more likely that port mapping won the previous
  830. // select race.
  831. if iceCompleted && portMappingExternalAddr == "" && !doSTUN && doPortMapping {
  832. timer := time.NewTimer(
  833. common.ValueOrDefault(
  834. config.WebRTCDialCoordinator.WebRTCAwaitPortMappingTimeout(),
  835. portMappingAwaitTimeout))
  836. defer timer.Stop()
  837. select {
  838. case portMappingExternalAddr = <-portMapper.portMappingExternalAddress():
  839. case <-timer.C:
  840. // Continue without port mapping
  841. case <-ctx.Done():
  842. return nil, nil, nil, errors.Trace(ctx.Err())
  843. }
  844. timer.Stop()
  845. }
  846. if portMapper != nil && portMappingExternalAddr == "" {
  847. // Release any port mapping resources when not using it.
  848. portMapper.close()
  849. conn.portMapper = nil
  850. } else if portMappingExternalAddr != "" {
  851. // Update responding port mapping types for metrics.
  852. //
  853. // Limitation: if there are multiple responding protocol types, it's
  854. // not known here which was used for this dial.
  855. config.WebRTCDialCoordinator.SetPortMappingTypes(
  856. getRespondingPortMappingTypes(config.WebRTCDialCoordinator.NetworkID()))
  857. }
  858. }
  859. config.Logger.WithTraceFields(common.LogFields{
  860. "ice_completed": iceCompleted,
  861. "port_mapping": portMappingExternalAddr != "",
  862. }).Info("webrtc_candidates_gathered")
  863. // Get the offer or answer, now populated with any ICE candidates.
  864. localDescription := conn.peerConnection.LocalDescription()
  865. // Adjust the SDP, removing local network addresses and adding any
  866. // port mapping candidate. Clients (offer) are permitted to have
  867. // no ICE candidates but proxies (answer) must have at least one
  868. //candidate.
  869. errorOnNoCandidates := !isOffer
  870. adjustedSDP, metrics, err := prepareSDPAddresses(
  871. []byte(localDescription.SDP),
  872. errorOnNoCandidates,
  873. portMappingExternalAddr,
  874. config.WebRTCDialCoordinator.DisableIPv6ICECandidates(),
  875. hasPersonalCompartmentIDs)
  876. if err != nil {
  877. return nil, nil, nil, errors.Trace(err)
  878. }
  879. // When STUN was attempted, ICE completed, and a STUN server-reflexive
  880. // candidate is present, notify the WebRTCDialCoordinator so that it can
  881. // set replay for that STUN server selection.
  882. if iceCompleted && doSTUN {
  883. hasServerReflexive := false
  884. for _, candidateType := range metrics.iceCandidateTypes {
  885. if candidateType == ICECandidateServerReflexive {
  886. hasServerReflexive = true
  887. }
  888. }
  889. if hasServerReflexive {
  890. config.WebRTCDialCoordinator.STUNServerAddressSucceeded(RFC5780, stunServerAddress)
  891. } else {
  892. config.WebRTCDialCoordinator.STUNServerAddressFailed(RFC5780, stunServerAddress)
  893. }
  894. }
  895. // The WebRTCConn is prepared, but the data channel is not yet connected.
  896. // On the offer end, the peer's following answer must be input to
  897. // SetRemoteSDP. And both ends must call AwaitInitialDataChannel to await
  898. // the data channel establishment.
  899. return conn,
  900. &WebRTCSessionDescription{
  901. Type: int(localDescription.Type),
  902. SDP: string(adjustedSDP),
  903. },
  904. metrics,
  905. nil
  906. }
  907. func (conn *webRTCConn) setDataChannel(dataChannel *webrtc.DataChannel) {
  908. // Assumes the caller holds conn.mutex, or is newWebRTCConn, creating the
  909. // conn.
  910. conn.dataChannel = dataChannel
  911. conn.dataChannel.OnOpen(conn.onDataChannelOpen)
  912. conn.dataChannel.OnClose(conn.onDataChannelClose)
  913. // Set up flow control (see comment in conn.Write)
  914. conn.dataChannel.SetBufferedAmountLowThreshold(dataChannelBufferedAmountLowThreshold)
  915. conn.dataChannel.OnBufferedAmountLow(func() {
  916. select {
  917. case conn.dataChannelWriteBufferSignal <- struct{}{}:
  918. default:
  919. }
  920. })
  921. }
  922. // SetRemoteSDP takes the answer SDP that is received in response to an offer
  923. // SDP. SetRemoteSDP initiates the WebRTC connection establishment on the
  924. // offer end.
  925. func (conn *webRTCConn) SetRemoteSDP(
  926. peerSDP WebRTCSessionDescription,
  927. hasPersonalCompartmentIDs bool) error {
  928. conn.mutex.Lock()
  929. defer conn.mutex.Unlock()
  930. SDP := peerSDP.SDP
  931. if hasPersonalCompartmentIDs {
  932. // In personal pairing mode, the peer SDP may include private IP
  933. // addresses. To avoid unnecessary network traffic, filter out any
  934. // peer private IP addresses for which there is no corresponding
  935. // local, active interface.
  936. errorOnNoCandidates := false
  937. allowPrivateIPAddressCandidates := true
  938. filterPrivateIPAddressCandidates := true
  939. adjustedSDP, _, err := filterSDPAddresses(
  940. []byte(peerSDP.SDP),
  941. errorOnNoCandidates,
  942. nil,
  943. common.GeoIPData{},
  944. allowPrivateIPAddressCandidates,
  945. filterPrivateIPAddressCandidates)
  946. if err != nil {
  947. return errors.Trace(err)
  948. }
  949. SDP = string(adjustedSDP)
  950. }
  951. pionSessionDescription := webrtc.SessionDescription{
  952. Type: webrtc.SDPType(peerSDP.Type),
  953. SDP: SDP,
  954. }
  955. err := conn.peerConnection.SetRemoteDescription(pionSessionDescription)
  956. if err != nil {
  957. return errors.Trace(err)
  958. }
  959. return nil
  960. }
  961. // AwaitReadyToProxy returns when the data channel is established, or media
  962. // streams are ready to send data, or when an error has occured.
  963. func (conn *webRTCConn) AwaitReadyToProxy(ctx context.Context, connectionID ID) error {
  964. // Don't lock the mutex, or else necessary operations will deadlock.
  965. select {
  966. case <-conn.readyToProxySignal:
  967. // ICE is complete and DTLS is connected. In data channel mode, the
  968. // data channel is established using SCTP, which involves a further
  969. // handshake. In media stream mode, due to its unidirectional nature,
  970. // there is no equivalent to the the data channel establishment step.
  971. // See OnTrack comment in newWebRTCConn.
  972. err := conn.recordSelectedICECandidateStats()
  973. if err != nil {
  974. conn.config.Logger.WithTraceFields(common.LogFields{
  975. "error": err.Error()}).Warning("recordCandidateStats failed")
  976. // Continue without log
  977. }
  978. case <-ctx.Done():
  979. return errors.Tracef("with ICE candidate pairs %s: %w",
  980. conn.getICECandidatePairsSummary(),
  981. ctx.Err())
  982. case <-conn.closedSignal:
  983. return errors.TraceNew("connection has closed")
  984. }
  985. if conn.config.UseMediaStreams && conn.config.ReliableTransport {
  986. // The SRTP protocol used in media stream mode doesn't offer
  987. // reliable/ordered transport, so when that transport property is
  988. // required, add a reliability layer based on QUIC. This layer is
  989. // fully established here before returning read-to-proxy.
  990. err := conn.addRTPReliabilityLayer(ctx)
  991. if err != nil {
  992. return errors.Trace(err)
  993. }
  994. }
  995. conn.config.Logger.WithTraceFields(common.LogFields{
  996. "connectionID": connectionID,
  997. }).Info("WebRTC tunnel established")
  998. return nil
  999. }
  1000. func (conn *webRTCConn) getICECandidatePairsSummary() string {
  1001. conn.mutex.Lock()
  1002. defer conn.mutex.Unlock()
  1003. stateCounts := map[webrtc.StatsICECandidatePairState]int{}
  1004. statsReport := conn.peerConnection.GetStats()
  1005. for key, stats := range statsReport {
  1006. // Uses the pion StatsReport key formats "candidate:<ID>"
  1007. // and "candidate:<ID>-candidate:<ID>"
  1008. key, found := strings.CutPrefix(key, "candidate:")
  1009. if !found {
  1010. continue
  1011. }
  1012. candidateIDs := strings.Split(key, "-candidate:")
  1013. if len(candidateIDs) != 2 {
  1014. continue
  1015. }
  1016. candidatePairStats, ok := stats.(webrtc.ICECandidatePairStats)
  1017. if !ok {
  1018. continue
  1019. }
  1020. stateCounts[candidatePairStats.State] += 1
  1021. }
  1022. if len(stateCounts) == 0 {
  1023. return "(none)"
  1024. }
  1025. var strs []string
  1026. for state, count := range stateCounts {
  1027. strs = append(strs, fmt.Sprintf("%s(%d)", state, count))
  1028. }
  1029. return strings.Join(strs, ", ")
  1030. }
  1031. func (conn *webRTCConn) recordSelectedICECandidateStats() error {
  1032. conn.mutex.Lock()
  1033. defer conn.mutex.Unlock()
  1034. statsReport := conn.peerConnection.GetStats()
  1035. foundNominatedPair := false
  1036. for key, stats := range statsReport {
  1037. // Uses the pion StatsReport key formats "candidate:<ID>"
  1038. // and "candidate:<ID>-candidate:<ID>"
  1039. key, found := strings.CutPrefix(key, "candidate:")
  1040. if !found {
  1041. continue
  1042. }
  1043. candidateIDs := strings.Split(key, "-candidate:")
  1044. if len(candidateIDs) != 2 {
  1045. continue
  1046. }
  1047. candidatePairStats, ok := stats.(webrtc.ICECandidatePairStats)
  1048. if !ok ||
  1049. candidatePairStats.State != webrtc.StatsICECandidatePairStateSucceeded ||
  1050. !candidatePairStats.Nominated {
  1051. continue
  1052. }
  1053. localKey := fmt.Sprintf("candidate:%s", candidateIDs[0])
  1054. stats, ok := statsReport[localKey]
  1055. if !ok {
  1056. return errors.TraceNew("missing local ICECandidateStats")
  1057. }
  1058. localCandidateStats, ok := stats.(webrtc.ICECandidateStats)
  1059. if !ok {
  1060. return errors.TraceNew("unexpected local ICECandidateStats")
  1061. }
  1062. remoteKey := fmt.Sprintf("candidate:%s", candidateIDs[1])
  1063. stats, ok = statsReport[remoteKey]
  1064. if !ok {
  1065. return errors.TraceNew("missing remote ICECandidateStats")
  1066. }
  1067. remoteCandidateStats, ok := stats.(webrtc.ICECandidateStats)
  1068. if !ok {
  1069. return errors.TraceNew("unexpected remote ICECandidateStats")
  1070. }
  1071. // Use the same ICE candidate type names as logged in broker logs.
  1072. logCandidateType := func(
  1073. iceCandidateType webrtc.ICECandidateType) string {
  1074. logType := ICECandidateUnknown
  1075. switch iceCandidateType {
  1076. case webrtc.ICECandidateTypeHost:
  1077. logType = ICECandidateHost
  1078. case webrtc.ICECandidateTypeSrflx:
  1079. logType = ICECandidateServerReflexive
  1080. case webrtc.ICECandidateTypePrflx:
  1081. logType = ICECandidatePeerReflexive
  1082. }
  1083. return logType.String()
  1084. }
  1085. conn.iceCandidatePairMetrics = common.LogFields{}
  1086. // TODO: log which of local/remote candidate is initiator
  1087. conn.iceCandidatePairMetrics["inproxy_webrtc_local_ice_candidate_type"] =
  1088. logCandidateType(localCandidateStats.CandidateType)
  1089. localIP := net.ParseIP(localCandidateStats.IP)
  1090. isIPv6 := "0"
  1091. if localIP != nil && localIP.To4() == nil {
  1092. isIPv6 = "1"
  1093. }
  1094. isPrivate := "0"
  1095. if localIP != nil && localIP.IsPrivate() {
  1096. isPrivate = "1"
  1097. }
  1098. conn.iceCandidatePairMetrics["inproxy_webrtc_local_ice_candidate_is_IPv6"] =
  1099. isIPv6
  1100. conn.iceCandidatePairMetrics["inproxy_webrtc_local_ice_candidate_is_private_IP"] =
  1101. isPrivate
  1102. conn.iceCandidatePairMetrics["inproxy_webrtc_local_ice_candidate_port"] =
  1103. localCandidateStats.Port
  1104. conn.iceCandidatePairMetrics["inproxy_webrtc_remote_ice_candidate_type"] =
  1105. logCandidateType(remoteCandidateStats.CandidateType)
  1106. remoteIP := net.ParseIP(remoteCandidateStats.IP)
  1107. isIPv6 = "0"
  1108. if remoteIP != nil && remoteIP.To4() == nil {
  1109. isIPv6 = "1"
  1110. }
  1111. isPrivate = "0"
  1112. if remoteIP != nil && remoteIP.IsPrivate() {
  1113. isPrivate = "1"
  1114. }
  1115. conn.iceCandidatePairMetrics["inproxy_webrtc_remote_ice_candidate_is_IPv6"] =
  1116. isIPv6
  1117. conn.iceCandidatePairMetrics["inproxy_webrtc_remote_ice_candidate_is_private_IP"] =
  1118. isPrivate
  1119. conn.iceCandidatePairMetrics["inproxy_webrtc_remote_ice_candidate_port"] =
  1120. remoteCandidateStats.Port
  1121. foundNominatedPair = true
  1122. break
  1123. }
  1124. if !foundNominatedPair {
  1125. return errors.TraceNew("missing nominated ICECandidateStatsPair")
  1126. }
  1127. return nil
  1128. }
  1129. func (conn *webRTCConn) Close() error {
  1130. conn.mutex.Lock()
  1131. defer conn.mutex.Unlock()
  1132. if conn.isClosed {
  1133. return nil
  1134. }
  1135. if conn.portMapper != nil {
  1136. conn.portMapper.close()
  1137. }
  1138. // Neither sendMediaTrack nor receiveMediaTrack have a Close operation.
  1139. if conn.sendMediaTrackRTP != nil {
  1140. _ = conn.sendMediaTrackRTP.Stop()
  1141. }
  1142. if conn.mediaTrackReliabilityLayer != nil {
  1143. _ = conn.mediaTrackReliabilityLayer.Close()
  1144. }
  1145. if conn.dataChannelConn != nil {
  1146. _ = conn.dataChannelConn.Close()
  1147. }
  1148. if conn.dataChannel != nil {
  1149. _ = conn.dataChannel.Close()
  1150. }
  1151. if conn.peerConnection != nil {
  1152. // TODO: use PeerConnection.GracefulClose (requires pion/webrtc 3.2.51)?
  1153. _ = conn.peerConnection.Close()
  1154. }
  1155. // Close the udpConn to interrupt any blocking DTLS handshake:
  1156. // https://github.com/pion/webrtc/blob/c1467e4871c78ee3f463b50d858d13dc6f2874a4/dtlstransport.go#L334-L340
  1157. //
  1158. // Limitation: there is no guarantee that pion sends any closing packets
  1159. // before the UDP socket is closed here.
  1160. if conn.udpConn != nil {
  1161. _ = conn.udpConn.Close()
  1162. }
  1163. close(conn.closedSignal)
  1164. conn.isClosed = true
  1165. return nil
  1166. }
  1167. func (conn *webRTCConn) IsClosed() bool {
  1168. conn.mutex.Lock()
  1169. defer conn.mutex.Unlock()
  1170. return conn.isClosed
  1171. }
  1172. func (conn *webRTCConn) Read(p []byte) (int, error) {
  1173. if !conn.config.UseMediaStreams {
  1174. // Data channel mode.
  1175. n, err := conn.readDataChannel(p)
  1176. return n, errors.TraceReader(err)
  1177. }
  1178. if conn.mediaTrackReliabilityLayer != nil {
  1179. // Media stream mode with reliability layer.
  1180. n, err := conn.mediaTrackReliabilityLayer.Read(p)
  1181. return n, errors.TraceReader(err)
  1182. }
  1183. // Media stream mode without reliability layer.
  1184. n, err := conn.readMediaTrack(p)
  1185. return n, errors.TraceReader(err)
  1186. }
  1187. func (conn *webRTCConn) Write(p []byte) (int, error) {
  1188. if !conn.config.UseMediaStreams {
  1189. // Data channel mode.
  1190. n, err := conn.writeDataChannelMessage(p, false)
  1191. return n, errors.Trace(err)
  1192. }
  1193. if conn.mediaTrackReliabilityLayer != nil {
  1194. // Media stream mode with reliability layer.
  1195. n, err := conn.mediaTrackReliabilityLayer.Write(p)
  1196. return n, errors.Trace(err)
  1197. }
  1198. // Media stream mode without reliability layer.
  1199. n, err := conn.writeMediaTrackPacket(p, false)
  1200. return n, errors.Trace(err)
  1201. }
  1202. func (conn *webRTCConn) LocalAddr() net.Addr {
  1203. conn.mutex.Lock()
  1204. defer conn.mutex.Unlock()
  1205. // This is the local UDP socket address, not the external, public address.
  1206. return conn.udpConn.LocalAddr()
  1207. }
  1208. func (conn *webRTCConn) RemoteAddr() net.Addr {
  1209. conn.mutex.Lock()
  1210. defer conn.mutex.Unlock()
  1211. // Not supported.
  1212. return nil
  1213. }
  1214. func (conn *webRTCConn) SetDeadline(t time.Time) error {
  1215. conn.mutex.Lock()
  1216. defer conn.mutex.Unlock()
  1217. return errors.TraceNew("not supported")
  1218. }
  1219. func (conn *webRTCConn) SetReadDeadline(t time.Time) error {
  1220. conn.mutex.Lock()
  1221. defer conn.mutex.Unlock()
  1222. if conn.isClosed {
  1223. return errors.TraceNew("closed")
  1224. }
  1225. if conn.config.UseMediaStreams {
  1226. // TODO: add support
  1227. return errors.TraceNew("not supported")
  1228. }
  1229. readDeadliner, ok := conn.dataChannelConn.(datachannel.ReadDeadliner)
  1230. if !ok {
  1231. return errors.TraceNew("no data channel")
  1232. }
  1233. return readDeadliner.SetReadDeadline(t)
  1234. }
  1235. func (conn *webRTCConn) SetWriteDeadline(t time.Time) error {
  1236. conn.mutex.Lock()
  1237. defer conn.mutex.Unlock()
  1238. return errors.TraceNew("not supported")
  1239. }
  1240. // GetMetrics implements the common.MetricsSource interface and returns log
  1241. // fields detailing the WebRTC dial parameters.
  1242. func (conn *webRTCConn) GetMetrics() common.LogFields {
  1243. conn.mutex.Lock()
  1244. defer conn.mutex.Unlock()
  1245. logFields := make(common.LogFields)
  1246. logFields.Add(conn.iceCandidatePairMetrics)
  1247. randomizeDTLS := "0"
  1248. if conn.config.DoDTLSRandomization {
  1249. randomizeDTLS = "1"
  1250. }
  1251. logFields["inproxy_webrtc_randomize_dtls"] = randomizeDTLS
  1252. useMediaStreams := "0"
  1253. if conn.config.UseMediaStreams {
  1254. useMediaStreams = "1"
  1255. }
  1256. logFields["inproxy_webrtc_use_media_streams"] = useMediaStreams
  1257. logFields["inproxy_webrtc_padded_messages_sent"] = atomic.LoadInt32(&conn.paddedMessagesSent)
  1258. logFields["inproxy_webrtc_padded_messages_received"] = atomic.LoadInt32(&conn.paddedMessagesReceived)
  1259. logFields["inproxy_webrtc_decoy_messages_sent"] = atomic.LoadInt32(&conn.decoyMessagesSent)
  1260. logFields["inproxy_webrtc_decoy_messages_received"] = atomic.LoadInt32(&conn.decoyMessagesReceived)
  1261. return logFields
  1262. }
  1263. func (conn *webRTCConn) onConnectionStateChange(state webrtc.PeerConnectionState) {
  1264. switch state {
  1265. case webrtc.PeerConnectionStateConnected:
  1266. if conn.config.UseMediaStreams {
  1267. // webrtc.PeerConnectionStateConnected is received once the DTLS
  1268. // connection is established. At this point, media track data may
  1269. // be sent. In media stream mode, unblock AwaitForReadyToProxy to
  1270. // allow peers to start sending data. In data channel mode, wait
  1271. // and signal in onDataChannelOpen.
  1272. conn.readyToProxyOnce.Do(func() { close(conn.readyToProxySignal) })
  1273. }
  1274. case webrtc.PeerConnectionStateDisconnected,
  1275. webrtc.PeerConnectionStateFailed,
  1276. webrtc.PeerConnectionStateClosed:
  1277. // Close the WebRTCConn when the connection is no longer connected. Close
  1278. // will lock conn.mutex, so do not aquire the lock here.
  1279. //
  1280. // Currently, ICE Restart is not used, and there is no transition from
  1281. // Disconnected back to Connected.
  1282. conn.Close()
  1283. }
  1284. conn.config.Logger.WithTraceFields(common.LogFields{
  1285. "state": state.String(),
  1286. }).Debug("peer connection state changed")
  1287. }
  1288. func (conn *webRTCConn) onICECandidate(candidate *webrtc.ICECandidate) {
  1289. if candidate == nil {
  1290. return
  1291. }
  1292. conn.config.Logger.WithTraceFields(common.LogFields{
  1293. "candidate": candidate.String(),
  1294. }).Debug("new ICE candidate")
  1295. }
  1296. func (conn *webRTCConn) onICEBindingRequest(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool {
  1297. // SetICEBindingRequestHandler is used to hook onICEBindingRequest into
  1298. // STUN bind events for logging. The return values is always false as
  1299. // this callback makes no adjustments to ICE candidate selection. When
  1300. // the data channel or media track tunnel has already opened, skip
  1301. // logging events, as this callback appears to be invoked for keepalive
  1302. // pings.
  1303. if local == nil || remote == nil {
  1304. return false
  1305. }
  1306. select {
  1307. case <-conn.readyToProxySignal:
  1308. return false
  1309. default:
  1310. }
  1311. conn.config.Logger.WithTraceFields(common.LogFields{
  1312. "local_candidate": local.String(),
  1313. "remote_candidate": remote.String(),
  1314. }).Debug("new ICE STUN binding request")
  1315. return false
  1316. }
  1317. func (conn *webRTCConn) onICEConnectionStateChange(state webrtc.ICEConnectionState) {
  1318. conn.mutex.Lock()
  1319. defer conn.mutex.Unlock()
  1320. conn.config.Logger.WithTraceFields(common.LogFields{
  1321. "state": state.String(),
  1322. }).Debug("ICE connection state changed")
  1323. }
  1324. func (conn *webRTCConn) onICEGatheringStateChange(state webrtc.ICEGathererState) {
  1325. conn.config.Logger.WithTraceFields(common.LogFields{
  1326. "state": state.String(),
  1327. }).Debug("ICE gathering state changed")
  1328. }
  1329. func (conn *webRTCConn) onNegotiationNeeded() {
  1330. conn.config.Logger.WithTrace().Debug("negotiation needed")
  1331. }
  1332. func (conn *webRTCConn) onSignalingStateChange(state webrtc.SignalingState) {
  1333. conn.config.Logger.WithTraceFields(common.LogFields{
  1334. "state": state.String(),
  1335. }).Debug("signaling state changed")
  1336. }
  1337. func (conn *webRTCConn) onDataChannel(dataChannel *webrtc.DataChannel) {
  1338. conn.mutex.Lock()
  1339. defer conn.mutex.Unlock()
  1340. conn.setDataChannel(dataChannel)
  1341. conn.config.Logger.WithTraceFields(common.LogFields{
  1342. "label": dataChannel.Label(),
  1343. "ID": dataChannel.ID(),
  1344. }).Debug("new data channel")
  1345. }
  1346. func (conn *webRTCConn) onMediaTrack(track *webrtc.TrackRemote, _ *webrtc.RTPReceiver) {
  1347. conn.mutex.Lock()
  1348. defer conn.mutex.Unlock()
  1349. conn.receiveMediaTrack = track
  1350. close(conn.receiveMediaTrackOpenedSignal)
  1351. conn.config.Logger.WithTraceFields(common.LogFields{
  1352. "ID": track.ID(),
  1353. "payload_type": track.Kind().String(),
  1354. }).Info("media track open")
  1355. }
  1356. func (conn *webRTCConn) onDataChannelOpen() {
  1357. conn.mutex.Lock()
  1358. defer conn.mutex.Unlock()
  1359. dataChannelConn, err := conn.dataChannel.Detach()
  1360. if err == nil {
  1361. conn.dataChannelConn = dataChannelConn
  1362. // TODO: can a data channel be connected, disconnected, and then
  1363. // reestablished in one session?
  1364. conn.readyToProxyOnce.Do(func() { close(conn.readyToProxySignal) })
  1365. }
  1366. conn.config.Logger.WithTraceFields(common.LogFields{
  1367. "detachError": err,
  1368. }).Info("data channel open")
  1369. }
  1370. func (conn *webRTCConn) onDataChannelClose() {
  1371. // Close the WebRTCConn when the data channel is closed. Close will lock
  1372. // conn.mutex, so do not aquire the lock here.
  1373. conn.Close()
  1374. conn.config.Logger.WithTrace().Info("data channel closed")
  1375. }
  1376. func (conn *webRTCConn) readDataChannel(p []byte) (int, error) {
  1377. for {
  1378. n, err := conn.readDataChannelMessage(p)
  1379. if err != nil || n > 0 {
  1380. return n, errors.TraceReader(err)
  1381. }
  1382. // A decoy message was read; discard and read again.
  1383. }
  1384. }
  1385. func (conn *webRTCConn) readDataChannelMessage(p []byte) (int, error) {
  1386. // Don't hold this lock, or else concurrent Writes will be blocked.
  1387. conn.mutex.Lock()
  1388. isClosed := conn.isClosed
  1389. dataChannelConn := conn.dataChannelConn
  1390. conn.mutex.Unlock()
  1391. if isClosed {
  1392. return 0, errors.TraceNew("closed")
  1393. }
  1394. if dataChannelConn == nil {
  1395. return 0, errors.TraceNew("no data channel")
  1396. }
  1397. // The input read buffer, p, may not be the same length as the message
  1398. // read from the data channel. Buffer the read message if another Read
  1399. // call is necessary to consume it. As per https://pkg.go.dev/io#Reader,
  1400. // dataChannelConn bytes read are processed even when
  1401. // dataChannelConn.Read returns an error; the error value is stored and
  1402. // returned with the Read call that consumes the end of the message buffer.
  1403. conn.readMutex.Lock()
  1404. defer conn.readMutex.Unlock()
  1405. if conn.readOffset == conn.readLength {
  1406. n, err := dataChannelConn.Read(conn.readBuffer)
  1407. conn.readOffset = 0
  1408. conn.readLength = n
  1409. conn.readError = err
  1410. // Skip over padding.
  1411. if n > 0 && !conn.peerPaddingDone {
  1412. paddingSize, n := binary.Varint(conn.readBuffer[0:conn.readLength])
  1413. if (paddingSize == 0 && n <= 0) || paddingSize >= int64(conn.readLength) {
  1414. return 0, errors.TraceNew("invalid padding")
  1415. }
  1416. if paddingSize < 0 {
  1417. // When the padding header indicates a padding size of -1, the
  1418. // peer is indicating that padding is done. Subsequent
  1419. // messages will have no padding header or padding bytes.
  1420. conn.peerPaddingDone = true
  1421. conn.readOffset += n
  1422. } else {
  1423. conn.readOffset += n + int(paddingSize)
  1424. atomic.AddInt32(&conn.paddedMessagesReceived, 1)
  1425. if conn.readOffset == conn.readLength {
  1426. atomic.AddInt32(&conn.decoyMessagesReceived, 1)
  1427. }
  1428. }
  1429. }
  1430. }
  1431. n := copy(p, conn.readBuffer[conn.readOffset:conn.readLength])
  1432. conn.readOffset += n
  1433. var err error
  1434. if conn.readOffset == conn.readLength {
  1435. err = conn.readError
  1436. }
  1437. // When decoy messages are enabled, periodically respond to an incoming
  1438. // messages with an immediate outbound decoy message. This is similar to
  1439. // the design here:
  1440. // https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/c4f6a593a645db4479a7032a9e97d3c0b905cdfc/psiphon/common/quic/obfuscator.go#L361-L409
  1441. //
  1442. // writeDataChannelMessage handles conn.decoyMessageCount, which is
  1443. // synchronized with conn.WriteMutex, as well as other specific logic.
  1444. // Here we just signal writeDataChannelMessage based on the read event.
  1445. //
  1446. // When the data channel already has buffered writes in excess of a decoy
  1447. // message size, the writeDataChannelMessage skips the decoy message and
  1448. // returns without blocking, so Read calls will not block.
  1449. if !conn.decoyDone.Load() {
  1450. _, _ = conn.writeDataChannelMessage(nil, true)
  1451. }
  1452. return n, errors.TraceReader(err)
  1453. }
  1454. func (conn *webRTCConn) writeDataChannelMessage(p []byte, decoy bool) (int, error) {
  1455. if p != nil && decoy {
  1456. return 0, errors.TraceNew("invalid write parameters")
  1457. }
  1458. // pion/sctp doesn't handle 0-byte writes correctly, so drop/skip at this level.
  1459. //
  1460. // Testing shows that the SCTP connection stalls after a 0-byte write. In
  1461. // the pion/sctp implementation,
  1462. // https://github.com/pion/sctp/blob/v1.8.8/stream.go#L254-L278 and
  1463. // https://github.com/pion/sctp/blob/v1.8.8/stream.go#L280-L336, it
  1464. // appears that a zero-byte write won't send an SCTP messages but does
  1465. // increment a sequence number.
  1466. if len(p) == 0 && !decoy {
  1467. return 0, nil
  1468. }
  1469. // Don't hold this lock, or else concurrent Reads will be blocked.
  1470. conn.mutex.Lock()
  1471. isClosed := conn.isClosed
  1472. bufferedAmount := conn.dataChannel.BufferedAmount()
  1473. dataChannelConn := conn.dataChannelConn
  1474. conn.mutex.Unlock()
  1475. if isClosed {
  1476. return 0, errors.TraceNew("closed")
  1477. }
  1478. if dataChannelConn == nil {
  1479. return 0, errors.TraceNew("no data channel")
  1480. }
  1481. // Only proceed with a decoy message when no pending writes are buffered.
  1482. //
  1483. // This check is made before acquiring conn.writeMutex so that, in most
  1484. // cases, writeMessage won't block Read calls when a concurrent Write is
  1485. // holding conn.writeMutex and potentially blocking on flow control.
  1486. // There's still a chance that this test passes, and a concurrent Write
  1487. // arrives at the same time.
  1488. if decoy && bufferedAmount > 0 {
  1489. return 0, nil
  1490. }
  1491. conn.writeMutex.Lock()
  1492. defer conn.writeMutex.Unlock()
  1493. writeSize := len(p)
  1494. // Determine padding size and padding header size.
  1495. doPadding := false
  1496. paddingSize := 0
  1497. var paddingHeader [binary.MaxVarintLen32]byte
  1498. paddingHeaderSize := 0
  1499. if decoy {
  1500. if conn.decoyMessageCount < 1 {
  1501. return 0, nil
  1502. }
  1503. if !conn.trafficShapingPRNG.FlipWeightedCoin(
  1504. conn.config.TrafficShapingParameters.DecoyMessageProbability) {
  1505. return 0, nil
  1506. }
  1507. conn.decoyMessageCount -= 1
  1508. decoySize := conn.trafficShapingPRNG.Range(
  1509. conn.config.TrafficShapingParameters.MinDecoySize,
  1510. conn.config.TrafficShapingParameters.MaxDecoySize)
  1511. // When sending a decoy message, the entire message is padding.
  1512. doPadding = true
  1513. paddingSize = decoySize
  1514. if conn.decoyMessageCount == 0 {
  1515. // Set the shared flag that readMessage uses to stop invoking
  1516. // writeMessage for decoy events.
  1517. conn.decoyDone.Store(true)
  1518. }
  1519. } else if conn.paddedMessageCount > 0 {
  1520. // Add padding to a normal write.
  1521. conn.paddedMessageCount -= 1
  1522. doPadding = true
  1523. paddingSize = prng.Range(
  1524. conn.config.TrafficShapingParameters.MinPaddingSize,
  1525. conn.config.TrafficShapingParameters.MaxPaddingSize)
  1526. } else if conn.decoyMessageCount > 0 {
  1527. // Padding normal messages is done, but there are still outstanding
  1528. // decoy messages, so add a padding header indicating padding size 0
  1529. // to this normal message.
  1530. doPadding = true
  1531. paddingSize = 0
  1532. } else if !conn.trafficShapingDone {
  1533. // Padding normal messages is done and all decoy messages are sent, so
  1534. // send a special padding header with padding size -1, signaling the
  1535. // peer that no additional padding will be performed and no
  1536. // subsequent messages will contain a padding header.
  1537. doPadding = true
  1538. paddingSize = -1
  1539. }
  1540. if doPadding {
  1541. if paddingSize > 0 {
  1542. // Reduce, if necessary, to stay within the maximum data channel
  1543. // message size. This is not expected to happen for the io.Copy use
  1544. // case, with 32K message size, plus reasonable padding sizes.
  1545. if writeSize+binary.MaxVarintLen32+paddingSize > dataChannelMaxMessageSize {
  1546. paddingSize -= (writeSize + binary.MaxVarintLen32 + paddingSize) - dataChannelMaxMessageSize
  1547. if paddingSize < 0 {
  1548. paddingSize = 0
  1549. }
  1550. }
  1551. // Add padding overhead to total writeSize before the flow control check.
  1552. writeSize += paddingSize
  1553. }
  1554. paddingHeaderSize = binary.PutVarint(paddingHeader[:], int64(paddingSize))
  1555. writeSize += paddingHeaderSize
  1556. }
  1557. if writeSize > dataChannelMaxMessageSize {
  1558. return 0, errors.TraceNew("write too large")
  1559. }
  1560. // Flow control is required to ensure that Write calls don't result in
  1561. // unbounded buffering in pion/webrtc. Use similar logic and the same
  1562. // buffer size thresholds as the pion sample code.
  1563. //
  1564. // https://github.com/pion/webrtc/tree/master/examples/data-channels-flow-control#when-do-we-need-it:
  1565. // > Send or SendText methods are called on DataChannel to send data to
  1566. // > the connected peer. The methods return immediately, but it does not
  1567. // > mean the data was actually sent onto the wire. Instead, it is
  1568. // > queued in a buffer until it actually gets sent out to the wire.
  1569. // >
  1570. // > When you have a large amount of data to send, it is an application's
  1571. // > responsibility to control the buffered amount in order not to
  1572. // > indefinitely grow the buffer size to eventually exhaust the memory.
  1573. // If the pion write buffer is too full, wait for a signal that sufficient
  1574. // write data has been consumed before writing more.
  1575. if !isClosed && bufferedAmount+uint64(writeSize) > dataChannelMaxBufferedAmount {
  1576. select {
  1577. case <-conn.dataChannelWriteBufferSignal:
  1578. case <-conn.closedSignal:
  1579. return 0, errors.TraceNew("connection has closed")
  1580. }
  1581. }
  1582. if conn.trafficShapingDone {
  1583. // When traffic shaping is done, p is written directly without the
  1584. // additional trafficShapingBuffer copy.
  1585. // Limitation: if len(p) > 65536, the dataChannelConn.Write will fail. In
  1586. // practise, this is not expected to happen with typical use cases such
  1587. // as io.Copy, which uses a 32K buffer.
  1588. n, err := dataChannelConn.Write(p)
  1589. return n, errors.Trace(err)
  1590. }
  1591. conn.trafficShapingBuffer.Reset()
  1592. conn.trafficShapingBuffer.Write(paddingHeader[:paddingHeaderSize])
  1593. if paddingSize > 0 {
  1594. conn.trafficShapingBuffer.Write(prng.Bytes(paddingSize))
  1595. }
  1596. conn.trafficShapingBuffer.Write(p)
  1597. // Limitation: see above; len(p) + padding must be <= 65536.
  1598. _, err := dataChannelConn.Write(conn.trafficShapingBuffer.Bytes())
  1599. if decoy {
  1600. atomic.AddInt32(&conn.decoyMessagesSent, 1)
  1601. } else if doPadding && paddingSize > 0 {
  1602. atomic.AddInt32(&conn.paddedMessagesSent, 1)
  1603. }
  1604. if conn.paddedMessageCount == 0 && conn.decoyMessageCount == 0 && paddingSize == -1 {
  1605. // Set flag indicating -1 padding size was sent and release traffic
  1606. // shaping resources.
  1607. conn.trafficShapingDone = true
  1608. conn.trafficShapingPRNG = nil
  1609. conn.trafficShapingBuffer = nil
  1610. }
  1611. return len(p), errors.Trace(err)
  1612. }
  1613. // GetQUICMaxPacketSizeAdjustment returns the value to be specified in
  1614. // Psiphon's quic-go configuration ClientMaxPacketSizeAdjustment
  1615. // ServerMaxPacketSizeAdjustment fields. Psiphon's quic-go max packet size
  1616. // adjustment reduces the QUIC payload to accomodate overhead from
  1617. // obfuscation, as in Obfuscated QUIC. In the in-proxy case, the same
  1618. // mechanism is used to ensure that QUIC packets fit within the space
  1619. // available for SRTP packet payloads, allowing for the overhead of the RTP
  1620. // packet. Beyond that allowance, the adjustment is tuned to produce SRTP
  1621. // packets that match common SRTP traffic with maximum packet sizes of 1200
  1622. // bytes, excluding IP and UDP headers.
  1623. //
  1624. // INPROXY-QUIC-OSSH must apply GetQUICMaxPacketSizeAdjustment on both the
  1625. // client and server side. In addition, the client must disable
  1626. // DisablePathMTUDiscovery.
  1627. func GetQUICMaxPacketSizeAdjustment(isIPv6 bool) int {
  1628. // Limitations:
  1629. //
  1630. // - For INPROXY-QUIC-OSSH, the second hop egressing from the proxy is
  1631. // identical regardless of whether the 1st hop uses data channel mode
  1632. // or media stream mode. Currently, the INPROXY-QUIC-OSSH server won't
  1633. // be able to distinguish, early enough, between the modes used by the
  1634. // 1st hop. In order to conform with the required adustment for media
  1635. // stream mode, the server must always apply the adjustment. This
  1636. // reduction in QUIC packet size may impact the performance of data
  1637. // channel mode. Furthermore, the lower maximum QUIC packet size is
  1638. // directly observable on the 2nd hop.
  1639. // common/quic.MAX_PRE_DISCOVERY_PACKET_SIZE_IPV4 = 1252
  1640. // common/quic.MAX_PRE_DISCOVERY_PACKET_SIZE_IPV6 = 1232
  1641. quicMTU := 1252
  1642. if isIPv6 {
  1643. quicMTU = 1232
  1644. }
  1645. targetMTUAdjustment := quicMTU - mediaTrackMaxUDPPayloadLength
  1646. if targetMTUAdjustment < 0 {
  1647. targetMTUAdjustment = 0
  1648. }
  1649. adjustment := targetMTUAdjustment + mediaTrackRTPPacketOverhead
  1650. if adjustment < 0 {
  1651. adjustment = 0
  1652. }
  1653. return adjustment
  1654. }
  1655. func (conn *webRTCConn) readMediaTrack(p []byte) (int, error) {
  1656. for {
  1657. n, err := conn.readMediaTrackPacket(p)
  1658. if err != nil || n > 0 {
  1659. return n, errors.TraceReader(err)
  1660. }
  1661. // A decoy message was read; discard and read again.
  1662. }
  1663. }
  1664. func (conn *webRTCConn) readMediaTrackPacket(p []byte) (int, error) {
  1665. // Await opening the peer's media track, the OnTrack event. This
  1666. // synchronization is necessary since AwaitReadyToProxy returns before
  1667. // receiving a media track packet from the peer, which triggers OnTrack.
  1668. select {
  1669. case <-conn.receiveMediaTrackOpenedSignal:
  1670. case <-conn.closedSignal:
  1671. return 0, errors.TraceNew("closed")
  1672. }
  1673. // Don't hold this lock, or else concurrent Writes will be blocked.
  1674. conn.mutex.Lock()
  1675. isClosed := conn.isClosed
  1676. receiveMediaTrack := conn.receiveMediaTrack
  1677. conn.mutex.Unlock()
  1678. if isClosed {
  1679. return 0, errors.TraceNew("closed")
  1680. }
  1681. if receiveMediaTrack == nil {
  1682. return 0, errors.TraceNew("no media track")
  1683. }
  1684. conn.readMutex.Lock()
  1685. defer conn.readMutex.Unlock()
  1686. // Use the lower-level Read and Unmarshal functions to avoid per-call allocations
  1687. // performed by the higher-level ReadRTP.
  1688. n, _, err := receiveMediaTrack.Read(conn.readBuffer)
  1689. if err != nil {
  1690. return 0, errors.TraceReader(err)
  1691. }
  1692. err = conn.receiveMediaTrackPacket.Unmarshal(conn.readBuffer[:n])
  1693. if err != nil {
  1694. return 0, errors.Trace(err)
  1695. }
  1696. payload := conn.receiveMediaTrackPacket.Payload
  1697. if len(payload) < 1 {
  1698. return 0, errors.TraceNew("invalid padding")
  1699. }
  1700. // Read the padding header byte, which is always present (see comment in
  1701. // writeMediaTrackPacket).
  1702. paddingSize := int(payload[0])
  1703. if paddingSize == 255 {
  1704. // When the header is 255, this is a decoy packet with no application
  1705. // payload. Discard the entire packet. Return n = 0 bytes read, and
  1706. // the caller will read again.
  1707. return 0, nil
  1708. }
  1709. if len(payload) < 1+paddingSize {
  1710. return 0, errors.Tracef("invalid padding: %d < %d", len(payload), 1+paddingSize)
  1711. }
  1712. payload = payload[1+paddingSize:]
  1713. // Unlike the data channel case, there is no carry over data left in
  1714. // conn.readBuffer between readMediaTrackPacket calls: the entire packet
  1715. // payload must be read in this one call.
  1716. if len(p) < len(payload) {
  1717. return 0, errors.Tracef("read buffer too short: %d < %d", len(p), len(payload))
  1718. }
  1719. copy(p, payload)
  1720. // When decoy messages are enabled, periodically respond to an incoming
  1721. // messages with an immediate outbound decoy message.
  1722. //
  1723. // writeMediaTrackPacket handles conn.decoyMessageCount, which is
  1724. // synchronized with conn.WriteMutex, as well as other specific logic.
  1725. // Here we just signal writeDataChannelMessage based on the read event.
  1726. if !conn.decoyDone.Load() {
  1727. _, _ = conn.writeMediaTrackPacket(nil, true)
  1728. }
  1729. return len(payload), nil
  1730. }
  1731. func (conn *webRTCConn) writeMediaTrackPacket(p []byte, decoy bool) (int, error) {
  1732. if p != nil && decoy {
  1733. return 0, errors.TraceNew("invalid write parameters")
  1734. }
  1735. // Don't hold this lock, or else concurrent Writes will be blocked.
  1736. conn.mutex.Lock()
  1737. isClosed := conn.isClosed
  1738. sendMediaTrack := conn.sendMediaTrack
  1739. conn.mutex.Unlock()
  1740. if isClosed {
  1741. return 0, errors.TraceNew("closed")
  1742. }
  1743. if sendMediaTrack == nil {
  1744. return 0, errors.TraceNew("no media track")
  1745. }
  1746. conn.writeMutex.Lock()
  1747. defer conn.writeMutex.Unlock()
  1748. // Packet writes can't be split.
  1749. maxRTPPayloadLength := mediaTrackMaxRTPPayloadLength
  1750. if len(p) > maxRTPPayloadLength {
  1751. return 0, errors.Tracef("write too large: %d > %d", len(p), maxRTPPayloadLength)
  1752. }
  1753. // Determine padding size and padding header size.
  1754. // Limitation: unlike data channel padding, the header size is fixed, not
  1755. // a varint, and is always sent. This is due to the fixed QUIC max packet
  1756. // size adjustment. To limit the overhead, and because the maximum SRTP
  1757. // payload size is much smaller than the maximum data channel message
  1758. // size, the padding is limited to 254 bytes, represented with a 1 byte
  1759. // header. The value 255 is reserved to signal that the entire packet is
  1760. // a decoy packet.
  1761. conn.trafficShapingBuffer.Reset()
  1762. if decoy {
  1763. if conn.decoyMessageCount < 1 {
  1764. return 0, nil
  1765. }
  1766. if !conn.trafficShapingPRNG.FlipWeightedCoin(
  1767. conn.config.TrafficShapingParameters.DecoyMessageProbability) {
  1768. return 0, nil
  1769. }
  1770. conn.decoyMessageCount -= 1
  1771. // When sending a decoy message, the entire message is padding, and
  1772. // the padding can be up to the full packet size.
  1773. //
  1774. // Note that the actual decoy payload size is decoySize+1, including
  1775. // the padding header.
  1776. decoySize := conn.trafficShapingPRNG.Range(
  1777. conn.config.TrafficShapingParameters.MinDecoySize,
  1778. conn.config.TrafficShapingParameters.MaxDecoySize)
  1779. if decoySize > maxRTPPayloadLength-1 {
  1780. // Ensure there's space for the 1 byte padding header.
  1781. decoySize = maxRTPPayloadLength - 1
  1782. }
  1783. // Set the padding header to 255, which indicates a decoy packet.
  1784. conn.trafficShapingBuffer.WriteByte(255)
  1785. if decoySize > 0 {
  1786. conn.trafficShapingBuffer.Write(prng.Bytes(decoySize))
  1787. }
  1788. if conn.decoyMessageCount == 0 {
  1789. // Set the shared flag that readMessage uses to stop invoking
  1790. // writeMessage for decoy events.
  1791. conn.decoyDone.Store(true)
  1792. }
  1793. } else {
  1794. // Add padding to a normal write.
  1795. paddingSize := 0
  1796. if conn.paddedMessageCount > 0 {
  1797. paddingSize = prng.Range(
  1798. conn.config.TrafficShapingParameters.MinPaddingSize,
  1799. conn.config.TrafficShapingParameters.MaxPaddingSize)
  1800. if paddingSize > 254 {
  1801. // The maximum padding size is 254.
  1802. paddingSize = 254
  1803. }
  1804. if len(p)+1+paddingSize > maxRTPPayloadLength {
  1805. paddingSize -= (len(p) + 1 + paddingSize) - maxRTPPayloadLength
  1806. }
  1807. if paddingSize < 0 {
  1808. paddingSize = 0
  1809. }
  1810. conn.paddedMessageCount -= 1
  1811. }
  1812. conn.trafficShapingBuffer.WriteByte(byte(paddingSize))
  1813. if paddingSize > 0 {
  1814. conn.trafficShapingBuffer.Write(prng.Bytes(paddingSize))
  1815. }
  1816. conn.trafficShapingBuffer.Write(p)
  1817. }
  1818. paddedPayload := conn.trafficShapingBuffer.Bytes()
  1819. // Sanity check, in case there's a bug in the padding logic above; +1 here
  1820. // is the padding header.
  1821. if len(paddedPayload) > maxRTPPayloadLength+1 {
  1822. return 0, errors.Tracef("write too large: %d > %d", len(paddedPayload), maxRTPPayloadLength)
  1823. }
  1824. // Send the RTP packet.
  1825. // Dynamic plaintext RTP header values are set here: the sequence number
  1826. // is set when sending the packet; the timestamp, initialized in
  1827. // newWebRTCConn, is updated once payload equivalent to a complete
  1828. // video "frame" has been sent. See the "Plaintext RTP header fields"
  1829. // comment in newWebRTCConn.
  1830. conn.sendMediaTrackPacket.SequenceNumber = conn.sendMediaTrackSequencer.NextSequenceNumber()
  1831. conn.sendMediaTrackPacket.Payload = paddedPayload
  1832. err := sendMediaTrack.WriteRTP(conn.sendMediaTrackPacket)
  1833. if err != nil {
  1834. return 0, errors.Trace(err)
  1835. }
  1836. conn.sendMediaTrackRemainingFrameSize -= len(paddedPayload)
  1837. if conn.sendMediaTrackRemainingFrameSize <= 0 {
  1838. conn.sendMediaTrackPacket.Timestamp += uint32(conn.sendMediaTrackTimestampTick)
  1839. conn.sendMediaTrackRemainingFrameSize = prng.Range(conn.sendMediaTrackFrameSizeRange[0], conn.sendMediaTrackFrameSizeRange[1])
  1840. }
  1841. return len(p), nil
  1842. }
  1843. func (conn *webRTCConn) addRTPReliabilityLayer(ctx context.Context) error {
  1844. // Add a QUIC layer over the SRTP packet flow to provide reliable delivery
  1845. // and ordering. The proxy runs a QUIC server and the client runs a QUIC
  1846. // client that connects to the proxy's server. As all of the QUIC traffic
  1847. // is encapsulated in the secure SRTP layer.
  1848. // Wrap the RTP track read and write operations in a mediaTrackPacketConn
  1849. // provides the net.PacketConn interface required by quic-go. There is no
  1850. // Close-on-error for mediaTrackPacketConn since it doesn't allocate or use
  1851. // any resources.
  1852. mediaTrackPacketConn := newMediaTrackPacketConn(conn)
  1853. // Use the Psiphon QUIC obfuscated PSK mechanism to facilitate a faster
  1854. // QUIC TLS handshake. QUIC client hello randomization is also
  1855. // initialized, as it will vary the QUIC handshake traffic shape within
  1856. // the SRTP packet flow.
  1857. var obfuscatedPSKKey [32]byte
  1858. obfuscationSecret, err := deriveObfuscationSecret(
  1859. conn.config.ClientRootObfuscationSecret, "in-proxy-RTP-QUIC-reliability-layer")
  1860. if err != nil {
  1861. return errors.Trace(err)
  1862. }
  1863. obfuscationSeed := prng.Seed(obfuscationSecret)
  1864. copy(obfuscatedPSKKey[:], prng.NewPRNGWithSeed(&obfuscationSeed).Bytes(len(obfuscatedPSKKey)))
  1865. // To effectively disable them, quic-go's idle timeouts and keep-alives
  1866. // are initialized to the maximum possible duration. The higher-level
  1867. // WebRTC connection will provide this functionality.
  1868. maxDuration := time.Duration(math.MaxInt64)
  1869. // Set the handshake timeout to align with the ctx deadline. Setting
  1870. // HandshakeIdleTimeout to maxDuration causes the quic-go dial to fail.
  1871. // Assumes ctx has a deadline.
  1872. deadline, _ := ctx.Deadline()
  1873. handshakeIdleTimeout := time.Until(deadline) / 2
  1874. if conn.isOffer {
  1875. // The client is a QUIC client.
  1876. // Initialize the obfuscated PSK.
  1877. sessionCache := common.WrapClientSessionCache(tls.NewLRUClientSessionCache(1), "")
  1878. obfuscatedSessionState, err := tls.NewObfuscatedClientSessionState(
  1879. obfuscatedPSKKey, true, false)
  1880. if err != nil {
  1881. return errors.Trace(err)
  1882. }
  1883. sessionCache.Put(
  1884. "", tls.MakeClientSessionState(
  1885. obfuscatedSessionState.SessionTicket,
  1886. obfuscatedSessionState.Vers,
  1887. obfuscatedSessionState.CipherSuite,
  1888. obfuscatedSessionState.MasterSecret,
  1889. obfuscatedSessionState.CreatedAt,
  1890. obfuscatedSessionState.AgeAdd,
  1891. obfuscatedSessionState.UseBy))
  1892. tlsConfig := &tls.Config{
  1893. InsecureSkipVerify: true,
  1894. InsecureSkipTimeVerify: true,
  1895. NextProtos: []string{"h3"},
  1896. ServerName: values.GetHostName(),
  1897. ClientSessionCache: sessionCache,
  1898. }
  1899. isIPv6 := true // remote addr is synthetic uniqueIPv6Address
  1900. maxPacketSizeAdjustment := GetQUICMaxPacketSizeAdjustment(isIPv6)
  1901. // Set ClientMaxPacketSizeAdjustment to so that quic-go will produce
  1902. // packets with a small enough max size to produce the overall target
  1903. // packet MTU.
  1904. quicConfig := &quic_go.Config{
  1905. HandshakeIdleTimeout: handshakeIdleTimeout,
  1906. MaxIdleTimeout: maxDuration,
  1907. KeepAlivePeriod: maxDuration,
  1908. Versions: []quic_go.VersionNumber{0x1},
  1909. ClientHelloSeed: &obfuscationSeed,
  1910. ClientMaxPacketSizeAdjustment: maxPacketSizeAdjustment,
  1911. DisablePathMTUDiscovery: true,
  1912. }
  1913. deadline, ok := ctx.Deadline()
  1914. if ok {
  1915. quicConfig.HandshakeIdleTimeout = time.Until(deadline)
  1916. }
  1917. // Establish the QUIC connection with the server and open a single
  1918. // data stream for relaying traffic.
  1919. //
  1920. // Use DialEarly, in combination with the "established" PSK, for
  1921. // 0-RTT, which potentially allows data to be sent with the
  1922. // handshake; this could include the open stream message from the
  1923. // following OpenStreamSync call. There is no replay concern with
  1924. // 0-RTT here, as the QUIC traffic is encapsualted in the secure SRTP
  1925. // flow.
  1926. quicConn, err := quic_go.DialEarly(
  1927. ctx,
  1928. mediaTrackPacketConn,
  1929. mediaTrackPacketConn.remoteAddr,
  1930. tlsConfig,
  1931. quicConfig)
  1932. if err != nil {
  1933. return errors.Trace(err)
  1934. }
  1935. quicStream, err := quicConn.OpenStreamSync(ctx)
  1936. if err != nil {
  1937. // Ensure any background quic-go goroutines are stopped.
  1938. _ = quicConn.CloseWithError(0, "")
  1939. return errors.Trace(err)
  1940. }
  1941. conn.mediaTrackReliabilityLayer = &reliableConn{
  1942. mediaTrackConn: mediaTrackPacketConn,
  1943. quicConn: quicConn,
  1944. quicStream: quicStream,
  1945. }
  1946. return nil
  1947. } else {
  1948. // The proxy is a QUIC server.
  1949. // Use an ephemeral, self-signed certificate.
  1950. certificate, privateKey, _, err := common.GenerateWebServerCertificate(
  1951. values.GetHostName())
  1952. if err != nil {
  1953. return errors.Trace(err)
  1954. }
  1955. tlsCertificate, err := tls.X509KeyPair([]byte(certificate), []byte(privateKey))
  1956. if err != nil {
  1957. return errors.Trace(err)
  1958. }
  1959. tlsConfig := &tls.Config{
  1960. Certificates: []tls.Certificate{tlsCertificate},
  1961. NextProtos: []string{"h3"},
  1962. }
  1963. tlsConfig.SetSessionTicketKeys([][32]byte{
  1964. obfuscatedPSKKey,
  1965. })
  1966. // Anti-probing via VerifyClientHelloRandom, for passthrough, is not
  1967. // necessary here and is not initialized.
  1968. quicConfig := &quic_go.Config{
  1969. Allow0RTT: true,
  1970. HandshakeIdleTimeout: handshakeIdleTimeout,
  1971. MaxIdleTimeout: maxDuration,
  1972. KeepAlivePeriod: maxDuration,
  1973. MaxIncomingStreams: 1,
  1974. MaxIncomingUniStreams: -1,
  1975. VerifyClientHelloRandom: nil,
  1976. ServerMaxPacketSizeAdjustment: func(addr net.Addr) int {
  1977. isIPv6 := true // remote addr is synthetic uniqueIPv6Address
  1978. return GetQUICMaxPacketSizeAdjustment(isIPv6)
  1979. },
  1980. }
  1981. quicTransport := &quic_go.Transport{
  1982. Conn: mediaTrackPacketConn,
  1983. DisableVersionNegotiationPackets: true,
  1984. }
  1985. quicListener, err := quicTransport.ListenEarly(tlsConfig, quicConfig)
  1986. if err != nil {
  1987. return errors.Trace(err)
  1988. }
  1989. // Accept the single expected QUIC client and its QUIC data stream.
  1990. quicConn, err := quicListener.Accept(ctx)
  1991. if err != nil {
  1992. _ = quicTransport.Close()
  1993. return errors.Trace(err)
  1994. }
  1995. quicStream, err := quicConn.AcceptStream(ctx)
  1996. if err != nil {
  1997. _ = quicConn.CloseWithError(0, "")
  1998. _ = quicTransport.Close()
  1999. return errors.Trace(err)
  2000. }
  2001. // Closing the quic-go Transport/Listener closes all client
  2002. // connections, so retain the Transport for the duration of the
  2003. // overall connection.
  2004. conn.mediaTrackReliabilityLayer = &reliableConn{
  2005. mediaTrackConn: mediaTrackPacketConn,
  2006. quicTransport: quicTransport,
  2007. quicConn: quicConn,
  2008. quicStream: quicStream,
  2009. }
  2010. return nil
  2011. }
  2012. }
  2013. // incrementingIPv6Address provides successive, distinct IPv6 addresses from
  2014. // the 2001:db8::/32 range, reserved for documentation purposes as defined in
  2015. // RFC 3849. It will wrap after 2^96 calls.
  2016. type incrementingIPv6Address struct {
  2017. mutex sync.Mutex
  2018. ip [12]byte
  2019. }
  2020. var uniqueIPv6Address incrementingIPv6Address
  2021. func (inc *incrementingIPv6Address) next() net.IP {
  2022. inc.mutex.Lock()
  2023. defer inc.mutex.Unlock()
  2024. for i := 11; i >= 0; i-- {
  2025. inc.ip[i]++
  2026. if inc.ip[i] != 0 {
  2027. break
  2028. }
  2029. }
  2030. ip := make([]byte, 16)
  2031. copy(ip[0:4], []byte{0x20, 0x01, 0x0d, 0xb8})
  2032. copy(ip[4:16], inc.ip[:])
  2033. return net.IP(ip)
  2034. }
  2035. // mediaTrackPacketConn provides the required net.PacketConn interface for
  2036. // quic-go to use to read and write packets to the RTP media track conn.
  2037. type mediaTrackPacketConn struct {
  2038. webRTCConn *webRTCConn
  2039. localAddr net.Addr
  2040. remoteAddr net.Addr
  2041. isClosed int32
  2042. }
  2043. func newMediaTrackPacketConn(conn *webRTCConn) *mediaTrackPacketConn {
  2044. // Create distinct, artificial local/remote addrs for the synthetic
  2045. // net.PacketConn.
  2046. //
  2047. // For its local operations, quic-go references local/remote addrs for the
  2048. // net.PacketConns it uses. Furthermore, the quic-go server listener
  2049. // currently uses a singleton multiplexer, connMultiplexer, which panics
  2050. // if multiple conns with the same local addr are added. Since this is a
  2051. // singleton, this panic occurs even when using distinct quic-go
  2052. // listeners per conn.
  2053. //
  2054. // No actual network traffic is sent to these artificial addresses.
  2055. ip := uniqueIPv6Address.next()
  2056. localAddr := &net.UDPAddr{IP: ip, Port: 1}
  2057. remoteAddr := &net.UDPAddr{IP: ip, Port: 2}
  2058. return &mediaTrackPacketConn{
  2059. webRTCConn: conn,
  2060. localAddr: localAddr,
  2061. remoteAddr: remoteAddr,
  2062. }
  2063. }
  2064. func (conn *mediaTrackPacketConn) ReadFrom(p []byte) (int, net.Addr, error) {
  2065. if atomic.LoadInt32(&conn.isClosed) == 1 {
  2066. return 0, conn.remoteAddr, errors.TraceNew("closed")
  2067. }
  2068. n, err := conn.webRTCConn.readMediaTrack(p)
  2069. return n, conn.remoteAddr, errors.TraceReader(err)
  2070. }
  2071. func (conn *mediaTrackPacketConn) WriteTo(p []byte, addr net.Addr) (int, error) {
  2072. if atomic.LoadInt32(&conn.isClosed) == 1 {
  2073. return 0, errors.TraceNew("closed")
  2074. }
  2075. n, err := conn.webRTCConn.writeMediaTrackPacket(p, false)
  2076. return n, errors.Trace(err)
  2077. }
  2078. func (conn *mediaTrackPacketConn) Close() error {
  2079. if !atomic.CompareAndSwapInt32(&conn.isClosed, 0, 1) {
  2080. return nil
  2081. }
  2082. return nil
  2083. }
  2084. func (conn *mediaTrackPacketConn) LocalAddr() net.Addr {
  2085. return conn.localAddr
  2086. }
  2087. func (conn *mediaTrackPacketConn) SetDeadline(t time.Time) error {
  2088. return errors.TraceNew("not supported")
  2089. }
  2090. func (conn *mediaTrackPacketConn) SetReadDeadline(t time.Time) error {
  2091. // When a quic-go DialEarly fails, it invokes Transport.Close. In turn,
  2092. // Transport.Close calls this SetReadDeadline in order to interrupt any
  2093. // blocked read. The underlying pion/webrtc.TrackRemote has a
  2094. // SetReadDeadline. However, at this time webRTCConn.receiveMediaTrack
  2095. // may be nil, and readMediaTrack may be blocking on
  2096. // receiveMediaTrackOpenedSignal.
  2097. //
  2098. // Simply calling webRTCConn.Close unblocks both that case and the case
  2099. // where receiveMediaTrack exists and is blocked on read.
  2100. //
  2101. // Invoke in a goroutine to avoid a deadlock that would otherwise occur
  2102. // when webRTCConn.Close is invoked directly, as it will call down to
  2103. // mediaTrackPacketConn.SetReadDeadline via reliableConn.Close. The
  2104. // webRTCConn.Close isClosed check ensures there isn't an endless loop of
  2105. // calls.
  2106. //
  2107. // Assumes that mediaTrackPacketConn.SetReadDeadline is called only in
  2108. // this terminating quic-go case.
  2109. go func() {
  2110. _ = conn.webRTCConn.Close()
  2111. }()
  2112. return nil
  2113. }
  2114. func (conn *mediaTrackPacketConn) SetWriteDeadline(t time.Time) error {
  2115. return errors.TraceNew("not supported")
  2116. }
  2117. // reliableConn provides a reliable/ordered delivery layer on top of the media
  2118. // track RTP conn. This is implemented as a QUIC connection.
  2119. type reliableConn struct {
  2120. mediaTrackConn *mediaTrackPacketConn
  2121. quicTransport *quic_go.Transport
  2122. quicConn quic_go.EarlyConnection
  2123. quicStream quic_go.Stream
  2124. readMutex sync.Mutex
  2125. writeMutex sync.Mutex
  2126. isClosed int32
  2127. }
  2128. func (conn *reliableConn) Read(b []byte) (int, error) {
  2129. if atomic.LoadInt32(&conn.isClosed) == 1 {
  2130. return 0, errors.TraceNew("closed")
  2131. }
  2132. // Add mutex to provide full net.Conn concurrency semantics.
  2133. // https://github.com/lucas-clemente/quic-go/blob/9cc23135d0477baf83aa4715de39ae7070039cb2/stream.go#L64
  2134. // "Read() and Write() may be called concurrently, but multiple calls to
  2135. // "Read() or Write() individually must be synchronized manually."
  2136. conn.readMutex.Lock()
  2137. defer conn.readMutex.Unlock()
  2138. n, err := conn.quicStream.Read(b)
  2139. if quic.IsIETFErrorIndicatingClosed(err) {
  2140. _ = conn.Close()
  2141. err = io.EOF
  2142. }
  2143. return n, errors.TraceReader(err)
  2144. }
  2145. func (conn *reliableConn) Write(b []byte) (int, error) {
  2146. if atomic.LoadInt32(&conn.isClosed) == 1 {
  2147. return 0, errors.TraceNew("closed")
  2148. }
  2149. conn.writeMutex.Lock()
  2150. defer conn.writeMutex.Unlock()
  2151. n, err := conn.quicStream.Write(b)
  2152. if quic.IsIETFErrorIndicatingClosed(err) {
  2153. _ = conn.Close()
  2154. if n == len(b) {
  2155. err = nil
  2156. }
  2157. }
  2158. return n, errors.Trace(err)
  2159. }
  2160. func (conn *reliableConn) Close() error {
  2161. if !atomic.CompareAndSwapInt32(&conn.isClosed, 0, 1) {
  2162. return nil
  2163. }
  2164. // Close mediaTrackConn first, or else quic-go's Close will attempt to
  2165. // Write, which leads to deadlock between webRTCConn.writeMediaTrack and
  2166. // webRTCConn.Close. The graceful QUIC close write will fails, but that's
  2167. // not an issue.
  2168. _ = conn.mediaTrackConn.Close()
  2169. err := conn.quicConn.CloseWithError(0, "")
  2170. if conn.quicTransport != nil {
  2171. conn.quicTransport.Close()
  2172. }
  2173. return errors.Trace(err)
  2174. }
  2175. func (conn *reliableConn) LocalAddr() net.Addr {
  2176. return conn.quicConn.LocalAddr()
  2177. }
  2178. func (conn *reliableConn) RemoteAddr() net.Addr {
  2179. return conn.quicConn.RemoteAddr()
  2180. }
  2181. func (conn *reliableConn) SetDeadline(t time.Time) error {
  2182. return conn.quicStream.SetDeadline(t)
  2183. }
  2184. func (conn *reliableConn) SetReadDeadline(t time.Time) error {
  2185. return conn.quicStream.SetReadDeadline(t)
  2186. }
  2187. func (conn *reliableConn) SetWriteDeadline(t time.Time) error {
  2188. return conn.quicStream.SetWriteDeadline(t)
  2189. }
  2190. // prepareSDPAddresses adjusts the SDP, pruning local network addresses and
  2191. // adding any port mapping as a host candidate.
  2192. func prepareSDPAddresses(
  2193. encodedSDP []byte,
  2194. errorOnNoCandidates bool,
  2195. portMappingExternalAddr string,
  2196. disableIPv6Candidates bool,
  2197. allowPrivateIPAddressCandidates bool) ([]byte, *webRTCSDPMetrics, error) {
  2198. modifiedSDP, metrics, err := processSDPAddresses(
  2199. encodedSDP,
  2200. errorOnNoCandidates,
  2201. portMappingExternalAddr,
  2202. disableIPv6Candidates,
  2203. allowPrivateIPAddressCandidates,
  2204. false,
  2205. nil,
  2206. common.GeoIPData{})
  2207. return modifiedSDP, metrics, errors.Trace(err)
  2208. }
  2209. // filterSDPAddresses checks that the SDP does not contain an empty list of
  2210. // candidates, bogon candidates, or candidates outside of the country and ASN
  2211. // for the specified expectedGeoIPData. Invalid candidates are stripped and a
  2212. // filtered SDP is returned.
  2213. func filterSDPAddresses(
  2214. encodedSDP []byte,
  2215. errorOnNoCandidates bool,
  2216. lookupGeoIP LookupGeoIP,
  2217. expectedGeoIPData common.GeoIPData,
  2218. allowPrivateIPAddressCandidates bool,
  2219. filterPrivateIPAddressCandidates bool) ([]byte, *webRTCSDPMetrics, error) {
  2220. filteredSDP, metrics, err := processSDPAddresses(
  2221. encodedSDP,
  2222. errorOnNoCandidates,
  2223. "",
  2224. false,
  2225. allowPrivateIPAddressCandidates,
  2226. filterPrivateIPAddressCandidates,
  2227. lookupGeoIP,
  2228. expectedGeoIPData)
  2229. return filteredSDP, metrics, errors.Trace(err)
  2230. }
  2231. // webRTCSDPMetrics are network capability metrics values for an SDP.
  2232. type webRTCSDPMetrics struct {
  2233. iceCandidateTypes []ICECandidateType
  2234. hasIPv6 bool
  2235. hasPrivateIP bool
  2236. filteredICECandidates []string
  2237. }
  2238. // processSDPAddresses is based on snowflake/common/util.StripLocalAddresses
  2239. // https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/blob/v2.5.1/common/util/util.go#L70-99
  2240. /*
  2241. This file contains the license for "Snowflake"
  2242. a free software project which provides a WebRTC pluggable transport.
  2243. ================================================================================
  2244. Copyright (c) 2016, Serene Han, Arlo Breault
  2245. Copyright (c) 2019-2020, The Tor Project, Inc
  2246. Redistribution and use in source and binary forms, with or without modification,
  2247. are permitted provided that the following conditions are met:
  2248. * Redistributions of source code must retain the above copyright notice, this
  2249. list of conditions and the following disclaimer.
  2250. * Redistributions in binary form must reproduce the above copyright notice,
  2251. this list of conditions and the following disclaimer in the documentation and/or
  2252. other materials provided with the distribution.
  2253. * Neither the names of the copyright owners nor the names of its
  2254. contributors may be used to endorse or promote products derived from this
  2255. software without specific prior written permission.
  2256. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  2257. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  2258. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  2259. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  2260. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  2261. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  2262. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  2263. ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  2264. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  2265. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  2266. ================================================================================
  2267. */
  2268. func processSDPAddresses(
  2269. encodedSDP []byte,
  2270. errorOnNoCandidates bool,
  2271. portMappingExternalAddr string,
  2272. disableIPv6Candidates bool,
  2273. allowPrivateIPAddressCandidates bool,
  2274. filterPrivateIPAddressCandidates bool,
  2275. lookupGeoIP LookupGeoIP,
  2276. expectedGeoIPData common.GeoIPData) ([]byte, *webRTCSDPMetrics, error) {
  2277. var sessionDescription sdp.SessionDescription
  2278. err := sessionDescription.Unmarshal(encodedSDP)
  2279. if err != nil {
  2280. return nil, nil, errors.Trace(err)
  2281. }
  2282. candidateTypes := map[ICECandidateType]bool{}
  2283. hasIPv6 := false
  2284. hasPrivateIP := false
  2285. filteredCandidateReasons := make(map[string]int)
  2286. var portMappingICECandidates []sdp.Attribute
  2287. if portMappingExternalAddr != "" {
  2288. // Prepare ICE candidate attibute pair for the port mapping, modeled
  2289. // after the definition of host candidates.
  2290. host, portStr, err := net.SplitHostPort(portMappingExternalAddr)
  2291. if err != nil {
  2292. return nil, nil, errors.Trace(err)
  2293. }
  2294. port, err := strconv.Atoi(portStr)
  2295. if err != nil {
  2296. return nil, nil, errors.Trace(err)
  2297. }
  2298. // Only IPv4 port mapping addresses are supported due to the
  2299. // NewCandidateHost limitation noted below. It is expected that port
  2300. // mappings will be IPv4, as NAT and IPv6 is not a typical combination.
  2301. hostIP := net.ParseIP(host)
  2302. if hostIP != nil && hostIP.To4() != nil {
  2303. for _, component := range []webrtc.ICEComponent{webrtc.ICEComponentRTP, webrtc.ICEComponentRTCP} {
  2304. // The candidate ID is generated and the priority and foundation
  2305. // use the default for hosts.
  2306. //
  2307. // Limitation: NewCandidateHost initializes the networkType to
  2308. // NetworkTypeUDP4, and this field is not-exported.
  2309. // https://github.com/pion/ice/blob/6d301287654b05a36248842c278d58d501454bff/candidate_host.go#L27-L64
  2310. iceCandidate, err := ice.NewCandidateHost(&ice.CandidateHostConfig{
  2311. Network: "udp",
  2312. Address: host,
  2313. Port: port,
  2314. Component: uint16(component),
  2315. })
  2316. if err != nil {
  2317. return nil, nil, errors.Trace(err)
  2318. }
  2319. portMappingICECandidates = append(
  2320. portMappingICECandidates,
  2321. sdp.Attribute{Key: "candidate", Value: iceCandidate.Marshal()})
  2322. }
  2323. candidateTypes[ICECandidatePortMapping] = true
  2324. }
  2325. }
  2326. candidateCount := len(portMappingICECandidates)
  2327. for _, mediaDescription := range sessionDescription.MediaDescriptions {
  2328. addPortMappingCandidates := len(portMappingICECandidates) > 0
  2329. var attributes []sdp.Attribute
  2330. for _, attribute := range mediaDescription.Attributes {
  2331. // Insert the port mapping candidate either before the
  2332. // first "a=candidate", or before "a=end-of-candidates"(there may
  2333. // be no "a=candidate" attributes).
  2334. if addPortMappingCandidates &&
  2335. (attribute.IsICECandidate() || attribute.Key == sdp.AttrKeyEndOfCandidates) {
  2336. attributes = append(attributes, portMappingICECandidates...)
  2337. addPortMappingCandidates = false
  2338. }
  2339. if attribute.IsICECandidate() {
  2340. candidate, err := ice.UnmarshalCandidate(attribute.Value)
  2341. if err != nil {
  2342. return nil, nil, errors.Trace(err)
  2343. }
  2344. candidateIP := net.ParseIP(candidate.Address())
  2345. if candidateIP == nil {
  2346. return nil, nil, errors.TraceNew("unexpected non-IP")
  2347. }
  2348. candidateIsIPv6 := false
  2349. if candidateIP.To4() == nil {
  2350. if disableIPv6Candidates {
  2351. reason := fmt.Sprintf("disabled %s IPv6",
  2352. candidate.Type().String())
  2353. filteredCandidateReasons[reason] += 1
  2354. continue
  2355. }
  2356. candidateIsIPv6 = true
  2357. }
  2358. // Strip non-routable bogons, including RFC 1918/4193 private
  2359. // IP addresses. Same-LAN client/proxy hops are not expected
  2360. // to be useful, and this also avoids unnecessary network traffic.
  2361. //
  2362. // Well-behaved clients and proxies should strip these values;
  2363. // the broker enforces this with filtering.
  2364. //
  2365. // In personal pairing mode, private IP addresses are allowed,
  2366. // as connection may be made between devices the same LAN and
  2367. // not all routers support NAT hairpinning.
  2368. candidateIsPrivateIP := candidateIP.IsPrivate()
  2369. if !GetAllowBogonWebRTCConnections() &&
  2370. !(candidateIsPrivateIP && allowPrivateIPAddressCandidates) &&
  2371. common.IsBogon(candidateIP) {
  2372. version := "IPv4"
  2373. if candidateIsIPv6 {
  2374. version = "IPv6"
  2375. }
  2376. reason := fmt.Sprintf("bogon %s %s",
  2377. candidate.Type().String(), version)
  2378. filteredCandidateReasons[reason] += 1
  2379. continue
  2380. }
  2381. // In personal pairing mode, filter out any private IP
  2382. // addresses for which there is no corresponding local,
  2383. // active interface. This avoids unnecessary network traffic.
  2384. // This filtering option is applied post-broker exchange,
  2385. // with the SDP received, via the broker, from the peer.
  2386. if candidateIsPrivateIP && filterPrivateIPAddressCandidates {
  2387. if !hasInterfaceForPrivateIPAddress(candidateIP) {
  2388. continue
  2389. }
  2390. }
  2391. // The broker will check that clients and proxies specify only
  2392. // candidates that map to the same GeoIP country and ASN as
  2393. // the client/proxy connection to the broker. This limits
  2394. // misuse of candidates to connect to other locations.
  2395. // Legitimate candidates will not all have the exact same IP
  2396. // address, as there could be a mix of IPv4 and IPv6, as well
  2397. // as potentially different NAT paths.
  2398. //
  2399. // In some cases, legitimate clients and proxies may
  2400. // unintentionally submit candidates with mismatching GeoIP.
  2401. // This can occur, for example, when a STUN candidate is only
  2402. // a partial hole punch through double NAT, and when internal
  2403. // network addresses misuse non-private IP ranges (so are
  2404. // technically not bogons). Instead of outright rejecting
  2405. // SDPs containing unexpected GeoIP candidates, they are
  2406. // instead stripped out and the resulting filtered SDP is
  2407. // used.
  2408. if lookupGeoIP != nil {
  2409. candidateGeoIPData := lookupGeoIP(candidate.Address())
  2410. if candidateGeoIPData.Country != expectedGeoIPData.Country ||
  2411. candidateGeoIPData.ASN != expectedGeoIPData.ASN {
  2412. version := "IPv4"
  2413. if candidateIsIPv6 {
  2414. version = "IPv6"
  2415. }
  2416. reason := fmt.Sprintf(
  2417. "unexpected GeoIP %s %s: %s/%s",
  2418. candidate.Type().String(),
  2419. version,
  2420. candidateGeoIPData.Country,
  2421. candidateGeoIPData.ASN)
  2422. filteredCandidateReasons[reason] += 1
  2423. continue
  2424. }
  2425. }
  2426. if candidateIsIPv6 {
  2427. hasIPv6 = true
  2428. }
  2429. if candidateIsPrivateIP {
  2430. hasPrivateIP = true
  2431. }
  2432. // These types are not reported:
  2433. // - CandidateTypeRelay: TURN servers are not used.
  2434. // - CandidateTypePeerReflexive: this candidate type only
  2435. // emerges later in the connection process.
  2436. switch candidate.Type() {
  2437. case ice.CandidateTypeHost:
  2438. candidateTypes[ICECandidateHost] = true
  2439. case ice.CandidateTypeServerReflexive:
  2440. candidateTypes[ICECandidateServerReflexive] = true
  2441. }
  2442. candidateCount += 1
  2443. }
  2444. attributes = append(attributes, attribute)
  2445. }
  2446. mediaDescription.Attributes = attributes
  2447. }
  2448. if errorOnNoCandidates && candidateCount == 0 {
  2449. return nil, nil, errors.TraceNew("no candidates")
  2450. }
  2451. encodedSDP, err = sessionDescription.Marshal()
  2452. if err != nil {
  2453. return nil, nil, errors.Trace(err)
  2454. }
  2455. metrics := &webRTCSDPMetrics{
  2456. hasIPv6: hasIPv6,
  2457. hasPrivateIP: hasPrivateIP,
  2458. }
  2459. for candidateType := range candidateTypes {
  2460. metrics.iceCandidateTypes = append(metrics.iceCandidateTypes, candidateType)
  2461. }
  2462. for reason, count := range filteredCandidateReasons {
  2463. metrics.filteredICECandidates = append(metrics.filteredICECandidates,
  2464. fmt.Sprintf("%s: %d", reason, count))
  2465. }
  2466. return encodedSDP, metrics, nil
  2467. }
  2468. type pionLoggerFactory struct {
  2469. logger common.Logger
  2470. stopLogging func() bool
  2471. debugLogging bool
  2472. }
  2473. func newPionLoggerFactory(
  2474. logger common.Logger, stopLogging func() bool, debugLogging bool) *pionLoggerFactory {
  2475. return &pionLoggerFactory{
  2476. logger: logger,
  2477. stopLogging: stopLogging,
  2478. debugLogging: debugLogging,
  2479. }
  2480. }
  2481. func (f *pionLoggerFactory) NewLogger(scope string) pion_logging.LeveledLogger {
  2482. return newPionLogger(scope, f.logger, f.stopLogging, f.debugLogging)
  2483. }
  2484. // pionLogger wraps common.Logger and implements
  2485. // https://pkg.go.dev/github.com/pion/logging#LeveledLogger for passing into
  2486. // pion.
  2487. type pionLogger struct {
  2488. scope string
  2489. logger common.Logger
  2490. stopLogging func() bool
  2491. debugLogging bool
  2492. warnNoPairs int32
  2493. }
  2494. func newPionLogger(
  2495. scope string, logger common.Logger, stopLogging func() bool, debugLogging bool) *pionLogger {
  2496. return &pionLogger{
  2497. scope: scope,
  2498. logger: logger,
  2499. stopLogging: stopLogging,
  2500. debugLogging: debugLogging,
  2501. }
  2502. }
  2503. func (l *pionLogger) Trace(msg string) {
  2504. if l.stopLogging() || !l.debugLogging {
  2505. return
  2506. }
  2507. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  2508. }
  2509. func (l *pionLogger) Tracef(format string, args ...interface{}) {
  2510. if l.stopLogging() || !l.debugLogging {
  2511. return
  2512. }
  2513. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2514. }
  2515. func (l *pionLogger) Debug(msg string) {
  2516. if l.stopLogging() || !l.debugLogging {
  2517. return
  2518. }
  2519. l.logger.WithTrace().Debug(fmt.Sprintf("[webRTC: %s: %s", l.scope, msg))
  2520. }
  2521. func (l *pionLogger) Debugf(format string, args ...interface{}) {
  2522. if l.stopLogging() || !l.debugLogging {
  2523. return
  2524. }
  2525. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2526. }
  2527. func (l *pionLogger) Info(msg string) {
  2528. if l.stopLogging() {
  2529. return
  2530. }
  2531. l.logger.WithTrace().Info(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  2532. }
  2533. func (l *pionLogger) Infof(format string, args ...interface{}) {
  2534. if l.stopLogging() {
  2535. return
  2536. }
  2537. l.logger.WithTrace().Info(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2538. }
  2539. func (l *pionLogger) Warn(msg string) {
  2540. if l.stopLogging() {
  2541. return
  2542. }
  2543. // To reduce diagnostic log noise, only log this message once per dial attempt.
  2544. if msg == "Failed to ping without candidate pairs. Connection is not possible yet." &&
  2545. !atomic.CompareAndSwapInt32(&l.warnNoPairs, 0, 1) {
  2546. return
  2547. }
  2548. l.logger.WithTrace().Warning(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  2549. }
  2550. func (l *pionLogger) Warnf(format string, args ...interface{}) {
  2551. if l.stopLogging() {
  2552. return
  2553. }
  2554. l.logger.WithTrace().Warning(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2555. }
  2556. func (l *pionLogger) Error(msg string) {
  2557. if l.stopLogging() {
  2558. return
  2559. }
  2560. l.logger.WithTrace().Error(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  2561. }
  2562. func (l *pionLogger) Errorf(format string, args ...interface{}) {
  2563. if l.stopLogging() {
  2564. return
  2565. }
  2566. l.logger.WithTrace().Error(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2567. }
  2568. func hasInterfaceForPrivateIPAddress(IP net.IP) bool {
  2569. if !IP.IsPrivate() {
  2570. return false
  2571. }
  2572. // The anet package is used to work around net.Interfaces not working on
  2573. // Android at this time: https://github.com/golang/go/issues/40569.
  2574. //
  2575. // Any errors are silently dropped; the caller will proceed without using
  2576. // the input private IP; and equivalent anet calls are made in
  2577. // pionNetwork.Interfaces, with errors logged.
  2578. netInterfaces, err := anet.Interfaces()
  2579. if err != nil {
  2580. return false
  2581. }
  2582. for _, netInterface := range netInterfaces {
  2583. // Note: don't exclude interfaces with the net.FlagPointToPoint flag,
  2584. // which is set for certain mobile networks
  2585. if netInterface.Flags&net.FlagUp == 0 {
  2586. continue
  2587. }
  2588. addrs, err := anet.InterfaceAddrsByInterface(&netInterface)
  2589. if err != nil {
  2590. continue
  2591. }
  2592. for _, addr := range addrs {
  2593. _, IPNet, err := net.ParseCIDR(addr.String())
  2594. if err != nil {
  2595. continue
  2596. }
  2597. if IPNet.Contains(IP) {
  2598. return true
  2599. }
  2600. }
  2601. }
  2602. return false
  2603. }
  2604. // pionNetwork implements pion/transport.Net.
  2605. //
  2606. // Via the SettingsEngine, pion is configured to use a pionNetwork instance,
  2607. // which providing alternative implementations for various network functions.
  2608. // The Interfaces implementation provides a workaround for Android
  2609. // net.Interfaces issues and reduces the number of IPv6 candidates to avoid
  2610. // excess STUN requests; and the ResolveUDPAddr implementation hooks into the
  2611. // Psiphon custom resolver.
  2612. type pionNetwork struct {
  2613. dialCtx context.Context
  2614. logger pion_logging.LeveledLogger
  2615. webRTCDialCoordinator WebRTCDialCoordinator
  2616. }
  2617. func newPionNetwork(
  2618. dialCtx context.Context,
  2619. logger pion_logging.LeveledLogger,
  2620. webRTCDialCoordinator WebRTCDialCoordinator) *pionNetwork {
  2621. return &pionNetwork{
  2622. dialCtx: dialCtx,
  2623. logger: logger,
  2624. webRTCDialCoordinator: webRTCDialCoordinator,
  2625. }
  2626. }
  2627. func (p *pionNetwork) Interfaces() ([]*transport.Interface, error) {
  2628. // To determine the active IPv4 and IPv6 interfaces, let the OS bind IPv4
  2629. // and IPv6 UDP sockets with a specified external destination address.
  2630. // Then iterate over all interfaces, but return interface info for only
  2631. // the interfaces those sockets were bound to.
  2632. //
  2633. // The destination IPs are the IPs that currently resolve for example.com.
  2634. // No actual traffic to these IPs or example.com is sent, as the UDP
  2635. // sockets are not used to send any packets.
  2636. //
  2637. // This scheme should select just one IPv4 and one IPv6 address, which
  2638. // should be the active, externally routable addresses, and the IPv6
  2639. // address should be the preferred, non-deprecated temporary IPv6 address.
  2640. //
  2641. // In post-ICE gathering processing, processSDPAddresses will also strip
  2642. // all bogon addresses, so there is no explicit bogon check here.
  2643. //
  2644. // Limitations:
  2645. //
  2646. // - The active interface could change between the socket operation and
  2647. // iterating over all interfaces. Higher-level code is expected to
  2648. // react to active network changes.
  2649. //
  2650. // - The public IPs for example.com may not be robust in all routing
  2651. // situations. Alternatively, we could use the configured STUN server
  2652. // as the test destination, but the STUN server domain is not resolved
  2653. // at this point and STUN is not always configured and used.
  2654. //
  2655. // - The results could be cached and reused.
  2656. var defaultIPv4, defaultIPv6 net.IP
  2657. udpConnIPv4, err := p.webRTCDialCoordinator.UDPConn(
  2658. context.Background(), "udp4", "93.184.216.34:3478")
  2659. if err == nil {
  2660. defaultIPv4 = udpConnIPv4.LocalAddr().(*net.UDPAddr).IP
  2661. udpConnIPv4.Close()
  2662. }
  2663. udpConnIPv6, err := p.webRTCDialCoordinator.UDPConn(
  2664. context.Background(), "udp6", "[2606:2800:220:1:248:1893:25c8:1946]:3478")
  2665. if err == nil {
  2666. defaultIPv6 = udpConnIPv6.LocalAddr().(*net.UDPAddr).IP
  2667. udpConnIPv6.Close()
  2668. }
  2669. // The anet package is used to work around net.Interfaces not working on
  2670. // Android at this time: https://github.com/golang/go/issues/40569.
  2671. transportInterfaces := []*transport.Interface{}
  2672. netInterfaces, err := anet.Interfaces()
  2673. if err != nil {
  2674. return nil, errors.Trace(err)
  2675. }
  2676. for _, netInterface := range netInterfaces {
  2677. // Note: don't exclude interfaces with the net.FlagPointToPoint flag,
  2678. // which is set for certain mobile networks
  2679. if (netInterface.Flags&net.FlagUp == 0) ||
  2680. (!GetAllowBogonWebRTCConnections() && (netInterface.Flags&net.FlagLoopback != 0)) {
  2681. continue
  2682. }
  2683. addrs, err := anet.InterfaceAddrsByInterface(&netInterface)
  2684. if err != nil {
  2685. return nil, errors.Trace(err)
  2686. }
  2687. var transportInterface *transport.Interface
  2688. for _, addr := range addrs {
  2689. IP, _, err := net.ParseCIDR(addr.String())
  2690. if err != nil {
  2691. return nil, errors.Trace(err)
  2692. }
  2693. if IP.Equal(defaultIPv4) || IP.Equal(defaultIPv6) ||
  2694. (GetAllowBogonWebRTCConnections() && (netInterface.Flags&net.FlagLoopback != 0)) {
  2695. if transportInterface == nil {
  2696. transportInterface = transport.NewInterface(netInterface)
  2697. }
  2698. transportInterface.AddAddress(addr)
  2699. }
  2700. }
  2701. if transportInterface != nil {
  2702. transportInterfaces = append(transportInterfaces, transportInterface)
  2703. }
  2704. }
  2705. return transportInterfaces, nil
  2706. }
  2707. func (p *pionNetwork) ResolveUDPAddr(network, address string) (retAddr *net.UDPAddr, retErr error) {
  2708. defer func() {
  2709. if retErr != nil {
  2710. // Explicitly log an error since certain pion operations -- e.g.,
  2711. // ICE gathering -- don't propagate all pion/transport.Net errors.
  2712. p.logger.Errorf("pionNetwork.ResolveUDPAddr failed: %v", retErr)
  2713. }
  2714. }()
  2715. // Currently, pion appears to call ResolveUDPAddr with "udp4"/udp6"
  2716. // instead of "ip4"/"ip6", as expected by, e.g., net.Resolver.LookupIP.
  2717. // Convert to "ip4"/"ip6".
  2718. // Specifying v4/v6 ensures that the resolved IP address is the correct
  2719. // type. In the case of STUN servers, the correct type is required in
  2720. // order to create the correct IPv4 or IPv6 whole punch address.
  2721. switch network {
  2722. case "udp4", "tcp4":
  2723. network = "ip4"
  2724. case "udp6", "tcp6":
  2725. network = "ip6"
  2726. default:
  2727. network = "ip"
  2728. }
  2729. // Currently, pion appears to call ResolveUDPAddr with an improperly
  2730. // formatted address, <IPv6>:443 not [<IPv6>]:443; handle this case.
  2731. index := strings.LastIndex(address, ":")
  2732. if index != -1 {
  2733. address = net.JoinHostPort(address[:index], address[index+1:])
  2734. }
  2735. // Use the Psiphon custom resolver to resolve any STUN server domains.
  2736. resolvedAddress, err := p.webRTCDialCoordinator.ResolveAddress(
  2737. p.dialCtx, network, address)
  2738. if err != nil {
  2739. return nil, errors.Trace(err)
  2740. }
  2741. IPStr, portStr, err := net.SplitHostPort(resolvedAddress)
  2742. if err != nil {
  2743. return nil, errors.Trace(err)
  2744. }
  2745. IP := net.ParseIP(IPStr)
  2746. if IP == nil {
  2747. return nil, errors.TraceNew("invalid IP address")
  2748. }
  2749. port, err := strconv.Atoi(portStr)
  2750. if err != nil {
  2751. return nil, errors.Trace(err)
  2752. }
  2753. return &net.UDPAddr{IP: IP, Port: port}, nil
  2754. }
  2755. var errNotSupported = std_errors.New("not supported")
  2756. func (p *pionNetwork) ListenPacket(network string, address string) (net.PacketConn, error) {
  2757. // Explicitly log an error since certain pion operations -- e.g., ICE
  2758. // gathering -- don't propagate all pion/transport.Net errors.
  2759. p.logger.Errorf("unexpected pionNetwork.ListenPacket call from %s", stacktrace.GetParentFunctionName())
  2760. return nil, errors.Trace(errNotSupported)
  2761. }
  2762. func (p *pionNetwork) ListenUDP(network string, locAddr *net.UDPAddr) (transport.UDPConn, error) {
  2763. p.logger.Errorf("unexpected pionNetwork.ListenUDP call from %s", stacktrace.GetParentFunctionName())
  2764. return nil, errors.Trace(errNotSupported)
  2765. }
  2766. func (p *pionNetwork) ListenTCP(network string, laddr *net.TCPAddr) (transport.TCPListener, error) {
  2767. p.logger.Errorf("unexpected pionNetwork.ListenTCP call from %s", stacktrace.GetParentFunctionName())
  2768. return nil, errors.Trace(errNotSupported)
  2769. }
  2770. func (p *pionNetwork) Dial(network, address string) (net.Conn, error) {
  2771. p.logger.Errorf("unexpected pionNetwork.Dial call from %s", stacktrace.GetParentFunctionName())
  2772. return nil, errors.Trace(errNotSupported)
  2773. }
  2774. func (p *pionNetwork) DialUDP(network string, laddr, raddr *net.UDPAddr) (transport.UDPConn, error) {
  2775. p.logger.Errorf("unexpected pionNetwork.DialUDP call from %s", stacktrace.GetParentFunctionName())
  2776. return nil, errors.Trace(errNotSupported)
  2777. }
  2778. func (p *pionNetwork) DialTCP(network string, laddr, raddr *net.TCPAddr) (transport.TCPConn, error) {
  2779. p.logger.Errorf("unexpected pionNetwork.DialTCP call from %s", stacktrace.GetParentFunctionName())
  2780. return nil, errors.Trace(errNotSupported)
  2781. }
  2782. func (p *pionNetwork) ResolveIPAddr(network, address string) (*net.IPAddr, error) {
  2783. p.logger.Errorf("unexpected pionNetwork.ResolveIPAddr call from %s", stacktrace.GetParentFunctionName())
  2784. return nil, errors.Trace(errNotSupported)
  2785. }
  2786. func (p *pionNetwork) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
  2787. p.logger.Errorf("unexpected pionNetwork.ResolveTCPAddr call from %s", stacktrace.GetParentFunctionName())
  2788. return nil, errors.Trace(errNotSupported)
  2789. }
  2790. func (p *pionNetwork) InterfaceByIndex(index int) (*transport.Interface, error) {
  2791. p.logger.Errorf("unexpected pionNetwork.InterfaceByIndex call from %s", stacktrace.GetParentFunctionName())
  2792. return nil, errors.Trace(errNotSupported)
  2793. }
  2794. func (p *pionNetwork) InterfaceByName(name string) (*transport.Interface, error) {
  2795. p.logger.Errorf("unexpected pionNetwork.InterfaceByName call from %s", stacktrace.GetParentFunctionName())
  2796. return nil, errors.Trace(errNotSupported)
  2797. }
  2798. func (p *pionNetwork) CreateDialer(dialer *net.Dialer) transport.Dialer {
  2799. return &pionNetworkDialer{pionNetwork: p}
  2800. }
  2801. type pionNetworkDialer struct {
  2802. pionNetwork *pionNetwork
  2803. }
  2804. func (d pionNetworkDialer) Dial(network, address string) (net.Conn, error) {
  2805. d.pionNetwork.logger.Errorf("unexpected pionNetworkDialer.Dial call from %s", stacktrace.GetParentFunctionName())
  2806. return nil, errors.Trace(errNotSupported)
  2807. }