webrtc.go 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831
  1. /*
  2. * Copyright (c) 2023, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package inproxy
  20. import (
  21. "bytes"
  22. "context"
  23. "encoding/binary"
  24. std_errors "errors"
  25. "fmt"
  26. "net"
  27. "strconv"
  28. "strings"
  29. "sync"
  30. "sync/atomic"
  31. "time"
  32. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  33. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  34. inproxy_dtls "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy/dtls"
  35. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/stacktrace"
  37. "github.com/pion/datachannel"
  38. "github.com/pion/dtls/v2"
  39. "github.com/pion/ice/v2"
  40. pion_logging "github.com/pion/logging"
  41. "github.com/pion/sdp/v3"
  42. "github.com/pion/transport/v2"
  43. "github.com/pion/webrtc/v3"
  44. "github.com/wlynxg/anet"
  45. )
  46. const (
  47. dataChannelAwaitTimeout = 20 * time.Second
  48. dataChannelBufferedAmountLowThreshold uint64 = 512 * 1024
  49. dataChannelMaxBufferedAmount uint64 = 1024 * 1024
  50. dataChannelMaxMessageSize = 65536
  51. // Psiphon uses a fork of github.com/pion/dtls/v2, selected with go mod
  52. // replace, which has an idential API apart from dtls.IsPsiphon. If
  53. // dtls.IsPsiphon is undefined, the build is not using the fork.
  54. //
  55. // Limitation: this doesn't check that the vendored code is exactly the
  56. // same code as the fork.
  57. assertDTLSFork = dtls.IsPsiphon
  58. // Similarly, check for the fork of github.com/pion/ice/v2.
  59. assertICEFork = ice.IsPsiphon
  60. // Note that Psiphon also uses a fork of github.com/pion/webrtc/v3, but it
  61. // has an API change which will cause builds to fail when not present.
  62. )
  63. // WebRTCConn is a WebRTC connection between two peers, with a data channel
  64. // used to relay streams or packets between them. WebRTCConn implements the
  65. // net.Conn interface.
  66. type WebRTCConn struct {
  67. config *WebRTCConfig
  68. trafficShapingParameters *DataChannelTrafficShapingParameters
  69. mutex sync.Mutex
  70. udpConn net.PacketConn
  71. portMapper *portMapper
  72. isClosed bool
  73. closedSignal chan struct{}
  74. peerConnection *webrtc.PeerConnection
  75. dataChannel *webrtc.DataChannel
  76. dataChannelConn datachannel.ReadWriteCloser
  77. dataChannelOpenedSignal chan struct{}
  78. dataChannelOpenedOnce sync.Once
  79. dataChannelWriteBufferSignal chan struct{}
  80. decoyDone bool
  81. readMutex sync.Mutex
  82. readBuffer []byte
  83. readOffset int
  84. readLength int
  85. readError error
  86. peerPaddingDone bool
  87. writeMutex sync.Mutex
  88. trafficShapingPRNG *prng.PRNG
  89. trafficShapingBuffer *bytes.Buffer
  90. paddedMessageCount int
  91. decoyMessageCount int
  92. trafficShapingDone bool
  93. paddedMessagesSent int32
  94. paddedMessagesReceived int32
  95. decoyMessagesSent int32
  96. decoyMessagesReceived int32
  97. }
  98. // WebRTCConfig specifies the configuration for a WebRTC dial.
  99. type WebRTCConfig struct {
  100. // Logger is used to log events.
  101. Logger common.Logger
  102. // EnableDebugLogging indicates whether to log pion/webrtc debug and trace
  103. // events. When enabled, these events will be logged to the specified
  104. // Logger at a Debug log level.
  105. EnableDebugLogging bool
  106. // WebRTCDialCoordinator specifies specific WebRTC dial strategies and
  107. // settings; WebRTCDialCoordinator also facilities dial replay by
  108. // receiving callbacks when individual dial steps succeed or fail.
  109. WebRTCDialCoordinator WebRTCDialCoordinator
  110. // ClientRootObfuscationSecret is generated (or replayed) by the client
  111. // and sent to the proxy and used to drive obfuscation operations.
  112. ClientRootObfuscationSecret ObfuscationSecret
  113. // DoDTLSRandomization indicates whether to perform DTLS randomization.
  114. DoDTLSRandomization bool
  115. // TrafficShapingParameters indicates whether and how to perform data channel traffic shaping.
  116. TrafficShapingParameters *DataChannelTrafficShapingParameters
  117. // ReliableTransport indicates whether to configure the WebRTC data
  118. // channel to use reliable transport. Set ReliableTransport when proxying
  119. // a TCP stream, and unset it when proxying a UDP packets flow with its
  120. // own reliability later, such as QUIC.
  121. ReliableTransport bool
  122. }
  123. // NewWebRTCConnWithOffer initiates a new WebRTC connection. An offer SDP is
  124. // returned, to be sent to the peer. After the offer SDP is forwarded and an
  125. // answer SDP received in response, call SetRemoteSDP with the answer SDP and
  126. // then call AwaitInitialDataChannel to await the eventual WebRTC connection
  127. // establishment.
  128. func NewWebRTCConnWithOffer(
  129. ctx context.Context,
  130. config *WebRTCConfig) (
  131. *WebRTCConn, webrtc.SessionDescription, *SDPMetrics, error) {
  132. conn, SDP, metrics, err := newWebRTCConn(ctx, config, nil)
  133. if err != nil {
  134. return nil, webrtc.SessionDescription{}, nil, errors.Trace(err)
  135. }
  136. return conn, *SDP, metrics, nil
  137. }
  138. // NewWebRTCConnWithAnswer creates a new WebRTC connection initiated by a peer
  139. // that provided an offer SDP. An answer SDP is returned to be sent to the
  140. // peer. After the answer SDP is forwarded, call AwaitInitialDataChannel to
  141. // await the eventual WebRTC connection establishment.
  142. func NewWebRTCConnWithAnswer(
  143. ctx context.Context,
  144. config *WebRTCConfig,
  145. peerSDP webrtc.SessionDescription) (
  146. *WebRTCConn, webrtc.SessionDescription, *SDPMetrics, error) {
  147. conn, SDP, metrics, err := newWebRTCConn(ctx, config, &peerSDP)
  148. if err != nil {
  149. return nil, webrtc.SessionDescription{}, nil, errors.Trace(err)
  150. }
  151. return conn, *SDP, metrics, nil
  152. }
  153. func newWebRTCConn(
  154. ctx context.Context,
  155. config *WebRTCConfig,
  156. peerSDP *webrtc.SessionDescription) (
  157. retConn *WebRTCConn,
  158. retSDP *webrtc.SessionDescription,
  159. retMetrics *SDPMetrics,
  160. retErr error) {
  161. isOffer := peerSDP == nil
  162. udpConn, err := config.WebRTCDialCoordinator.UDPListen(ctx)
  163. if err != nil {
  164. return nil, nil, nil, errors.Trace(err)
  165. }
  166. // Initialize WebRTC
  167. // There is no explicit anti-probing measures for the proxy side of the
  168. // WebRTC connection, since each proxy "listener" is ephemeral, and since
  169. // the WebRTC data channel protocol authenticates peers with
  170. // certificates, so even if a probe were to find an ephemeral proxy
  171. // listener, the listener can respond the same as a normal WebRTC end
  172. // point would respond to a peer that doesn't have the correct credentials.
  173. //
  174. // pion's Mux API is used, as it enables providing a pre-created UDP
  175. // socket which is configured with necessary BindToDevice settings. We do
  176. // not actually multiplex multiple client connections on a single proxy
  177. // connection. As a proxy creates a new UDP socket and Mux for each
  178. // client, this currently open issue should not impact our
  179. // implementation: "Listener doesn't process parallel handshakes",
  180. // https://github.com/pion/dtls/issues/279.
  181. //
  182. // We detach data channels in order to use the standard Read/Write APIs.
  183. // As detaching avoids using the pion DataChannel read loop, this
  184. // currently open issue should not impact our
  185. // implementation: "DataChannel.readLoop goroutine leak",
  186. // https://github.com/pion/webrtc/issues/2098.
  187. // UDPMux Limitations:
  188. //
  189. // For Psiphon, WebRTCDialCoordinator.UDPListen will call
  190. // https://pkg.go.dev/net#ListenUDP with an unspecified IP address, in
  191. // order to listen on all available interfaces, both IPv4 and IPv6.
  192. // However, using webrtc.NewICEUDPMux and a UDP conn with an unspecified
  193. // IP address results in this log warning: "UDPMuxDefault should not
  194. // listening on unspecified address, use NewMultiUDPMuxFromPort instead".
  195. //
  196. // With NewICEUDPMux and an unspecified IP address, pion currently
  197. // enumerates local, active interfaces and derives a list of listening
  198. // addresses, combining each interface's IP addresses with the assigned
  199. // port:
  200. // https://github.com/pion/ice/blob/8c5b0991ef3bb070e47afda96faf090e8bf94be6/net.go#L35.
  201. // While this works ok in many cases, this PR,
  202. // https://github.com/pion/ice/pull/475, indicates the nature of the
  203. // issue with UDPMuxDefault:
  204. //
  205. // > When we have multiple host candidates and been mux to a single port,
  206. // > if these candidates share a same conn (either tcp or udp), they
  207. // > might read other's [messages causing failure].
  208. //
  209. // This PR, https://github.com/pion/ice/pull/473, also describes the issue:
  210. //
  211. // > When using UDPMux and UniversalUDPMux, it is possible that a
  212. // > registerConnForAddress() could be called twice or more for the same
  213. // > remote candidate (endpoint) by different candidates. E.g., when
  214. // > different HOST candidates ping the same remote candidate, the
  215. // > udpMuxedConn gets stored once. The second candidate will never
  216. // > receive a response. This is also the case when a single socket is
  217. // > used for gathering SRFLX and HOST candidates.
  218. //
  219. // PR 475 introduced MultiUDPMuxDefault to address the issue. However, at
  220. // this time, https://github.com/pion/ice/releases/tag/v2.3.6, there's an
  221. // open bug with MultiUDPMuxDefault
  222. // https://github.com/pion/ice/issues/507: "Multi UDP Mux can't works
  223. // when remote also enables Multi UDP Mux". Running the test program
  224. // attached to the bug confirms that no data channel is established;
  225. // while switching the test code to use NewICEUDPMux results in a
  226. // successful data channel connection. Since we need to use a Mux API on
  227. // both clients and proxies, we can't yet use MultiUDPMux.
  228. //
  229. // We patch pion/webrtc to add the SetICEUDPMuxSrflx functionality from
  230. // the currently unmerged https://github.com/pion/webrtc/pull/2298.
  231. // Without SetICEUDPMuxSrflx, STUN operations don't use the mux.
  232. //
  233. // We patch pion/ice gatherCandidatesSrflxUDPMux vendor patch to include
  234. // only the correct network type (IPv4 or IPv6) address candidates.
  235. // Without this patch, we observed up to 2x duplicate/redundant STUN
  236. // candidates.
  237. //
  238. // TODO: implement and try using transport.Net UDP dial functions in place
  239. // of NewICEUDPMux and pre-dialed UDP conn; track all dialed UDP
  240. // connections to close on WebRTCConn.Close; this approach would require
  241. // an alternative approach to injecting port mapping candidates, which
  242. // currently depends on the mux UDP socket being available outside of pion.
  243. // Another limitation and issue with NewICEUDPMux is that its enumeration
  244. // of all local interfaces and IPs includes many IPv6 addresses for
  245. // certain interfaces. For example, on macOS,
  246. // https://apple.stackexchange.com/a/371661, there are "secured" IPv6
  247. // addresses and many "temporary" IPv6 addresses, with all but one
  248. // temporary address being "deprecated". Instead of a full enumeration,
  249. // we should select only the non-deprecated temporary IPv6 address --
  250. // both for performance (avoid excess STUN requests) and privacy.
  251. //
  252. // Go has a proposal to expose the necessary IPv6 address information:
  253. // https://github.com/golang/go/issues/42694. However, as of Android SDK
  254. // 30, Go's net.InterfaceAddrs doesn't work at all:
  255. // https://github.com/pion/transport/issues/228,
  256. // https://github.com/golang/go/issues/40569.
  257. //
  258. // Note that it's not currently possible to
  259. // webrtc.SettingEngine.SetIPFilter to limit IPv6 selection to a single
  260. // candidate; that IP filter is not passed through to localInterfaces in
  261. // the NewUDPMuxDefault case. And even if it were, there's no guarantee
  262. // that the the first IPv6 address passed to the filter would be the
  263. // non-deprecated temporary address.
  264. //
  265. // To workaround net.Interface issues, we use SettingEngine.SetNet to plug
  266. // in an alternative implementation of net.Interface which selects only
  267. // one IPv4 and one IPv6 active interface and IP address and uses the
  268. // anet package for Android. See pionNetwork for more details.
  269. deadline, _ := ctx.Deadline()
  270. TTL := time.Until(deadline)
  271. pionLoggerFactory := newPionLoggerFactory(
  272. config.Logger,
  273. config.EnableDebugLogging)
  274. pionNetwork := newPionNetwork(
  275. ctx, pionLoggerFactory.NewLogger("net"), config.WebRTCDialCoordinator)
  276. udpMux := webrtc.NewICEUniversalUDPMux(
  277. pionLoggerFactory.NewLogger("mux"), udpConn, TTL, pionNetwork)
  278. settingEngine := webrtc.SettingEngine{
  279. LoggerFactory: pionLoggerFactory,
  280. }
  281. settingEngine.SetNet(pionNetwork)
  282. settingEngine.DetachDataChannels()
  283. settingEngine.SetICEMulticastDNSMode(ice.MulticastDNSModeDisabled)
  284. settingEngine.SetICEUDPMux(udpMux)
  285. settingEngine.SetICEUDPMuxSrflx(udpMux)
  286. // Set this behavior to look like common web browser WebRTC stacks.
  287. settingEngine.SetDTLSInsecureSkipHelloVerify(true)
  288. // Initialize data channel obfuscation
  289. config.Logger.WithTraceFields(common.LogFields{
  290. "dtls_randomization": config.DoDTLSRandomization,
  291. "data_channel_traffic_shaping": config.TrafficShapingParameters != nil,
  292. }).Info("data_channel_obfuscation")
  293. // Facilitate DTLS Client/ServerHello randomization. The client decides
  294. // whether to do DTLS randomization and generates and the proxy receives
  295. // ClientRootObfuscationSecret, so the client can orchestrate replay on
  296. // both ends of the connection by reusing an obfuscation secret. Derive a
  297. // secret specific to DTLS. SetDTLSSeed will futher derive a secure PRNG
  298. // seed specific to either the client or proxy end of the connection
  299. // (so each peer's randomization will be distinct).
  300. //
  301. // To avoid forking many pion repos in order to pass the seed through to
  302. // the DTLS implementation, SetDTLSSeed attaches the seed to the DTLS
  303. // dial context.
  304. //
  305. // Either SetDTLSSeed or SetNoDTLSSeed should be set for each conn, as the
  306. // pion/dtl fork treats no-seed as an error, as a check against the
  307. // context value mechanism.
  308. var dtlsCtx context.Context
  309. if config.DoDTLSRandomization {
  310. dtlsObfuscationSecret, err := deriveObfuscationSecret(
  311. config.ClientRootObfuscationSecret, "in-proxy-DTLS-seed")
  312. if err != nil {
  313. return nil, nil, nil, errors.Trace(err)
  314. }
  315. baseSeed := prng.Seed(dtlsObfuscationSecret)
  316. dtlsCtx, err = inproxy_dtls.SetDTLSSeed(ctx, &baseSeed, isOffer)
  317. if err != nil {
  318. return nil, nil, nil, errors.Trace(err)
  319. }
  320. } else {
  321. dtlsCtx = inproxy_dtls.SetNoDTLSSeed(ctx)
  322. }
  323. settingEngine.SetDTLSConnectContextMaker(func() (context.Context, func()) {
  324. return context.WithCancel(dtlsCtx)
  325. })
  326. webRTCAPI := webrtc.NewAPI(webrtc.WithSettingEngine(settingEngine))
  327. // Configure traffic shaping, which adds random padding and decoy messages
  328. // to data channel message flows.
  329. var trafficShapingPRNG *prng.PRNG
  330. trafficShapingBuffer := new(bytes.Buffer)
  331. paddedMessageCount := 0
  332. decoyMessageCount := 0
  333. if config.TrafficShapingParameters != nil {
  334. trafficShapingContext := "in-proxy-data-channel-traffic-shaping-offer"
  335. if !isOffer {
  336. trafficShapingContext = "in-proxy-data-channel-traffic-shaping-answer"
  337. }
  338. trafficShapingObfuscationSecret, err := deriveObfuscationSecret(
  339. config.ClientRootObfuscationSecret, trafficShapingContext)
  340. if err != nil {
  341. return nil, nil, nil, errors.Trace(err)
  342. }
  343. seed := prng.Seed(trafficShapingObfuscationSecret)
  344. trafficShapingPRNG = prng.NewPRNGWithSeed(&seed)
  345. paddedMessageCount = trafficShapingPRNG.Range(
  346. config.TrafficShapingParameters.MinPaddedMessages,
  347. config.TrafficShapingParameters.MaxPaddedMessages)
  348. decoyMessageCount = trafficShapingPRNG.Range(
  349. config.TrafficShapingParameters.MinDecoyMessages,
  350. config.TrafficShapingParameters.MaxDecoyMessages)
  351. }
  352. // NAT traversal setup
  353. // When DisableInboundForMobleNetworks is set, skip both STUN and port
  354. // mapping for mobile networks. Most mobile networks use CGNAT and
  355. // neither STUN nor port mapping will be effective. It's faster to not
  356. // wait for something that ultimately won't work.
  357. disableInbound := config.WebRTCDialCoordinator.DisableInboundForMobleNetworks() &&
  358. config.WebRTCDialCoordinator.NetworkType() == NetworkTypeMobile
  359. // Try to establish a port mapping (UPnP-IGD, PCP, or NAT-PMP). The port
  360. // mapper will attempt to identify the local gateway and query various
  361. // port mapping protocols. portMapper.start launches this process and
  362. // does not block. Port mappings are not part of the WebRTC standard, or
  363. // supported by pion/webrtc. Instead, if a port mapping is established,
  364. // it's edited into the SDP as a new host-type ICE candidate.
  365. localPort := udpConn.LocalAddr().(*net.UDPAddr).Port
  366. portMapper := newPortMapper(config.Logger, localPort)
  367. doPortMapping := !disableInbound && !config.WebRTCDialCoordinator.DisablePortMapping()
  368. if doPortMapping {
  369. portMapper.start()
  370. }
  371. // Select a STUN server for ICE hole punching. The STUN server to be used
  372. // needs only support bind and not full RFC5780 NAT discovery.
  373. //
  374. // Each dial trys only one STUN server; in Psiphon tunnel establishment,
  375. // other, concurrent in-proxy dials may select alternative STUN servers
  376. // via WebRTCDialCoordinator. When the STUN server operation is successful,
  377. // WebRTCDialCoordinator will be signaled so that it may configure the STUN
  378. // server selection for replay.
  379. //
  380. // The STUN server will observe proxy IP addresses. Enumeration is
  381. // mitigated by using various public STUN servers, including Psiphon STUN
  382. // servers for proxies in non-censored regions. Proxies are also more
  383. // ephemeral than Psiphon servers.
  384. RFC5780 := false
  385. stunServerAddress := config.WebRTCDialCoordinator.STUNServerAddress(RFC5780)
  386. // Proceed even when stunServerAddress is "" and !DisableSTUN, as ICE may
  387. // find other host candidates.
  388. doSTUN := stunServerAddress != "" && !disableInbound && !config.WebRTCDialCoordinator.DisableSTUN()
  389. var ICEServers []webrtc.ICEServer
  390. if doSTUN {
  391. // stunServerAddress domain names are resolved with the Psiphon custom
  392. // resolver via pionNetwork.ResolveUDPAddr
  393. ICEServers = []webrtc.ICEServer{{URLs: []string{"stun:" + stunServerAddress}}}
  394. }
  395. peerConnection, err := webRTCAPI.NewPeerConnection(
  396. webrtc.Configuration{
  397. ICEServers: ICEServers,
  398. })
  399. if err != nil {
  400. return nil, nil, nil, errors.Trace(err)
  401. }
  402. conn := &WebRTCConn{
  403. config: config,
  404. udpConn: udpConn,
  405. portMapper: portMapper,
  406. closedSignal: make(chan struct{}),
  407. peerConnection: peerConnection,
  408. dataChannelOpenedSignal: make(chan struct{}),
  409. dataChannelWriteBufferSignal: make(chan struct{}, 1),
  410. // A data channel uses SCTP and is message oriented. The maximum
  411. // message size supported by pion/webrtc is 65536:
  412. // https://github.com/pion/webrtc/blob/dce970438344727af9c9965f88d958c55d32e64d/datachannel.go#L19.
  413. // This read buffer must be as large as the maximum message size or
  414. // else a read may fail with io.ErrShortBuffer.
  415. readBuffer: make([]byte, dataChannelMaxMessageSize),
  416. trafficShapingPRNG: trafficShapingPRNG,
  417. trafficShapingBuffer: trafficShapingBuffer,
  418. paddedMessageCount: paddedMessageCount,
  419. decoyMessageCount: decoyMessageCount,
  420. }
  421. defer func() {
  422. if retErr != nil {
  423. // Cleanup on early return
  424. conn.Close()
  425. // Notify the WebRTCDialCoordinator that the operation failed so
  426. // that it can clear replay for that STUN server selection.
  427. //
  428. // Limitation: the error here may be due to failures unrelated to
  429. // the STUN server.
  430. if ctx.Err() == nil && doSTUN {
  431. config.WebRTCDialCoordinator.STUNServerAddressFailed(RFC5780, stunServerAddress)
  432. }
  433. }
  434. }()
  435. conn.peerConnection.OnConnectionStateChange(conn.onConnectionStateChange)
  436. conn.peerConnection.OnICECandidate(conn.onICECandidate)
  437. conn.peerConnection.OnICEConnectionStateChange(conn.onICEConnectionStateChange)
  438. conn.peerConnection.OnICEGatheringStateChange(conn.onICEGatheringStateChange)
  439. conn.peerConnection.OnNegotiationNeeded(conn.onNegotiationNeeded)
  440. conn.peerConnection.OnSignalingStateChange(conn.onSignalingStateChange)
  441. conn.peerConnection.OnDataChannel(conn.onDataChannel)
  442. // As a future enhancement, consider using media channels instead of data
  443. // channels, as media channels may be more common. Proxied QUIC would
  444. // work over an unreliable media channel. Note that a media channel is
  445. // still prefixed with STUN and DTLS exchanges before SRTP begins, so the
  446. // first few packets are the same as a data channel.
  447. // The offer sets the data channel configuration.
  448. if isOffer {
  449. dataChannelInit := &webrtc.DataChannelInit{}
  450. if !config.ReliableTransport {
  451. ordered := false
  452. dataChannelInit.Ordered = &ordered
  453. maxRetransmits := uint16(0)
  454. dataChannelInit.MaxRetransmits = &maxRetransmits
  455. }
  456. // TODO: randomize length?
  457. dataChannelLabel := "in-proxy-data-channel"
  458. dataChannel, err := peerConnection.CreateDataChannel(
  459. dataChannelLabel, dataChannelInit)
  460. if err != nil {
  461. return nil, nil, nil, errors.Trace(err)
  462. }
  463. conn.setDataChannel(dataChannel)
  464. }
  465. // Prepare to await full ICE completion, including STUN candidates.
  466. // Trickle ICE is not used, simplifying the broker API. It's expected
  467. // that most clients and proxies will be behind a NAT, and not have
  468. // publicly addressable host candidates. TURN is not used. So most
  469. // candidates will be STUN, or server-reflexive, candidates.
  470. //
  471. // Later, the first to complete out of ICE or port mapping is used.
  472. //
  473. // TODO: stop waiting if an IPv6 host candidate is found?
  474. iceComplete := webrtc.GatheringCompletePromise(conn.peerConnection)
  475. // Create an offer, or input a peer's offer to create an answer.
  476. if isOffer {
  477. offer, err := conn.peerConnection.CreateOffer(nil)
  478. if err != nil {
  479. return nil, nil, nil, errors.Trace(err)
  480. }
  481. err = conn.peerConnection.SetLocalDescription(offer)
  482. if err != nil {
  483. return nil, nil, nil, errors.Trace(err)
  484. }
  485. } else {
  486. err = conn.peerConnection.SetRemoteDescription(*peerSDP)
  487. if err != nil {
  488. return nil, nil, nil, errors.Trace(err)
  489. }
  490. answer, err := conn.peerConnection.CreateAnswer(nil)
  491. if err != nil {
  492. return nil, nil, nil, errors.Trace(err)
  493. }
  494. err = conn.peerConnection.SetLocalDescription(answer)
  495. if err != nil {
  496. return nil, nil, nil, errors.Trace(err)
  497. }
  498. }
  499. // Await either ICE or port mapping completion.
  500. // As a future enhancement, track which of ICE or port mapping succeeds
  501. // and is then followed by a failed WebRTC dial; stop trying the method
  502. // that often fails.
  503. iceCompleted := false
  504. portMappingExternalAddr := ""
  505. select {
  506. case <-iceComplete:
  507. iceCompleted = true
  508. case portMappingExternalAddr = <-portMapper.portMappingExternalAddress():
  509. // Set responding port mapping types for metrics.
  510. //
  511. // Limitation: if there are multiple responding protocol types, it's
  512. // not known here which was used for this dial.
  513. config.WebRTCDialCoordinator.SetPortMappingTypes(
  514. getRespondingPortMappingTypes(config.WebRTCDialCoordinator.NetworkID()))
  515. case <-ctx.Done():
  516. return nil, nil, nil, errors.Trace(ctx.Err())
  517. }
  518. // Release any port mapping resources when not using it.
  519. if portMapper != nil && portMappingExternalAddr == "" {
  520. portMapper.close()
  521. conn.portMapper = nil
  522. }
  523. // Get the offer or answer, now populated with any ICE candidates.
  524. localDescription := conn.peerConnection.LocalDescription()
  525. // Adjust the SDP, removing local network addresses and adding any
  526. // port mapping candidate. Clients (offer) are permitted to have
  527. // no ICE candidates but proxies (answer) must have at least one
  528. //candidate.
  529. errorOnNoCandidates := !isOffer
  530. adjustedSDP, metrics, err := PrepareSDPAddresses(
  531. []byte(localDescription.SDP),
  532. errorOnNoCandidates,
  533. portMappingExternalAddr,
  534. config.WebRTCDialCoordinator.DisableIPv6ICECandidates())
  535. if err != nil {
  536. return nil, nil, nil, errors.Trace(err)
  537. }
  538. // When STUN was attempted, ICE completed, and a STUN server-reflexive
  539. // candidate is present, notify the WebRTCDialCoordinator so that it can
  540. // set replay for that STUN server selection.
  541. if iceCompleted && doSTUN {
  542. hasServerReflexive := false
  543. for _, candidateType := range metrics.ICECandidateTypes {
  544. if candidateType == ICECandidateServerReflexive {
  545. hasServerReflexive = true
  546. }
  547. }
  548. if hasServerReflexive {
  549. config.WebRTCDialCoordinator.STUNServerAddressSucceeded(RFC5780, stunServerAddress)
  550. } else {
  551. config.WebRTCDialCoordinator.STUNServerAddressFailed(RFC5780, stunServerAddress)
  552. }
  553. }
  554. // The WebRTCConn is prepared, but the data channel is not yet connected.
  555. // On the offer end, the peer's following answer must be input to
  556. // SetRemoteSDP. And both ends must call AwaitInitialDataChannel to await
  557. // the data channel establishment.
  558. return conn,
  559. &webrtc.SessionDescription{
  560. Type: localDescription.Type,
  561. SDP: string(adjustedSDP),
  562. },
  563. metrics,
  564. nil
  565. }
  566. func (conn *WebRTCConn) setDataChannel(dataChannel *webrtc.DataChannel) {
  567. // Assumes the caller holds conn.mutex, or is newWebRTCConn, creating the
  568. // conn.
  569. conn.dataChannel = dataChannel
  570. conn.dataChannel.OnOpen(conn.onDataChannelOpen)
  571. conn.dataChannel.OnClose(conn.onDataChannelClose)
  572. // Set up flow control (see comment in conn.Write)
  573. conn.dataChannel.SetBufferedAmountLowThreshold(dataChannelBufferedAmountLowThreshold)
  574. conn.dataChannel.OnBufferedAmountLow(func() {
  575. select {
  576. case conn.dataChannelWriteBufferSignal <- struct{}{}:
  577. default:
  578. }
  579. })
  580. }
  581. // SetRemoteSDP takes the answer SDP that is received in response to an offer
  582. // SDP. SetRemoteSDP initiates the WebRTC connection establishment on the
  583. // offer end.
  584. func (conn *WebRTCConn) SetRemoteSDP(peerSDP webrtc.SessionDescription) error {
  585. conn.mutex.Lock()
  586. defer conn.mutex.Unlock()
  587. err := conn.peerConnection.SetRemoteDescription(peerSDP)
  588. if err != nil {
  589. return errors.Trace(err)
  590. }
  591. return nil
  592. }
  593. // AwaitInitialDataChannel returns when the data channel is established, or
  594. // when an error has occured.
  595. func (conn *WebRTCConn) AwaitInitialDataChannel(ctx context.Context) error {
  596. // Don't lock the mutex, or else necessary operations will deadlock.
  597. select {
  598. case <-conn.dataChannelOpenedSignal:
  599. // The data channel is connected.
  600. //
  601. // TODO: for metrics, determine which end was the network connection
  602. // initiator; and determine which type of ICE candidate was
  603. // successful (note that peer-reflexive candidates aren't in either
  604. // SDP and emerge only during ICE negotiation).
  605. case <-ctx.Done():
  606. return errors.Trace(ctx.Err())
  607. case <-conn.closedSignal:
  608. return errors.TraceNew("connection has closed")
  609. }
  610. return nil
  611. }
  612. func (conn *WebRTCConn) Close() error {
  613. conn.mutex.Lock()
  614. defer conn.mutex.Unlock()
  615. if conn.isClosed {
  616. return nil
  617. }
  618. if conn.portMapper != nil {
  619. conn.portMapper.close()
  620. }
  621. if conn.dataChannelConn != nil {
  622. conn.dataChannelConn.Close()
  623. }
  624. if conn.dataChannel != nil {
  625. conn.dataChannel.Close()
  626. }
  627. if conn.peerConnection != nil {
  628. conn.peerConnection.Close()
  629. }
  630. // Close the udpConn to interrupt any blocking DTLS handshake:
  631. // https://github.com/pion/webrtc/blob/c1467e4871c78ee3f463b50d858d13dc6f2874a4/dtlstransport.go#L334-L340
  632. //
  633. // Limitation: there is no guarantee that pion sends any closing packets
  634. // before the UDP socket is closed here.
  635. if conn.udpConn != nil {
  636. conn.udpConn.Close()
  637. }
  638. close(conn.closedSignal)
  639. conn.isClosed = true
  640. return nil
  641. }
  642. func (conn *WebRTCConn) IsClosed() bool {
  643. conn.mutex.Lock()
  644. defer conn.mutex.Unlock()
  645. return conn.isClosed
  646. }
  647. func (conn *WebRTCConn) Read(p []byte) (int, error) {
  648. for {
  649. n, err := conn.readMessage(p)
  650. if err != nil || n > 0 {
  651. return n, err
  652. }
  653. // A decoy message was read; discard and read again.
  654. }
  655. }
  656. func (conn *WebRTCConn) readMessage(p []byte) (int, error) {
  657. // Don't hold this lock, or else concurrent Writes will be blocked.
  658. conn.mutex.Lock()
  659. isClosed := conn.isClosed
  660. dataChannelConn := conn.dataChannelConn
  661. decoyDone := conn.decoyDone
  662. conn.mutex.Unlock()
  663. if isClosed {
  664. return 0, errors.TraceNew("closed")
  665. }
  666. if dataChannelConn == nil {
  667. return 0, errors.TraceNew("no data channel")
  668. }
  669. // The input read buffer, p, may not be the same length as the message
  670. // read from the data channel. Buffer the read message if another Read
  671. // call is necessary to consume it. As per https://pkg.go.dev/io#Reader,
  672. // dataChannelConn bytes read are processed even when
  673. // dataChannelConn.Read returns an error; the error value is stored and
  674. // returned with the Read call that consumes the end of the message buffer.
  675. conn.readMutex.Lock()
  676. defer conn.readMutex.Unlock()
  677. if conn.readOffset == conn.readLength {
  678. n, err := dataChannelConn.Read(conn.readBuffer)
  679. conn.readOffset = 0
  680. conn.readLength = n
  681. conn.readError = err
  682. // Skip over padding.
  683. if n > 0 && !conn.peerPaddingDone {
  684. paddingSize, n := binary.Varint(conn.readBuffer[0:conn.readLength])
  685. if (paddingSize == 0 && n <= 0) || paddingSize >= int64(conn.readLength) {
  686. return 0, errors.TraceNew("invalid padding")
  687. }
  688. if paddingSize < 0 {
  689. // When the padding header indicates a padding size of -1, the
  690. // peer is indicating that padding is done. Subsequent
  691. // messages will have no padding header or padding bytes.
  692. conn.peerPaddingDone = true
  693. conn.readOffset += n
  694. } else {
  695. conn.readOffset += n + int(paddingSize)
  696. atomic.AddInt32(&conn.paddedMessagesReceived, 1)
  697. if conn.readOffset == conn.readLength {
  698. atomic.AddInt32(&conn.decoyMessagesReceived, 1)
  699. }
  700. }
  701. }
  702. }
  703. n := copy(p, conn.readBuffer[conn.readOffset:conn.readLength])
  704. conn.readOffset += n
  705. var err error
  706. if conn.readOffset == conn.readLength {
  707. err = conn.readError
  708. }
  709. // When decoy messages are enabled, periodically response to an incoming
  710. // messages with an immediate outbound decoy message. This is similar to
  711. // the design here:
  712. // https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/c4f6a593a645db4479a7032a9e97d3c0b905cdfc/psiphon/common/quic/obfuscator.go#L361-L409
  713. //
  714. // writeMessage handles conn.decoyMessageCount, which is syncronized with
  715. // conn.WriteMutex, as well as other specific logic. Here we just signal
  716. // writeMessage based on the read event.
  717. //
  718. // When the data channel already has buffered writes in excess of a decoy
  719. // message size, the writeMessage skips the decoy message and returns
  720. // without blocking, so Read calls will not block.
  721. if !decoyDone {
  722. _, _ = conn.writeMessage(nil, true)
  723. }
  724. return n, errors.Trace(err)
  725. }
  726. func (conn *WebRTCConn) Write(p []byte) (int, error) {
  727. return conn.writeMessage(p, false)
  728. }
  729. func (conn *WebRTCConn) writeMessage(p []byte, decoy bool) (int, error) {
  730. if p != nil && decoy {
  731. return 0, errors.TraceNew("invalid write parameters")
  732. }
  733. // pion/sctp doesn't handle 0-byte writes correctly, so drop/skip at this level.
  734. //
  735. // Testing shows that the SCTP connection stalls after a 0-byte write. In
  736. // the pion/sctp implementation,
  737. // https://github.com/pion/sctp/blob/v1.8.8/stream.go#L254-L278 and
  738. // https://github.com/pion/sctp/blob/v1.8.8/stream.go#L280-L336, it
  739. // appears that a zero-byte write won't send an SCTP messages but does
  740. // increment a sequence number.
  741. if len(p) == 0 && !decoy {
  742. return 0, nil
  743. }
  744. // Don't hold this lock, or else concurrent Reads will be blocked.
  745. conn.mutex.Lock()
  746. isClosed := conn.isClosed
  747. bufferedAmount := conn.dataChannel.BufferedAmount()
  748. dataChannelConn := conn.dataChannelConn
  749. conn.mutex.Unlock()
  750. if isClosed {
  751. return 0, errors.TraceNew("closed")
  752. }
  753. if dataChannelConn == nil {
  754. return 0, errors.TraceNew("no data channel")
  755. }
  756. // Only proceed with a decoy message when no pending writes are buffered.
  757. //
  758. // This check is made before acquiring conn.writeMutex so that, in most
  759. // cases, writeMessage won't block Read calls when a concurrent Write is
  760. // holding conn.writeMutex and potentially blocking on flow control.
  761. // There's still a chance that this test passes, and a concurrent Write
  762. // arrives at the same time.
  763. if decoy && bufferedAmount > 0 {
  764. return 0, nil
  765. }
  766. conn.writeMutex.Lock()
  767. defer conn.writeMutex.Unlock()
  768. writeSize := len(p)
  769. // Determine padding size and padding header size.
  770. doPadding := false
  771. paddingSize := 0
  772. var paddingHeader [binary.MaxVarintLen32]byte
  773. paddingHeaderSize := 0
  774. if decoy {
  775. if conn.decoyMessageCount < 1 {
  776. return 0, nil
  777. }
  778. if !conn.trafficShapingPRNG.FlipWeightedCoin(
  779. conn.config.TrafficShapingParameters.DecoyMessageProbability) {
  780. return 0, nil
  781. }
  782. conn.decoyMessageCount -= 1
  783. decoySize := conn.trafficShapingPRNG.Range(
  784. conn.config.TrafficShapingParameters.MinDecoySize,
  785. conn.config.TrafficShapingParameters.MaxDecoySize)
  786. // When sending a decoy message, the entire message is padding.
  787. doPadding = true
  788. paddingSize = decoySize
  789. if conn.decoyMessageCount == 0 {
  790. // Set the shared flag that readMessage uses to stop invoking
  791. // writeMessage for decoy events.
  792. conn.mutex.Lock()
  793. conn.decoyDone = true
  794. conn.mutex.Unlock()
  795. }
  796. } else if conn.paddedMessageCount > 0 {
  797. // Add padding to a normal write.
  798. conn.paddedMessageCount -= 1
  799. doPadding = true
  800. paddingSize = prng.Range(
  801. conn.config.TrafficShapingParameters.MinPaddingSize,
  802. conn.config.TrafficShapingParameters.MaxPaddingSize)
  803. } else if conn.decoyMessageCount > 0 {
  804. // Padding normal messages is done, but there are still outstanding
  805. // decoy messages, so add a padding header indicating padding size 0
  806. // to this normal message.
  807. doPadding = true
  808. paddingSize = 0
  809. } else if !conn.trafficShapingDone {
  810. // Padding normal messages is done and all decoy messages are sent, so
  811. // send a special padding header with padding size -1, signaling the
  812. // peer that no additional padding will be performed and no
  813. // subsequent messages will contain a padding header.
  814. doPadding = true
  815. paddingSize = -1
  816. }
  817. if doPadding {
  818. if paddingSize > 0 {
  819. // Reduce, if necessary, to stay within the maximum data channel
  820. // message size. This is not expected to happen for the io.Copy use
  821. // case, with 32K message size, plus reasonable padding sizes.
  822. if writeSize+binary.MaxVarintLen32+paddingSize > dataChannelMaxMessageSize {
  823. paddingSize -= (writeSize + binary.MaxVarintLen32 + paddingSize) - dataChannelMaxMessageSize
  824. if paddingSize < 0 {
  825. paddingSize = 0
  826. }
  827. }
  828. // Add padding overhead to total writeSize before the flow control check.
  829. writeSize += paddingSize
  830. }
  831. paddingHeaderSize = binary.PutVarint(paddingHeader[:], int64(paddingSize))
  832. writeSize += paddingHeaderSize
  833. }
  834. if writeSize > dataChannelMaxMessageSize {
  835. return 0, errors.TraceNew("write too large")
  836. }
  837. // Flow control is required to ensure that Write calls don't result in
  838. // unbounded buffering in pion/webrtc. Use similar logic and the same
  839. // buffer size thresholds as the pion sample code.
  840. //
  841. // https://github.com/pion/webrtc/tree/master/examples/data-channels-flow-control#when-do-we-need-it:
  842. // > Send or SendText methods are called on DataChannel to send data to
  843. // > the connected peer. The methods return immediately, but it does not
  844. // > mean the data was actually sent onto the wire. Instead, it is
  845. // > queued in a buffer until it actually gets sent out to the wire.
  846. // >
  847. // > When you have a large amount of data to send, it is an application's
  848. // > responsibility to control the buffered amount in order not to
  849. // > indefinitely grow the buffer size to eventually exhaust the memory.
  850. // If the pion write buffer is too full, wait for a signal that sufficient
  851. // write data has been consumed before writing more.
  852. if !isClosed && bufferedAmount+uint64(writeSize) > dataChannelMaxBufferedAmount {
  853. select {
  854. case <-conn.dataChannelWriteBufferSignal:
  855. case <-conn.closedSignal:
  856. return 0, errors.TraceNew("connection has closed")
  857. }
  858. }
  859. if conn.trafficShapingDone {
  860. // When traffic shaping is done, p is written directly without the
  861. // additional trafficShapingBuffer copy.
  862. // Limitation: if len(p) > 65536, the dataChannelConn.Write will fail. In
  863. // practise, this is not expected to happen with typical use cases such
  864. // as io.Copy, which uses a 32K buffer.
  865. n, err := dataChannelConn.Write(p)
  866. return n, errors.Trace(err)
  867. }
  868. conn.trafficShapingBuffer.Reset()
  869. conn.trafficShapingBuffer.Write(paddingHeader[:paddingHeaderSize])
  870. if paddingSize > 0 {
  871. conn.trafficShapingBuffer.Write(prng.Bytes(paddingSize))
  872. }
  873. conn.trafficShapingBuffer.Write(p)
  874. // Limitation: see above; len(p) + padding must be <= 65536.
  875. _, err := dataChannelConn.Write(conn.trafficShapingBuffer.Bytes())
  876. if decoy {
  877. atomic.AddInt32(&conn.decoyMessagesSent, 1)
  878. } else if doPadding && paddingSize > 0 {
  879. atomic.AddInt32(&conn.paddedMessagesSent, 1)
  880. }
  881. if conn.paddedMessageCount == 0 && conn.decoyMessageCount == 0 && paddingSize == -1 {
  882. // Set flag indicating -1 padding size was sent and release traffic
  883. // shaping resources.
  884. conn.trafficShapingDone = true
  885. conn.trafficShapingPRNG = nil
  886. conn.trafficShapingBuffer = nil
  887. }
  888. return len(p), errors.Trace(err)
  889. }
  890. func (conn *WebRTCConn) LocalAddr() net.Addr {
  891. conn.mutex.Lock()
  892. defer conn.mutex.Unlock()
  893. // This is the local UDP socket address, not the external, public address.
  894. return conn.udpConn.LocalAddr()
  895. }
  896. func (conn *WebRTCConn) RemoteAddr() net.Addr {
  897. conn.mutex.Lock()
  898. defer conn.mutex.Unlock()
  899. // Not supported.
  900. return nil
  901. }
  902. func (conn *WebRTCConn) SetDeadline(t time.Time) error {
  903. conn.mutex.Lock()
  904. defer conn.mutex.Unlock()
  905. return errors.TraceNew("not supported")
  906. }
  907. func (conn *WebRTCConn) SetReadDeadline(t time.Time) error {
  908. conn.mutex.Lock()
  909. defer conn.mutex.Unlock()
  910. return errors.TraceNew("not supported")
  911. }
  912. func (conn *WebRTCConn) SetWriteDeadline(t time.Time) error {
  913. conn.mutex.Lock()
  914. defer conn.mutex.Unlock()
  915. return errors.TraceNew("not supported")
  916. }
  917. // GetMetrics implements the common.MetricsSource interface and returns log
  918. // fields detailing the WebRTC dial parameters.
  919. func (conn *WebRTCConn) GetMetrics() common.LogFields {
  920. // TODO: determine which WebRTC ICE candidate was chosen, and log its
  921. // type (host, server reflexive, etc.), port number(s), and whether it's
  922. // IPv6.
  923. logFields := make(common.LogFields)
  924. randomizeDTLS := "0"
  925. if conn.config.DoDTLSRandomization {
  926. randomizeDTLS = "1"
  927. }
  928. logFields["inproxy_webrtc_randomize_dtls"] = randomizeDTLS
  929. logFields["inproxy_webrtc_padded_messages_sent"] = atomic.LoadInt32(&conn.paddedMessagesSent)
  930. logFields["inproxy_webrtc_padded_messages_received"] = atomic.LoadInt32(&conn.paddedMessagesReceived)
  931. logFields["inproxy_webrtc_decoy_messages_sent"] = atomic.LoadInt32(&conn.decoyMessagesSent)
  932. logFields["inproxy_webrtc_decoy_messages_received"] = atomic.LoadInt32(&conn.decoyMessagesReceived)
  933. return logFields
  934. }
  935. func (conn *WebRTCConn) onConnectionStateChange(state webrtc.PeerConnectionState) {
  936. if state == webrtc.PeerConnectionStateFailed {
  937. conn.Close()
  938. }
  939. conn.config.Logger.WithTraceFields(common.LogFields{
  940. "state": state.String(),
  941. }).Info("peer connection state changed")
  942. }
  943. func (conn *WebRTCConn) onICECandidate(candidate *webrtc.ICECandidate) {
  944. conn.config.Logger.WithTraceFields(common.LogFields{
  945. "candidate": candidate,
  946. }).Info("new ICE candidate")
  947. }
  948. func (conn *WebRTCConn) onICEConnectionStateChange(state webrtc.ICEConnectionState) {
  949. conn.config.Logger.WithTraceFields(common.LogFields{
  950. "state": state.String(),
  951. }).Info("ICE connection state changed")
  952. }
  953. func (conn *WebRTCConn) onICEGatheringStateChange(state webrtc.ICEGathererState) {
  954. conn.config.Logger.WithTraceFields(common.LogFields{
  955. "state": state.String(),
  956. }).Info("ICE gathering state changed")
  957. }
  958. func (conn *WebRTCConn) onNegotiationNeeded() {
  959. conn.config.Logger.WithTrace().Info("negotiation needed")
  960. }
  961. func (conn *WebRTCConn) onSignalingStateChange(state webrtc.SignalingState) {
  962. conn.config.Logger.WithTraceFields(common.LogFields{
  963. "state": state.String(),
  964. }).Info("signaling state changed")
  965. }
  966. func (conn *WebRTCConn) onDataChannel(dataChannel *webrtc.DataChannel) {
  967. conn.mutex.Lock()
  968. defer conn.mutex.Unlock()
  969. conn.setDataChannel(dataChannel)
  970. conn.config.Logger.WithTraceFields(common.LogFields{
  971. "label": dataChannel.Label(),
  972. "ID": dataChannel.ID(),
  973. }).Info("new data channel")
  974. }
  975. func (conn *WebRTCConn) onDataChannelOpen() {
  976. conn.mutex.Lock()
  977. defer conn.mutex.Unlock()
  978. dataChannelConn, err := conn.dataChannel.Detach()
  979. if err == nil {
  980. conn.dataChannelConn = dataChannelConn
  981. // TODO: can a data channel be connected, disconnected, and then
  982. // reestablished in one session?
  983. conn.dataChannelOpenedOnce.Do(func() { close(conn.dataChannelOpenedSignal) })
  984. }
  985. conn.config.Logger.WithTraceFields(common.LogFields{
  986. "detachError": err,
  987. }).Info("data channel open")
  988. }
  989. func (conn *WebRTCConn) onDataChannelClose() {
  990. // Close the WebRTCConn when the data channel is closed. Close will lock
  991. // conn.mutex, so do lot aquire the lock here.
  992. conn.Close()
  993. conn.config.Logger.WithTrace().Info("data channel closed")
  994. }
  995. // PrepareSDPAddresses adjusts the SDP, pruning local network addresses and
  996. // adding any port mapping as a host candidate.
  997. func PrepareSDPAddresses(
  998. encodedSDP []byte,
  999. errorOnNoCandidates bool,
  1000. portMappingExternalAddr string,
  1001. disableIPv6Candidates bool) ([]byte, *SDPMetrics, error) {
  1002. modifiedSDP, metrics, err := processSDPAddresses(
  1003. encodedSDP,
  1004. portMappingExternalAddr,
  1005. disableIPv6Candidates,
  1006. false, // bogons are expected, and stripped out
  1007. errorOnNoCandidates,
  1008. nil,
  1009. common.GeoIPData{})
  1010. return modifiedSDP, metrics, errors.Trace(err)
  1011. }
  1012. // ValidateSDPAddresses checks that the SDP does not contain an empty list of
  1013. // candidates, bogon candidates, or candidates outside of the country and ASN
  1014. // for the specified expectedGeoIPData.
  1015. func ValidateSDPAddresses(
  1016. encodedSDP []byte,
  1017. errorOnNoCandidates bool,
  1018. lookupGeoIP LookupGeoIP,
  1019. expectedGeoIPData common.GeoIPData) (*SDPMetrics, error) {
  1020. _, metrics, err := processSDPAddresses(
  1021. encodedSDP,
  1022. "",
  1023. false,
  1024. true, // bogons should already by stripped out
  1025. errorOnNoCandidates,
  1026. lookupGeoIP,
  1027. expectedGeoIPData)
  1028. return metrics, errors.Trace(err)
  1029. }
  1030. // SDPMetrics are network capability metrics values for an SDP.
  1031. type SDPMetrics struct {
  1032. ICECandidateTypes []ICECandidateType
  1033. HasIPv6 bool
  1034. }
  1035. // processSDPAddresses is based on snowflake/common/util.StripLocalAddresses
  1036. // https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/blob/v2.5.1/common/util/util.go#L70-99
  1037. /*
  1038. This file contains the license for "Snowflake"
  1039. a free software project which provides a WebRTC pluggable transport.
  1040. ================================================================================
  1041. Copyright (c) 2016, Serene Han, Arlo Breault
  1042. Copyright (c) 2019-2020, The Tor Project, Inc
  1043. Redistribution and use in source and binary forms, with or without modification,
  1044. are permitted provided that the following conditions are met:
  1045. * Redistributions of source code must retain the above copyright notice, this
  1046. list of conditions and the following disclaimer.
  1047. * Redistributions in binary form must reproduce the above copyright notice,
  1048. this list of conditions and the following disclaimer in the documentation and/or
  1049. other materials provided with the distribution.
  1050. * Neither the names of the copyright owners nor the names of its
  1051. contributors may be used to endorse or promote products derived from this
  1052. software without specific prior written permission.
  1053. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  1054. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  1055. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  1056. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  1057. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  1058. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  1059. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  1060. ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  1061. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  1062. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1063. ================================================================================
  1064. */
  1065. func processSDPAddresses(
  1066. encodedSDP []byte,
  1067. portMappingExternalAddr string,
  1068. disableIPv6Candidates bool,
  1069. errorOnBogon bool,
  1070. errorOnNoCandidates bool,
  1071. lookupGeoIP LookupGeoIP,
  1072. expectedGeoIPData common.GeoIPData) ([]byte, *SDPMetrics, error) {
  1073. var sessionDescription sdp.SessionDescription
  1074. err := sessionDescription.Unmarshal(encodedSDP)
  1075. if err != nil {
  1076. return nil, nil, errors.Trace(err)
  1077. }
  1078. candidateTypes := map[ICECandidateType]bool{}
  1079. hasIPv6 := false
  1080. var portMappingICECandidates []sdp.Attribute
  1081. if portMappingExternalAddr != "" {
  1082. // Prepare ICE candidate attibute pair for the port mapping, modeled after the definition of host candidates.
  1083. host, portStr, err := net.SplitHostPort(portMappingExternalAddr)
  1084. if err != nil {
  1085. return nil, nil, errors.Trace(err)
  1086. }
  1087. port, _ := strconv.Atoi(portStr)
  1088. // Only IPv4 port mapping addresses are supported due to the
  1089. // NewCandidateHost limitation noted below. It is expected that port
  1090. // mappings will be IPv4, as NAT and IPv6 is not a typical combination.
  1091. hostIP := net.ParseIP(host)
  1092. if hostIP != nil && hostIP.To4() != nil {
  1093. for _, component := range []webrtc.ICEComponent{webrtc.ICEComponentRTP, webrtc.ICEComponentRTCP} {
  1094. // The candidate ID is generated and the priorty and foundation
  1095. // use the default for hosts.
  1096. //
  1097. // Limitation: NewCandidateHost initializes the networkType to
  1098. // NetworkTypeUDP4, and this field is not-exported.
  1099. // https://github.com/pion/ice/blob/6d301287654b05a36248842c278d58d501454bff/candidate_host.go#L27-L64
  1100. iceCandidate, err := ice.NewCandidateHost(&ice.CandidateHostConfig{
  1101. Network: "udp",
  1102. Address: host,
  1103. Port: port,
  1104. Component: uint16(component),
  1105. })
  1106. if err != nil {
  1107. return nil, nil, errors.Trace(err)
  1108. }
  1109. portMappingICECandidates = append(
  1110. portMappingICECandidates,
  1111. sdp.Attribute{Key: "candidate", Value: iceCandidate.Marshal()})
  1112. }
  1113. candidateTypes[ICECandidatePortMapping] = true
  1114. }
  1115. }
  1116. candidateCount := len(portMappingICECandidates)
  1117. for _, mediaDescription := range sessionDescription.MediaDescriptions {
  1118. addPortMappingCandidates := len(portMappingICECandidates) > 0
  1119. var attributes []sdp.Attribute
  1120. for _, attribute := range mediaDescription.Attributes {
  1121. // Insert the port mapping candidate either before the
  1122. // first "a=candidate", or before "a=end-of-candidates"(there may
  1123. // be no "a=candidate" attributes).
  1124. if addPortMappingCandidates &&
  1125. (attribute.IsICECandidate() || attribute.Key == sdp.AttrKeyEndOfCandidates) {
  1126. attributes = append(attributes, portMappingICECandidates...)
  1127. addPortMappingCandidates = false
  1128. }
  1129. if attribute.IsICECandidate() {
  1130. candidate, err := ice.UnmarshalCandidate(attribute.Value)
  1131. if err != nil {
  1132. return nil, nil, errors.Trace(err)
  1133. }
  1134. candidateIP := net.ParseIP(candidate.Address())
  1135. if candidateIP == nil {
  1136. return nil, nil, errors.TraceNew("unexpected non-IP")
  1137. }
  1138. if candidateIP.To4() == nil {
  1139. if disableIPv6Candidates {
  1140. continue
  1141. }
  1142. hasIPv6 = true
  1143. }
  1144. // Strip non-routable bogons, including LAN addresses.
  1145. // Same-LAN client/proxy hops are not expected to be useful,
  1146. // and this also avoids unnecessary local network traffic.
  1147. //
  1148. // Well-behaved clients and proxies will strip these values;
  1149. // the broker enforces this and uses errorOnBogon.
  1150. if !GetAllowBogonWebRTCConnections() &&
  1151. common.IsBogon(candidateIP) {
  1152. if errorOnBogon {
  1153. return nil, nil, errors.TraceNew("unexpected bogon")
  1154. }
  1155. continue
  1156. }
  1157. // The broker will check that clients and proxies specify only
  1158. // candidates that map to the same GeoIP country and ASN as
  1159. // the client/proxy connection to the broker. This limits
  1160. // misuse of candidate to connect to other locations.
  1161. // Legitimate candidates will not all have the exact same IP
  1162. // address, as there could be a mix of IPv4 and IPv6, as well
  1163. // as potentially different NAT paths.
  1164. if lookupGeoIP != nil {
  1165. candidateGeoIPData := lookupGeoIP(candidate.Address())
  1166. if candidateGeoIPData.Country != expectedGeoIPData.Country {
  1167. return nil, nil, errors.TraceNew("unexpected GeoIP country")
  1168. }
  1169. if candidateGeoIPData.ASN != expectedGeoIPData.ASN {
  1170. return nil, nil, errors.TraceNew("unexpected GeoIP ASN")
  1171. }
  1172. }
  1173. // These types are not reported:
  1174. // - CandidateTypeRelay: TURN servers are not used.
  1175. // - CandidateTypePeerReflexive: this candidate type only
  1176. // emerges later in the connection process.
  1177. switch candidate.Type() {
  1178. case ice.CandidateTypeHost:
  1179. candidateTypes[ICECandidateHost] = true
  1180. case ice.CandidateTypeServerReflexive:
  1181. candidateTypes[ICECandidateServerReflexive] = true
  1182. }
  1183. candidateCount += 1
  1184. }
  1185. attributes = append(attributes, attribute)
  1186. }
  1187. mediaDescription.Attributes = attributes
  1188. }
  1189. if errorOnNoCandidates && candidateCount == 0 {
  1190. return nil, nil, errors.TraceNew("no candidates")
  1191. }
  1192. encodedSDP, err = sessionDescription.Marshal()
  1193. if err != nil {
  1194. return nil, nil, errors.Trace(err)
  1195. }
  1196. metrics := &SDPMetrics{
  1197. HasIPv6: hasIPv6,
  1198. }
  1199. for candidateType := range candidateTypes {
  1200. metrics.ICECandidateTypes = append(metrics.ICECandidateTypes, candidateType)
  1201. }
  1202. return encodedSDP, metrics, nil
  1203. }
  1204. type pionLoggerFactory struct {
  1205. logger common.Logger
  1206. debugLogging bool
  1207. }
  1208. func newPionLoggerFactory(logger common.Logger, debugLogging bool) *pionLoggerFactory {
  1209. return &pionLoggerFactory{
  1210. logger: logger,
  1211. debugLogging: debugLogging,
  1212. }
  1213. }
  1214. func (f *pionLoggerFactory) NewLogger(scope string) pion_logging.LeveledLogger {
  1215. return newPionLogger(scope, f.logger, f.debugLogging)
  1216. }
  1217. // pionLogger wraps common.Logger and implements
  1218. // https://pkg.go.dev/github.com/pion/logging#LeveledLogger for passing into
  1219. // pion.
  1220. type pionLogger struct {
  1221. scope string
  1222. logger common.Logger
  1223. debugLogging bool
  1224. }
  1225. func newPionLogger(scope string, logger common.Logger, debugLogging bool) *pionLogger {
  1226. return &pionLogger{
  1227. scope: scope,
  1228. logger: logger,
  1229. debugLogging: debugLogging,
  1230. }
  1231. }
  1232. func (l *pionLogger) Trace(msg string) {
  1233. if !l.debugLogging {
  1234. return
  1235. }
  1236. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  1237. }
  1238. func (l *pionLogger) Tracef(format string, args ...interface{}) {
  1239. if !l.debugLogging {
  1240. return
  1241. }
  1242. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  1243. }
  1244. func (l *pionLogger) Debug(msg string) {
  1245. if !l.debugLogging {
  1246. return
  1247. }
  1248. l.logger.WithTrace().Debug(fmt.Sprintf("[webRTC: %s: %s", l.scope, msg))
  1249. }
  1250. func (l *pionLogger) Debugf(format string, args ...interface{}) {
  1251. if !l.debugLogging {
  1252. return
  1253. }
  1254. l.logger.WithTrace().Debug(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  1255. }
  1256. func (l *pionLogger) Info(msg string) {
  1257. l.logger.WithTrace().Info(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  1258. }
  1259. func (l *pionLogger) Infof(format string, args ...interface{}) {
  1260. l.logger.WithTrace().Info(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  1261. }
  1262. func (l *pionLogger) Warn(msg string) {
  1263. l.logger.WithTrace().Warning(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  1264. }
  1265. func (l *pionLogger) Warnf(format string, args ...interface{}) {
  1266. l.logger.WithTrace().Warning(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  1267. }
  1268. func (l *pionLogger) Error(msg string) {
  1269. l.logger.WithTrace().Error(fmt.Sprintf("webRTC: %s: %s", l.scope, msg))
  1270. }
  1271. func (l *pionLogger) Errorf(format string, args ...interface{}) {
  1272. l.logger.WithTrace().Error(fmt.Sprintf("webRTC: %s: %s", l.scope, fmt.Sprintf(format, args...)))
  1273. }
  1274. // pionNetwork implements pion/transport.Net.
  1275. //
  1276. // Via the SettingsEngine, pion is configured to use a pionNetwork instance,
  1277. // which providing alternative implementations for various network functions.
  1278. // The Interfaces implementation provides a workaround for Android
  1279. // net.Interfaces issues and reduces the number of IPv6 candidates to avoid
  1280. // excess STUN requests; and the ResolveUDPAddr implementation hooks into the
  1281. // Psiphon custom resolver.
  1282. type pionNetwork struct {
  1283. dialCtx context.Context
  1284. logger pion_logging.LeveledLogger
  1285. webRTCDialCoordinator WebRTCDialCoordinator
  1286. }
  1287. func newPionNetwork(
  1288. dialCtx context.Context,
  1289. logger pion_logging.LeveledLogger,
  1290. webRTCDialCoordinator WebRTCDialCoordinator) *pionNetwork {
  1291. return &pionNetwork{
  1292. dialCtx: dialCtx,
  1293. logger: logger,
  1294. webRTCDialCoordinator: webRTCDialCoordinator,
  1295. }
  1296. }
  1297. func (p *pionNetwork) Interfaces() ([]*transport.Interface, error) {
  1298. // To determine the active IPv4 and IPv6 interfaces, let the OS bind IPv4
  1299. // and IPv6 UDP sockets with a specified external destination address.
  1300. // Then iterate over all interfaces, but return interface info for only
  1301. // the interfaces those sockets were bound to.
  1302. //
  1303. // The destination IPs are the IPs that currently resolve for example.com.
  1304. // No actual traffic to these IPs or example.com is sent, as the UDP
  1305. // sockets are not used to send any packets.
  1306. //
  1307. // This scheme should select just one IPv4 and one IPv6 address, which
  1308. // should be the active, externally routable addresses, and the IPv6
  1309. // address should be the preferred, non-deprecated temporary IPv6 address.
  1310. //
  1311. // The anet package is used to work around net.Interfaces not working on
  1312. // Android at this time: https://github.com/golang/go/issues/40569.
  1313. //
  1314. // In post-ICE gathering processing, processSDPAddresses will also strip
  1315. // all bogon addresses, so there is no explicit bogon check here.
  1316. //
  1317. // Limitations:
  1318. //
  1319. // - The active interface could change between the socket operation and
  1320. // iterating over all interfaces. Higher-level code is expected to
  1321. // react to active network changes.
  1322. //
  1323. // - The public IPs for example.com may not be robust in all routing
  1324. // situations. Alternatively, we could use the configured STUN server
  1325. // as the test destination, but the STUN server domain is not resolved
  1326. // at this point and STUN is not always configured and used.
  1327. //
  1328. // - The results could be cached and reused.
  1329. var defaultIPv4, defaultIPv6 net.IP
  1330. udpConnIPv4, err := p.webRTCDialCoordinator.UDPConn(
  1331. context.Background(), "udp4", "93.184.216.34:3478")
  1332. if err == nil {
  1333. defaultIPv4 = udpConnIPv4.LocalAddr().(*net.UDPAddr).IP
  1334. udpConnIPv4.Close()
  1335. }
  1336. udpConnIPv6, err := p.webRTCDialCoordinator.UDPConn(
  1337. context.Background(), "udp6", "[2606:2800:220:1:248:1893:25c8:1946]:3478")
  1338. if err == nil {
  1339. defaultIPv6 = udpConnIPv6.LocalAddr().(*net.UDPAddr).IP
  1340. udpConnIPv6.Close()
  1341. }
  1342. transportInterfaces := []*transport.Interface{}
  1343. netInterfaces, err := anet.Interfaces()
  1344. if err != nil {
  1345. return nil, errors.Trace(err)
  1346. }
  1347. for _, netInterface := range netInterfaces {
  1348. // Note: don't exclude interfaces with the net.FlagPointToPoint flag,
  1349. // which is set for certain mobile networks
  1350. if (netInterface.Flags&net.FlagUp == 0) ||
  1351. (!GetAllowBogonWebRTCConnections() && (netInterface.Flags&net.FlagLoopback != 0)) {
  1352. continue
  1353. }
  1354. addrs, err := anet.InterfaceAddrsByInterface(&netInterface)
  1355. if err != nil {
  1356. return nil, errors.Trace(err)
  1357. }
  1358. var transportInterface *transport.Interface
  1359. for _, addr := range addrs {
  1360. IP, _, err := net.ParseCIDR(addr.String())
  1361. if err != nil {
  1362. return nil, errors.Trace(err)
  1363. }
  1364. if IP.Equal(defaultIPv4) || IP.Equal(defaultIPv6) ||
  1365. (GetAllowBogonWebRTCConnections() && (netInterface.Flags&net.FlagLoopback != 0)) {
  1366. if transportInterface == nil {
  1367. transportInterface = transport.NewInterface(netInterface)
  1368. }
  1369. transportInterface.AddAddress(addr)
  1370. }
  1371. }
  1372. if transportInterface != nil {
  1373. transportInterfaces = append(transportInterfaces, transportInterface)
  1374. }
  1375. }
  1376. return transportInterfaces, nil
  1377. }
  1378. func (p *pionNetwork) ResolveUDPAddr(network, address string) (retAddr *net.UDPAddr, retErr error) {
  1379. defer func() {
  1380. if retErr != nil {
  1381. // Explicitly log an error since certain pion operations -- e.g.,
  1382. // ICE gathering -- don't propagate all pion/transport.Net errors.
  1383. p.logger.Errorf("pionNetwork.ResolveUDPAddr failed: %v", retErr)
  1384. }
  1385. }()
  1386. // Currently, pion appears to call ResolveUDPAddr with "udp4"/udp6"
  1387. // instead of "ip4"/"ip6", as expected by, e.g., net.Resolver.LookupIP.
  1388. // Convert to "ip4"/"ip6".
  1389. // Specifying v4/v6 ensures that the resolved IP address is the correct
  1390. // type. In the case of STUN servers, the correct type is required in
  1391. // order to create the correct IPv4 or IPv6 whole punch address.
  1392. switch network {
  1393. case "udp4", "tcp4":
  1394. network = "ip4"
  1395. case "udp6", "tcp6":
  1396. network = "ip6"
  1397. default:
  1398. network = "ip"
  1399. }
  1400. // Currently, pion appears to call ResolveUDPAddr with an improperly
  1401. // formatted address, <IPv6>:443 not [<IPv6>]:443; handle this case.
  1402. index := strings.LastIndex(address, ":")
  1403. if index != -1 {
  1404. address = net.JoinHostPort(address[:index], address[index+1:])
  1405. }
  1406. // Use the Psiphon custom resolver to resolve any STUN server domains.
  1407. resolvedAddress, err := p.webRTCDialCoordinator.ResolveAddress(
  1408. p.dialCtx, network, address)
  1409. if err != nil {
  1410. return nil, errors.Trace(err)
  1411. }
  1412. IPStr, portStr, err := net.SplitHostPort(resolvedAddress)
  1413. if err != nil {
  1414. return nil, errors.Trace(err)
  1415. }
  1416. IP := net.ParseIP(IPStr)
  1417. if IP == nil {
  1418. return nil, errors.TraceNew("invalid IP address")
  1419. }
  1420. port, err := strconv.Atoi(portStr)
  1421. if err != nil {
  1422. return nil, errors.Trace(err)
  1423. }
  1424. return &net.UDPAddr{IP: IP, Port: port}, nil
  1425. }
  1426. var errNotSupported = std_errors.New("not supported")
  1427. func (p *pionNetwork) ListenPacket(network string, address string) (net.PacketConn, error) {
  1428. // Explicitly log an error since certain pion operations -- e.g., ICE
  1429. // gathering -- don't propagate all pion/transport.Net errors.
  1430. p.logger.Errorf("unexpected pionNetwork.ListenPacket call from %s", stacktrace.GetParentFunctionName())
  1431. return nil, errors.Trace(errNotSupported)
  1432. }
  1433. func (p *pionNetwork) ListenUDP(network string, locAddr *net.UDPAddr) (transport.UDPConn, error) {
  1434. p.logger.Errorf("unexpected pionNetwork.ListenUDP call from %s", stacktrace.GetParentFunctionName())
  1435. return nil, errors.Trace(errNotSupported)
  1436. }
  1437. func (p *pionNetwork) ListenTCP(network string, laddr *net.TCPAddr) (transport.TCPListener, error) {
  1438. p.logger.Errorf("unexpected pionNetwork.ListenTCP call from %s", stacktrace.GetParentFunctionName())
  1439. return nil, errors.Trace(errNotSupported)
  1440. }
  1441. func (p *pionNetwork) Dial(network, address string) (net.Conn, error) {
  1442. p.logger.Errorf("unexpected pionNetwork.Dial call from %s", stacktrace.GetParentFunctionName())
  1443. return nil, errors.Trace(errNotSupported)
  1444. }
  1445. func (p *pionNetwork) DialUDP(network string, laddr, raddr *net.UDPAddr) (transport.UDPConn, error) {
  1446. p.logger.Errorf("unexpected pionNetwork.DialUDP call from %s", stacktrace.GetParentFunctionName())
  1447. return nil, errors.Trace(errNotSupported)
  1448. }
  1449. func (p *pionNetwork) DialTCP(network string, laddr, raddr *net.TCPAddr) (transport.TCPConn, error) {
  1450. p.logger.Errorf("unexpected pionNetwork.DialTCP call from %s", stacktrace.GetParentFunctionName())
  1451. return nil, errors.Trace(errNotSupported)
  1452. }
  1453. func (p *pionNetwork) ResolveIPAddr(network, address string) (*net.IPAddr, error) {
  1454. p.logger.Errorf("unexpected pionNetwork.ResolveIPAddr call from %s", stacktrace.GetParentFunctionName())
  1455. return nil, errors.Trace(errNotSupported)
  1456. }
  1457. func (p *pionNetwork) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
  1458. p.logger.Errorf("unexpected pionNetwork.ResolveTCPAddr call from %s", stacktrace.GetParentFunctionName())
  1459. return nil, errors.Trace(errNotSupported)
  1460. }
  1461. func (p *pionNetwork) InterfaceByIndex(index int) (*transport.Interface, error) {
  1462. p.logger.Errorf("unexpected pionNetwork.InterfaceByIndex call from %s", stacktrace.GetParentFunctionName())
  1463. return nil, errors.Trace(errNotSupported)
  1464. }
  1465. func (p *pionNetwork) InterfaceByName(name string) (*transport.Interface, error) {
  1466. p.logger.Errorf("unexpected pionNetwork.InterfaceByName call from %s", stacktrace.GetParentFunctionName())
  1467. return nil, errors.Trace(errNotSupported)
  1468. }
  1469. func (p *pionNetwork) CreateDialer(dialer *net.Dialer) transport.Dialer {
  1470. return &pionNetworkDialer{pionNetwork: p}
  1471. }
  1472. type pionNetworkDialer struct {
  1473. pionNetwork *pionNetwork
  1474. }
  1475. func (d pionNetworkDialer) Dial(network, address string) (net.Conn, error) {
  1476. d.pionNetwork.logger.Errorf("unexpected pionNetworkDialer.Dial call from %s", stacktrace.GetParentFunctionName())
  1477. return nil, errors.Trace(errNotSupported)
  1478. }