STUN supports two types of transactions: REQUEST/RESPONSE transactions and INDICATION transactions. STUN itself is not a traversal solution but a protocol used in NAT traversal solutions like ICE and TURN.
The STUN protocol helps terminals behind a NAT determine the public IP address and port allocated to them by the NAT.
In ICE, the STUN protocol is used for connectivity checks (BINDING_REQUEST/RESPONSE) and ICE keep-alive (BINDING_INDICATION). In the TURN protocol, the STUN protocol is used for the establishment of Allocations and can act as a carrier for relay data (such as sendindication and dataindication). ICE and TURN are two different uses of STUN.
Here, we will temporarily discuss the protocol itself:

STUN Message Format
The STUN protocol structure consists of a 20-byte header and several attributes. The number of attributes can be zero, and they are uniformly big-endian binary sequences. The message is divided into two parts:
- 20-byte STUN Header
- Body carrying zero or more attributes
STUN Header
The message header consists of 20 bytes, with the following breakdown:
// STUN packet transaction id = 96 bits
#define STUN_TRANSACTION_ID_LEN (UINT16) 12
// STUN Header
typedef struct {
UINT16 stunMessageType; // 14 bit
UINT16 messageLength; // 16 bit
UINT32 magicCookie; // 32 bit
BYTE transactionId[STUN_TRANSACTION_ID_LEN]; // 96 bit
} StunHeader, *PStunHeader;

Message Type
The Message Type is in host byte order and is quite important:

1. BINDING/Address Binding
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0001 | BINDING REQUEST |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0011 | BINDING INDICATION |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0101 | BINDING RESPONSE SUCCESS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0111 | BINDING RESPONSE ERROR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2. SHARED SECRET
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0002 | SHARED SECRET REQUEST |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0102 | SHARED SECRET RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0112 | SHARED SECRET ERROR RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3. ALLOCATE
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0003 | ALLOCATE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0103 | ALLOCATE SUCCESS RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0113 | ALLOCATE ERROR RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4. REFRESH
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0004 | REFRESH |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0104 | REFRESH SUCCESS RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0114 | REFRESH ERROR RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5. SEND
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0006 | SEND |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0106 | SEND INDICATION |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6. DATA
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0007 | DATA |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0107 | DATA INDICATION |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7. CREATE PERMISSION
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0008 | CREATE PERMISSION |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0108 | CREATE PERMISSION SUCCESS RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0118 | CREATE PERMISSION ERROR RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8. CHANNEL BIND
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0009 | CHANNEL BIND REQUEST |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0109 | CHANNEL BIND SUCCESS RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0119 | CHANNEL BIND ERROR RESPONSE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Message Length
The length here refers to the total length of all STUN Attributes:

The following is the STUN Attributes:

Magic Cookie & Transaction ID
During transmission, the Cookie is generally considered part of the Transaction ID, so the Transaction ID is considered to be 16 bytes long. However, in [RFC 3489] or [RFC 5389], the Cookie is a fixed value 0x2112A442
.

The Transaction ID is generated by the requester and must be the same in replies as in requests. The same request uses the same Transaction ID, but clients need to choose a new Transaction ID for new transactions.

STUN Attributes
The attributes are structured (STUN Attributes) following the Header, arranged one after another:

STUN Attributes consist of an Attribute Header and an Attribute Body. The Attribute Header includes the Type and Length, with a fixed length of 4 bytes. The Attribute Body length is variable, determined by the Length.
Below, we explain some important attributes:
/**
* STUN attribute types
*/
typedef enum {
STUN_ATTRIBUTE_TYPE_MAPPED_ADDRESS = (UINT16)0x0001,
STUN_ATTRIBUTE_TYPE_RESPONSE_ADDRESS = (UINT16)0x0002,
STUN_ATTRIBUTE_TYPE_CHANGE_REQUEST = (UINT16)0x0003,
STUN_ATTRIBUTE_TYPE_SOURCE_ADDRESS = (UINT16)0x0004,
STUN_ATTRIBUTE_TYPE_CHANGED_ADDRESS = (UINT16)0x0005,
STUN_ATTRIBUTE_TYPE_USERNAME = (UINT16)0x0006,
STUN_ATTRIBUTE_TYPE_PASSWORD = (UINT16)0x0007,
STUN_ATTRIBUTE_TYPE_MESSAGE_INTEGRITY = (UINT16)0x0008,
STUN_ATTRIBUTE_TYPE_ERROR_CODE = (UINT16)0x0009,
STUN_ATTRIBUTE_TYPE_UNKNOWN_ATTRIBUTES = (UINT16)0x000A,
STUN_ATTRIBUTE_TYPE_REFLECTED_FROM = (UINT16)0x000B,
STUN_ATTRIBUTE_TYPE_XOR_MAPPED_ADDRESS = (UINT16)0x0020,
STUN_ATTRIBUTE_TYPE_PRIORITY = (UINT16)0x0024,
STUN_ATTRIBUTE_TYPE_USE_CANDIDATE = (UINT16)0x0025,
STUN_ATTRIBUTE_TYPE_FINGERPRINT = (UINT16)0x8028,
STUN_ATTRIBUTE_TYPE_ICE_CONTROLLED = (UINT16)0x8029,
STUN_ATTRIBUTE_TYPE_ICE_CONTROLLING = (UINT16)0x802A,
STUN_ATTRIBUTE_TYPE_CHANNEL_NUMBER = (UINT16)0x000C,
STUN_ATTRIBUTE_TYPE_LIFETIME = (UINT16)0x000D,
STUN_ATTRIBUTE_TYPE_XOR_PEER_ADDRESS = (UINT16)0x0012,
STUN_ATTRIBUTE_TYPE_DATA = (UINT16)0x0013,
STUN_ATTRIBUTE_TYPE_REALM = (UINT16)0x0014,
STUN_ATTRIBUTE_TYPE_NONCE = (UINT16)0x0015,
STUN_ATTRIBUTE_TYPE_XOR_RELAYED_ADDRESS = (UINT16)0x0016,
STUN_ATTRIBUTE_TYPE_EVEN_PORT = (UINT16)0x0018,
STUN_ATTRIBUTE_TYPE_REQUESTED_TRANSPORT = (UINT16)0x0019,
STUN_ATTRIBUTE_TYPE_DONT_FRAGMENT = (UINT16)0x001A,
STUN_ATTRIBUTE_TYPE_RESERVATION_TOKEN = (UINT16)0x0022,
} STUN_ATTRIBUTE_TYPE;
MAPPED-ADDRESS
Represents the âreflected addressâ of a NAT client. The Family indicates the protocol family, including IPv4 and IPv6. IPv4 is 0x01, and IPv6 is 0x02. Note that Port and Address are in network order and need to be converted to host order when viewed locally.


