rtc

package module
v0.0.0-...-109c5d9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 13, 2021 License: Apache-2.0 Imports: 16 Imported by: 0

README

Signaling / Discovery / Control Plane

WebRTC and peer to peer communication depends on a separate 'control plane' to exchange:

For Dial:

  • address of a peer, real or TURN gateways. ( Endpoint in Istio terms )
  • SHA of cert for DTLS for the peer.
  • a password for the TURN server
  • local public address (real, TURN or NAT), to send to the remote peer.

For Accept:

  • notification - can be webpush or use a long-lived connection with the CP
  • a descriptor for the connection (SDP), including client cert SHA, addresses
  • TURN passwords if a TURN server is used.

The control plane does not need to be trusted.

Connected signaling

The most battery and network efficient signaling for accept on a low-use server is using Webpush or GCM.

An active server (in foreground and having active clients) should create one or more WebRTC association with its Gateway. The gateway should have a directly reachable address, so it doesn't need ICE. To avoid extra dependencies, the address of the gateway can be used as TURN server.

Alternatively, if the CP only support HTTPS and possibly only H1:

  • use STUN to get candidate IPs
  • make a single /register or /dial request, using self-signed JWT/VAPID
  • for accept, the request will be made periodically, to keep the port open
  • for dial, the response will include a TURN server for destination.

Server may use a database or DHT or K8S to track endpoints.

Disconnected signaling

Assuming all nodes are isolated and possibly on separate networks created using P2P:

  • in each network nodes use mDNS or dmesh multicast to locate gateways. For P2P, the well-known address of the P2P server can be used.
  • each gateway node operates a TURN server, capable of connecting to known nodes.
  • each gateway node handles discovery

Like in dmesh, powered nodes will attempt to start P2P APs and act as gateways. If no gateway is found un-powered nodes will take turn as gateways and AP.

For small meshes the gateways can create full corss-connection and have the full discovery database. For large meshhes - possibly use IPFS DHT.

If any node is connected to unmetered internet it can provide connectivity, as a TURN server.

Addressing

  1. Each node has a persistent EC256 cert, used for WebRTC DTLS. The SHA will be exchanged in the SDP address.
  2. Based on the cert SHA, an IPv6 address is also generated.
  3. (optional) The cert can also be used as IPFS address.

For Webpush, a second EC256 certificate is used, with 'audience' the public EC256 of the control plane. Since webpush cert can't be shared in browser, 2 certs need to be used. On native apps the cert can be the same.

WebRTC and raw RTCP

Protocols and comments

  • RTC - for media, control using RTCP. Not used in this project, essential for WebRTC media. Packet: 12B header, 32bit timestamp, 16bit seq. 10... start. MUX by dst port, each session should use a different port.

  • SCTP(RFC4690) - stream control transmission protocol. Originally over IP. WebRTC uses UDP + DTLS, with mTLS. Cert SHA exchanged out of band, multiple ways. It is possible to use it over UDP, with TLS and HTTP/2 or TCP on top - but one handshake per stream, and the H2 multiplexing seems less efficient than the native sctp.

    Each side can open streams, options for allowing loss and out of order, message boundary.

    • Address may change during session, multiple addresses !

    • VerificationTAG == association ID (32 bit on each side)

    • Header: src/dst port (16bit), 32bit Verification, 32bit checksum

    • Chunk Type(8), Chunk Flag(8), Chunk Len(16)

    • selective ack, heartbeat, cookie,

    • Inside chunk, TLV with 16 bit T/L

    SCTP data: 16 bit stream ID, TSN 32b(per chunk seq), stream seq number 16, 32 bit 'app identification'.

  • SCTP over UDP RFC6951:

    • 'IP address MUST NOT be listed'
    • SCTP sends heartbeats
    • port 9899 (sctp-tunneling)
    • store UDP src port/IP for the association
  • DTLS: small changes to TLS for UDP encap, seq. number is explicit. UDP packet start with TLS packet record. No session ID, only SRC/DST IP/Port.

    • Type, version (254, 253), Epoch (per cipher - can be session ID ?), Seq, length, data
    • No association ID.
    • Handshake has extra fields: message seq, fragment off, fragment len
  • SCTP-over-DTLS (RFC8261) -

    • DTLS connection before SCTP
    • multiple assocs over DTLS. SCTP port numbers for mux ?
  • STUN

    • Addr 4, value: 2112A442
    • stun.l.google.com:19302
    • can multiplex on same port
    • RFC 7983 Multiplexing Scheme Updates for RFC 5764 September 2016
    • _stun._udp.example.com -> 3478 UDP/TCP, 5349 TLS,
  • MUX - Byte0: - 0,1,2,3: STUN - 16,19: ZRTP (DH for RTP) - 20..63: DTLS (23==app data) - 64..79: TURN channel, 0..0x5000 - 127..129: RTP

  • TURN

    • extends STUN
    • auth compatible with SIP, HMAC of message with same pass.
    • username can be synthetic - ex. a date, or the sha of cert.
    • pass needs to be deterministic - used to compute HMAC-SHA1

