Stun协议的格式记录

Stun协议的格式,定义在https://www.ietf.org/rfc/rfc3489.txt

11.1  Message Header

   All STUN messages consist of a 20 byte header:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      STUN Message Type        |         Message Length        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                            Transaction ID
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                                                   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   The Message Types can take on the following values:

      0x0001  :  Binding Request
      0x0101  :  Binding Response
      0x0111  :  Binding Error Response
      0x0002  :  Shared Secret Request
      0x0102  :  Shared Secret Response
      0x0112  :  Shared Secret Error Response
11.2  Message Attributes

   After the header are 0 or more attributes.  Each attribute is TLV
   encoded, with a 16 bit type, 16 bit length, and variable value:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Type                  |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             Value                             ....
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   The following types are defined:

   0x0001: MAPPED-ADDRESS
   0x0002: RESPONSE-ADDRESS
   0x0003: CHANGE-REQUEST
   0x0004: SOURCE-ADDRESS
   0x0005: CHANGED-ADDRESS
   0x0006: USERNAME
   0x0007: PASSWORD
   0x0008: MESSAGE-INTEGRITY
   0x0009: ERROR-CODE
   0x000a: UNKNOWN-ATTRIBUTES
   0x000b: REFLECTED-FROM

基本格式是消息体之后,跟着Attribute,Attribute的type有很多种,根据不同的类型进行解析。

Value值基本上是Mapped-Address一样

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |x x x x x x x x|    Family     |           Port                |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             Address                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

在https://tools.ietf.org/html/rfc5389中,对STUN进行了新的兼容定义,现在好多都使用5389了

5389的新定义如下:

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |0 0|     STUN Message Type     |         Message Length        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         Magic Cookie                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                     Transaction ID (96 bits)                  |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                  Figure 2: Format of STUN Message Header
将原来的128bit的TransactionID分割为2部分,一部分是magic cookie,一部分是id。
The magic cookie field MUST contain the fixed value 0x2112A442 in
   network byte order
magic cookie是一个常量
比3489多了一个属性:

15.2. XOR-MAPPED-ADDRESS



   The XOR-MAPPED-ADDRESS attribute is identical to the MAPPED-ADDRESS
   attribute, except that the reflexive transport address is obfuscated
   through the XOR function.

   The format of the XOR-MAPPED-ADDRESS is:

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |x x x x x x x x|    Family     |         X-Port                |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                X-Address (Variable)
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

             Figure 6: Format of XOR-MAPPED-ADDRESS Attribute

   The Family represents the IP address family, and is encoded
   identically to the Family in MAPPED-ADDRESS.





Rosenberg, et al.           Standards Track                    [Page 33]


RFC 5389                          STUN                      October 2008


   X-Port is computed by taking the mapped port in host byte order,
   XOR'ing it with the most significant 16 bits of the magic cookie, and
   then the converting the result to network byte order.  If the IP
   address family is IPv4, X-Address is computed by taking the mapped IP
   address in host byte order, XOR'ing it with the magic cookie, and
   converting the result to network byte order.  If the IP address
   family is IPv6, X-Address is computed by taking the mapped IP address
   in host byte order, XOR'ing it with the concatenation of the magic
   cookie and the 96-bit transaction ID, and converting the result to
   network byte order.
如果使用XOR-MAPPED-ADDRESS,需要做异或操作。

贴上一段代码:
struct StunMessageHeader
{
    unsigned short msg_type;
    unsigned short msg_len;
    unsigned int magic;
    unsigned char id[12];
};

#define STUN_MAGIC 0x2112A442
#define STUN_MSG_TYPE_BINDING_REQUEST 0x0001
#define STUN_MSG_TYPE_BINDING_RESPONSE 0x0101
#define STUN_MSG_TYPE_BINDING_ERR_RESPONS 0x0111
#define STUN_MSG_TYPE_SHARED_SECRET_REQUEST    0x0002
#define STUN_MSG_TYPE_SHARED_SECRET_RESPONSE 0x0102
#define STUN_MSG_TYPE_SHARED_SECRET_ERR_RESPONSE 0x0112
#define STUN_ATTR_MAPPED_ADDRESS        0x0001
#define STUN_ATTR_RESPONSE_ADDRESS        0x0002
#define STUN_ATTR_CHANGE_REQUEST        0x0003
#define STUN_ATTR_SOURCE_ADDRESS        0x0004
#define STUN_ATTR_CHANGE_ADDRESS        0x0005
#define STUN_ATTR_USERNAME                0x0006
#define STUN_ATTR_PASSWORD                0x0007
#define STUN_ATTR_MESSAGE_INTEGRITY        0x0008
#define STUN_ATTR_ERROR_CODE            0x0009
#define STUN_ATTR_UNKNOWN_ATTRIBUTES    0x000a
#define STUN_ATTR_REFLECTED_FROM        0x000b
#define STUN_ATTR_REALM                    0x0014
#define STUN_ATTR_NONCE                    0x0015
#define STUN_ATTR_XOR_MAPPED_ADDRESS    0x0020

struct StunAttributeHeader
{
    unsigned short type;
    unsigned short length;
};
struct MappedAddress
{
    unsigned char reseved;
    unsigned char family;
    unsigned short port;
    unsigned int address;
};

void GetBindingRequest(unsigned char* buf, int* len)
{
    StunMessageHeader binding;
    memset(&binding, 0, sizeof(binding));
    binding.msg_type = htons(STUN_MSG_TYPE_BINDING_REQUEST);
    binding.magic = htonl(STUN_MAGIC);
  unsigned long long temp = srand();
memcpy(binding.id, (unsigned char*)&temp, 8); memcpy(buf, &binding, sizeof(binding)); *len = sizeof(binding); } bool ParseMappedAddr(unsigned char* buf, int len, std::string& mappedIp, int* mappedPort) { StunMessageHeader* head = (StunMessageHeader*)buf; head->msg_type = htons(head->msg_type); head->msg_len = htons(head->msg_len); if (head->msg_type == STUN_MSG_TYPE_BINDING_RESPONSE) { if (head->msg_len > 0) { StunAttributeHeader* attr = (StunAttributeHeader*)(buf + 20); attr->type = htons(attr->type); attr->length = htons(attr->length); if (attr->type == STUN_ATTR_XOR_MAPPED_ADDRESS) { if (attr->length > 0) { MappedAddress* mapaddr = (MappedAddress*)(buf + 24); mapaddr->port = htons(mapaddr->port); mapaddr->port ^= STUN_MAGIC >> 16; mapaddr->address = htonl(mapaddr->address); mapaddr->address ^= STUN_MAGIC; char buf[16]; sprintf(buf, "%d.%d.%d.%d", mapaddr->address >> 24, mapaddr->address >> 16 & 0xff, mapaddr->address >> 8 & 0xff, mapaddr->address & 0xff); mappedIp = buf; *mappedPort = mapaddr->port; return true; } } else if (attr->type == STUN_ATTR_MAPPED_ADDRESS) { if (attr->length > 0) { MappedAddress* mapaddr = (MappedAddress*)(buf + 24); mapaddr->port = htons(mapaddr->port); mapaddr->address = htonl(mapaddr->address); char buf[16]; sprintf(buf, "%d.%d.%d.%d", mapaddr->address >> 24, mapaddr->address >> 16 & 0xff, mapaddr->address >> 8 & 0xff, mapaddr->address & 0xff); mappedIp = buf; *mappedPort = mapaddr->port; return true; } } } } return false;
}



 

posted @ 2019-01-04 13:58  media_myself  阅读(1281)  评论(0编辑  收藏  举报