webrtc.go 111 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460
  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 int32
  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. if !atomic.CompareAndSwapInt32(&conn.isClosed, 0, 1) {
  1131. return nil
  1132. }
  1133. // Synchronize reading these conn fields, which may be initialized by
  1134. // concurrent callbacks such as onDataChannel and onMediaTrack.
  1135. //
  1136. // To avoid potential deadlocks, don't continue to hold the lock while
  1137. // closing individual components. For example, internally, the quic-go
  1138. // implementation underlying reliableConn can concurrently call through
  1139. // to writeMediaTrackPacket, which attempts to temporarily lock
  1140. // conn.mutex, while reliableConn's quicConn.Close will wait on that
  1141. // write operation.
  1142. conn.mutex.Lock()
  1143. portMapper := conn.portMapper
  1144. sendMediaTrackRTP := conn.sendMediaTrackRTP
  1145. mediaTrackReliabilityLayer := conn.mediaTrackReliabilityLayer
  1146. dataChannelConn := conn.dataChannelConn
  1147. dataChannel := conn.dataChannel
  1148. peerConnection := conn.peerConnection
  1149. udpConn := conn.udpConn
  1150. conn.mutex.Unlock()
  1151. // Signal closing, which will unblock some waiting conditions, before
  1152. // awaiting the close of each component.
  1153. close(conn.closedSignal)
  1154. // Close the udpConn to interrupt any blocking DTLS handshake:
  1155. // https://github.com/pion/webrtc/blob/c1467e4871c78ee3f463b50d858d13dc6f2874a4/dtlstransport.go#L334-L340
  1156. //
  1157. // Limitation: there is no guarantee that pion sends any closing packets
  1158. // before the UDP socket is closed here.
  1159. if udpConn != nil {
  1160. _ = udpConn.Close()
  1161. }
  1162. // Neither sendMediaTrack nor receiveMediaTrack have a Close operation.
  1163. if portMapper != nil {
  1164. portMapper.close()
  1165. }
  1166. if sendMediaTrackRTP != nil {
  1167. _ = sendMediaTrackRTP.Stop()
  1168. }
  1169. if mediaTrackReliabilityLayer != nil {
  1170. _ = mediaTrackReliabilityLayer.Close()
  1171. }
  1172. if dataChannelConn != nil {
  1173. _ = dataChannelConn.Close()
  1174. }
  1175. if dataChannel != nil {
  1176. _ = dataChannel.Close()
  1177. }
  1178. if peerConnection != nil {
  1179. // TODO: use PeerConnection.GracefulClose (requires pion/webrtc 3.2.51)?
  1180. _ = peerConnection.Close()
  1181. }
  1182. return nil
  1183. }
  1184. func (conn *webRTCConn) IsClosed() bool {
  1185. return atomic.LoadInt32(&conn.isClosed) == 1
  1186. }
  1187. func (conn *webRTCConn) Read(p []byte) (int, error) {
  1188. if !conn.config.UseMediaStreams {
  1189. // Data channel mode.
  1190. n, err := conn.readDataChannel(p)
  1191. return n, errors.TraceReader(err)
  1192. }
  1193. if conn.mediaTrackReliabilityLayer != nil {
  1194. // Media stream mode with reliability layer.
  1195. n, err := conn.mediaTrackReliabilityLayer.Read(p)
  1196. return n, errors.TraceReader(err)
  1197. }
  1198. // Media stream mode without reliability layer.
  1199. n, err := conn.readMediaTrack(p)
  1200. return n, errors.TraceReader(err)
  1201. }
  1202. func (conn *webRTCConn) Write(p []byte) (int, error) {
  1203. if !conn.config.UseMediaStreams {
  1204. // Data channel mode.
  1205. n, err := conn.writeDataChannelMessage(p, false)
  1206. return n, errors.Trace(err)
  1207. }
  1208. if conn.mediaTrackReliabilityLayer != nil {
  1209. // Media stream mode with reliability layer.
  1210. n, err := conn.mediaTrackReliabilityLayer.Write(p)
  1211. return n, errors.Trace(err)
  1212. }
  1213. // Media stream mode without reliability layer.
  1214. n, err := conn.writeMediaTrackPacket(p, false)
  1215. return n, errors.Trace(err)
  1216. }
  1217. func (conn *webRTCConn) LocalAddr() net.Addr {
  1218. conn.mutex.Lock()
  1219. defer conn.mutex.Unlock()
  1220. // This is the local UDP socket address, not the external, public address.
  1221. return conn.udpConn.LocalAddr()
  1222. }
  1223. func (conn *webRTCConn) RemoteAddr() net.Addr {
  1224. conn.mutex.Lock()
  1225. defer conn.mutex.Unlock()
  1226. // Not supported.
  1227. return nil
  1228. }
  1229. func (conn *webRTCConn) SetDeadline(t time.Time) error {
  1230. conn.mutex.Lock()
  1231. defer conn.mutex.Unlock()
  1232. return errors.TraceNew("not supported")
  1233. }
  1234. func (conn *webRTCConn) SetReadDeadline(t time.Time) error {
  1235. conn.mutex.Lock()
  1236. defer conn.mutex.Unlock()
  1237. if conn.IsClosed() {
  1238. return errors.TraceNew("closed")
  1239. }
  1240. if conn.config.UseMediaStreams {
  1241. // This is the same workaround used and documented in
  1242. // mediaTrackPacketConn.SetReadDeadline.
  1243. //
  1244. // As in mediaTrackPacketConn, this assumes that SetReadDeadline is
  1245. // called only in the terminating quic-go case.
  1246. go func() {
  1247. _ = conn.Close()
  1248. }()
  1249. }
  1250. readDeadliner, ok := conn.dataChannelConn.(datachannel.ReadDeadliner)
  1251. if !ok {
  1252. return errors.TraceNew("no data channel")
  1253. }
  1254. return readDeadliner.SetReadDeadline(t)
  1255. }
  1256. func (conn *webRTCConn) SetWriteDeadline(t time.Time) error {
  1257. conn.mutex.Lock()
  1258. defer conn.mutex.Unlock()
  1259. return errors.TraceNew("not supported")
  1260. }
  1261. // GetMetrics implements the common.MetricsSource interface and returns log
  1262. // fields detailing the WebRTC dial parameters.
  1263. func (conn *webRTCConn) GetMetrics() common.LogFields {
  1264. conn.mutex.Lock()
  1265. defer conn.mutex.Unlock()
  1266. logFields := make(common.LogFields)
  1267. logFields.Add(conn.iceCandidatePairMetrics)
  1268. randomizeDTLS := "0"
  1269. if conn.config.DoDTLSRandomization {
  1270. randomizeDTLS = "1"
  1271. }
  1272. logFields["inproxy_webrtc_randomize_dtls"] = randomizeDTLS
  1273. useMediaStreams := "0"
  1274. if conn.config.UseMediaStreams {
  1275. useMediaStreams = "1"
  1276. }
  1277. logFields["inproxy_webrtc_use_media_streams"] = useMediaStreams
  1278. logFields["inproxy_webrtc_padded_messages_sent"] = atomic.LoadInt32(&conn.paddedMessagesSent)
  1279. logFields["inproxy_webrtc_padded_messages_received"] = atomic.LoadInt32(&conn.paddedMessagesReceived)
  1280. logFields["inproxy_webrtc_decoy_messages_sent"] = atomic.LoadInt32(&conn.decoyMessagesSent)
  1281. logFields["inproxy_webrtc_decoy_messages_received"] = atomic.LoadInt32(&conn.decoyMessagesReceived)
  1282. return logFields
  1283. }
  1284. func (conn *webRTCConn) onConnectionStateChange(state webrtc.PeerConnectionState) {
  1285. switch state {
  1286. case webrtc.PeerConnectionStateConnected:
  1287. if conn.config.UseMediaStreams {
  1288. // webrtc.PeerConnectionStateConnected is received once the DTLS
  1289. // connection is established. At this point, media track data may
  1290. // be sent. In media stream mode, unblock AwaitForReadyToProxy to
  1291. // allow peers to start sending data. In data channel mode, wait
  1292. // and signal in onDataChannelOpen.
  1293. conn.readyToProxyOnce.Do(func() { close(conn.readyToProxySignal) })
  1294. }
  1295. case webrtc.PeerConnectionStateDisconnected,
  1296. webrtc.PeerConnectionStateFailed,
  1297. webrtc.PeerConnectionStateClosed:
  1298. // Close the WebRTCConn when the connection is no longer connected. Close
  1299. // will lock conn.mutex, so do not aquire the lock here.
  1300. //
  1301. // Currently, ICE Restart is not used, and there is no transition from
  1302. // Disconnected back to Connected.
  1303. conn.Close()
  1304. }
  1305. conn.config.Logger.WithTraceFields(common.LogFields{
  1306. "state": state.String(),
  1307. }).Debug("peer connection state changed")
  1308. }
  1309. func (conn *webRTCConn) onICECandidate(candidate *webrtc.ICECandidate) {
  1310. if candidate == nil {
  1311. return
  1312. }
  1313. conn.config.Logger.WithTraceFields(common.LogFields{
  1314. "candidate": candidate.String(),
  1315. }).Debug("new ICE candidate")
  1316. }
  1317. func (conn *webRTCConn) onICEBindingRequest(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool {
  1318. // SetICEBindingRequestHandler is used to hook onICEBindingRequest into
  1319. // STUN bind events for logging. The return values is always false as
  1320. // this callback makes no adjustments to ICE candidate selection. When
  1321. // the data channel or media track tunnel has already opened, skip
  1322. // logging events, as this callback appears to be invoked for keepalive
  1323. // pings.
  1324. if local == nil || remote == nil {
  1325. return false
  1326. }
  1327. select {
  1328. case <-conn.readyToProxySignal:
  1329. return false
  1330. default:
  1331. }
  1332. conn.config.Logger.WithTraceFields(common.LogFields{
  1333. "local_candidate": local.String(),
  1334. "remote_candidate": remote.String(),
  1335. }).Debug("new ICE STUN binding request")
  1336. return false
  1337. }
  1338. func (conn *webRTCConn) onICEConnectionStateChange(state webrtc.ICEConnectionState) {
  1339. conn.mutex.Lock()
  1340. defer conn.mutex.Unlock()
  1341. conn.config.Logger.WithTraceFields(common.LogFields{
  1342. "state": state.String(),
  1343. }).Debug("ICE connection state changed")
  1344. }
  1345. func (conn *webRTCConn) onICEGatheringStateChange(state webrtc.ICEGathererState) {
  1346. conn.config.Logger.WithTraceFields(common.LogFields{
  1347. "state": state.String(),
  1348. }).Debug("ICE gathering state changed")
  1349. }
  1350. func (conn *webRTCConn) onNegotiationNeeded() {
  1351. conn.config.Logger.WithTrace().Debug("negotiation needed")
  1352. }
  1353. func (conn *webRTCConn) onSignalingStateChange(state webrtc.SignalingState) {
  1354. conn.config.Logger.WithTraceFields(common.LogFields{
  1355. "state": state.String(),
  1356. }).Debug("signaling state changed")
  1357. }
  1358. func (conn *webRTCConn) onDataChannel(dataChannel *webrtc.DataChannel) {
  1359. conn.mutex.Lock()
  1360. defer conn.mutex.Unlock()
  1361. conn.setDataChannel(dataChannel)
  1362. conn.config.Logger.WithTraceFields(common.LogFields{
  1363. "label": dataChannel.Label(),
  1364. "ID": dataChannel.ID(),
  1365. }).Debug("new data channel")
  1366. }
  1367. func (conn *webRTCConn) onMediaTrack(track *webrtc.TrackRemote, _ *webrtc.RTPReceiver) {
  1368. conn.mutex.Lock()
  1369. defer conn.mutex.Unlock()
  1370. conn.receiveMediaTrack = track
  1371. close(conn.receiveMediaTrackOpenedSignal)
  1372. conn.config.Logger.WithTraceFields(common.LogFields{
  1373. "ID": track.ID(),
  1374. "payload_type": track.Kind().String(),
  1375. }).Info("media track open")
  1376. }
  1377. func (conn *webRTCConn) onDataChannelOpen() {
  1378. conn.mutex.Lock()
  1379. defer conn.mutex.Unlock()
  1380. dataChannelConn, err := conn.dataChannel.Detach()
  1381. if err == nil {
  1382. conn.dataChannelConn = dataChannelConn
  1383. // TODO: can a data channel be connected, disconnected, and then
  1384. // reestablished in one session?
  1385. conn.readyToProxyOnce.Do(func() { close(conn.readyToProxySignal) })
  1386. }
  1387. conn.config.Logger.WithTraceFields(common.LogFields{
  1388. "detachError": err,
  1389. }).Info("data channel open")
  1390. }
  1391. func (conn *webRTCConn) onDataChannelClose() {
  1392. // Close the WebRTCConn when the data channel is closed. Close will lock
  1393. // conn.mutex, so do not aquire the lock here.
  1394. conn.Close()
  1395. conn.config.Logger.WithTrace().Info("data channel closed")
  1396. }
  1397. func (conn *webRTCConn) readDataChannel(p []byte) (int, error) {
  1398. for {
  1399. n, err := conn.readDataChannelMessage(p)
  1400. if err != nil || n > 0 {
  1401. return n, errors.TraceReader(err)
  1402. }
  1403. // A decoy message was read; discard and read again.
  1404. }
  1405. }
  1406. func (conn *webRTCConn) readDataChannelMessage(p []byte) (int, error) {
  1407. if conn.IsClosed() {
  1408. return 0, errors.TraceNew("closed")
  1409. }
  1410. // Don't hold this lock, or else concurrent Writes will be blocked.
  1411. conn.mutex.Lock()
  1412. dataChannelConn := conn.dataChannelConn
  1413. conn.mutex.Unlock()
  1414. if dataChannelConn == nil {
  1415. return 0, errors.TraceNew("no data channel")
  1416. }
  1417. // The input read buffer, p, may not be the same length as the message
  1418. // read from the data channel. Buffer the read message if another Read
  1419. // call is necessary to consume it. As per https://pkg.go.dev/io#Reader,
  1420. // dataChannelConn bytes read are processed even when
  1421. // dataChannelConn.Read returns an error; the error value is stored and
  1422. // returned with the Read call that consumes the end of the message buffer.
  1423. conn.readMutex.Lock()
  1424. defer conn.readMutex.Unlock()
  1425. if conn.readOffset == conn.readLength {
  1426. n, err := dataChannelConn.Read(conn.readBuffer)
  1427. conn.readOffset = 0
  1428. conn.readLength = n
  1429. conn.readError = err
  1430. if conn.readLength == 0 && conn.readError != nil {
  1431. // No bytes were read, so return the error immediately.
  1432. return 0, errors.TraceReader(err)
  1433. }
  1434. // Skip over padding.
  1435. if conn.readLength > 0 && !conn.peerPaddingDone {
  1436. paddingSize, n := binary.Varint(conn.readBuffer[0:conn.readLength])
  1437. if (paddingSize == 0 && n <= 0) || paddingSize > int64(conn.readLength-n) {
  1438. return 0, errors.Tracef(
  1439. "invalid padding: %d, %d, %d, %w",
  1440. n, paddingSize, conn.readLength, conn.readError)
  1441. }
  1442. if paddingSize < 0 {
  1443. // When the padding header indicates a padding size of -1, the
  1444. // peer is indicating that padding is done. Subsequent
  1445. // messages will have no padding header or padding bytes.
  1446. conn.peerPaddingDone = true
  1447. conn.readOffset += n
  1448. } else {
  1449. conn.readOffset += n + int(paddingSize)
  1450. atomic.AddInt32(&conn.paddedMessagesReceived, 1)
  1451. if conn.readOffset == conn.readLength {
  1452. atomic.AddInt32(&conn.decoyMessagesReceived, 1)
  1453. }
  1454. }
  1455. }
  1456. }
  1457. n := copy(p, conn.readBuffer[conn.readOffset:conn.readLength])
  1458. conn.readOffset += n
  1459. var err error
  1460. if conn.readOffset == conn.readLength {
  1461. err = conn.readError
  1462. }
  1463. // When decoy messages are enabled, periodically respond to an incoming
  1464. // messages with an immediate outbound decoy message. This is similar to
  1465. // the design here:
  1466. // https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/c4f6a593a645db4479a7032a9e97d3c0b905cdfc/psiphon/common/quic/obfuscator.go#L361-L409
  1467. //
  1468. // writeDataChannelMessage handles conn.decoyMessageCount, which is
  1469. // synchronized with conn.WriteMutex, as well as other specific logic.
  1470. // Here we just signal writeDataChannelMessage based on the read event.
  1471. //
  1472. // When the data channel already has buffered writes in excess of a decoy
  1473. // message size, the writeDataChannelMessage skips the decoy message and
  1474. // returns without blocking, so Read calls will not block.
  1475. if !conn.decoyDone.Load() {
  1476. _, _ = conn.writeDataChannelMessage(nil, true)
  1477. }
  1478. return n, errors.TraceReader(err)
  1479. }
  1480. func (conn *webRTCConn) writeDataChannelMessage(p []byte, decoy bool) (int, error) {
  1481. if p != nil && decoy {
  1482. return 0, errors.TraceNew("invalid write parameters")
  1483. }
  1484. // pion/sctp doesn't handle 0-byte writes correctly, so drop/skip at this level.
  1485. //
  1486. // Testing shows that the SCTP connection stalls after a 0-byte write. In
  1487. // the pion/sctp implementation,
  1488. // https://github.com/pion/sctp/blob/v1.8.8/stream.go#L254-L278 and
  1489. // https://github.com/pion/sctp/blob/v1.8.8/stream.go#L280-L336, it
  1490. // appears that a zero-byte write won't send an SCTP messages but does
  1491. // increment a sequence number.
  1492. if len(p) == 0 && !decoy {
  1493. return 0, nil
  1494. }
  1495. if conn.IsClosed() {
  1496. return 0, errors.TraceNew("closed")
  1497. }
  1498. // Don't hold this lock, or else concurrent Reads will be blocked.
  1499. conn.mutex.Lock()
  1500. dataChannel := conn.dataChannel
  1501. dataChannelConn := conn.dataChannelConn
  1502. conn.mutex.Unlock()
  1503. if dataChannel == nil || dataChannelConn == nil {
  1504. return 0, errors.TraceNew("no data channel")
  1505. }
  1506. bufferedAmount := dataChannel.BufferedAmount()
  1507. // Only proceed with a decoy message when no pending writes are buffered.
  1508. //
  1509. // This check is made before acquiring conn.writeMutex so that, in most
  1510. // cases, writeMessage won't block Read calls when a concurrent Write is
  1511. // holding conn.writeMutex and potentially blocking on flow control.
  1512. // There's still a chance that this test passes, and a concurrent Write
  1513. // arrives at the same time.
  1514. if decoy && bufferedAmount > 0 {
  1515. return 0, nil
  1516. }
  1517. conn.writeMutex.Lock()
  1518. defer conn.writeMutex.Unlock()
  1519. writeSize := len(p)
  1520. // Determine padding size and padding header size.
  1521. doPadding := false
  1522. paddingSize := 0
  1523. var paddingHeader [binary.MaxVarintLen32]byte
  1524. paddingHeaderSize := 0
  1525. if decoy {
  1526. if conn.decoyMessageCount < 1 {
  1527. return 0, nil
  1528. }
  1529. if !conn.trafficShapingPRNG.FlipWeightedCoin(
  1530. conn.config.TrafficShapingParameters.DecoyMessageProbability) {
  1531. return 0, nil
  1532. }
  1533. conn.decoyMessageCount -= 1
  1534. decoySize := conn.trafficShapingPRNG.Range(
  1535. conn.config.TrafficShapingParameters.MinDecoySize,
  1536. conn.config.TrafficShapingParameters.MaxDecoySize)
  1537. // When sending a decoy message, the entire message is padding.
  1538. doPadding = true
  1539. paddingSize = decoySize
  1540. if conn.decoyMessageCount == 0 {
  1541. // Set the shared flag that readMessage uses to stop invoking
  1542. // writeMessage for decoy events.
  1543. conn.decoyDone.Store(true)
  1544. }
  1545. } else if conn.paddedMessageCount > 0 {
  1546. // Add padding to a normal write.
  1547. conn.paddedMessageCount -= 1
  1548. doPadding = true
  1549. paddingSize = prng.Range(
  1550. conn.config.TrafficShapingParameters.MinPaddingSize,
  1551. conn.config.TrafficShapingParameters.MaxPaddingSize)
  1552. } else if conn.decoyMessageCount > 0 {
  1553. // Padding normal messages is done, but there are still outstanding
  1554. // decoy messages, so add a padding header indicating padding size 0
  1555. // to this normal message.
  1556. doPadding = true
  1557. paddingSize = 0
  1558. } else if !conn.trafficShapingDone {
  1559. // Padding normal messages is done and all decoy messages are sent, so
  1560. // send a special padding header with padding size -1, signaling the
  1561. // peer that no additional padding will be performed and no
  1562. // subsequent messages will contain a padding header.
  1563. doPadding = true
  1564. paddingSize = -1
  1565. }
  1566. if doPadding {
  1567. if paddingSize > 0 {
  1568. // Reduce, if necessary, to stay within the maximum data channel
  1569. // message size. This is not expected to happen for the io.Copy use
  1570. // case, with 32K message size, plus reasonable padding sizes.
  1571. if writeSize+binary.MaxVarintLen32+paddingSize > dataChannelMaxMessageSize {
  1572. paddingSize -= (writeSize + binary.MaxVarintLen32 + paddingSize) - dataChannelMaxMessageSize
  1573. if paddingSize < 0 {
  1574. paddingSize = 0
  1575. }
  1576. }
  1577. // Add padding overhead to total writeSize before the flow control check.
  1578. writeSize += paddingSize
  1579. }
  1580. paddingHeaderSize = binary.PutVarint(paddingHeader[:], int64(paddingSize))
  1581. writeSize += paddingHeaderSize
  1582. }
  1583. if writeSize > dataChannelMaxMessageSize {
  1584. return 0, errors.TraceNew("write too large")
  1585. }
  1586. // Flow control is required to ensure that Write calls don't result in
  1587. // unbounded buffering in pion/webrtc. Use similar logic and the same
  1588. // buffer size thresholds as the pion sample code.
  1589. //
  1590. // https://github.com/pion/webrtc/tree/master/examples/data-channels-flow-control#when-do-we-need-it:
  1591. // > Send or SendText methods are called on DataChannel to send data to
  1592. // > the connected peer. The methods return immediately, but it does not
  1593. // > mean the data was actually sent onto the wire. Instead, it is
  1594. // > queued in a buffer until it actually gets sent out to the wire.
  1595. // >
  1596. // > When you have a large amount of data to send, it is an application's
  1597. // > responsibility to control the buffered amount in order not to
  1598. // > indefinitely grow the buffer size to eventually exhaust the memory.
  1599. // If the pion write buffer is too full, wait for a signal that sufficient
  1600. // write data has been consumed before writing more.
  1601. if !conn.IsClosed() && bufferedAmount+uint64(writeSize) > dataChannelMaxBufferedAmount {
  1602. select {
  1603. case <-conn.dataChannelWriteBufferSignal:
  1604. case <-conn.closedSignal:
  1605. return 0, errors.TraceNew("connection has closed")
  1606. }
  1607. }
  1608. if conn.trafficShapingDone {
  1609. // When traffic shaping is done, p is written directly without the
  1610. // additional trafficShapingBuffer copy.
  1611. // Limitation: if len(p) > 65536, the dataChannelConn.Write will fail. In
  1612. // practise, this is not expected to happen with typical use cases such
  1613. // as io.Copy, which uses a 32K buffer.
  1614. n, err := dataChannelConn.Write(p)
  1615. return n, errors.Trace(err)
  1616. }
  1617. conn.trafficShapingBuffer.Reset()
  1618. conn.trafficShapingBuffer.Write(paddingHeader[:paddingHeaderSize])
  1619. if paddingSize > 0 {
  1620. conn.trafficShapingBuffer.Write(prng.Bytes(paddingSize))
  1621. }
  1622. conn.trafficShapingBuffer.Write(p)
  1623. // Limitation: see above; len(p) + padding must be <= 65536.
  1624. _, err := dataChannelConn.Write(conn.trafficShapingBuffer.Bytes())
  1625. if decoy {
  1626. atomic.AddInt32(&conn.decoyMessagesSent, 1)
  1627. } else if doPadding && paddingSize > 0 {
  1628. atomic.AddInt32(&conn.paddedMessagesSent, 1)
  1629. }
  1630. if conn.paddedMessageCount == 0 && conn.decoyMessageCount == 0 && paddingSize == -1 {
  1631. // Set flag indicating -1 padding size was sent and release traffic
  1632. // shaping resources.
  1633. conn.trafficShapingDone = true
  1634. conn.trafficShapingPRNG = nil
  1635. conn.trafficShapingBuffer = nil
  1636. }
  1637. return len(p), errors.Trace(err)
  1638. }
  1639. // GetQUICMaxPacketSizeAdjustment returns the value to be specified in
  1640. // Psiphon's quic-go configuration ClientMaxPacketSizeAdjustment
  1641. // ServerMaxPacketSizeAdjustment fields. Psiphon's quic-go max packet size
  1642. // adjustment reduces the QUIC payload to accomodate overhead from
  1643. // obfuscation, as in Obfuscated QUIC. In the in-proxy case, the same
  1644. // mechanism is used to ensure that QUIC packets fit within the space
  1645. // available for SRTP packet payloads, allowing for the overhead of the RTP
  1646. // packet. Beyond that allowance, the adjustment is tuned to produce SRTP
  1647. // packets that match common SRTP traffic with maximum packet sizes of 1200
  1648. // bytes, excluding IP and UDP headers.
  1649. //
  1650. // INPROXY-QUIC-OSSH must apply GetQUICMaxPacketSizeAdjustment on both the
  1651. // client and server side. In addition, the client must disable
  1652. // DisablePathMTUDiscovery.
  1653. func GetQUICMaxPacketSizeAdjustment() int {
  1654. // Limitations:
  1655. //
  1656. // - For INPROXY-QUIC-OSSH, the second hop egressing from the proxy is
  1657. // identical regardless of whether the 1st hop uses data channel mode
  1658. // or media stream mode. Currently, the INPROXY-QUIC-OSSH server won't
  1659. // be able to distinguish, early enough, between the modes used by the
  1660. // 1st hop. In order to conform with the required adustment for media
  1661. // stream mode, the server must always apply the adjustment. This
  1662. // reduction in QUIC packet size may impact the performance of data
  1663. // channel mode. Furthermore, the lower maximum QUIC packet size is
  1664. // directly observable on the 2nd hop.
  1665. // common/quic.MAX_PRE_DISCOVERY_PACKET_SIZE = 1280
  1666. quicMTU := 1280
  1667. targetMTUAdjustment := quicMTU - mediaTrackMaxUDPPayloadLength
  1668. if targetMTUAdjustment < 0 {
  1669. targetMTUAdjustment = 0
  1670. }
  1671. adjustment := targetMTUAdjustment + mediaTrackRTPPacketOverhead
  1672. if adjustment < 0 {
  1673. adjustment = 0
  1674. }
  1675. return adjustment
  1676. }
  1677. func (conn *webRTCConn) readMediaTrack(p []byte) (int, error) {
  1678. for {
  1679. n, err := conn.readMediaTrackPacket(p)
  1680. if err != nil || n > 0 {
  1681. return n, errors.TraceReader(err)
  1682. }
  1683. // A decoy message was read; discard and read again.
  1684. }
  1685. }
  1686. func (conn *webRTCConn) readMediaTrackPacket(p []byte) (int, error) {
  1687. // Await opening the peer's media track, the OnTrack event. This
  1688. // synchronization is necessary since AwaitReadyToProxy returns before
  1689. // receiving a media track packet from the peer, which triggers OnTrack.
  1690. select {
  1691. case <-conn.receiveMediaTrackOpenedSignal:
  1692. case <-conn.closedSignal:
  1693. return 0, errors.TraceNew("closed")
  1694. }
  1695. if conn.IsClosed() {
  1696. return 0, errors.TraceNew("closed")
  1697. }
  1698. // Don't hold this lock, or else concurrent Writes will be blocked.
  1699. conn.mutex.Lock()
  1700. receiveMediaTrack := conn.receiveMediaTrack
  1701. conn.mutex.Unlock()
  1702. if receiveMediaTrack == nil {
  1703. return 0, errors.TraceNew("no media track")
  1704. }
  1705. conn.readMutex.Lock()
  1706. defer conn.readMutex.Unlock()
  1707. // Use the lower-level Read and Unmarshal functions to avoid per-call allocations
  1708. // performed by the higher-level ReadRTP.
  1709. n, _, err := receiveMediaTrack.Read(conn.readBuffer)
  1710. if err != nil {
  1711. return 0, errors.TraceReader(err)
  1712. }
  1713. err = conn.receiveMediaTrackPacket.Unmarshal(conn.readBuffer[:n])
  1714. if err != nil {
  1715. return 0, errors.Trace(err)
  1716. }
  1717. payload := conn.receiveMediaTrackPacket.Payload
  1718. if len(payload) < 1 {
  1719. return 0, errors.TraceNew("invalid padding")
  1720. }
  1721. // Read the padding header byte, which is always present (see comment in
  1722. // writeMediaTrackPacket).
  1723. paddingSize := int(payload[0])
  1724. if paddingSize == 255 {
  1725. // When the header is 255, this is a decoy packet with no application
  1726. // payload. Discard the entire packet. Return n = 0 bytes read, and
  1727. // the caller will read again.
  1728. return 0, nil
  1729. }
  1730. if len(payload) < 1+paddingSize {
  1731. return 0, errors.Tracef("invalid padding: %d < %d", len(payload), 1+paddingSize)
  1732. }
  1733. payload = payload[1+paddingSize:]
  1734. // Unlike the data channel case, there is no carry over data left in
  1735. // conn.readBuffer between readMediaTrackPacket calls: the entire packet
  1736. // payload must be read in this one call.
  1737. if len(p) < len(payload) {
  1738. return 0, errors.Tracef("read buffer too short: %d < %d", len(p), len(payload))
  1739. }
  1740. copy(p, payload)
  1741. // When decoy messages are enabled, periodically respond to an incoming
  1742. // messages with an immediate outbound decoy message.
  1743. //
  1744. // writeMediaTrackPacket handles conn.decoyMessageCount, which is
  1745. // synchronized with conn.WriteMutex, as well as other specific logic.
  1746. // Here we just signal writeDataChannelMessage based on the read event.
  1747. if !conn.decoyDone.Load() {
  1748. _, _ = conn.writeMediaTrackPacket(nil, true)
  1749. }
  1750. return len(payload), nil
  1751. }
  1752. func (conn *webRTCConn) writeMediaTrackPacket(p []byte, decoy bool) (int, error) {
  1753. if p != nil && decoy {
  1754. return 0, errors.TraceNew("invalid write parameters")
  1755. }
  1756. if conn.IsClosed() {
  1757. return 0, errors.TraceNew("closed")
  1758. }
  1759. // Don't hold this lock, or else concurrent Writes will be blocked.
  1760. conn.mutex.Lock()
  1761. sendMediaTrack := conn.sendMediaTrack
  1762. conn.mutex.Unlock()
  1763. if sendMediaTrack == nil {
  1764. return 0, errors.TraceNew("no media track")
  1765. }
  1766. conn.writeMutex.Lock()
  1767. defer conn.writeMutex.Unlock()
  1768. // Packet writes can't be split.
  1769. maxRTPPayloadLength := mediaTrackMaxRTPPayloadLength
  1770. if len(p) > maxRTPPayloadLength {
  1771. return 0, errors.Tracef("write too large: %d > %d", len(p), maxRTPPayloadLength)
  1772. }
  1773. // Determine padding size and padding header size.
  1774. // Limitation: unlike data channel padding, the header size is fixed, not
  1775. // a varint, and is always sent. This is due to the fixed QUIC max packet
  1776. // size adjustment. To limit the overhead, and because the maximum SRTP
  1777. // payload size is much smaller than the maximum data channel message
  1778. // size, the padding is limited to 254 bytes, represented with a 1 byte
  1779. // header. The value 255 is reserved to signal that the entire packet is
  1780. // a decoy packet.
  1781. conn.trafficShapingBuffer.Reset()
  1782. if decoy {
  1783. if conn.decoyMessageCount < 1 {
  1784. return 0, nil
  1785. }
  1786. if !conn.trafficShapingPRNG.FlipWeightedCoin(
  1787. conn.config.TrafficShapingParameters.DecoyMessageProbability) {
  1788. return 0, nil
  1789. }
  1790. conn.decoyMessageCount -= 1
  1791. // When sending a decoy message, the entire message is padding, and
  1792. // the padding can be up to the full packet size.
  1793. //
  1794. // Note that the actual decoy payload size is decoySize+1, including
  1795. // the padding header.
  1796. decoySize := conn.trafficShapingPRNG.Range(
  1797. conn.config.TrafficShapingParameters.MinDecoySize,
  1798. conn.config.TrafficShapingParameters.MaxDecoySize)
  1799. if decoySize > maxRTPPayloadLength-1 {
  1800. // Ensure there's space for the 1 byte padding header.
  1801. decoySize = maxRTPPayloadLength - 1
  1802. }
  1803. // Set the padding header to 255, which indicates a decoy packet.
  1804. conn.trafficShapingBuffer.WriteByte(255)
  1805. if decoySize > 0 {
  1806. conn.trafficShapingBuffer.Write(prng.Bytes(decoySize))
  1807. }
  1808. if conn.decoyMessageCount == 0 {
  1809. // Set the shared flag that readMessage uses to stop invoking
  1810. // writeMessage for decoy events.
  1811. conn.decoyDone.Store(true)
  1812. }
  1813. } else {
  1814. // Add padding to a normal write.
  1815. paddingSize := 0
  1816. if conn.paddedMessageCount > 0 {
  1817. paddingSize = prng.Range(
  1818. conn.config.TrafficShapingParameters.MinPaddingSize,
  1819. conn.config.TrafficShapingParameters.MaxPaddingSize)
  1820. if paddingSize > 254 {
  1821. // The maximum padding size is 254.
  1822. paddingSize = 254
  1823. }
  1824. if len(p)+1+paddingSize > maxRTPPayloadLength {
  1825. paddingSize -= (len(p) + 1 + paddingSize) - maxRTPPayloadLength
  1826. }
  1827. if paddingSize < 0 {
  1828. paddingSize = 0
  1829. }
  1830. conn.paddedMessageCount -= 1
  1831. }
  1832. conn.trafficShapingBuffer.WriteByte(byte(paddingSize))
  1833. if paddingSize > 0 {
  1834. conn.trafficShapingBuffer.Write(prng.Bytes(paddingSize))
  1835. }
  1836. conn.trafficShapingBuffer.Write(p)
  1837. }
  1838. paddedPayload := conn.trafficShapingBuffer.Bytes()
  1839. // Sanity check, in case there's a bug in the padding logic above; +1 here
  1840. // is the padding header.
  1841. if len(paddedPayload) > maxRTPPayloadLength+1 {
  1842. return 0, errors.Tracef("write too large: %d > %d", len(paddedPayload), maxRTPPayloadLength)
  1843. }
  1844. // Send the RTP packet.
  1845. // Dynamic plaintext RTP header values are set here: the sequence number
  1846. // is set when sending the packet; the timestamp, initialized in
  1847. // newWebRTCConn, is updated once payload equivalent to a complete
  1848. // video "frame" has been sent. See the "Plaintext RTP header fields"
  1849. // comment in newWebRTCConn.
  1850. conn.sendMediaTrackPacket.SequenceNumber = conn.sendMediaTrackSequencer.NextSequenceNumber()
  1851. conn.sendMediaTrackPacket.Payload = paddedPayload
  1852. err := sendMediaTrack.WriteRTP(conn.sendMediaTrackPacket)
  1853. if err != nil {
  1854. return 0, errors.Trace(err)
  1855. }
  1856. conn.sendMediaTrackRemainingFrameSize -= len(paddedPayload)
  1857. if conn.sendMediaTrackRemainingFrameSize <= 0 {
  1858. conn.sendMediaTrackPacket.Timestamp += uint32(conn.sendMediaTrackTimestampTick)
  1859. conn.sendMediaTrackRemainingFrameSize = prng.Range(conn.sendMediaTrackFrameSizeRange[0], conn.sendMediaTrackFrameSizeRange[1])
  1860. }
  1861. return len(p), nil
  1862. }
  1863. func (conn *webRTCConn) addRTPReliabilityLayer(ctx context.Context) error {
  1864. // Add a QUIC layer over the SRTP packet flow to provide reliable delivery
  1865. // and ordering. The proxy runs a QUIC server and the client runs a QUIC
  1866. // client that connects to the proxy's server. As all of the QUIC traffic
  1867. // is encapsulated in the secure SRTP layer.
  1868. // Wrap the RTP track read and write operations in a mediaTrackPacketConn
  1869. // provides the net.PacketConn interface required by quic-go. There is no
  1870. // Close-on-error for mediaTrackPacketConn since it doesn't allocate or use
  1871. // any resources.
  1872. mediaTrackPacketConn := newMediaTrackPacketConn(conn)
  1873. // Use the Psiphon QUIC obfuscated PSK mechanism to facilitate a faster
  1874. // QUIC TLS handshake. QUIC client hello randomization is also
  1875. // initialized, as it will vary the QUIC handshake traffic shape within
  1876. // the SRTP packet flow.
  1877. var obfuscatedPSKKey [32]byte
  1878. obfuscationSecret, err := deriveObfuscationSecret(
  1879. conn.config.ClientRootObfuscationSecret, "in-proxy-RTP-QUIC-reliability-layer")
  1880. if err != nil {
  1881. return errors.Trace(err)
  1882. }
  1883. obfuscationSeed := prng.Seed(obfuscationSecret)
  1884. copy(obfuscatedPSKKey[:], prng.NewPRNGWithSeed(&obfuscationSeed).Bytes(len(obfuscatedPSKKey)))
  1885. // To effectively disable them, quic-go's idle timeouts and keep-alives
  1886. // are initialized to the maximum possible duration. The higher-level
  1887. // WebRTC connection will provide this functionality.
  1888. maxDuration := time.Duration(math.MaxInt64)
  1889. // Set the handshake timeout to align with the ctx deadline. Setting
  1890. // HandshakeIdleTimeout to maxDuration causes the quic-go dial to fail.
  1891. // Assumes ctx has a deadline.
  1892. deadline, _ := ctx.Deadline()
  1893. handshakeIdleTimeout := time.Until(deadline) / 2
  1894. if conn.isOffer {
  1895. // The client is a QUIC client.
  1896. // Initialize the obfuscated PSK.
  1897. sessionCache := common.WrapClientSessionCache(tls.NewLRUClientSessionCache(1), "")
  1898. obfuscatedSessionState, err := tls.NewObfuscatedClientSessionState(
  1899. obfuscatedPSKKey, true, false)
  1900. if err != nil {
  1901. return errors.Trace(err)
  1902. }
  1903. sessionCache.Put(
  1904. "", tls.MakeClientSessionState(
  1905. obfuscatedSessionState.SessionTicket,
  1906. obfuscatedSessionState.Vers,
  1907. obfuscatedSessionState.CipherSuite,
  1908. obfuscatedSessionState.MasterSecret,
  1909. obfuscatedSessionState.CreatedAt,
  1910. obfuscatedSessionState.AgeAdd,
  1911. obfuscatedSessionState.UseBy))
  1912. tlsConfig := &tls.Config{
  1913. InsecureSkipVerify: true,
  1914. InsecureSkipTimeVerify: true,
  1915. NextProtos: []string{"h3"},
  1916. ServerName: values.GetHostName(),
  1917. ClientSessionCache: sessionCache,
  1918. }
  1919. maxPacketSizeAdjustment := GetQUICMaxPacketSizeAdjustment()
  1920. // Set ClientMaxPacketSizeAdjustment to so that quic-go will produce
  1921. // packets with a small enough max size to produce the overall target
  1922. // packet MTU.
  1923. quicConfig := &quic_go.Config{
  1924. HandshakeIdleTimeout: handshakeIdleTimeout,
  1925. MaxIdleTimeout: maxDuration,
  1926. KeepAlivePeriod: maxDuration,
  1927. Versions: []quic_go.Version{0x1},
  1928. ClientHelloSeed: &obfuscationSeed,
  1929. ClientMaxPacketSizeAdjustment: maxPacketSizeAdjustment,
  1930. DisablePathMTUDiscovery: true,
  1931. }
  1932. deadline, ok := ctx.Deadline()
  1933. if ok {
  1934. quicConfig.HandshakeIdleTimeout = time.Until(deadline)
  1935. }
  1936. // Establish the QUIC connection with the server and open a single
  1937. // data stream for relaying traffic.
  1938. //
  1939. // Use DialEarly, in combination with the "established" PSK, for
  1940. // 0-RTT, which potentially allows data to be sent with the
  1941. // handshake; this could include the open stream message from the
  1942. // following OpenStreamSync call. There is no replay concern with
  1943. // 0-RTT here, as the QUIC traffic is encapsualted in the secure SRTP
  1944. // flow.
  1945. quicConn, err := quic_go.DialEarly(
  1946. ctx,
  1947. mediaTrackPacketConn,
  1948. mediaTrackPacketConn.remoteAddr,
  1949. tlsConfig,
  1950. quicConfig)
  1951. if err != nil {
  1952. return errors.Trace(err)
  1953. }
  1954. quicStream, err := quicConn.OpenStreamSync(ctx)
  1955. if err != nil {
  1956. // Ensure any background quic-go goroutines are stopped.
  1957. _ = quicConn.CloseWithError(0, "")
  1958. return errors.Trace(err)
  1959. }
  1960. conn.mediaTrackReliabilityLayer = &reliableConn{
  1961. mediaTrackConn: mediaTrackPacketConn,
  1962. quicConn: quicConn,
  1963. quicStream: quicStream,
  1964. }
  1965. return nil
  1966. } else {
  1967. // The proxy is a QUIC server.
  1968. // Use an ephemeral, self-signed certificate.
  1969. certificate, privateKey, _, err := common.GenerateWebServerCertificate(
  1970. values.GetHostName())
  1971. if err != nil {
  1972. return errors.Trace(err)
  1973. }
  1974. tlsCertificate, err := tls.X509KeyPair([]byte(certificate), []byte(privateKey))
  1975. if err != nil {
  1976. return errors.Trace(err)
  1977. }
  1978. tlsConfig := &tls.Config{
  1979. Certificates: []tls.Certificate{tlsCertificate},
  1980. NextProtos: []string{"h3"},
  1981. }
  1982. tlsConfig.SetSessionTicketKeys([][32]byte{
  1983. obfuscatedPSKKey,
  1984. })
  1985. // Anti-probing via VerifyClientHelloRandom, for passthrough, is not
  1986. // necessary here and is not initialized.
  1987. quicConfig := &quic_go.Config{
  1988. Allow0RTT: true,
  1989. HandshakeIdleTimeout: handshakeIdleTimeout,
  1990. MaxIdleTimeout: maxDuration,
  1991. KeepAlivePeriod: maxDuration,
  1992. MaxIncomingStreams: 1,
  1993. MaxIncomingUniStreams: -1,
  1994. VerifyClientHelloRandom: nil,
  1995. ServerMaxPacketSizeAdjustment: func(addr net.Addr) int {
  1996. return GetQUICMaxPacketSizeAdjustment()
  1997. },
  1998. }
  1999. quicTransport := &quic_go.Transport{
  2000. Conn: mediaTrackPacketConn,
  2001. DisableVersionNegotiationPackets: true,
  2002. }
  2003. quicListener, err := quicTransport.ListenEarly(tlsConfig, quicConfig)
  2004. if err != nil {
  2005. return errors.Trace(err)
  2006. }
  2007. // Accept the single expected QUIC client and its QUIC data stream.
  2008. quicConn, err := quicListener.Accept(ctx)
  2009. if err != nil {
  2010. _ = quicTransport.Close()
  2011. return errors.Trace(err)
  2012. }
  2013. quicStream, err := quicConn.AcceptStream(ctx)
  2014. if err != nil {
  2015. _ = quicConn.CloseWithError(0, "")
  2016. _ = quicTransport.Close()
  2017. return errors.Trace(err)
  2018. }
  2019. // Closing the quic-go Transport/Listener closes all client
  2020. // connections, so retain the Transport for the duration of the
  2021. // overall connection.
  2022. conn.mediaTrackReliabilityLayer = &reliableConn{
  2023. mediaTrackConn: mediaTrackPacketConn,
  2024. quicTransport: quicTransport,
  2025. quicConn: quicConn,
  2026. quicStream: quicStream,
  2027. }
  2028. return nil
  2029. }
  2030. }
  2031. // incrementingIPv6Address provides successive, distinct IPv6 addresses from
  2032. // the 2001:db8::/32 range, reserved for documentation purposes as defined in
  2033. // RFC 3849. It will wrap after 2^96 calls.
  2034. type incrementingIPv6Address struct {
  2035. mutex sync.Mutex
  2036. ip [12]byte
  2037. }
  2038. var uniqueIPv6Address incrementingIPv6Address
  2039. func (inc *incrementingIPv6Address) next() net.IP {
  2040. inc.mutex.Lock()
  2041. defer inc.mutex.Unlock()
  2042. for i := 11; i >= 0; i-- {
  2043. inc.ip[i]++
  2044. if inc.ip[i] != 0 {
  2045. break
  2046. }
  2047. }
  2048. ip := make([]byte, 16)
  2049. copy(ip[0:4], []byte{0x20, 0x01, 0x0d, 0xb8})
  2050. copy(ip[4:16], inc.ip[:])
  2051. return net.IP(ip)
  2052. }
  2053. // mediaTrackPacketConn provides the required net.PacketConn interface for
  2054. // quic-go to use to read and write packets to the RTP media track conn.
  2055. type mediaTrackPacketConn struct {
  2056. webRTCConn *webRTCConn
  2057. localAddr net.Addr
  2058. remoteAddr net.Addr
  2059. isClosed int32
  2060. }
  2061. func newMediaTrackPacketConn(conn *webRTCConn) *mediaTrackPacketConn {
  2062. // Create distinct, artificial local/remote addrs for the synthetic
  2063. // net.PacketConn.
  2064. //
  2065. // For its local operations, quic-go references local/remote addrs for the
  2066. // net.PacketConns it uses. Furthermore, the quic-go server listener
  2067. // currently uses a singleton multiplexer, connMultiplexer, which panics
  2068. // if multiple conns with the same local addr are added. Since this is a
  2069. // singleton, this panic occurs even when using distinct quic-go
  2070. // listeners per conn.
  2071. //
  2072. // No actual network traffic is sent to these artificial addresses.
  2073. ip := uniqueIPv6Address.next()
  2074. localAddr := &net.UDPAddr{IP: ip, Port: 1}
  2075. remoteAddr := &net.UDPAddr{IP: ip, Port: 2}
  2076. return &mediaTrackPacketConn{
  2077. webRTCConn: conn,
  2078. localAddr: localAddr,
  2079. remoteAddr: remoteAddr,
  2080. }
  2081. }
  2082. func (conn *mediaTrackPacketConn) ReadFrom(p []byte) (int, net.Addr, error) {
  2083. if atomic.LoadInt32(&conn.isClosed) == 1 {
  2084. return 0, conn.remoteAddr, errors.TraceNew("closed")
  2085. }
  2086. n, err := conn.webRTCConn.readMediaTrack(p)
  2087. return n, conn.remoteAddr, errors.TraceReader(err)
  2088. }
  2089. func (conn *mediaTrackPacketConn) WriteTo(p []byte, addr net.Addr) (int, error) {
  2090. if atomic.LoadInt32(&conn.isClosed) == 1 {
  2091. return 0, errors.TraceNew("closed")
  2092. }
  2093. n, err := conn.webRTCConn.writeMediaTrackPacket(p, false)
  2094. return n, errors.Trace(err)
  2095. }
  2096. func (conn *mediaTrackPacketConn) Close() error {
  2097. if !atomic.CompareAndSwapInt32(&conn.isClosed, 0, 1) {
  2098. return nil
  2099. }
  2100. return nil
  2101. }
  2102. func (conn *mediaTrackPacketConn) LocalAddr() net.Addr {
  2103. return conn.localAddr
  2104. }
  2105. func (conn *mediaTrackPacketConn) SetDeadline(t time.Time) error {
  2106. return errors.TraceNew("not supported")
  2107. }
  2108. func (conn *mediaTrackPacketConn) SetReadDeadline(t time.Time) error {
  2109. // Workaround:
  2110. //
  2111. // When a quic-go DialEarly fails, it invokes Transport.Close. In turn,
  2112. // Transport.Close calls this SetReadDeadline in order to interrupt any
  2113. // blocked read. The underlying pion/webrtc.TrackRemote has a
  2114. // SetReadDeadline. However, at this time webRTCConn.receiveMediaTrack
  2115. // may be nil, and readMediaTrack may be blocking on
  2116. // receiveMediaTrackOpenedSignal.
  2117. //
  2118. // In addition, as of v2.2.4, pion/transport/v2/packetio.Buffer.Read,
  2119. // which underlies receiveMediaTrack.Read, isn't interrupted when
  2120. // SetReadDeadline is update -- it only checks and applies the read
  2121. // deadline once before blocking.
  2122. //
  2123. // Simply calling webRTCConn.Close unblocks both cases.
  2124. //
  2125. // Invoke in a goroutine to avoid a deadlock that would otherwise occur
  2126. // when webRTCConn.Close is invoked directly, as it will call down to
  2127. // mediaTrackPacketConn.SetReadDeadline via reliableConn.Close. The
  2128. // webRTCConn.Close isClosed check ensures there isn't an endless loop of
  2129. // calls.
  2130. //
  2131. // Assumes that mediaTrackPacketConn.SetReadDeadline is called only in
  2132. // this terminating quic-go case.
  2133. go func() {
  2134. _ = conn.webRTCConn.Close()
  2135. }()
  2136. return nil
  2137. }
  2138. func (conn *mediaTrackPacketConn) SetWriteDeadline(t time.Time) error {
  2139. return errors.TraceNew("not supported")
  2140. }
  2141. // reliableConn provides a reliable/ordered delivery layer on top of the media
  2142. // track RTP conn. This is implemented as a QUIC connection.
  2143. type reliableConn struct {
  2144. mediaTrackConn *mediaTrackPacketConn
  2145. quicTransport *quic_go.Transport
  2146. quicConn quic_go.EarlyConnection
  2147. quicStream quic_go.Stream
  2148. readMutex sync.Mutex
  2149. writeMutex sync.Mutex
  2150. isClosed int32
  2151. }
  2152. func (conn *reliableConn) Read(b []byte) (int, error) {
  2153. if atomic.LoadInt32(&conn.isClosed) == 1 {
  2154. return 0, errors.TraceNew("closed")
  2155. }
  2156. // Add mutex to provide full net.Conn concurrency semantics.
  2157. // https://github.com/lucas-clemente/quic-go/blob/9cc23135d0477baf83aa4715de39ae7070039cb2/stream.go#L64
  2158. // "Read() and Write() may be called concurrently, but multiple calls to
  2159. // "Read() or Write() individually must be synchronized manually."
  2160. conn.readMutex.Lock()
  2161. defer conn.readMutex.Unlock()
  2162. n, err := conn.quicStream.Read(b)
  2163. if quic.IsIETFErrorIndicatingClosed(err) {
  2164. _ = conn.Close()
  2165. err = io.EOF
  2166. }
  2167. return n, errors.TraceReader(err)
  2168. }
  2169. func (conn *reliableConn) Write(b []byte) (int, error) {
  2170. if atomic.LoadInt32(&conn.isClosed) == 1 {
  2171. return 0, errors.TraceNew("closed")
  2172. }
  2173. conn.writeMutex.Lock()
  2174. defer conn.writeMutex.Unlock()
  2175. n, err := conn.quicStream.Write(b)
  2176. if quic.IsIETFErrorIndicatingClosed(err) {
  2177. _ = conn.Close()
  2178. if n == len(b) {
  2179. err = nil
  2180. }
  2181. }
  2182. return n, errors.Trace(err)
  2183. }
  2184. func (conn *reliableConn) Close() error {
  2185. if !atomic.CompareAndSwapInt32(&conn.isClosed, 0, 1) {
  2186. return nil
  2187. }
  2188. // Close mediaTrackConn first, or else quic-go's Close will attempt to
  2189. // Write, which leads to deadlock between webRTCConn.writeMediaTrack and
  2190. // webRTCConn.Close. The graceful QUIC close write will fail, but that's
  2191. // not an issue.
  2192. _ = conn.mediaTrackConn.Close()
  2193. err := conn.quicConn.CloseWithError(0, "")
  2194. if conn.quicTransport != nil {
  2195. conn.quicTransport.Close()
  2196. }
  2197. return errors.Trace(err)
  2198. }
  2199. func (conn *reliableConn) LocalAddr() net.Addr {
  2200. return conn.quicConn.LocalAddr()
  2201. }
  2202. func (conn *reliableConn) RemoteAddr() net.Addr {
  2203. return conn.quicConn.RemoteAddr()
  2204. }
  2205. func (conn *reliableConn) SetDeadline(t time.Time) error {
  2206. return conn.quicStream.SetDeadline(t)
  2207. }
  2208. func (conn *reliableConn) SetReadDeadline(t time.Time) error {
  2209. return conn.quicStream.SetReadDeadline(t)
  2210. }
  2211. func (conn *reliableConn) SetWriteDeadline(t time.Time) error {
  2212. return conn.quicStream.SetWriteDeadline(t)
  2213. }
  2214. // prepareSDPAddresses adjusts the SDP, pruning local network addresses and
  2215. // adding any port mapping as a host candidate.
  2216. func prepareSDPAddresses(
  2217. encodedSDP []byte,
  2218. errorOnNoCandidates bool,
  2219. portMappingExternalAddr string,
  2220. disableIPv6Candidates bool,
  2221. allowPrivateIPAddressCandidates bool) ([]byte, *webRTCSDPMetrics, error) {
  2222. modifiedSDP, metrics, err := processSDPAddresses(
  2223. encodedSDP,
  2224. errorOnNoCandidates,
  2225. portMappingExternalAddr,
  2226. disableIPv6Candidates,
  2227. allowPrivateIPAddressCandidates,
  2228. false,
  2229. nil,
  2230. common.GeoIPData{})
  2231. return modifiedSDP, metrics, errors.Trace(err)
  2232. }
  2233. // filterSDPAddresses checks that the SDP does not contain an empty list of
  2234. // candidates, bogon candidates, or candidates outside of the country and ASN
  2235. // for the specified expectedGeoIPData. Invalid candidates are stripped and a
  2236. // filtered SDP is returned.
  2237. func filterSDPAddresses(
  2238. encodedSDP []byte,
  2239. errorOnNoCandidates bool,
  2240. lookupGeoIP LookupGeoIP,
  2241. expectedGeoIPData common.GeoIPData,
  2242. allowPrivateIPAddressCandidates bool,
  2243. filterPrivateIPAddressCandidates bool) ([]byte, *webRTCSDPMetrics, error) {
  2244. filteredSDP, metrics, err := processSDPAddresses(
  2245. encodedSDP,
  2246. errorOnNoCandidates,
  2247. "",
  2248. false,
  2249. allowPrivateIPAddressCandidates,
  2250. filterPrivateIPAddressCandidates,
  2251. lookupGeoIP,
  2252. expectedGeoIPData)
  2253. return filteredSDP, metrics, errors.Trace(err)
  2254. }
  2255. // webRTCSDPMetrics are network capability metrics values for an SDP.
  2256. type webRTCSDPMetrics struct {
  2257. iceCandidateTypes []ICECandidateType
  2258. hasIPv6 bool
  2259. hasPrivateIP bool
  2260. filteredICECandidates []string
  2261. }
  2262. // processSDPAddresses is based on snowflake/common/util.StripLocalAddresses
  2263. // https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/blob/v2.5.1/common/util/util.go#L70-99
  2264. /*
  2265. This file contains the license for "Snowflake"
  2266. a free software project which provides a WebRTC pluggable transport.
  2267. ================================================================================
  2268. Copyright (c) 2016, Serene Han, Arlo Breault
  2269. Copyright (c) 2019-2020, The Tor Project, Inc
  2270. Redistribution and use in source and binary forms, with or without modification,
  2271. are permitted provided that the following conditions are met:
  2272. * Redistributions of source code must retain the above copyright notice, this
  2273. list of conditions and the following disclaimer.
  2274. * Redistributions in binary form must reproduce the above copyright notice,
  2275. this list of conditions and the following disclaimer in the documentation and/or
  2276. other materials provided with the distribution.
  2277. * Neither the names of the copyright owners nor the names of its
  2278. contributors may be used to endorse or promote products derived from this
  2279. software without specific prior written permission.
  2280. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  2281. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  2282. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  2283. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  2284. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  2285. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  2286. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  2287. ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  2288. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  2289. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  2290. ================================================================================
  2291. */
  2292. func processSDPAddresses(
  2293. encodedSDP []byte,
  2294. errorOnNoCandidates bool,
  2295. portMappingExternalAddr string,
  2296. disableIPv6Candidates bool,
  2297. allowPrivateIPAddressCandidates bool,
  2298. filterPrivateIPAddressCandidates bool,
  2299. lookupGeoIP LookupGeoIP,
  2300. expectedGeoIPData common.GeoIPData) ([]byte, *webRTCSDPMetrics, error) {
  2301. var sessionDescription sdp.SessionDescription
  2302. err := sessionDescription.Unmarshal(encodedSDP)
  2303. if err != nil {
  2304. return nil, nil, errors.Trace(err)
  2305. }
  2306. candidateTypes := map[ICECandidateType]bool{}
  2307. hasIPv6 := false
  2308. hasPrivateIP := false
  2309. filteredCandidateReasons := make(map[string]int)
  2310. var portMappingICECandidates []sdp.Attribute
  2311. if portMappingExternalAddr != "" {
  2312. // Prepare ICE candidate attibute pair for the port mapping, modeled
  2313. // after the definition of host candidates.
  2314. host, portStr, err := net.SplitHostPort(portMappingExternalAddr)
  2315. if err != nil {
  2316. return nil, nil, errors.Trace(err)
  2317. }
  2318. port, err := strconv.Atoi(portStr)
  2319. if err != nil {
  2320. return nil, nil, errors.Trace(err)
  2321. }
  2322. // Only IPv4 port mapping addresses are supported due to the
  2323. // NewCandidateHost limitation noted below. It is expected that port
  2324. // mappings will be IPv4, as NAT and IPv6 is not a typical combination.
  2325. hostIP := net.ParseIP(host)
  2326. if hostIP != nil && hostIP.To4() != nil {
  2327. for _, component := range []webrtc.ICEComponent{webrtc.ICEComponentRTP, webrtc.ICEComponentRTCP} {
  2328. // The candidate ID is generated and the priority and foundation
  2329. // use the default for hosts.
  2330. //
  2331. // Limitation: NewCandidateHost initializes the networkType to
  2332. // NetworkTypeUDP4, and this field is not-exported.
  2333. // https://github.com/pion/ice/blob/6d301287654b05a36248842c278d58d501454bff/candidate_host.go#L27-L64
  2334. iceCandidate, err := ice.NewCandidateHost(&ice.CandidateHostConfig{
  2335. Network: "udp",
  2336. Address: host,
  2337. Port: port,
  2338. Component: uint16(component),
  2339. })
  2340. if err != nil {
  2341. return nil, nil, errors.Trace(err)
  2342. }
  2343. portMappingICECandidates = append(
  2344. portMappingICECandidates,
  2345. sdp.Attribute{Key: "candidate", Value: iceCandidate.Marshal()})
  2346. }
  2347. candidateTypes[ICECandidatePortMapping] = true
  2348. }
  2349. }
  2350. candidateCount := len(portMappingICECandidates)
  2351. for _, mediaDescription := range sessionDescription.MediaDescriptions {
  2352. addPortMappingCandidates := len(portMappingICECandidates) > 0
  2353. var attributes []sdp.Attribute
  2354. for _, attribute := range mediaDescription.Attributes {
  2355. // Insert the port mapping candidate either before the
  2356. // first "a=candidate", or before "a=end-of-candidates"(there may
  2357. // be no "a=candidate" attributes).
  2358. if addPortMappingCandidates &&
  2359. (attribute.IsICECandidate() || attribute.Key == sdp.AttrKeyEndOfCandidates) {
  2360. attributes = append(attributes, portMappingICECandidates...)
  2361. addPortMappingCandidates = false
  2362. }
  2363. if attribute.IsICECandidate() {
  2364. candidate, err := ice.UnmarshalCandidate(attribute.Value)
  2365. if err != nil {
  2366. return nil, nil, errors.Trace(err)
  2367. }
  2368. candidateIP := net.ParseIP(candidate.Address())
  2369. if candidateIP == nil {
  2370. return nil, nil, errors.TraceNew("unexpected non-IP")
  2371. }
  2372. candidateIsIPv6 := false
  2373. if candidateIP.To4() == nil {
  2374. if disableIPv6Candidates {
  2375. reason := fmt.Sprintf("disabled %s IPv6",
  2376. candidate.Type().String())
  2377. filteredCandidateReasons[reason] += 1
  2378. continue
  2379. }
  2380. candidateIsIPv6 = true
  2381. }
  2382. // Strip non-routable bogons, including RFC 1918/4193 private
  2383. // IP addresses. Same-LAN client/proxy hops are not expected
  2384. // to be useful, and this also avoids unnecessary network traffic.
  2385. //
  2386. // Well-behaved clients and proxies should strip these values;
  2387. // the broker enforces this with filtering.
  2388. //
  2389. // In personal pairing mode, private IP addresses are allowed,
  2390. // as connection may be made between devices the same LAN and
  2391. // not all routers support NAT hairpinning.
  2392. candidateIsPrivateIP := candidateIP.IsPrivate()
  2393. if !GetAllowBogonWebRTCConnections() &&
  2394. !(candidateIsPrivateIP && allowPrivateIPAddressCandidates) &&
  2395. common.IsBogon(candidateIP) {
  2396. version := "IPv4"
  2397. if candidateIsIPv6 {
  2398. version = "IPv6"
  2399. }
  2400. reason := fmt.Sprintf("bogon %s %s",
  2401. candidate.Type().String(), version)
  2402. filteredCandidateReasons[reason] += 1
  2403. continue
  2404. }
  2405. // In personal pairing mode, filter out any private IP
  2406. // addresses for which there is no corresponding local,
  2407. // active interface. This avoids unnecessary network traffic.
  2408. // This filtering option is applied post-broker exchange,
  2409. // with the SDP received, via the broker, from the peer.
  2410. if candidateIsPrivateIP && filterPrivateIPAddressCandidates {
  2411. if !hasInterfaceForPrivateIPAddress(candidateIP) {
  2412. continue
  2413. }
  2414. }
  2415. // The broker will check that clients and proxies specify only
  2416. // candidates that map to the same GeoIP country and ASN as
  2417. // the client/proxy connection to the broker. This limits
  2418. // misuse of candidates to connect to other locations.
  2419. // Legitimate candidates will not all have the exact same IP
  2420. // address, as there could be a mix of IPv4 and IPv6, as well
  2421. // as potentially different NAT paths.
  2422. //
  2423. // In some cases, legitimate clients and proxies may
  2424. // unintentionally submit candidates with mismatching GeoIP.
  2425. // This can occur, for example, when a STUN candidate is only
  2426. // a partial hole punch through double NAT, and when internal
  2427. // network addresses misuse non-private IP ranges (so are
  2428. // technically not bogons). Instead of outright rejecting
  2429. // SDPs containing unexpected GeoIP candidates, they are
  2430. // instead stripped out and the resulting filtered SDP is
  2431. // used.
  2432. if lookupGeoIP != nil {
  2433. candidateGeoIPData := lookupGeoIP(candidate.Address())
  2434. if candidateGeoIPData.Country != expectedGeoIPData.Country ||
  2435. candidateGeoIPData.ASN != expectedGeoIPData.ASN {
  2436. version := "IPv4"
  2437. if candidateIsIPv6 {
  2438. version = "IPv6"
  2439. }
  2440. reason := fmt.Sprintf(
  2441. "unexpected GeoIP %s %s: %s/%s",
  2442. candidate.Type().String(),
  2443. version,
  2444. candidateGeoIPData.Country,
  2445. candidateGeoIPData.ASN)
  2446. filteredCandidateReasons[reason] += 1
  2447. continue
  2448. }
  2449. }
  2450. if candidateIsIPv6 {
  2451. hasIPv6 = true
  2452. }
  2453. if candidateIsPrivateIP {
  2454. hasPrivateIP = true
  2455. }
  2456. // These types are not reported:
  2457. // - CandidateTypeRelay: TURN servers are not used.
  2458. // - CandidateTypePeerReflexive: this candidate type only
  2459. // emerges later in the connection process.
  2460. switch candidate.Type() {
  2461. case ice.CandidateTypeHost:
  2462. candidateTypes[ICECandidateHost] = true
  2463. case ice.CandidateTypeServerReflexive:
  2464. candidateTypes[ICECandidateServerReflexive] = true
  2465. }
  2466. candidateCount += 1
  2467. }
  2468. attributes = append(attributes, attribute)
  2469. }
  2470. mediaDescription.Attributes = attributes
  2471. }
  2472. if errorOnNoCandidates && candidateCount == 0 {
  2473. return nil, nil, errors.TraceNew("no candidates")
  2474. }
  2475. encodedSDP, err = sessionDescription.Marshal()
  2476. if err != nil {
  2477. return nil, nil, errors.Trace(err)
  2478. }
  2479. metrics := &webRTCSDPMetrics{
  2480. hasIPv6: hasIPv6,
  2481. hasPrivateIP: hasPrivateIP,
  2482. }
  2483. for candidateType := range candidateTypes {
  2484. metrics.iceCandidateTypes = append(metrics.iceCandidateTypes, candidateType)
  2485. }
  2486. for reason, count := range filteredCandidateReasons {
  2487. metrics.filteredICECandidates = append(metrics.filteredICECandidates,
  2488. fmt.Sprintf("%s: %d", reason, count))
  2489. }
  2490. return encodedSDP, metrics, nil
  2491. }
  2492. type pionLoggerFactory struct {
  2493. logger common.Logger
  2494. stopLogging func() bool
  2495. debugLogging bool
  2496. }
  2497. func newPionLoggerFactory(
  2498. logger common.Logger, stopLogging func() bool, debugLogging bool) *pionLoggerFactory {
  2499. return &pionLoggerFactory{
  2500. logger: logger,
  2501. stopLogging: stopLogging,
  2502. debugLogging: debugLogging,
  2503. }
  2504. }
  2505. func (f *pionLoggerFactory) NewLogger(scope string) pion_logging.LeveledLogger {
  2506. return newPionLogger(scope, f.logger, f.stopLogging, f.debugLogging)
  2507. }
  2508. // pionLogger wraps common.Logger and implements
  2509. // https://pkg.go.dev/github.com/pion/logging#LeveledLogger for passing into
  2510. // pion.
  2511. type pionLogger struct {
  2512. scope string
  2513. logger common.Logger
  2514. stopLogging func() bool
  2515. debugLogging bool
  2516. warnNoPairs int32
  2517. }
  2518. func newPionLogger(
  2519. scope string, logger common.Logger, stopLogging func() bool, debugLogging bool) *pionLogger {
  2520. return &pionLogger{
  2521. scope: scope,
  2522. logger: logger,
  2523. stopLogging: stopLogging,
  2524. debugLogging: debugLogging,
  2525. }
  2526. }
  2527. func (l *pionLogger) Trace(msg string) {
  2528. if l.stopLogging() || !l.debugLogging {
  2529. return
  2530. }
  2531. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  2532. }
  2533. func (l *pionLogger) Tracef(format string, args ...interface{}) {
  2534. if l.stopLogging() || !l.debugLogging {
  2535. return
  2536. }
  2537. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2538. }
  2539. func (l *pionLogger) Debug(msg string) {
  2540. if l.stopLogging() || !l.debugLogging {
  2541. return
  2542. }
  2543. l.logger.WithTrace().Debug(fmt.Sprintf("[webRTC: %s: %s", l.scope, msg))
  2544. }
  2545. func (l *pionLogger) Debugf(format string, args ...interface{}) {
  2546. if l.stopLogging() || !l.debugLogging {
  2547. return
  2548. }
  2549. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2550. }
  2551. func (l *pionLogger) Info(msg string) {
  2552. if l.stopLogging() {
  2553. return
  2554. }
  2555. l.logger.WithTrace().Info(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  2556. }
  2557. func (l *pionLogger) Infof(format string, args ...interface{}) {
  2558. if l.stopLogging() {
  2559. return
  2560. }
  2561. l.logger.WithTrace().Info(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2562. }
  2563. func (l *pionLogger) Warn(msg string) {
  2564. if l.stopLogging() {
  2565. return
  2566. }
  2567. // To reduce diagnostic log noise, only log this message once per dial attempt.
  2568. if msg == "Failed to ping without candidate pairs. Connection is not possible yet." &&
  2569. !atomic.CompareAndSwapInt32(&l.warnNoPairs, 0, 1) {
  2570. return
  2571. }
  2572. l.logger.WithTrace().Warning(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  2573. }
  2574. func (l *pionLogger) Warnf(format string, args ...interface{}) {
  2575. if l.stopLogging() {
  2576. return
  2577. }
  2578. l.logger.WithTrace().Warning(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2579. }
  2580. func (l *pionLogger) Error(msg string) {
  2581. if l.stopLogging() {
  2582. return
  2583. }
  2584. l.logger.WithTrace().Error(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  2585. }
  2586. func (l *pionLogger) Errorf(format string, args ...interface{}) {
  2587. if l.stopLogging() {
  2588. return
  2589. }
  2590. l.logger.WithTrace().Error(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  2591. }
  2592. func hasInterfaceForPrivateIPAddress(IP net.IP) bool {
  2593. if !IP.IsPrivate() {
  2594. return false
  2595. }
  2596. // The anet package is used to work around net.Interfaces not working on
  2597. // Android at this time: https://github.com/golang/go/issues/40569.
  2598. //
  2599. // Any errors are silently dropped; the caller will proceed without using
  2600. // the input private IP; and equivalent anet calls are made in
  2601. // pionNetwork.Interfaces, with errors logged.
  2602. netInterfaces, err := anet.Interfaces()
  2603. if err != nil {
  2604. return false
  2605. }
  2606. for _, netInterface := range netInterfaces {
  2607. // Note: don't exclude interfaces with the net.FlagPointToPoint flag,
  2608. // which is set for certain mobile networks
  2609. if netInterface.Flags&net.FlagUp == 0 {
  2610. continue
  2611. }
  2612. addrs, err := anet.InterfaceAddrsByInterface(&netInterface)
  2613. if err != nil {
  2614. continue
  2615. }
  2616. for _, addr := range addrs {
  2617. _, IPNet, err := net.ParseCIDR(addr.String())
  2618. if err != nil {
  2619. continue
  2620. }
  2621. if IPNet.Contains(IP) {
  2622. return true
  2623. }
  2624. }
  2625. }
  2626. return false
  2627. }
  2628. // pionNetwork implements pion/transport.Net.
  2629. //
  2630. // Via the SettingsEngine, pion is configured to use a pionNetwork instance,
  2631. // which providing alternative implementations for various network functions.
  2632. // The Interfaces implementation provides a workaround for Android
  2633. // net.Interfaces issues and reduces the number of IPv6 candidates to avoid
  2634. // excess STUN requests; and the ResolveUDPAddr implementation hooks into the
  2635. // Psiphon custom resolver.
  2636. type pionNetwork struct {
  2637. dialCtx context.Context
  2638. logger pion_logging.LeveledLogger
  2639. webRTCDialCoordinator WebRTCDialCoordinator
  2640. }
  2641. func newPionNetwork(
  2642. dialCtx context.Context,
  2643. logger pion_logging.LeveledLogger,
  2644. webRTCDialCoordinator WebRTCDialCoordinator) *pionNetwork {
  2645. return &pionNetwork{
  2646. dialCtx: dialCtx,
  2647. logger: logger,
  2648. webRTCDialCoordinator: webRTCDialCoordinator,
  2649. }
  2650. }
  2651. func (p *pionNetwork) Interfaces() ([]*transport.Interface, error) {
  2652. // To determine the active IPv4 and IPv6 interfaces, let the OS bind IPv4
  2653. // and IPv6 UDP sockets with a specified external destination address.
  2654. // Then iterate over all interfaces, but return interface info for only
  2655. // the interfaces those sockets were bound to.
  2656. //
  2657. // The destination IPs are the IPs that currently resolve for example.com.
  2658. // No actual traffic to these IPs or example.com is sent, as the UDP
  2659. // sockets are not used to send any packets.
  2660. //
  2661. // This scheme should select just one IPv4 and one IPv6 address, which
  2662. // should be the active, externally routable addresses, and the IPv6
  2663. // address should be the preferred, non-deprecated temporary IPv6 address.
  2664. //
  2665. // In post-ICE gathering processing, processSDPAddresses will also strip
  2666. // all bogon addresses, so there is no explicit bogon check here.
  2667. //
  2668. // Limitations:
  2669. //
  2670. // - The active interface could change between the socket operation and
  2671. // iterating over all interfaces. Higher-level code is expected to
  2672. // react to active network changes.
  2673. //
  2674. // - The public IPs for example.com may not be robust in all routing
  2675. // situations. Alternatively, we could use the configured STUN server
  2676. // as the test destination, but the STUN server domain is not resolved
  2677. // at this point and STUN is not always configured and used.
  2678. //
  2679. // - The results could be cached and reused.
  2680. var defaultIPv4, defaultIPv6 net.IP
  2681. udpConnIPv4, err := p.webRTCDialCoordinator.UDPConn(
  2682. context.Background(), "udp4", "93.184.216.34:3478")
  2683. if err == nil {
  2684. defaultIPv4 = udpConnIPv4.LocalAddr().(*net.UDPAddr).IP
  2685. udpConnIPv4.Close()
  2686. }
  2687. udpConnIPv6, err := p.webRTCDialCoordinator.UDPConn(
  2688. context.Background(), "udp6", "[2606:2800:220:1:248:1893:25c8:1946]:3478")
  2689. if err == nil {
  2690. defaultIPv6 = udpConnIPv6.LocalAddr().(*net.UDPAddr).IP
  2691. udpConnIPv6.Close()
  2692. }
  2693. // The anet package is used to work around net.Interfaces not working on
  2694. // Android at this time: https://github.com/golang/go/issues/40569.
  2695. transportInterfaces := []*transport.Interface{}
  2696. netInterfaces, err := anet.Interfaces()
  2697. if err != nil {
  2698. return nil, errors.Trace(err)
  2699. }
  2700. for _, netInterface := range netInterfaces {
  2701. // Note: don't exclude interfaces with the net.FlagPointToPoint flag,
  2702. // which is set for certain mobile networks
  2703. if (netInterface.Flags&net.FlagUp == 0) ||
  2704. (!GetAllowBogonWebRTCConnections() && (netInterface.Flags&net.FlagLoopback != 0)) {
  2705. continue
  2706. }
  2707. addrs, err := anet.InterfaceAddrsByInterface(&netInterface)
  2708. if err != nil {
  2709. return nil, errors.Trace(err)
  2710. }
  2711. var transportInterface *transport.Interface
  2712. for _, addr := range addrs {
  2713. IP, _, err := net.ParseCIDR(addr.String())
  2714. if err != nil {
  2715. return nil, errors.Trace(err)
  2716. }
  2717. if IP.Equal(defaultIPv4) || IP.Equal(defaultIPv6) ||
  2718. (GetAllowBogonWebRTCConnections() && (netInterface.Flags&net.FlagLoopback != 0)) {
  2719. if transportInterface == nil {
  2720. transportInterface = transport.NewInterface(netInterface)
  2721. }
  2722. transportInterface.AddAddress(addr)
  2723. }
  2724. }
  2725. if transportInterface != nil {
  2726. transportInterfaces = append(transportInterfaces, transportInterface)
  2727. }
  2728. }
  2729. return transportInterfaces, nil
  2730. }
  2731. func (p *pionNetwork) ResolveUDPAddr(network, address string) (retAddr *net.UDPAddr, retErr error) {
  2732. defer func() {
  2733. if retErr != nil {
  2734. // Explicitly log an error since certain pion operations -- e.g.,
  2735. // ICE gathering -- don't propagate all pion/transport.Net errors.
  2736. p.logger.Errorf("pionNetwork.ResolveUDPAddr failed: %v", retErr)
  2737. }
  2738. }()
  2739. // Currently, pion appears to call ResolveUDPAddr with "udp4"/udp6"
  2740. // instead of "ip4"/"ip6", as expected by, e.g., net.Resolver.LookupIP.
  2741. // Convert to "ip4"/"ip6".
  2742. // Specifying v4/v6 ensures that the resolved IP address is the correct
  2743. // type. In the case of STUN servers, the correct type is required in
  2744. // order to create the correct IPv4 or IPv6 whole punch address.
  2745. switch network {
  2746. case "udp4", "tcp4":
  2747. network = "ip4"
  2748. case "udp6", "tcp6":
  2749. network = "ip6"
  2750. default:
  2751. network = "ip"
  2752. }
  2753. // Currently, pion appears to call ResolveUDPAddr with an improperly
  2754. // formatted address, <IPv6>:443 not [<IPv6>]:443; handle this case.
  2755. index := strings.LastIndex(address, ":")
  2756. if index != -1 {
  2757. address = net.JoinHostPort(address[:index], address[index+1:])
  2758. }
  2759. // Use the Psiphon custom resolver to resolve any STUN server domains.
  2760. resolvedAddress, err := p.webRTCDialCoordinator.ResolveAddress(
  2761. p.dialCtx, network, address)
  2762. if err != nil {
  2763. return nil, errors.Trace(err)
  2764. }
  2765. IPStr, portStr, err := net.SplitHostPort(resolvedAddress)
  2766. if err != nil {
  2767. return nil, errors.Trace(err)
  2768. }
  2769. IP := net.ParseIP(IPStr)
  2770. if IP == nil {
  2771. return nil, errors.TraceNew("invalid IP address")
  2772. }
  2773. port, err := strconv.Atoi(portStr)
  2774. if err != nil {
  2775. return nil, errors.Trace(err)
  2776. }
  2777. return &net.UDPAddr{IP: IP, Port: port}, nil
  2778. }
  2779. var errNotSupported = std_errors.New("not supported")
  2780. func (p *pionNetwork) ListenPacket(network string, address string) (net.PacketConn, error) {
  2781. // Explicitly log an error since certain pion operations -- e.g., ICE
  2782. // gathering -- don't propagate all pion/transport.Net errors.
  2783. p.logger.Errorf("unexpected pionNetwork.ListenPacket call from %s", stacktrace.GetParentFunctionName())
  2784. return nil, errors.Trace(errNotSupported)
  2785. }
  2786. func (p *pionNetwork) ListenUDP(network string, locAddr *net.UDPAddr) (transport.UDPConn, error) {
  2787. p.logger.Errorf("unexpected pionNetwork.ListenUDP call from %s", stacktrace.GetParentFunctionName())
  2788. return nil, errors.Trace(errNotSupported)
  2789. }
  2790. func (p *pionNetwork) ListenTCP(network string, laddr *net.TCPAddr) (transport.TCPListener, error) {
  2791. p.logger.Errorf("unexpected pionNetwork.ListenTCP call from %s", stacktrace.GetParentFunctionName())
  2792. return nil, errors.Trace(errNotSupported)
  2793. }
  2794. func (p *pionNetwork) Dial(network, address string) (net.Conn, error) {
  2795. p.logger.Errorf("unexpected pionNetwork.Dial call from %s", stacktrace.GetParentFunctionName())
  2796. return nil, errors.Trace(errNotSupported)
  2797. }
  2798. func (p *pionNetwork) DialUDP(network string, laddr, raddr *net.UDPAddr) (transport.UDPConn, error) {
  2799. p.logger.Errorf("unexpected pionNetwork.DialUDP call from %s", stacktrace.GetParentFunctionName())
  2800. return nil, errors.Trace(errNotSupported)
  2801. }
  2802. func (p *pionNetwork) DialTCP(network string, laddr, raddr *net.TCPAddr) (transport.TCPConn, error) {
  2803. p.logger.Errorf("unexpected pionNetwork.DialTCP call from %s", stacktrace.GetParentFunctionName())
  2804. return nil, errors.Trace(errNotSupported)
  2805. }
  2806. func (p *pionNetwork) ResolveIPAddr(network, address string) (*net.IPAddr, error) {
  2807. p.logger.Errorf("unexpected pionNetwork.ResolveIPAddr call from %s", stacktrace.GetParentFunctionName())
  2808. return nil, errors.Trace(errNotSupported)
  2809. }
  2810. func (p *pionNetwork) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
  2811. p.logger.Errorf("unexpected pionNetwork.ResolveTCPAddr call from %s", stacktrace.GetParentFunctionName())
  2812. return nil, errors.Trace(errNotSupported)
  2813. }
  2814. func (p *pionNetwork) InterfaceByIndex(index int) (*transport.Interface, error) {
  2815. p.logger.Errorf("unexpected pionNetwork.InterfaceByIndex call from %s", stacktrace.GetParentFunctionName())
  2816. return nil, errors.Trace(errNotSupported)
  2817. }
  2818. func (p *pionNetwork) InterfaceByName(name string) (*transport.Interface, error) {
  2819. p.logger.Errorf("unexpected pionNetwork.InterfaceByName call from %s", stacktrace.GetParentFunctionName())
  2820. return nil, errors.Trace(errNotSupported)
  2821. }
  2822. func (p *pionNetwork) CreateDialer(dialer *net.Dialer) transport.Dialer {
  2823. return &pionNetworkDialer{pionNetwork: p}
  2824. }
  2825. type pionNetworkDialer struct {
  2826. pionNetwork *pionNetwork
  2827. }
  2828. func (d pionNetworkDialer) Dial(network, address string) (net.Conn, error) {
  2829. d.pionNetwork.logger.Errorf("unexpected pionNetworkDialer.Dial call from %s", stacktrace.GetParentFunctionName())
  2830. return nil, errors.Trace(errNotSupported)
  2831. }