亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

中繼服務協議詳解

2023-10-24 09:58:57
54
0

1. 協議及相關代碼

stun協議說明:datatracker.ietf.org/doc/html/rfc3489

stun協議擴展:datatracker.ietf.org/doc/html/rfc5389

turn協議說明:datatracker.ietf.org/doc/html/rfc5766

c實現:github.com/coturn/coturn

go實現:github.com/pion

2.turn協議概覽

turn協議是stun協議的擴展

stun消息頭

       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)                  |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

stun message type:定義了消息的class及method

message length:定義了消息的長度,不包含20字節的消息頭

magic cookie:固定值,stun協議的標識

transaction id:事務id

stun消息體

       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 (variable)                ....
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 

type:屬性名

length:value長度

value:屬性值,需注意,如果屬性值沒有填充滿一行(4字節),則需要填充滿,即對齊

 

整體協議的函數定義

// Message represents a single STUN packet. It uses aggressive internal
// buffering to enable zero-allocation encoding and decoding,
// so there are some usage constraints:
//
//	Message, its fields, results of m.Get or any attribute a.GetFrom
//	are valid only until Message.Raw is not modified.
type Message struct {
	Type          MessageType
	Length        uint32 // len(Raw) not including header
	TransactionID [TransactionIDSize]byte
	Attributes    Attributes
	Raw           []byte
}

// MessageType is STUN Message Type Field.
type MessageType struct {
	Method Method       // e.g. binding
	Class  MessageClass // e.g. request
}

stun消息頭的信息

//	 0                 1
//	 2  3  4 5 6 7 8 9 0 1 2 3 4 5
//	+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
//	|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
//	|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
//	+--+--+-+-+-+-+-+-+-+-+-+-+-+-+

協議中的C位,C1C0表示stun消息類

// MessageClass is 8-bit representation of 2-bit class of STUN Message Class.
type MessageClass byte

// Possible values for message class in STUN Message Type.
const (
	ClassRequest         MessageClass = 0x00 // 0b00
	ClassIndication      MessageClass = 0x01 // 0b01
	ClassSuccessResponse MessageClass = 0x02 // 0b10
	ClassErrorResponse   MessageClass = 0x03 // 0b11
)

class和method讀取go實現方式

// ReadValue decodes uint16 into MessageType.
func (t *MessageType) ReadValue(v uint16) {
	// Decoding class.
	// We are taking first bit from v >> 4 and second from v >> 7.
	c0 := (v >> classC0Shift) & c0Bit
	c1 := (v >> classC1Shift) & c1Bit
	class := c0 + c1
	t.Class = MessageClass(class)

	// Decoding method.
	a := v & methodABits                   // A(M0-M3)
	b := (v >> methodBShift) & methodBBits // B(M4-M6)
	d := (v >> methodDShift) & methodDBits // D(M7-M11)
	m := a + b + d
	t.Method = Method(m)
}

method定義如下:

// Method is uint16 representation of 12-bit STUN method.
type Method uint16

// Possible methods for STUN Message.
const (
	MethodBinding          Method = 0x001
	MethodAllocate         Method = 0x003
	MethodRefresh          Method = 0x004
	MethodSend             Method = 0x006
	MethodData             Method = 0x007
	MethodCreatePermission Method = 0x008
	MethodChannelBind      Method = 0x009
)

// Methods from RFC 6062.
const (
	MethodConnect           Method = 0x000a
	MethodConnectionBind    Method = 0x000b
	MethodConnectionAttempt Method = 0x000c
)

還有拓展的協議,可自行查閱

目前turnserver使用的class和method關系

服務端協議處理

func getMessageHandler(class stun.MessageClass, method stun.Method) (func(r Request, m *stun.Message) error, error) {
	switch class {
	case stun.ClassIndication:
		switch method {
		case stun.MethodSend:
			return handleSendIndication, nil
		default:
			return nil, fmt.Errorf("%w: %s", errUnexpectedMethod, method)
		}

	case stun.ClassRequest:
		switch method {
		case stun.MethodAllocate:
			return handleAllocateRequest, nil
		case stun.MethodRefresh:
			return handleRefreshRequest, nil
		case stun.MethodCreatePermission:
			return handleCreatePermissionRequest, nil
		case stun.MethodChannelBind:
			return handleChannelBindRequest, nil
		case stun.MethodBinding:
			return handleBindingRequest, nil
		default:
			return nil, fmt.Errorf("%w: %s", errUnexpectedMethod, method)
		}

	default:
		return nil, fmt.Errorf("%w: %s", errUnexpectedClass, class)
	}
}

客戶端側協議處理

