mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
Add bittorrent protocol sniffer support
This commit is contained in:
parent
fcb5a0157b
commit
683bda9838
86
common/sniff/bittorrent.go
Normal file
86
common/sniff/bittorrent.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package sniff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BittorrentTCPMessage(ctx context.Context, reader io.Reader) (*adapter.InboundContext, error) {
|
||||||
|
packet, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
if len(packet) < 20 {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
if packet[0] != 19 || string(packet[1:20]) != "BitTorrent protocol" {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
return &adapter.InboundContext{Protocol: C.ProtocolBittorrent}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BittorrentUDPMessage(ctx context.Context, packet []byte) (*adapter.InboundContext, error) {
|
||||||
|
pLen := len(packet)
|
||||||
|
if pLen < 20 {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := bytes.NewReader(packet)
|
||||||
|
|
||||||
|
var typeAndVersion uint8
|
||||||
|
|
||||||
|
if binary.Read(buffer, binary.BigEndian, &typeAndVersion) != nil {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
} else if packet[0]>>4&0xF > 4 || packet[0]&0xF != 1 {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
var extension uint8
|
||||||
|
|
||||||
|
if binary.Read(buffer, binary.BigEndian, &extension) != nil {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
} else if extension != 0 && extension != 1 {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
for extension != 0 {
|
||||||
|
if extension != 1 {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
if binary.Read(buffer, binary.BigEndian, &extension) != nil {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
var length uint8
|
||||||
|
|
||||||
|
if err := binary.Read(buffer, binary.BigEndian, &length); err != nil {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
if int32(pLen) >= int32(length) {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if int32(pLen) >= int32(2) {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp uint32
|
||||||
|
|
||||||
|
if err := binary.Read(buffer, binary.BigEndian, ×tamp); err != nil {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
if math.Abs(float64(time.Now().UnixMicro()-int64(timestamp))) > float64(24*time.Hour) {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
return &adapter.InboundContext{Protocol: C.ProtocolBittorrent}, nil
|
||||||
|
}
|
@ -6,4 +6,5 @@ const (
|
|||||||
ProtocolQUIC = "quic"
|
ProtocolQUIC = "quic"
|
||||||
ProtocolDNS = "dns"
|
ProtocolDNS = "dns"
|
||||||
ProtocolSTUN = "stun"
|
ProtocolSTUN = "stun"
|
||||||
|
ProtocolBittorrent = "bittorrent"
|
||||||
)
|
)
|
||||||
|
@ -3,9 +3,10 @@ If enabled in the inbound, the protocol and domain name (if present) of by the c
|
|||||||
#### Supported Protocols
|
#### Supported Protocols
|
||||||
|
|
||||||
| Network | Protocol | Domain Name |
|
| Network | Protocol | Domain Name |
|
||||||
|:-------:|:--------:|:-----------:|
|
|:-------:|:----------:|:-----------:|
|
||||||
| TCP | HTTP | Host |
|
| TCP | HTTP | Host |
|
||||||
| TCP | TLS | Server Name |
|
| TCP | TLS | Server Name |
|
||||||
| UDP | QUIC | Server Name |
|
| UDP | QUIC | Server Name |
|
||||||
| UDP | STUN | / |
|
| UDP | STUN | / |
|
||||||
| TCP/UDP | DNS | / |
|
| TCP/UDP | DNS | / |
|
||||||
|
| TCP/UDP | Bittorrent | / |
|
@ -3,9 +3,10 @@
|
|||||||
#### 支持的协议
|
#### 支持的协议
|
||||||
|
|
||||||
| 网络 | 协议 | 域名 |
|
| 网络 | 协议 | 域名 |
|
||||||
|:-------:|:----:|:-----------:|
|
|:-------:|:----------:|:-----------:|
|
||||||
| TCP | HTTP | Host |
|
| TCP | HTTP | Host |
|
||||||
| TCP | TLS | Server Name |
|
| TCP | TLS | Server Name |
|
||||||
| UDP | QUIC | Server Name |
|
| UDP | QUIC | Server Name |
|
||||||
| UDP | STUN | / |
|
| UDP | STUN | / |
|
||||||
| TCP/UDP | DNS | / |
|
| TCP/UDP | DNS | / |
|
||||||
|
| TCP/UDP | Bittorrent | / |
|
@ -26,9 +26,9 @@ import (
|
|||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-box/outbound"
|
"github.com/sagernet/sing-box/outbound"
|
||||||
"github.com/sagernet/sing-box/transport/fakeip"
|
"github.com/sagernet/sing-box/transport/fakeip"
|
||||||
"github.com/sagernet/sing-dns"
|
dns "github.com/sagernet/sing-dns"
|
||||||
"github.com/sagernet/sing-tun"
|
tun "github.com/sagernet/sing-tun"
|
||||||
"github.com/sagernet/sing-vmess"
|
vmess "github.com/sagernet/sing-vmess"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
@ -652,7 +652,7 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
|||||||
if metadata.InboundOptions.SniffEnabled {
|
if metadata.InboundOptions.SniffEnabled {
|
||||||
buffer := buf.NewPacket()
|
buffer := buf.NewPacket()
|
||||||
buffer.FullReset()
|
buffer.FullReset()
|
||||||
sniffMetadata, err := sniff.PeekStream(ctx, conn, buffer, time.Duration(metadata.InboundOptions.SniffTimeout), sniff.StreamDomainNameQuery, sniff.TLSClientHello, sniff.HTTPHost)
|
sniffMetadata, err := sniff.PeekStream(ctx, conn, buffer, time.Duration(metadata.InboundOptions.SniffTimeout), sniff.StreamDomainNameQuery, sniff.TLSClientHello, sniff.HTTPHost, sniff.BittorrentTCPMessage)
|
||||||
if sniffMetadata != nil {
|
if sniffMetadata != nil {
|
||||||
metadata.Protocol = sniffMetadata.Protocol
|
metadata.Protocol = sniffMetadata.Protocol
|
||||||
metadata.Domain = sniffMetadata.Domain
|
metadata.Domain = sniffMetadata.Domain
|
||||||
@ -771,7 +771,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
|||||||
metadata.Destination = destination
|
metadata.Destination = destination
|
||||||
}
|
}
|
||||||
if metadata.InboundOptions.SniffEnabled {
|
if metadata.InboundOptions.SniffEnabled {
|
||||||
sniffMetadata, _ := sniff.PeekPacket(ctx, buffer.Bytes(), sniff.DomainNameQuery, sniff.QUICClientHello, sniff.STUNMessage)
|
sniffMetadata, _ := sniff.PeekPacket(ctx, buffer.Bytes(), sniff.DomainNameQuery, sniff.QUICClientHello, sniff.STUNMessage, sniff.BittorrentUDPMessage)
|
||||||
if sniffMetadata != nil {
|
if sniffMetadata != nil {
|
||||||
metadata.Protocol = sniffMetadata.Protocol
|
metadata.Protocol = sniffMetadata.Protocol
|
||||||
metadata.Domain = sniffMetadata.Domain
|
metadata.Domain = sniffMetadata.Domain
|
||||||
|
Loading…
x
Reference in New Issue
Block a user