diff --git a/cmd/spoof-dpi/main.go b/cmd/spoof-dpi/main.go index 39774ca..7af2e5c 100644 --- a/cmd/spoof-dpi/main.go +++ b/cmd/spoof-dpi/main.go @@ -3,17 +3,34 @@ 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 := util.ParseArgs() + addr, port, dns, debug, banner, allowedHosts, allowedPattern := util.ParseArgs() + + 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) diff --git a/packet/https.go b/packet/https.go index dae1ba3..d9359b7 100644 --- a/packet/https.go +++ b/packet/https.go @@ -1,5 +1,9 @@ package packet +import ( + "regexp" +) + type HttpsPacket struct { raw []byte } @@ -14,10 +18,22 @@ 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()} } + // 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())) { + return [][]byte{(p.Raw())[:1], (p.Raw())[1:]} + } + + return [][]byte{p.Raw()} + } + return [][]byte{(p.Raw())[:1], (p.Raw())[1:]} } diff --git a/readme.md b/readme.md index 3ec5963..d1beb48 100644 --- a/readme.md +++ b/readme.md @@ -50,11 +50,17 @@ You can also build your own # Usage ``` Usage: spoof-dpi [options...] ---addr= | default: 127.0.0.1 ---dns= | default: 8.8.8.8 ---port= | default: 8080 ---debug= | default: false ---banner= | default: true +--addr= | default: 127.0.0.1 +--dns= | default: 8.8.8.8 +--port= | default: 8080 +--debug= | default: false +--banner= | default: true +--url= | Can be used multiple times. If set, + | it will bypass DPI only for this url. + | Example: --url=google.com --url=github.com +--pattern= | If set, it will bypass DPI only for packets + | that matches this regex pattern. + | Example: --pattern="google|github" ``` > If you are using any vpn extensions such as Hotspot Shield in Chrome browser, go to Settings > Extensions, and disable them. diff --git a/util/util.go b/util/util.go index 7a822c3..e79b996 100644 --- a/util/util.go +++ b/util/util.go @@ -7,16 +7,31 @@ import ( "github.com/pterm/pterm" ) -func ParseArgs() (string, int, string, bool, bool) { +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 + return *addr, *port, *dns, *debug, *banner, &allowedUrls, *allowedPattern } func PrintColoredBanner(addr string, port int, dns string, debug bool) {