Introduce DTLS sniffer

This commit is contained in:
世界 2024-07-07 15:45:50 +08:00
parent 6b101b5c58
commit 92da8fc64c
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
6 changed files with 99 additions and 16 deletions

31
common/sniff/dtls.go Normal file
View file

@ -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
common/sniff/dtls_test.go Normal file
View file

@ -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)
}

View file

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

View file

@ -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 | | 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 | / | | TCP/UDP | `bittorrent` | / |
| UDP | `dtls` | / |

View file

@ -1,12 +1,22 @@
---
icon: material/new-box
---
!!! quote "sing-box 1.10.0 中的更改"
:material-plus: BitTorrent 支持
:material-plus: DTLS 支持
如果在入站中启用,则可以嗅探连接的协议和域名(如果存在)。 如果在入站中启用,则可以嗅探连接的协议和域名(如果存在)。
#### 支持的协议 #### 支持的协议
| 网络 | 协议 | 域名 | | 网络 | 协议 | 域名 |
|:-------:|:-----------:|:-----------:| |:-------:|:------------:|:-----------:|
| 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 | / | | TCP/UDP | `bittorrent` | / |
| UDP | `dtls` | / |

View file

@ -966,6 +966,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