XOR-MAPPED-ADDRESS
Similar to the MAPPED-ADDRESS attribute, the difference is that the reflected address undergoes an XOR operation. The XOR operation is its own inverse operation, allowing the client to obtain the real reflected address through another XOR operation. This is done to address the issue of ALG altering addresses and ports.


USERNAME
The username used for message integrity checks identifies the username and password combination used in the integrity check.

MESSAGE-INTEGRITY
The HMAC-SHA1 value of a STUN message, with a length of 20 bytes, used for message integrity verification.

FINGERPRINT
The FINGERPRINT attribute may appear in all STUN messages. Its value is computed as the CRC-32 of the STUN message, XORed with the 32-bit value 0x5354554e (this XOR helps to handle scenarios where application packets also use CRC-32).
The 32-bit CRC defined by ITU V.42 [ITU.V42.2002] has a generator polynomial of x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1. When present, the FINGERPRINT attribute must be the last attribute in the message, and therefore appears after MESSAGE-INTEGRITY.
The FINGERPRINT attribute helps distinguish STUN packets from other protocol packets. Like MESSAGE-INTEGRITY, the CRC used in the FINGERPRINT attribute also covers the length field of the STUN message header. Therefore, this value must be correct before the CRC is computed, and the CRC attribute must be included as part of the message length.
When using the FINGERPRINT attribute in a message, the attribute is first placed in the message with a placeholder value, then the CRC is computed, and the attributeâs value is updated. If the MESSAGE-INTEGRITY attribute is also present, it must occur prior to computing the CRC with the correct message-integrity value, as the CRC also operates over the value of the MESSAGE-INTEGRITY attribute.

PRIORITY and USE-CANDIDATE
The terminal must include the PRIORITY attribute in its request to indicate its priority, calculated using a formula. If necessary, it can specify a particular candidate (i.e., the USE-CANDIDATE attribute).

UNKNOWN-ATTRIBUTES
This attribute appears only in error responses with an error code of 420.
ICE-CONTROLLING and ICE-CONTROLLED
The ICE process defines two roles: Controlling and Controlled.
Different roles impact the calculation of Candidate Pair priorities and Pair Nomination decisions. Generally, the role selection during a session is related to the session negotiation process, with the Offer party as Controlling and the Answer party as Controlled.

ICE-CONTROLLED or ICE-CONTROLLING attributes carry a âTie breakerâ field, which includes a randomly generated value by the local machine. The party receiving this Binding Request checks these two fields and, if they conflict with its current Role, compares the local Tie breaker value with the one in the message to determine the appropriate Role.
The method of determination is that the side with the larger Tie breaker value becomes the Controlling role. If itâs determined that the local side should change roles, it does so directly; if itâs determined that the remote side should change roles, a 487 error response is sent to this Binding Request, and the recipient of this error response changes roles accordingly.

ERROR-CODE
This attribute is used in âerror responseâ messages, containing the error code represented by values between 300 and 699, along with a UTF-8 formatted reason phrase.

SOFTWARE
This attribute is used when a proxy sends a message containing a description of the version, applicable to both clients and servers. Its value includes the manufacturer and version number. This attribute has no impact on the operation of the protocol and is used solely for diagnostics and debugging purposes. The SOFTWARE attribute is variable length, using a sequence of less than 128 UTF-8 encoded characters.

ALTERNATE-SERVER
This attribute indicates a different STUN server address that the STUN client can attempt. The format of the attribute is the same as that of the MAPPED-ADDRESS.