mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-05-25 13:47:41 +03:00
203 lines
3.4 KiB
Go
203 lines
3.4 KiB
Go
package v2raykcp
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
)
|
|
|
|
// used only by KCP to add an obfuscating header before encrypted payload.
|
|
type PacketHeader interface {
|
|
Size() int
|
|
Serialize([]byte)
|
|
}
|
|
|
|
// NewPacketHeader creates a new PacketHeader instance for the given header type.
|
|
// Supported values: none, srtp, utp, wechat-video,
|
|
// dtls, wireguard. Unknown types fall back to no header.
|
|
func NewPacketHeader(headerType string) PacketHeader {
|
|
switch headerType {
|
|
case "srtp":
|
|
return newSRTPHeader()
|
|
case "utp":
|
|
return newUTPHeader()
|
|
case "wechat-video":
|
|
return newWechatVideoHeader()
|
|
case "dtls":
|
|
return newDTLSHeader()
|
|
case "wireguard":
|
|
return newWireguardHeader()
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// HeaderSize returns the byte size of the header for the given type.
|
|
func HeaderSize(headerType string) int {
|
|
switch headerType {
|
|
case "srtp", "utp", "wireguard":
|
|
return 4
|
|
case "wechat-video", "dtls":
|
|
return 13
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// ----- SRTP -----
|
|
|
|
type srtpHeader struct {
|
|
header uint16
|
|
number uint16
|
|
}
|
|
|
|
func newSRTPHeader() *srtpHeader {
|
|
return &srtpHeader{
|
|
header: 0xB5E8,
|
|
number: randomUint16(),
|
|
}
|
|
}
|
|
|
|
func (*srtpHeader) Size() int {
|
|
return 4
|
|
}
|
|
|
|
func (s *srtpHeader) Serialize(b []byte) {
|
|
s.number++
|
|
binary.BigEndian.PutUint16(b, s.header)
|
|
binary.BigEndian.PutUint16(b[2:], s.number)
|
|
}
|
|
|
|
// ----- UTP -----
|
|
|
|
type utpHeader struct {
|
|
header byte
|
|
extension byte
|
|
connectionID uint16
|
|
}
|
|
|
|
func newUTPHeader() *utpHeader {
|
|
return &utpHeader{
|
|
header: 1,
|
|
extension: 0,
|
|
connectionID: randomUint16(),
|
|
}
|
|
}
|
|
|
|
func (*utpHeader) Size() int {
|
|
return 4
|
|
}
|
|
|
|
func (u *utpHeader) Serialize(b []byte) {
|
|
binary.BigEndian.PutUint16(b, u.connectionID)
|
|
b[2] = u.header
|
|
b[3] = u.extension
|
|
}
|
|
|
|
// ----- WeChat Video -----
|
|
|
|
type wechatVideoHeader struct {
|
|
sn uint32
|
|
}
|
|
|
|
func newWechatVideoHeader() *wechatVideoHeader {
|
|
return &wechatVideoHeader{
|
|
sn: randomUint32(),
|
|
}
|
|
}
|
|
|
|
func (*wechatVideoHeader) Size() int {
|
|
return 13
|
|
}
|
|
|
|
func (vc *wechatVideoHeader) Serialize(b []byte) {
|
|
vc.sn++
|
|
b[0] = 0xa1
|
|
b[1] = 0x08
|
|
binary.BigEndian.PutUint32(b[2:], vc.sn)
|
|
b[6] = 0x00
|
|
b[7] = 0x10
|
|
b[8] = 0x11
|
|
b[9] = 0x18
|
|
b[10] = 0x30
|
|
b[11] = 0x22
|
|
b[12] = 0x30
|
|
}
|
|
|
|
// ----- DTLS -----
|
|
|
|
type dtlsHeader struct {
|
|
epoch uint16
|
|
length uint16
|
|
sequence uint32
|
|
}
|
|
|
|
func newDTLSHeader() *dtlsHeader {
|
|
return &dtlsHeader{
|
|
epoch: randomUint16(),
|
|
sequence: 0,
|
|
length: 17,
|
|
}
|
|
}
|
|
|
|
func (*dtlsHeader) Size() int {
|
|
return 13
|
|
}
|
|
|
|
func (d *dtlsHeader) Serialize(b []byte) {
|
|
b[0] = 23 // application data
|
|
b[1] = 254
|
|
b[2] = 253
|
|
b[3] = byte(d.epoch >> 8)
|
|
b[4] = byte(d.epoch)
|
|
b[5] = 0
|
|
b[6] = 0
|
|
b[7] = byte(d.sequence >> 24)
|
|
b[8] = byte(d.sequence >> 16)
|
|
b[9] = byte(d.sequence >> 8)
|
|
b[10] = byte(d.sequence)
|
|
d.sequence++
|
|
b[11] = byte(d.length >> 8)
|
|
b[12] = byte(d.length)
|
|
d.length += 17
|
|
if d.length > 100 {
|
|
d.length -= 50
|
|
}
|
|
}
|
|
|
|
// ----- WireGuard -----
|
|
|
|
type wireguardHeader struct{}
|
|
|
|
func newWireguardHeader() *wireguardHeader {
|
|
return &wireguardHeader{}
|
|
}
|
|
|
|
func (*wireguardHeader) Size() int {
|
|
return 4
|
|
}
|
|
|
|
func (*wireguardHeader) Serialize(b []byte) {
|
|
b[0] = 0x04
|
|
b[1] = 0x00
|
|
b[2] = 0x00
|
|
b[3] = 0x00
|
|
}
|
|
|
|
// ----- helpers -----
|
|
|
|
func randomUint16() uint16 {
|
|
var b [2]byte
|
|
if _, err := rand.Read(b[:]); err != nil {
|
|
return 0
|
|
}
|
|
return binary.BigEndian.Uint16(b[:])
|
|
}
|
|
|
|
func randomUint32() uint32 {
|
|
var b [4]byte
|
|
if _, err := rand.Read(b[:]); err != nil {
|
|
return 0
|
|
}
|
|
return binary.BigEndian.Uint32(b[:])
|
|
}
|