Browse Source

Add uTP sniffer

世界 4 years ago
parent
commit
d781cc0cfd
2 changed files with 62 additions and 1 deletions
  1. 2 1
      app/dispatcher/sniffer.go
  2. 60 0
      common/protocol/bittorrent/bittorrent.go

+ 2 - 1
app/dispatcher/sniffer.go

@@ -37,7 +37,8 @@ func NewSniffer(ctx context.Context) *Sniffer {
 			{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b) }, false, net.Network_TCP},
 			{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
 			{func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
-			{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_UDP},
+			{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
+			{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffUTP(b) }, false, net.Network_UDP},
 		},
 	}
 	if sniffer, err := newFakeDNSSniffer(ctx); err == nil {

+ 60 - 0
common/protocol/bittorrent/bittorrent.go

@@ -1,7 +1,12 @@
 package bittorrent
 
 import (
+	"encoding/binary"
 	"errors"
+	"math"
+	"time"
+
+	"github.com/v2fly/v2ray-core/v4/common/buf"
 
 	"github.com/v2fly/v2ray-core/v4/common"
 )
@@ -29,3 +34,58 @@ func SniffBittorrent(b []byte) (*SniffHeader, error) {
 
 	return nil, errNotBittorrent
 }
+
+func SniffUTP(b []byte) (*SniffHeader, error) {
+	if len(b) < 20 {
+		return nil, common.ErrNoClue
+	}
+
+	buffer := buf.As(b)
+
+	var typeAndVersion uint8
+
+	if binary.Read(buffer, binary.BigEndian, &typeAndVersion) != nil {
+		return nil, common.ErrNoClue
+	} else if b[0]>>4&0xF > 4 || b[0]&0xF != 1 {
+		return nil, errNotBittorrent
+	}
+
+	var extension uint8
+
+	if binary.Read(buffer, binary.BigEndian, &extension) != nil {
+		return nil, common.ErrNoClue
+	} else if extension != 0 && extension != 1 {
+		return nil, errNotBittorrent
+	}
+
+	for extension != 0 {
+		if extension != 1 {
+			return nil, errNotBittorrent
+		}
+		if binary.Read(buffer, binary.BigEndian, &extension) != nil {
+			return nil, common.ErrNoClue
+		}
+
+		var length uint8
+		if err := binary.Read(buffer, binary.BigEndian, &length); err != nil {
+			return nil, common.ErrNoClue
+		}
+		if common.Error2(buffer.ReadBytes(int32(length))) != nil {
+			return nil, common.ErrNoClue
+		}
+	}
+
+	if common.Error2(buffer.ReadBytes(2)) != nil {
+		return nil, common.ErrNoClue
+	}
+
+	var timestamp uint32
+	if err := binary.Read(buffer, binary.BigEndian, &timestamp); err != nil {
+		return nil, common.ErrNoClue
+	}
+	if math.Abs(float64(time.Now().UnixMicro()-int64(timestamp))) > float64(24*time.Hour) {
+		return nil, errNotBittorrent
+	}
+
+	return &SniffHeader{}, nil
+}