223c7f5886
Pure-Go assembly of the WinDivert filter clause. Empty PID list → "false" (captures nothing — used during Discord-not-running window). Non-IPv4 upstream → 0.0.0.0 fallback (caller should validate; the builder degrades gracefully rather than panicking). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
62 lines
1.9 KiB
Go
62 lines
1.9 KiB
Go
package divert
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
)
|
|
|
|
// FilterParams collects the inputs needed to build a WinDivert filter
|
|
// expression for Drover's outbound capture.
|
|
type FilterParams struct {
|
|
// TargetPIDs is the set of PIDs whose outbound traffic should be
|
|
// captured (e.g. Discord variants). When empty, the resulting
|
|
// filter is "false" — captures nothing — which is the right
|
|
// behaviour while procscan reports zero Discord processes.
|
|
TargetPIDs []uint32
|
|
|
|
// OwnPID is drover.exe's own PID. Excluded from capture so our
|
|
// SOCKS5 traffic to the upstream proxy doesn't get re-captured.
|
|
OwnPID uint32
|
|
|
|
// UpstreamIP is the resolved IPv4 of the upstream SOCKS5 proxy.
|
|
// Excluded from capture as a second line of defence against
|
|
// self-loops. If unparseable, "0.0.0.0" is substituted (caller
|
|
// should validate before calling).
|
|
UpstreamIP string
|
|
}
|
|
|
|
// BuildFilter returns a WinDivert filter expression string suitable
|
|
// for WinDivertOpen. The expression captures only outbound IPv4 TCP/UDP
|
|
// from the listed PIDs, excluding our own process and the upstream
|
|
// proxy's IP.
|
|
func BuildFilter(p FilterParams) string {
|
|
if len(p.TargetPIDs) == 0 {
|
|
return "false"
|
|
}
|
|
|
|
upstream := p.UpstreamIP
|
|
if net.ParseIP(upstream).To4() == nil {
|
|
upstream = "0.0.0.0"
|
|
}
|
|
|
|
pidClauses := make([]string, len(p.TargetPIDs))
|
|
for i, pid := range p.TargetPIDs {
|
|
pidClauses[i] = fmt.Sprintf("processId == %d", pid)
|
|
}
|
|
pidClause := "(" + strings.Join(pidClauses, " or ") + ")"
|
|
|
|
parts := []string{
|
|
"outbound",
|
|
"(tcp or udp)",
|
|
"ip",
|
|
pidClause,
|
|
fmt.Sprintf("processId != %d", p.OwnPID),
|
|
fmt.Sprintf("ip.DstAddr != %s", upstream),
|
|
"not (ip.DstAddr >= 224.0.0.0 and ip.DstAddr <= 239.255.255.255)",
|
|
"not (ip.DstAddr >= 127.0.0.0 and ip.DstAddr <= 127.255.255.255)",
|
|
"not (ip.DstAddr >= 169.254.0.0 and ip.DstAddr <= 169.254.255.255)",
|
|
}
|
|
return strings.Join(parts, " and ")
|
|
}
|