diff --git a/cmd/spoof-dpi/main.go b/cmd/spoof-dpi/main.go index 7af2e5c..70b866a 100644 --- a/cmd/spoof-dpi/main.go +++ b/cmd/spoof-dpi/main.go @@ -3,38 +3,22 @@ package main import ( "os" "os/signal" - "regexp" - "strings" "syscall" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" "github.com/xvzc/SpoofDPI/doh" - "github.com/xvzc/SpoofDPI/packet" "github.com/xvzc/SpoofDPI/proxy" "github.com/xvzc/SpoofDPI/util" ) func main() { - addr, port, dns, debug, banner, allowedHosts, allowedPattern := util.ParseArgs() + util.ParseArgs() + config := util.GetConfig() - if(len(*allowedHosts) > 0) { - var escapedUrls []string - for _, host := range *allowedHosts { - escapedUrls = append(escapedUrls, regexp.QuoteMeta(host)) - } - - allowedHostsRegex := strings.Join(escapedUrls, "|") - packet.UrlsMatcher = regexp.MustCompile(allowedHostsRegex) - } - - if(allowedPattern != "") { - packet.PatternMatcher = regexp.MustCompile(allowedPattern) - } - - p := proxy.New(addr, port) - doh.Init(dns) - if debug { + p := proxy.New(*config.Addr, *config.Port) + doh.Init(*config.Dns) + if *config.Debug { log.SetLevel(log.DebugLevel) } else { log.SetLevel(log.InfoLevel) @@ -44,13 +28,13 @@ func main() { FullTimestamp: true, }) - if banner { - util.PrintColoredBanner(addr, port, dns, debug) + if *config.Banner { + util.PrintColoredBanner() } else { - util.PrintSimpleInfo(addr, port, dns, debug) + util.PrintSimpleInfo() } - if err := util.SetOsProxy(port); err != nil { + if err := util.SetOsProxy(*config.Port); err != nil { log.Fatal(err) } diff --git a/packet/https.go b/packet/https.go index d9359b7..6cf8c89 100644 --- a/packet/https.go +++ b/packet/https.go @@ -1,7 +1,7 @@ package packet import ( - "regexp" + "github.com/xvzc/SpoofDPI/util" ) type HttpsPacket struct { @@ -18,20 +18,18 @@ func (p *HttpsPacket) Raw() []byte { return p.raw } -var PatternMatcher *regexp.Regexp -var UrlsMatcher *regexp.Regexp - func (p *HttpsPacket) SplitInChunks() [][]byte { if len(p.Raw()) < 1 { return [][]byte{p.Raw()} } + config := util.GetConfig() // If the packet matches the pattern or the URLs, we don't split it - if PatternMatcher != nil || UrlsMatcher != nil { - if (PatternMatcher != nil && PatternMatcher.Match(p.Raw())) || (UrlsMatcher != nil && UrlsMatcher.Match(p.Raw())) { + if config.PatternExists() { + if (config.PatternMatches(p.Raw())) { return [][]byte{(p.Raw())[:1], (p.Raw())[1:]} } - + return [][]byte{p.Raw()} } diff --git a/util/config.go b/util/config.go new file mode 100644 index 0000000..e4dae79 --- /dev/null +++ b/util/config.go @@ -0,0 +1,111 @@ +package util + +import ( + "flag" + "fmt" + "regexp" + "strings" + + "github.com/pterm/pterm" + log "github.com/sirupsen/logrus" +) + +type Config struct { + Addr *string + Port *int + Dns *string + Debug *bool + Banner *bool + AllowedPattern *regexp.Regexp + AllowedUrls *regexp.Regexp +} + +type ArrayFlags []string + +func (i *ArrayFlags) String() string { + return "my string representation" +} + +func (i *ArrayFlags) Set(value string) error { + *i = append(*i, value) + return nil +} + +var config *Config +var allowedHosts ArrayFlags +var allowedPattern *string + +func GetConfig() *Config { + return config +} + +func (c *Config) PatternExists() bool { + return c.AllowedPattern != nil || c.AllowedUrls != nil +} + +func (c *Config) PatternMatches(bytes []byte) bool { + return (c.AllowedPattern != nil && c.AllowedPattern.Match(bytes)) || + (c.AllowedUrls != nil && c.AllowedUrls.Match(bytes)) +} + +func ParseArgs() { + config = &Config{} + config.Addr = flag.String("addr", "127.0.0.1", "Listen addr") + config.Port = flag.Int("port", 8080, "port") + config.Dns = flag.String("dns", "8.8.8.8", "DNS server") + config.Debug = flag.Bool("debug", false, "true | false") + config.Banner = flag.Bool("banner", true, "true | false") + + flag.Var(&allowedHosts, "url", "Bypass DPI only on this url, can be passed multiple times") + allowedPattern = flag.String( + "pattern", + "", + "Bypass DPI only on packets matching this regex pattern", + ) + + flag.Parse() + + if len(allowedHosts) > 0 { + var escapedUrls []string + for _, host := range allowedHosts { + escapedUrls = append(escapedUrls, regexp.QuoteMeta(host)) + } + + allowedHostsRegex := strings.Join(escapedUrls, "|") + config.AllowedUrls = regexp.MustCompile(allowedHostsRegex) + } + + if *allowedPattern != "" { + config.AllowedPattern = regexp.MustCompile(*allowedPattern) + } +} + +func PrintColoredBanner() { + cyan := pterm.NewLettersFromStringWithStyle("Spoof", pterm.NewStyle(pterm.FgCyan)) + purple := pterm.NewLettersFromStringWithStyle("DPI", pterm.NewStyle(pterm.FgLightMagenta)) + pterm.DefaultBigText.WithLetters(cyan, purple).Render() + + pterm.DefaultBulletList.WithItems([]pterm.BulletListItem{ + {Level: 0, Text: "ADDR : " + *config.Addr}, + {Level: 0, Text: "PORT : " + fmt.Sprint(*config.Port)}, + {Level: 0, Text: "DNS : " + *config.Dns}, + {Level: 0, Text: "DEBUG : " + fmt.Sprint(*config.Debug)}, + }).Render() + + if allowedHosts != nil && len(allowedHosts) > 0 { + log.Info("White listed urls: ", allowedHosts) + } + + if *allowedPattern != "" { + log.Info("Regex Pattern: ", *allowedPattern) + } +} + +func PrintSimpleInfo() { + fmt.Println("") + fmt.Println("- ADDR : ", *config.Addr) + fmt.Println("- PORT : ", *config.Port) + fmt.Println("- DNS : ", *config.Dns) + fmt.Println("- DEBUG : ", *config.Debug) + fmt.Println("") +} diff --git a/util/util.go b/util/util.go deleted file mode 100644 index e79b996..0000000 --- a/util/util.go +++ /dev/null @@ -1,57 +0,0 @@ -package util - -import ( - "flag" - "fmt" - - "github.com/pterm/pterm" -) - -type ArrayFlags []string - -func (i *ArrayFlags) String() string { - return "my string representation" -} - -func (i *ArrayFlags) Set(value string) error { - *i = append(*i, value) - return nil -} - -func ParseArgs() (string, int, string, bool, bool, *ArrayFlags, string) { - addr := flag.String("addr", "127.0.0.1", "Listen addr") - port := flag.Int("port", 8080, "port") - dns := flag.String("dns", "8.8.8.8", "DNS server") - debug := flag.Bool("debug", false, "true | false") - banner := flag.Bool("banner", true, "true | false") - - var allowedUrls ArrayFlags - flag.Var(&allowedUrls, "url", "Bypass DPI only on this url, can be passed multiple times") - allowedPattern := flag.String("pattern", "", "Bypass DPI only on packets matching this regex pattern") - - flag.Parse() - - return *addr, *port, *dns, *debug, *banner, &allowedUrls, *allowedPattern -} - -func PrintColoredBanner(addr string, port int, dns string, debug bool) { - cyan := pterm.NewLettersFromStringWithStyle("Spoof", pterm.NewStyle(pterm.FgCyan)) - purple := pterm.NewLettersFromStringWithStyle("DPI", pterm.NewStyle(pterm.FgLightMagenta)) - pterm.DefaultBigText.WithLetters(cyan, purple).Render() - - pterm.DefaultBulletList.WithItems([]pterm.BulletListItem{ - {Level: 0, Text: "ADDR : " + addr}, - {Level: 0, Text: "PORT : " + fmt.Sprint(port)}, - {Level: 0, Text: "DNS : " + dns}, - {Level: 0, Text: "DEBUG : " + fmt.Sprint(debug)}, - }).Render() -} - -func PrintSimpleInfo(addr string, port int, dns string, debug bool) { - fmt.Println("") - fmt.Println("- ADDR : ", addr) - fmt.Println("- PORT : ", port) - fmt.Println("- DNS : ", dns) - fmt.Println("- DEBUG : ", debug) - fmt.Println("") -}