Files
Xray-core/common/protocol/bittorrent/bittorrent.go
T

82 lines
1.6 KiB
Go
Raw Normal View History

2020-11-25 19:01:53 +08:00
package bittorrent
import (
2022-05-22 23:48:10 -04:00
"encoding/binary"
2020-11-25 19:01:53 +08:00
"errors"
2020-12-04 09:36:16 +08:00
"github.com/xtls/xray-core/common"
2020-11-25 19:01:53 +08:00
)
2021-10-19 12:57:14 -04:00
type SniffHeader struct{}
2020-11-25 19:01:53 +08:00
func (h *SniffHeader) Protocol() string {
return "bittorrent"
}
func (h *SniffHeader) Domain() string {
return ""
}
var errNotBittorrent = errors.New("not bittorrent header")
func SniffBittorrent(b []byte) (*SniffHeader, error) {
if len(b) < 20 {
return nil, common.ErrNoClue
}
if b[0] == 19 && string(b[1:20]) == "BitTorrent protocol" {
return &SniffHeader{}, nil
}
return nil, errNotBittorrent
}
2022-05-22 23:48:10 -04:00
func SniffUTP(b []byte) (*SniffHeader, error) {
if len(b) < 20 {
return nil, common.ErrNoClue
}
2026-08-26 00:49:14 +08:00
// type 4 (ST_SYN), version 1
if b[0] != 0x41 {
2022-05-22 23:48:10 -04:00
return nil, errNotBittorrent
}
2026-08-26 00:49:14 +08:00
// timestamp_difference is always 0 in new connections
if binary.BigEndian.Uint32(b[8:12]) != 0 {
2022-05-22 23:48:10 -04:00
return nil, errNotBittorrent
}
2026-08-26 00:49:14 +08:00
// Walk the extension chain. Selective ack (1) and extension bits (2)
extension, offset := b[1], 20
2022-05-22 23:48:10 -04:00
for extension != 0 {
2026-08-26 00:49:14 +08:00
if len(b) < offset+2 {
2022-05-22 23:48:10 -04:00
return nil, errNotBittorrent
}
2026-08-26 00:49:14 +08:00
length := int(b[offset+1])
switch extension {
case 1: // selective ack
if length < 4 || length%4 != 0 {
return nil, errNotBittorrent
}
case 2: // extension bits: fixed 8 bytes, sent in ST_SYN by µTorrent
if length != 8 {
return nil, errNotBittorrent
}
default:
return nil, errNotBittorrent
2022-05-22 23:48:10 -04:00
}
2026-08-26 00:49:14 +08:00
if len(b) < offset+2+length {
return nil, errNotBittorrent
2022-05-22 23:48:10 -04:00
}
2026-08-26 00:49:14 +08:00
extension = b[offset]
offset += 2 + length
2022-05-22 23:48:10 -04:00
}
2026-08-26 00:49:14 +08:00
// extensions should consume all ST_SYN payload
if len(b) != offset {
2022-05-22 23:48:10 -04:00
return nil, errNotBittorrent
}
return &SniffHeader{}, nil
}