Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for pattern file #144

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add support for loading patterns from file via -pattern-file option.
Ledorub committed Aug 20, 2024
commit 0122043f9de2618b1999c99636e7002b7866c9e9
6 changes: 4 additions & 2 deletions cmd/spoof-dpi/main.go
Original file line number Diff line number Diff line change
@@ -13,14 +13,16 @@ import (
)

func main() {
args := util.ParseArgs()
args := util.ParseArgs()
if *args.Version {
version.PrintVersion()
os.Exit(0)
}

config := util.GetConfig()
config.Load(args)
if err := config.Load(args); err != nil {
log.Fatalf("loading config: %s", err)
}

pxy := proxy.New(config)
if *config.Debug {
11 changes: 9 additions & 2 deletions util/args.go
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ type Args struct {
SystemProxy *bool
Timeout *int
AllowedPattern *StringArray
PatternFile *string
WindowSize *int
Version *bool
}
@@ -47,14 +48,20 @@ try lower values if the default value doesn't bypass the DPI;
when not given, the client hello packet will be sent in two parts:
fragmentation for the first data packet and the rest
`)
args.AllowedPattern = new(StringArray)
args.Version = flag.Bool("v", false, "print spoof-dpi's version; this may contain some other relevant information")

args.AllowedPattern = new(StringArray)
flag.Var(
args.AllowedPattern,
"pattern",
"bypass DPI only on packets matching this regex pattern; can be given multiple times",
)
args.PatternFile = flag.String(
"pattern-file",
"",
"bypass DPI only on packets matching regex patterns provided in a file (one per line)",
)

args.Version = flag.Bool("v", false, "print spoof-dpi's version; this may contain some other relevant information")

flag.Parse()

36 changes: 29 additions & 7 deletions util/config.go
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ func GetConfig() *Config {
return config
}

func (c *Config) Load(args *Args) {
func (c *Config) Load(args *Args) error {
c.Addr = args.Addr
c.Port = args.Port
c.DnsAddr = args.DnsAddr
@@ -41,18 +41,40 @@ func (c *Config) Load(args *Args) {
c.NoBanner = args.NoBanner
c.SystemProxy = args.SystemProxy
c.Timeout = args.Timeout
c.AllowedPatterns = parseAllowedPattern(args.AllowedPattern)
c.WindowSize = args.WindowSize

patterns, err := parseAllowedPattern(args.AllowedPattern, *args.PatternFile)
if err != nil {
return fmt.Errorf("parsing patterns: %w", err)
}
c.AllowedPatterns = patterns

return nil
}

func parseAllowedPattern(patterns *StringArray) []*regexp.Regexp {
var allowedPatterns []*regexp.Regexp
func parseAllowedPattern(patterns *StringArray, filePath string) ([]*regexp.Regexp, error) {
patternSet := make(map[*regexp.Regexp]struct{})

for _, pattern := range *patterns {
allowedPatterns = append(allowedPatterns, regexp.MustCompile(pattern))
filePatterns, err := loadPatternsFromFile(filePath)
if err != nil {
return nil, fmt.Errorf("loading patterns from file: %w", err)
}
for _, pattern := range filePatterns {
patternSet[pattern] = struct{}{}
}

return allowedPatterns
for _, rawPattern := range *patterns {
pattern := regexp.MustCompile(rawPattern)
patternSet[pattern] = struct{}{}
}

allowedPatterns := make([]*regexp.Regexp, len(patternSet))
writeI := 0
for pattern := range patternSet {
allowedPatterns[writeI] = pattern
writeI++
}
return allowedPatterns, nil
}

func PrintColoredBanner() {
41 changes: 41 additions & 0 deletions util/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package util

import (
"bufio"
"fmt"
"os"
"path/filepath"
"regexp"
)

func loadPatternsFromFile(path string) ([]*regexp.Regexp, error) {
if path == "" {
return nil, nil
}
path, err := filepath.Abs(path)
if err != nil {
return nil, fmt.Errorf("pattern file path: %w", err)
}

file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("opening pattern file: %w", err)
}
defer func() {
if e := file.Close(); e != nil && err == nil {
err = e
}
}()

var patterns []*regexp.Regexp
scanner := bufio.NewScanner(file)
for scanner.Scan() {
pattern := regexp.MustCompile(scanner.Text())
patterns = append(patterns, pattern)
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("parsing pattern file: %w", err)
}

return patterns, nil
}