The STUN protocol is a trivial query-response mechanism: The client asks the server for its external IP address and the server responds accordingly. The transport can be UDP, TCP, or TLS. STUN supports optional authentication, which is usually only used for TURN relaying.
The TURN protocol is an extension of STUN and works in an asymmetric manner. Three parties are involved: The client, the server, and the peer (actually, there can be multiple peers, but that’s not a common case). So, there are two communication links:
CLIENT <——link (1)——> SERVER <——link (2)——> PEER
Link (1) can use UDP, TCP, or TLS transports, link (2) will always use UDP. Note that the security implications of using TLS for link (1) aren’t necessarily the same as for other protocols, as WebRTC streams are end-to-end encrypted and credentials are ephemeral. Therefore, UDP is generally preferred for link (1) as well, in order to minimize latency. However, also offering TCP and TLS (esp. on port 443) might be useful as fallback options for clients behind restrictive firewalls.
The client talks to the server on a known port (e.g., 3478) over link (1), authenticates, and asks the server to open a UDP port on the relay_ipv4_addr or relay_ipv6_addr for the peer to talk to. This will be a random port within the relay_min_port to relay_max_port range, allocated for this peer specifically. The server communicates this relay address/port for link (2) to the client, which then communicates it to the peer. Any traffic sent by the peer over link (2) is relayed to the client over link (1), any traffic sent by the client over link (1) is relayed to the peer over link (2).
Note that the TURN peer isn’t necessarily the contact’s client: It might be the contact’s TURN server instead. If the contact is using the same TURN server, the server talks to itself.