if msg.Type.Class == stun.ClassIndication {
		switch msg.Type.Method {
		case stun.MethodData:
			var peerAddr proto.PeerAddress
			if err := peerAddr.GetFrom(msg); err != nil {
				return err
			}
			from = &net.UDPAddr{
				IP:   peerAddr.IP,
				Port: peerAddr.Port,
			}

			var data proto.Data
			if err := data.GetFrom(msg); err != nil {
				return err
			}

			c.log.Tracef("data indication received from %s", from.String())

			relayedConn := c.relayedUDPConn()
			if relayedConn == nil {
				c.log.Debug("no relayed conn allocated")
				return nil // Silently discard
			}
			relayedConn.HandleInbound(data, from)

替代stun協議傳輸的channeldata協議(用于傳輸音視頻數據)

stun協議header固定20字節 vs channeldata協議header固定4字節

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Channel Number        |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   /                       Application Data                        /
   /                                                               /
   |                                                               |
   |                               +-------------------------------+
   |                               |
   +-------------------------------+

 

3.安全性

沒有認證的訪問是不安全,支持的安全認證方式:

1)無認證(允許匿名訪問),在配置文件中的選項為no-auth,開啟這一選項,即使有一個user選項開啟了(在配置文件或者命令行或者usersdb文件中),no-auth也會被啟用;但如果no-auth,user,lt-cred-mech都沒有開啟,默認是開啟no-auth。

2)長期憑據機制,在配置文件中的選項為lt-cred-mech,如果no-auth和lt-cred-mech都未開啟,但有一個user選項開啟了(在配置文件或者命令行或者usersdb文件中),lt-cred-mech也會被自動開啟。

3)時間有限的長期憑據,在配置文件中的選項為use-auth-secret,需要實現TURN REST API使用認證秘密,可以在數據庫的turn_secret table里查詢,這是動態認證秘密,turn_secret table里的密鑰不固定,可以修改。

4)靜態認證密鑰,在配置文件中的選項為static-auth-secret,需要實現TURN REST API使用認證秘密,這是3)的簡單情形,即指定一個固定不變的密鑰

 

基于靜態認證用戶名密碼生成方案:

具體可查看 github.com/coturn/coturn/wiki/turnserver#turn-rest-api

temporary-username = "timestamp" + ":" + "username"

temporary-password = base64_encode(hmac-sha1(input=temporary-username, key=shared-secret))

0條評論
作者已關閉評論
鄭****輝
6文章數
0粉絲數
鄭****輝
6 文章 | 0 粉絲
鄭****輝
6文章數
0粉絲數
鄭****輝
6 文章 | 0 粉絲
原創

中繼服務協議詳解

2023-10-24 09:58:57
54
0

1. 協議及相關代碼

stun協議說明:datatracker.ietf.org/doc/html/rfc3489

stun協議擴展:datatracker.ietf.org/doc/html/rfc5389

turn協議說明:datatracker.ietf.org/doc/html/rfc5766

c實現:github.com/coturn/coturn

go實現:github.com/pion

2.turn協議概覽

turn協議是stun協議的擴展

stun消息頭

       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)                  |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

stun message type:定義了消息的class及method

message length:定義了消息的長度,不包含20字節的消息頭

magic cookie:固定值,stun協議的標識

transaction id:事務id

stun消息體

       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 (variable)                ....
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 

type:屬性名

length:value長度

value:屬性值,需注意,如果屬性值沒有填充滿一行(4字節),則需要填充滿,即對齊

 

整體協議的函數定義

// Message represents a single STUN packet. It uses aggressive internal
// buffering to enable zero-allocation encoding and decoding,
// so there are some usage constraints:
//
//	Message, its fields, results of m.Get or any attribute a.GetFrom
//	are valid only until Message.Raw is not modified.
type Message struct {
	Type          MessageType
	Length        uint32 // len(Raw) not including header
	TransactionID [TransactionIDSize]byte
	Attributes    Attributes
	Raw           []byte
}

// MessageType is STUN Message Type Field.
type MessageType struct {
	Method Method       // e.g. binding
	Class  MessageClass // e.g. request
}

stun消息頭的信息

//	 0                 1
//	 2  3  4 5 6 7 8 9 0 1 2 3 4 5
//	+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
//	|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
//	|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
//	+--+--+-+-+-+-+-+-+-+-+-+-+-+-+

協議中的C位,C1C0表示stun消息類

// MessageClass is 8-bit representation of 2-bit class of STUN Message Class.
type MessageClass byte

// Possible values for message class in STUN Message Type.
const (
	ClassRequest         MessageClass = 0x00 // 0b00
	ClassIndication      MessageClass = 0x01 // 0b01
	ClassSuccessResponse MessageClass = 0x02 // 0b10
	ClassErrorResponse   MessageClass = 0x03 // 0b11
)

class和method讀取go實現方式

