feature: add source IP exclusion with CIDR support

Features:
- Add exclude_source_ips configuration option
- Support single IPs (192.168.1.1) and CIDR ranges (10.0.0.0/8)
- Filter packets in parser before TLS processing
- Log exclusion configuration at startup
- New ipfilter package with IP/CIDR matching
- Unit tests for ipfilter package

Configuration example:
  exclude_source_ips:
    - "10.0.0.0/8"       # Exclude private network
    - "192.168.1.1"      # Exclude specific IP
    - "172.16.0.0/12"    # Exclude another range
    - "2001:db8::/32"    # IPv6 support

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
toto
2026-03-04 11:57:48 +01:00
parent bf93ee6c4a
commit 432509f8f4
6 changed files with 291 additions and 2 deletions

View File

@ -9,6 +9,7 @@ import (
"time"
"ja4sentinel/api"
"ja4sentinel/internal/ipfilter"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
@ -63,15 +64,35 @@ type ParserImpl struct {
closeOnce sync.Once
maxTrackedFlows int
maxHelloBufferBytes int
sourceIPFilter *ipfilter.Filter
}
// NewParser creates a new TLS parser with connection state tracking
func NewParser() *ParserImpl {
return NewParserWithTimeout(30 * time.Second)
return NewParserWithTimeoutAndFilter(30*time.Second, nil)
}
// NewParserWithTimeout creates a new TLS parser with a custom flow timeout
func NewParserWithTimeout(timeout time.Duration) *ParserImpl {
return NewParserWithTimeoutAndFilter(timeout, nil)
}
// NewParserWithTimeoutAndFilter creates a new TLS parser with timeout and source IP filter
func NewParserWithTimeoutAndFilter(timeout time.Duration, excludeSourceIPs []string) *ParserImpl {
var filter *ipfilter.Filter
if len(excludeSourceIPs) > 0 {
f, err := ipfilter.New(excludeSourceIPs)
if err != nil {
// Log error but continue without filter
filter = nil
} else {
filter = f
ips, networks := filter.Count()
_ = ips
_ = networks
}
}
p := &ParserImpl{
flows: make(map[string]*ConnectionFlow),
flowTimeout: timeout,
@ -79,6 +100,7 @@ func NewParserWithTimeout(timeout time.Duration) *ParserImpl {
cleanupClose: make(chan struct{}),
maxTrackedFlows: DefaultMaxTrackedFlows,
maxHelloBufferBytes: DefaultMaxHelloBufferBytes,
sourceIPFilter: filter,
}
go p.cleanupLoop()
return p
@ -219,6 +241,11 @@ func (p *ParserImpl) Process(pkt api.RawPacket) (*api.TLSClientHello, error) {
srcPort = uint16(tcp.SrcPort)
dstPort = uint16(tcp.DstPort)
// Check if source IP should be excluded
if p.sourceIPFilter != nil && p.sourceIPFilter.ShouldExclude(srcIP) {
return nil, nil // Source IP is excluded
}
// Get TCP payload (TLS data)
payload := tcp.Payload
if len(payload) == 0 {