Browse Source

Add DTLS sniffer

世界 1 year ago
parent
commit
369bc7cea3

+ 31 - 0
common/sniff/dtls.go

@@ -0,0 +1,31 @@
+package sniff
+
+import (
+	"context"
+	"os"
+
+	"github.com/sagernet/sing-box/adapter"
+	C "github.com/sagernet/sing-box/constant"
+)
+
+func DTLSRecord(ctx context.Context, packet []byte) (*adapter.InboundContext, error) {
+	const fixedHeaderSize = 13
+	if len(packet) < fixedHeaderSize {
+		return nil, os.ErrInvalid
+	}
+	contentType := packet[0]
+	switch contentType {
+	case 20, 21, 22, 23, 25:
+	default:
+		return nil, os.ErrInvalid
+	}
+	versionMajor := packet[1]
+	if versionMajor != 0xfe {
+		return nil, os.ErrInvalid
+	}
+	versionMinor := packet[2]
+	if versionMinor != 0xff && versionMinor != 0xfd {
+		return nil, os.ErrInvalid
+	}
+	return &adapter.InboundContext{Protocol: C.ProtocolDTLS}, nil
+}

+ 30 - 0
common/sniff/dtls_test.go

@@ -0,0 +1,30 @@
+package sniff_test
+
+import (
+	"context"
+	"encoding/hex"
+	"testing"
+
+	"github.com/sagernet/sing-box/common/sniff"
+	C "github.com/sagernet/sing-box/constant"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestSniffDTLSClientHello(t *testing.T) {
+	t.Parallel()
+	packet, err := hex.DecodeString("16fefd0000000000000000007e010000720000000000000072fefd668a43523798e064bd806d0c87660de9c611a59bbdfc3892c4e072d94f2cafc40000000cc02bc02fc00ac014c02cc0300100003c000d0010000e0403050306030401050106010807ff01000100000a00080006001d00170018000b00020100000e000900060008000700010000170000")
+	require.NoError(t, err)
+	metadata, err := sniff.DTLSRecord(context.Background(), packet)
+	require.NoError(t, err)
+	require.Equal(t, metadata.Protocol, C.ProtocolDTLS)
+}
+
+func TestSniffDTLSClientApplicationData(t *testing.T) {
+	t.Parallel()
+	packet, err := hex.DecodeString("17fefd000100000000000100440001000000000001a4f682b77ecadd10f3f3a2f78d90566212366ff8209fd77314f5a49352f9bb9bd12f4daba0b4736ae29e46b9714d3b424b3e6d0234736619b5aa0d3f")
+	require.NoError(t, err)
+	metadata, err := sniff.DTLSRecord(context.Background(), packet)
+	require.NoError(t, err)
+	require.Equal(t, metadata.Protocol, C.ProtocolDTLS)
+}

+ 1 - 0
constant/protocol.go

@@ -7,4 +7,5 @@ const (
 	ProtocolDNS        = "dns"
 	ProtocolDNS        = "dns"
 	ProtocolSTUN       = "stun"
 	ProtocolSTUN       = "stun"
 	ProtocolBitTorrent = "bittorrent"
 	ProtocolBitTorrent = "bittorrent"
+	ProtocolDTLS       = "dtls"
 )
 )

+ 18 - 8
docs/configuration/route/sniff.md

@@ -1,12 +1,22 @@
+---
+icon: material/new-box
+---
+
+!!! quote "Changes in sing-box 1.10.0"
+
+    :material-plus: BitTorrent support
+    :material-plus: DTLS support
+
 If enabled in the inbound, the protocol and domain name (if present) of by the connection can be sniffed.
 If enabled in the inbound, the protocol and domain name (if present) of by the connection can be sniffed.
 
 
 #### Supported Protocols
 #### Supported Protocols
 
 
-| Network |  Protocol   | Domain Name |
-|:-------:|:-----------:|:-----------:|
-|   TCP   |    HTTP     |    Host     |
-|   TCP   |     TLS     | Server Name |
-|   UDP   |    QUIC     | Server Name |
-|   UDP   |    STUN     |      /      |
-| TCP/UDP |     DNS     |      /      |
-| TCP/UDP | BitTorrent  |      /      |
+| Network |   Protocol   | Domain Name |
+|:-------:|:------------:|:-----------:|
+|   TCP   |    `http`    |    Host     |
+|   TCP   |    `tls`     | Server Name |
+|   UDP   |    `quic`    | Server Name |
+|   UDP   |    `stun`    |      /      |
+| TCP/UDP |    `dns`     |      /      |
+| TCP/UDP | `bittorrent` |      /      |
+|   UDP   |    `dtls`    |      /      |

+ 18 - 8
docs/configuration/route/sniff.zh.md

@@ -1,12 +1,22 @@
+---
+icon: material/new-box
+---
+
+!!! quote "sing-box 1.10.0 中的更改"
+
+    :material-plus: BitTorrent 支持
+    :material-plus: DTLS 支持
+
 如果在入站中启用,则可以嗅探连接的协议和域名(如果存在)。
 如果在入站中启用,则可以嗅探连接的协议和域名(如果存在)。
 
 
 #### 支持的协议
 #### 支持的协议
 
 
-|   网络    |     协议      |     域名      |
-|:-------:|:-----------:|:-----------:|
-|   TCP   |    HTTP     |    Host     |
-|   TCP   |     TLS     | Server Name |
-|   UDP   |    QUIC     | Server Name |
-|   UDP   |    STUN     |      /      |
-| TCP/UDP |     DNS     |      /      |
-| TCP/UDP | BitTorrent  |      /      |
+|   网络    |      协议      |     域名      |
+|:-------:|:------------:|:-----------:|
+|   TCP   |    `http`    |    Host     |
+|   TCP   |    `tls`     | Server Name |
+|   UDP   |    `quic`    | Server Name |
+|   UDP   |    `stun`    |      /      |
+| TCP/UDP |    `dns`     |      /      |
+| TCP/UDP | `bittorrent` |      /      |
+|   UDP   |    `dtls`    |      /      |

+ 1 - 0
route/router.go

@@ -1000,6 +1000,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
 				sniff.STUNMessage,
 				sniff.STUNMessage,
 				sniff.UTP,
 				sniff.UTP,
 				sniff.UDPTracker,
 				sniff.UDPTracker,
+				sniff.DTLSRecord,
 			)
 			)
 				if sniffMetadata != nil {
 				if sniffMetadata != nil {
 					metadata.Protocol = sniffMetadata.Protocol
 					metadata.Protocol = sniffMetadata.Protocol