// ReadValue decodes uint16 into MessageType.
func (t *MessageType) ReadValue(v uint16) {
	// Decoding class.
	// We are taking first bit from v >> 4 and second from v >> 7.
	c0 := (v >> classC0Shift) & c0Bit
	c1 := (v >> classC1Shift) & c1Bit
	class := c0 + c1
	t.Class = MessageClass(class)

	// Decoding method.
	a := v & methodABits                   // A(M0-M3)
	b := (v >> methodBShift) & methodBBits // B(M4-M6)
	d := (v >> methodDShift) & methodDBits // D(M7-M11)
	m := a + b + d
	t.Method = Method(m)
}

method定義如下:

// Method is uint16 representation of 12-bit STUN method.
type Method uint16

// Possible methods for STUN Message.
const (
	MethodBinding          Method = 0x001
	MethodAllocate         Method = 0x003
	MethodRefresh          Method = 0x004
	MethodSend             Method = 0x006
	MethodData             Method = 0x007
	MethodCreatePermission Method = 0x008
	MethodChannelBind      Method = 0x009
)

// Methods from RFC 6062.
const (
	MethodConnect           Method = 0x000a
	MethodConnectionBind    Method = 0x000b
	MethodConnectionAttempt Method = 0x000c
)

還有拓展的協議,可自行查閱

目前turnserver使用的class和method關系

服務端協議處理

func getMessageHandler(class stun.MessageClass, method stun.Method) (func(r Request, m *stun.Message) error, error) {
	switch class {
	case stun.ClassIndication:
		switch method {
		case stun.MethodSend:
			return handleSendIndication, nil
		default:
			return nil, fmt.Errorf("%w: %s", errUnexpectedMethod, method)
		}

	case stun.ClassRequest:
		switch method {
		case stun.MethodAllocate:
			return handleAllocateRequest, nil
		case stun.MethodRefresh:
			return handleRefreshRequest, nil
		case stun.MethodCreatePermission:
			return handleCreatePermissionRequest, nil
		case stun.MethodChannelBind:
			return handleChannelBindRequest, nil
		case stun.MethodBinding:
			return handleBindingRequest, nil
		default:
			return nil, fmt.Errorf("%w: %s", errUnexpectedMethod, method)
		}

	default:
		return nil, fmt.Errorf("%w: %s", errUnexpectedClass, class)
	}
}

客戶端側協議處理

if msg.Type.Class == stun.ClassIndication {
		switch msg.Type.Method {
		case stun.MethodData:
			var peerAddr proto.PeerAddress
			if err := peerAddr.GetFrom(msg); err != nil {
				return err
			}
			from = &net.UDPAddr{
				IP:   peerAddr.IP,
				Port: peerAddr.Port,
			}

			var data proto.Data
			if err := data.GetFrom(msg); err != nil {
				return err
			}

			c.log.Tracef("data indication received from %s", from.String())

			relayedConn := c.relayedUDPConn()
			if relayedConn == nil {
				c.log.Debug("no relayed conn allocated")
				return nil // Silently discard
			}
			relayedConn.HandleInbound(data, from)

替代stun協議傳輸的channeldata協議(用于傳輸音視頻數據)

stun協議header固定20字節 vs channeldata協議header固定4字節

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Channel Number        |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   /                       Application Data                        /
   /                                                               /
   |                                                               |
   |                               +-------------------------------+
   |                               |
   +-------------------------------+

 

3.安全性

沒有認證的訪問是不安全,支持的安全認證方式:

1)無認證(允許匿名訪問),在配置文件中的選項為no-auth,開啟這一選項,即使有一個user選項開啟了(在配置文件或者命令行或者usersdb文件中),no-auth也會被啟用;但如果no-auth,user,lt-cred-mech都沒有開啟,默認是開啟no-auth。

2)長期憑據機制,在配置文件中的選項為lt-cred-mech,如果no-auth和lt-cred-mech都未開啟,但有一個user選項開啟了(在配置文件或者命令行或者usersdb文件中),lt-cred-mech也會被自動開啟。

3)時間有限的長期憑據,在配置文件中的選項為use-auth-secret,需要實現TURN REST API使用認證秘密,可以在數據庫的turn_secret table里查詢,這是動態認證秘密,turn_secret table里的密鑰不固定,可以修改。

4)靜態認證密鑰,在配置文件中的選項為static-auth-secret,需要實現TURN REST API使用認證秘密,這是3)的簡單情形,即指定一個固定不變的密鑰

 

基于靜態認證用戶名密碼生成方案:

具體可查看 github.com/coturn/coturn/wiki/turnserver#turn-rest-api

temporary-username = "timestamp" + ":" + "username"

temporary-password = base64_encode(hmac-sha1(input=temporary-username, key=shared-secret))

文章來自個人專欄
文章 | 訂閱
0條評論
作者已關閉評論
作者已關閉評論
0
0