settingengine.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. //go:build !js
  4. // +build !js
  5. package webrtc
  6. import (
  7. "context"
  8. "crypto/x509"
  9. "io"
  10. "net"
  11. "time"
  12. "github.com/pion/dtls/v2"
  13. dtlsElliptic "github.com/pion/dtls/v2/pkg/crypto/elliptic"
  14. "github.com/pion/ice/v2"
  15. "github.com/pion/logging"
  16. "github.com/pion/stun"
  17. "github.com/pion/transport/v2"
  18. "github.com/pion/transport/v2/packetio"
  19. "github.com/pion/transport/v2/vnet"
  20. "golang.org/x/net/proxy"
  21. )
  22. // SettingEngine allows influencing behavior in ways that are not
  23. // supported by the WebRTC API. This allows us to support additional
  24. // use-cases without deviating from the WebRTC API elsewhere.
  25. type SettingEngine struct {
  26. ephemeralUDP struct {
  27. PortMin uint16
  28. PortMax uint16
  29. }
  30. detach struct {
  31. DataChannels bool
  32. }
  33. timeout struct {
  34. ICEDisconnectedTimeout *time.Duration
  35. ICEFailedTimeout *time.Duration
  36. ICEKeepaliveInterval *time.Duration
  37. ICEHostAcceptanceMinWait *time.Duration
  38. ICESrflxAcceptanceMinWait *time.Duration
  39. ICEPrflxAcceptanceMinWait *time.Duration
  40. ICERelayAcceptanceMinWait *time.Duration
  41. }
  42. candidates struct {
  43. ICELite bool
  44. ICENetworkTypes []NetworkType
  45. InterfaceFilter func(string) bool
  46. IPFilter func(net.IP) bool
  47. NAT1To1IPs []string
  48. NAT1To1IPCandidateType ICECandidateType
  49. MulticastDNSMode ice.MulticastDNSMode
  50. MulticastDNSHostName string
  51. UsernameFragment string
  52. Password string
  53. IncludeLoopbackCandidate bool
  54. }
  55. replayProtection struct {
  56. DTLS *uint
  57. SRTP *uint
  58. SRTCP *uint
  59. }
  60. dtls struct {
  61. insecureSkipHelloVerify bool
  62. disableInsecureSkipVerify bool
  63. retransmissionInterval time.Duration
  64. ellipticCurves []dtlsElliptic.Curve
  65. connectContextMaker func() (context.Context, func())
  66. extendedMasterSecret dtls.ExtendedMasterSecretType
  67. clientAuth *dtls.ClientAuthType
  68. clientCAs *x509.CertPool
  69. rootCAs *x509.CertPool
  70. keyLogWriter io.Writer
  71. }
  72. sctp struct {
  73. maxReceiveBufferSize uint32
  74. enableZeroChecksum bool
  75. }
  76. sdpMediaLevelFingerprints bool
  77. answeringDTLSRole DTLSRole
  78. disableCertificateFingerprintVerification bool
  79. disableSRTPReplayProtection bool
  80. disableSRTCPReplayProtection bool
  81. net transport.Net
  82. BufferFactory func(packetType packetio.BufferPacketType, ssrc uint32) io.ReadWriteCloser
  83. LoggerFactory logging.LoggerFactory
  84. iceTCPMux ice.TCPMux
  85. iceUDPMux ice.UDPMux
  86. iceProxyDialer proxy.Dialer
  87. iceDisableActiveTCP bool
  88. iceBindingRequestHandler func(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool
  89. disableMediaEngineCopy bool
  90. srtpProtectionProfiles []dtls.SRTPProtectionProfile
  91. receiveMTU uint
  92. // [Psiphon] from https://github.com/pion/webrtc/pull/2298, https://github.com/pion/webrtc/commit/906f20c4
  93. iceUDPMuxSrflx ice.UniversalUDPMux
  94. iceMaxBindingRequests *uint16
  95. }
  96. // getReceiveMTU returns the configured MTU. If SettingEngine's MTU is configured to 0 it returns the default
  97. func (e *SettingEngine) getReceiveMTU() uint {
  98. if e.receiveMTU != 0 {
  99. return e.receiveMTU
  100. }
  101. return receiveMTU
  102. }
  103. // DetachDataChannels enables detaching data channels. When enabled
  104. // data channels have to be detached in the OnOpen callback using the
  105. // DataChannel.Detach method.
  106. func (e *SettingEngine) DetachDataChannels() {
  107. e.detach.DataChannels = true
  108. }
  109. // SetSRTPProtectionProfiles allows the user to override the default SRTP Protection Profiles
  110. // The default srtp protection profiles are provided by the function `defaultSrtpProtectionProfiles`
  111. func (e *SettingEngine) SetSRTPProtectionProfiles(profiles ...dtls.SRTPProtectionProfile) {
  112. e.srtpProtectionProfiles = profiles
  113. }
  114. // SetICETimeouts sets the behavior around ICE Timeouts
  115. //
  116. // disconnectedTimeout:
  117. //
  118. // Duration without network activity before an Agent is considered disconnected. Default is 5 Seconds
  119. //
  120. // failedTimeout:
  121. //
  122. // Duration without network activity before an Agent is considered failed after disconnected. Default is 25 Seconds
  123. //
  124. // keepAliveInterval:
  125. //
  126. // How often the ICE Agent sends extra traffic if there is no activity, if media is flowing no traffic will be sent. Default is 2 seconds
  127. func (e *SettingEngine) SetICETimeouts(disconnectedTimeout, failedTimeout, keepAliveInterval time.Duration) {
  128. e.timeout.ICEDisconnectedTimeout = &disconnectedTimeout
  129. e.timeout.ICEFailedTimeout = &failedTimeout
  130. e.timeout.ICEKeepaliveInterval = &keepAliveInterval
  131. }
  132. // SetHostAcceptanceMinWait sets the ICEHostAcceptanceMinWait
  133. func (e *SettingEngine) SetHostAcceptanceMinWait(t time.Duration) {
  134. e.timeout.ICEHostAcceptanceMinWait = &t
  135. }
  136. // SetSrflxAcceptanceMinWait sets the ICESrflxAcceptanceMinWait
  137. func (e *SettingEngine) SetSrflxAcceptanceMinWait(t time.Duration) {
  138. e.timeout.ICESrflxAcceptanceMinWait = &t
  139. }
  140. // SetPrflxAcceptanceMinWait sets the ICEPrflxAcceptanceMinWait
  141. func (e *SettingEngine) SetPrflxAcceptanceMinWait(t time.Duration) {
  142. e.timeout.ICEPrflxAcceptanceMinWait = &t
  143. }
  144. // SetRelayAcceptanceMinWait sets the ICERelayAcceptanceMinWait
  145. func (e *SettingEngine) SetRelayAcceptanceMinWait(t time.Duration) {
  146. e.timeout.ICERelayAcceptanceMinWait = &t
  147. }
  148. // SetEphemeralUDPPortRange limits the pool of ephemeral ports that
  149. // ICE UDP connections can allocate from. This affects both host candidates,
  150. // and the local address of server reflexive candidates.
  151. //
  152. // When portMin and portMax are left to the 0 default value, pion/ice candidate
  153. // gatherer replaces them and uses 1 for portMin and 65535 for portMax.
  154. func (e *SettingEngine) SetEphemeralUDPPortRange(portMin, portMax uint16) error {
  155. if portMax < portMin {
  156. return ice.ErrPort
  157. }
  158. e.ephemeralUDP.PortMin = portMin
  159. e.ephemeralUDP.PortMax = portMax
  160. return nil
  161. }
  162. // SetLite configures whether or not the ice agent should be a lite agent
  163. func (e *SettingEngine) SetLite(lite bool) {
  164. e.candidates.ICELite = lite
  165. }
  166. // SetNetworkTypes configures what types of candidate networks are supported
  167. // during local and server reflexive gathering.
  168. func (e *SettingEngine) SetNetworkTypes(candidateTypes []NetworkType) {
  169. e.candidates.ICENetworkTypes = candidateTypes
  170. }
  171. // SetInterfaceFilter sets the filtering functions when gathering ICE candidates
  172. // This can be used to exclude certain network interfaces from ICE. Which may be
  173. // useful if you know a certain interface will never succeed, or if you wish to reduce
  174. // the amount of information you wish to expose to the remote peer
  175. func (e *SettingEngine) SetInterfaceFilter(filter func(string) bool) {
  176. e.candidates.InterfaceFilter = filter
  177. }
  178. // SetIPFilter sets the filtering functions when gathering ICE candidates
  179. // This can be used to exclude certain ip from ICE. Which may be
  180. // useful if you know a certain ip will never succeed, or if you wish to reduce
  181. // the amount of information you wish to expose to the remote peer
  182. func (e *SettingEngine) SetIPFilter(filter func(net.IP) bool) {
  183. e.candidates.IPFilter = filter
  184. }
  185. // SetNAT1To1IPs sets a list of external IP addresses of 1:1 (D)NAT
  186. // and a candidate type for which the external IP address is used.
  187. // This is useful when you host a server using Pion on an AWS EC2 instance
  188. // which has a private address, behind a 1:1 DNAT with a public IP (e.g.
  189. // Elastic IP). In this case, you can give the public IP address so that
  190. // Pion will use the public IP address in its candidate instead of the private
  191. // IP address. The second argument, candidateType, is used to tell Pion which
  192. // type of candidate should use the given public IP address.
  193. // Two types of candidates are supported:
  194. //
  195. // ICECandidateTypeHost:
  196. //
  197. // The public IP address will be used for the host candidate in the SDP.
  198. //
  199. // ICECandidateTypeSrflx:
  200. //
  201. // A server reflexive candidate with the given public IP address will be added to the SDP.
  202. //
  203. // Please note that if you choose ICECandidateTypeHost, then the private IP address
  204. // won't be advertised with the peer. Also, this option cannot be used along with mDNS.
  205. //
  206. // If you choose ICECandidateTypeSrflx, it simply adds a server reflexive candidate
  207. // with the public IP. The host candidate is still available along with mDNS
  208. // capabilities unaffected. Also, you cannot give STUN server URL at the same time.
  209. // It will result in an error otherwise.
  210. func (e *SettingEngine) SetNAT1To1IPs(ips []string, candidateType ICECandidateType) {
  211. e.candidates.NAT1To1IPs = ips
  212. e.candidates.NAT1To1IPCandidateType = candidateType
  213. }
  214. // SetIncludeLoopbackCandidate enable pion to gather loopback candidates, it is useful
  215. // for some VM have public IP mapped to loopback interface
  216. func (e *SettingEngine) SetIncludeLoopbackCandidate(include bool) {
  217. e.candidates.IncludeLoopbackCandidate = include
  218. }
  219. // SetAnsweringDTLSRole sets the DTLS role that is selected when offering
  220. // The DTLS role controls if the WebRTC Client as a client or server. This
  221. // may be useful when interacting with non-compliant clients or debugging issues.
  222. //
  223. // DTLSRoleActive:
  224. //
  225. // Act as DTLS Client, send the ClientHello and starts the handshake
  226. //
  227. // DTLSRolePassive:
  228. //
  229. // Act as DTLS Server, wait for ClientHello
  230. func (e *SettingEngine) SetAnsweringDTLSRole(role DTLSRole) error {
  231. if role != DTLSRoleClient && role != DTLSRoleServer {
  232. return errSettingEngineSetAnsweringDTLSRole
  233. }
  234. e.answeringDTLSRole = role
  235. return nil
  236. }
  237. // SetVNet sets the VNet instance that is passed to pion/ice
  238. //
  239. // VNet is a virtual network layer for Pion, allowing users to simulate
  240. // different topologies, latency, loss and jitter. This can be useful for
  241. // learning WebRTC concepts or testing your application in a lab environment
  242. // Deprecated: Please use SetNet()
  243. func (e *SettingEngine) SetVNet(vnet *vnet.Net) {
  244. e.SetNet(vnet)
  245. }
  246. // SetNet sets the Net instance that is passed to pion/ice
  247. //
  248. // Net is an network interface layer for Pion, allowing users to replace
  249. // Pions network stack with a custom implementation.
  250. func (e *SettingEngine) SetNet(net transport.Net) {
  251. e.net = net
  252. }
  253. // SetICEMulticastDNSMode controls if pion/ice queries and generates mDNS ICE Candidates
  254. func (e *SettingEngine) SetICEMulticastDNSMode(multicastDNSMode ice.MulticastDNSMode) {
  255. e.candidates.MulticastDNSMode = multicastDNSMode
  256. }
  257. // SetMulticastDNSHostName sets a static HostName to be used by pion/ice instead of generating one on startup
  258. //
  259. // This should only be used for a single PeerConnection. Having multiple PeerConnections with the same HostName will cause
  260. // undefined behavior
  261. func (e *SettingEngine) SetMulticastDNSHostName(hostName string) {
  262. e.candidates.MulticastDNSHostName = hostName
  263. }
  264. // SetICECredentials sets a staic uFrag/uPwd to be used by pion/ice
  265. //
  266. // This is useful if you want to do signalless WebRTC session, or having a reproducible environment with static credentials
  267. func (e *SettingEngine) SetICECredentials(usernameFragment, password string) {
  268. e.candidates.UsernameFragment = usernameFragment
  269. e.candidates.Password = password
  270. }
  271. // DisableCertificateFingerprintVerification disables fingerprint verification after DTLS Handshake has finished
  272. func (e *SettingEngine) DisableCertificateFingerprintVerification(isDisabled bool) {
  273. e.disableCertificateFingerprintVerification = isDisabled
  274. }
  275. // SetDTLSReplayProtectionWindow sets a replay attack protection window size of DTLS connection.
  276. func (e *SettingEngine) SetDTLSReplayProtectionWindow(n uint) {
  277. e.replayProtection.DTLS = &n
  278. }
  279. // SetSRTPReplayProtectionWindow sets a replay attack protection window size of SRTP session.
  280. func (e *SettingEngine) SetSRTPReplayProtectionWindow(n uint) {
  281. e.disableSRTPReplayProtection = false
  282. e.replayProtection.SRTP = &n
  283. }
  284. // SetSRTCPReplayProtectionWindow sets a replay attack protection window size of SRTCP session.
  285. func (e *SettingEngine) SetSRTCPReplayProtectionWindow(n uint) {
  286. e.disableSRTCPReplayProtection = false
  287. e.replayProtection.SRTCP = &n
  288. }
  289. // DisableSRTPReplayProtection disables SRTP replay protection.
  290. func (e *SettingEngine) DisableSRTPReplayProtection(isDisabled bool) {
  291. e.disableSRTPReplayProtection = isDisabled
  292. }
  293. // DisableSRTCPReplayProtection disables SRTCP replay protection.
  294. func (e *SettingEngine) DisableSRTCPReplayProtection(isDisabled bool) {
  295. e.disableSRTCPReplayProtection = isDisabled
  296. }
  297. // SetSDPMediaLevelFingerprints configures the logic for DTLS Fingerprint insertion
  298. // If true, fingerprints will be inserted in the sdp at the fingerprint
  299. // level, instead of the session level. This helps with compatibility with
  300. // some webrtc implementations.
  301. func (e *SettingEngine) SetSDPMediaLevelFingerprints(sdpMediaLevelFingerprints bool) {
  302. e.sdpMediaLevelFingerprints = sdpMediaLevelFingerprints
  303. }
  304. // SetICETCPMux enables ICE-TCP when set to a non-nil value. Make sure that
  305. // NetworkTypeTCP4 or NetworkTypeTCP6 is enabled as well.
  306. func (e *SettingEngine) SetICETCPMux(tcpMux ice.TCPMux) {
  307. e.iceTCPMux = tcpMux
  308. }
  309. // SetICEUDPMux allows ICE traffic to come through a single UDP port, drastically
  310. // simplifying deployments where ports will need to be opened/forwarded.
  311. // UDPMux should be started prior to creating PeerConnections.
  312. func (e *SettingEngine) SetICEUDPMux(udpMux ice.UDPMux) {
  313. e.iceUDPMux = udpMux
  314. }
  315. // [Psiphon] from https://github.com/pion/webrtc/pull/2298
  316. // SetICEUDPMuxSrflx allows ICE traffic from server reflexive candidates to be
  317. // multiplexed onto a single port.
  318. func (e *SettingEngine) SetICEUDPMuxSrflx(udpMuxSrflx ice.UniversalUDPMux) {
  319. e.iceUDPMuxSrflx = udpMuxSrflx
  320. }
  321. // [Psiphon] from https://github.com/pion/webrtc/commit/906f20c4
  322. // SetICEMaxBindingRequests sets the maximum amount of binding requests
  323. // that can be sent on a candidate before it is considered invalid.
  324. func (e *SettingEngine) SetICEMaxBindingRequests(d uint16) {
  325. e.iceMaxBindingRequests = &d
  326. }
  327. // SetICEProxyDialer sets the proxy dialer interface based on golang.org/x/net/proxy.
  328. func (e *SettingEngine) SetICEProxyDialer(d proxy.Dialer) {
  329. e.iceProxyDialer = d
  330. }
  331. // DisableActiveTCP disables using active TCP for ICE. Active TCP is enabled by default
  332. func (e *SettingEngine) DisableActiveTCP(isDisabled bool) {
  333. e.iceDisableActiveTCP = isDisabled
  334. }
  335. // DisableMediaEngineCopy stops the MediaEngine from being copied. This allows a user to modify
  336. // the MediaEngine after the PeerConnection has been constructed. This is useful if you wish to
  337. // modify codecs after signaling. Make sure not to share MediaEngines between PeerConnections.
  338. func (e *SettingEngine) DisableMediaEngineCopy(isDisabled bool) {
  339. e.disableMediaEngineCopy = isDisabled
  340. }
  341. // SetReceiveMTU sets the size of read buffer that copies incoming packets. This is optional.
  342. // Leave this 0 for the default receiveMTU
  343. func (e *SettingEngine) SetReceiveMTU(receiveMTU uint) {
  344. e.receiveMTU = receiveMTU
  345. }
  346. // SetDTLSRetransmissionInterval sets the retranmission interval for DTLS.
  347. func (e *SettingEngine) SetDTLSRetransmissionInterval(interval time.Duration) {
  348. e.dtls.retransmissionInterval = interval
  349. }
  350. // SetDTLSInsecureSkipHelloVerify sets the skip HelloVerify flag for DTLS.
  351. // If true and when acting as DTLS server, will allow client to skip hello verify phase and
  352. // receive ServerHello after initial ClientHello. This will mean faster connect times,
  353. // but will have lower DoS attack resistance.
  354. func (e *SettingEngine) SetDTLSInsecureSkipHelloVerify(skip bool) {
  355. e.dtls.insecureSkipHelloVerify = skip
  356. }
  357. // SetDTLSDisableInsecureSkipVerify sets the disable skip insecure verify flag for DTLS.
  358. // This controls whether a client verifies the server's certificate chain and host name.
  359. func (e *SettingEngine) SetDTLSDisableInsecureSkipVerify(disable bool) {
  360. e.dtls.disableInsecureSkipVerify = disable
  361. }
  362. // SetDTLSEllipticCurves sets the elliptic curves for DTLS.
  363. func (e *SettingEngine) SetDTLSEllipticCurves(ellipticCurves ...dtlsElliptic.Curve) {
  364. e.dtls.ellipticCurves = ellipticCurves
  365. }
  366. // SetDTLSConnectContextMaker sets the context used during the DTLS Handshake.
  367. // It can be used to extend or reduce the timeout on the DTLS Handshake.
  368. // If nil, the default dtls.ConnectContextMaker is used. It can be implemented as following.
  369. //
  370. // func ConnectContextMaker() (context.Context, func()) {
  371. // return context.WithTimeout(context.Background(), 30*time.Second)
  372. // }
  373. func (e *SettingEngine) SetDTLSConnectContextMaker(connectContextMaker func() (context.Context, func())) {
  374. e.dtls.connectContextMaker = connectContextMaker
  375. }
  376. // SetDTLSExtendedMasterSecret sets the extended master secret type for DTLS.
  377. func (e *SettingEngine) SetDTLSExtendedMasterSecret(extendedMasterSecret dtls.ExtendedMasterSecretType) {
  378. e.dtls.extendedMasterSecret = extendedMasterSecret
  379. }
  380. // SetDTLSClientAuth sets the client auth type for DTLS.
  381. func (e *SettingEngine) SetDTLSClientAuth(clientAuth dtls.ClientAuthType) {
  382. e.dtls.clientAuth = &clientAuth
  383. }
  384. // SetDTLSClientCAs sets the client CA certificate pool for DTLS certificate verification.
  385. func (e *SettingEngine) SetDTLSClientCAs(clientCAs *x509.CertPool) {
  386. e.dtls.clientCAs = clientCAs
  387. }
  388. // SetDTLSRootCAs sets the root CA certificate pool for DTLS certificate verification.
  389. func (e *SettingEngine) SetDTLSRootCAs(rootCAs *x509.CertPool) {
  390. e.dtls.rootCAs = rootCAs
  391. }
  392. // SetDTLSKeyLogWriter sets the destination of the TLS key material for debugging.
  393. // Logging key material compromises security and should only be use for debugging.
  394. func (e *SettingEngine) SetDTLSKeyLogWriter(writer io.Writer) {
  395. e.dtls.keyLogWriter = writer
  396. }
  397. // SetSCTPMaxReceiveBufferSize sets the maximum receive buffer size.
  398. // Leave this 0 for the default maxReceiveBufferSize.
  399. func (e *SettingEngine) SetSCTPMaxReceiveBufferSize(maxReceiveBufferSize uint32) {
  400. e.sctp.maxReceiveBufferSize = maxReceiveBufferSize
  401. }
  402. // SetSCTPZeroChecksum enables the zero checksum feature in SCTP.
  403. // This removes the need to checksum every incoming/outgoing packet and will reduce
  404. // latency and CPU usage. This feature is not backwards compatible so is disabled by default
  405. func (e *SettingEngine) EnableSCTPZeroChecksum(isEnabled bool) {
  406. e.sctp.enableZeroChecksum = isEnabled
  407. }
  408. // SetICEBindingRequestHandler sets a callback that is fired on a STUN BindingRequest
  409. // This allows users to do things like
  410. // - Log incoming Binding Requests for debugging
  411. // - Implement draft-thatcher-ice-renomination
  412. // - Implement custom CandidatePair switching logic
  413. func (e *SettingEngine) SetICEBindingRequestHandler(bindingRequestHandler func(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool) {
  414. e.iceBindingRequestHandler = bindingRequestHandler
  415. }