Flow

Client:

  • Create PeerConnection, add DataChannel
  • SetLocalDescription, wait for iceGatheringState to complete
  • GetLocalDescription - should have all local IPs plus STUN/TURN
  • send offer - including all my IP:ports

The offer can be used to connect - it now acts as a server.

'Dial' will use the RTC to get the IPs of the other side and trigger the connection.

  • locate the dest and forward the offer
  • SetLocalDescription, SetRemoteDescription, wait for iceGatherState
  • send answer.

Middle proxies

WebRTC uses full e2e encryption. In the absence of direct connectivity, middle boxes can only rely on UDP-level NAT. In case of P2P networks, the STUN layer or special code must add the P2P node as a candidate, and create a binding.

A (P2P-client) -> GW1 (P2P-AP+CL) -> GW2 (P2P-AP) -> ... -> GW9 (P2P-AP) -> B(P2P-client)

There are only 2 options provided by the spec and browser impl:

  • STUN. A will get GW1 as the single candidate, using GW1 as signaling server. GW1 creates a UDP listener on 10.49.0.1:portGW1

Pion Implementation

DTLS

  • uses udp

UDP

  • uses transport (buffers)
  • emulate net.Conn, using the src IP:port as session

Raw connections can be forwarded !

Transport

  • uses logging
  • buffers
  • virtual net for testing

STUN

  • no dependencies

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DialDTLS

func DialDTLS(dest string) (io.ReadWriteCloser, error)

DialDTLS uses low-level dtls.

func DialSCTP

func DialSCTP() (io.ReadWriteCloser, error)

DialSCTP uses low-level SCTP to connect to an address.

func DialWebRTC

func DialWebRTC(inOffer *webrtc.SessionDescription) (*webrtc.SessionDescription, error)

func InitTURN

func InitTURN(publicIP string) error

InitTURN creates a TURN server for the connected mesh nodes. By default, it will only forward to the mesh.

TURN uses a username(max 513B) and 'message integrity code' Username is included in each message, followed by a HMAC-SHA1 using username:realm:pass

If realm is set, server will send a nonce and realm, which will be included For short term, the key is the pass. This is the last field ( maybe followed by fingerprint)

First request doesn't include user/nonce.

Responses use the same password, and are verified ( but not encrypted - DTLS is used on top)

func InitWebRTCS

func InitWebRTCS() (*webrtc.PeerConnection, *webrtc.SessionDescription, error)

Create a 'server' peer connection, return the address descriptor. - uses pion/ice.Agent - DTLS cert fingerprint (SHA-256), self-generated - session descriptor:

TODO: - session.URI

Types

type RTC

type RTC struct {
	Conn map[string]sctp.Association

	UGate *ugatesvc.UGate
}

func (*RTC) InitSCTP

func (r *RTC) InitSCTP(addr string) error

func (*RTC) InitSCTPS

func (r *RTC) InitSCTPS(port int) error

Blocking server. Issue: NetConn for a server needs to 'latch' to a port, to emulate a connection. Yet we want to use the same port on server side.

func (*RTC) RTCDirectHandler

func (rtc *RTC) RTCDirectHandler(w http.ResponseWriter, r *http.Request)

Returns a json with an offer for connecting this host, to allow a web or dmesh client to initiate a data channel. To reduce RT, the client acts as WebRTC server, includes an offer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL