diff --git a/Dockerfile.build b/Dockerfile.build deleted file mode 100644 index fb8e583..0000000 --- a/Dockerfile.build +++ /dev/null @@ -1,3 +0,0 @@ -FROM golang:1.17-alpine - -WORKDIR /app diff --git a/build b/build index 6478d36..848e8cb 100755 --- a/build +++ b/build @@ -1,6 +1,8 @@ #!/bin/sh -docker build ./ --file ./Dockerfile.build --tag spoof-dpi:latest && \ - docker run --rm \ - -v $(pwd):/app spoof-dpi:latest \ - sh make-releases.sh +docker run --rm \ + -it \ + --workdir /app/ \ + -v $(pwd):/app \ + golang:1.17-alpine \ + sh make-releases.sh diff --git a/cmd/spoof-dpi/main.go b/cmd/spoof-dpi/main.go index 70b866a..19d019d 100644 --- a/cmd/spoof-dpi/main.go +++ b/cmd/spoof-dpi/main.go @@ -16,7 +16,7 @@ func main() { util.ParseArgs() config := util.GetConfig() - p := proxy.New(*config.Addr, *config.Port) + p := proxy.New(config) doh.Init(*config.Dns) if *config.Debug { log.SetLevel(log.DebugLevel) @@ -28,10 +28,10 @@ func main() { FullTimestamp: true, }) - if *config.Banner { - util.PrintColoredBanner() - } else { + if *config.NoBanner { util.PrintSimpleInfo() + } else { + util.PrintColoredBanner() } if err := util.SetOsProxy(*config.Port); err != nil { diff --git a/install.sh b/install.sh index 409106a..e738761 100644 --- a/install.sh +++ b/install.sh @@ -1,7 +1,7 @@ #!bin/bash curl "https://api.github.com/repos/xvzc/SpoofDPI/releases/latest" | - grep '"tag_name":' | + grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | xargs -I {} curl -OL "https://github.com/xvzc/SpoofDPI/releases/download/"\{\}"/spoof-dpi-${1}.tar.gz" diff --git a/net/conn.go b/net/conn.go index 7959cf7..0937661 100644 --- a/net/conn.go +++ b/net/conn.go @@ -59,7 +59,7 @@ func (conn *Conn) ReadBytes() ([]byte, error) { return ret, nil } -func (lConn *Conn) HandleHttp(p *packet.HttpPacket) { +func (lConn *Conn) HandleHttp(p *packet.HttpPacket, timeout int) { p.Tidy() ip, err := doh.Lookup(p.Domain()) @@ -93,7 +93,7 @@ func (lConn *Conn) HandleHttp(p *packet.HttpPacket) { log.Debug("[HTTP] New connection to the server ", p.Domain(), " ", rConn.LocalAddr()) - go rConn.Serve(lConn, "[HTTP]", lConn.RemoteAddr().String(), p.Domain()) + go rConn.Serve(lConn, "[HTTP]", lConn.RemoteAddr().String(), p.Domain(), timeout) _, err = rConn.Write(p.Raw()) if err != nil { @@ -103,11 +103,11 @@ func (lConn *Conn) HandleHttp(p *packet.HttpPacket) { log.Debug("[HTTP] Sent a request to ", p.Domain()) - lConn.Serve(rConn, "[HTTP]", lConn.RemoteAddr().String(), p.Domain()) + lConn.Serve(rConn, "[HTTP]", lConn.RemoteAddr().String(), p.Domain(), timeout) } -func (lConn *Conn) HandleHttps(p *packet.HttpPacket) { +func (lConn *Conn) HandleHttps(p *packet.HttpPacket, timeout int) { ip, err := doh.Lookup(p.Domain()) if err != nil { log.Error("[HTTPS DOH] Error looking up for domain: ", p.Domain(), " ", err) @@ -162,21 +162,26 @@ func (lConn *Conn) HandleHttps(p *packet.HttpPacket) { chunks := pkt.SplitInChunks() - go rConn.Serve(lConn, "[HTTPS]", rConn.RemoteAddr().String(), p.Domain()) + go rConn.Serve(lConn, "[HTTPS]", rConn.RemoteAddr().String(), p.Domain(), timeout) if _, err := rConn.WriteChunks(chunks); err != nil { log.Debug("[HTTPS] Error writing client hello to ", p.Domain(), err) return } - lConn.Serve(rConn, "[HTTPS]", lConn.RemoteAddr().String(), p.Domain()) + lConn.Serve(rConn, "[HTTPS]", lConn.RemoteAddr().String(), p.Domain(), timeout) } -func (from *Conn) Serve(to *Conn, proto string, fd string, td string) { +func (from *Conn) Serve(to *Conn, proto string, fd string, td string, timeout int) { proto += " " for { - from.SetReadDeadline(time.Now().Add(2000 * time.Millisecond)) + if timeout > 0 { + from.SetReadDeadline( + time.Now().Add(time.Millisecond * time.Duration(timeout)), + ) + } + buf, err := from.ReadBytes() if err != nil { if err == io.EOF { diff --git a/proxy/proxy.go b/proxy/proxy.go index 0193a15..45fbd7c 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -1,22 +1,26 @@ package proxy import ( + "fmt" "os" log "github.com/sirupsen/logrus" "github.com/xvzc/SpoofDPI/net" "github.com/xvzc/SpoofDPI/packet" + "github.com/xvzc/SpoofDPI/util" ) type Proxy struct { - addr string - port int + addr string + port int + timeout int } -func New(addr string, port int) *Proxy { +func New(config *util.Config) *Proxy { return &Proxy{ - addr: addr, - port: port, + addr: *config.Addr, + port: *config.Port, + timeout: *config.Timeout, } } @@ -35,7 +39,11 @@ func (p *Proxy) Start() { os.Exit(1) } - log.Println("Created a listener on :", p.Port()) + if p.timeout > 0 { + log.Println(fmt.Sprintf("Connection timeout is set to %dms", p.timeout)) + } + + log.Println("Created a listener on port", p.Port()) for { conn, err := l.Accept() @@ -65,10 +73,10 @@ func (p *Proxy) Start() { if pkt.IsConnectMethod() { log.Debug("[HTTPS] Start") - conn.HandleHttps(pkt) + conn.HandleHttps(pkt, p.timeout) } else { log.Debug("[HTTP] Start") - conn.HandleHttp(pkt) + conn.HandleHttp(pkt, p.timeout) } }() } diff --git a/readme.md b/readme.md index f8773b7..042fd73 100644 --- a/readme.md +++ b/readme.md @@ -52,9 +52,11 @@ You can also build your own Usage: spoof-dpi [options...] --addr= | default: 127.0.0.1 --dns= | default: 8.8.8.8 ---port= | default: 8080 +--port= | default: 8080 --debug= | default: false ---banner= | default: true +--no-banner= | default: false +--timeout= | default: 0 + | Enforces specific connection timeout. Set 0 to turn off --url= | Can be used multiple times. If set, | it will bypass DPI only for this url. | Example: --url=google.com --url=github.com diff --git a/readme_ko.md b/readme_ko.md index 23f4632..c6c9120 100644 --- a/readme_ko.md +++ b/readme_ko.md @@ -50,11 +50,19 @@ wget -O - https://raw.githubusercontent.com/xvzc/SpoofDPI/main/install.sh | bash # 사용법 ``` 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 +--no-banner= | default: false +--timeout= | default: 0 + | Enforces specific connection timeout. Set 0 to turn off +--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" ``` > 만약 브라우저에서 Hotspot Shield와 같은 크롬 VPN 확장프로그램을 사용중이라면 Settings > Extension 으로 이동해 비활성화 해주시기바랍니다. diff --git a/readme_ru.md b/readme_ru.md index 1207e51..d187793 100644 --- a/readme_ru.md +++ b/readme_ru.md @@ -53,9 +53,11 @@ wget -O - https://raw.githubusercontent.com/xvzc/SpoofDPI/main/install.sh | bash Usage: spoof-dpi [options...] --addr= | default: 127.0.0.1 --dns= | default: 8.8.8.8 ---port= | default: 8080 +--port= | default: 8080 --debug= | default: false ---banner= | default: true +--no-banner= | default: false +--timeout= | default: 0 + | Enforces specific connection timeout. Set 0 to turn off --url= | Can be used multiple times. If set, | it will bypass DPI only for this url. | Example: --url=google.com --url=github.com diff --git a/readme_zh-cn.md b/readme_zh-cn.md index 25721d8..c22793c 100644 --- a/readme_zh-cn.md +++ b/readme_zh-cn.md @@ -57,11 +57,19 @@ You can also build your own ``` 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 +--no-banner= | default: false +--timeout= | default: 0 + | Enforces specific connection timeout. Set 0 to turn off +--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" ``` > 如果你在 Chrome 浏览器使用其他 VPN 扩展比如 Hotspot Shield 请去 设置 > 扩展程序禁用它们 diff --git a/util/config.go b/util/config.go index e4dae79..d73c09b 100644 --- a/util/config.go +++ b/util/config.go @@ -15,7 +15,8 @@ type Config struct { Port *int Dns *string Debug *bool - Banner *bool + NoBanner *bool + Timeout *int AllowedPattern *regexp.Regexp AllowedUrls *regexp.Regexp } @@ -54,7 +55,8 @@ func ParseArgs() { 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") + config.NoBanner = flag.Bool("no-banner", false, "true | false") + config.Timeout = flag.Int("timeout", 0, "timeout in milliseconds") flag.Var(&allowedHosts, "url", "Bypass DPI only on this url, can be passed multiple times") allowedPattern = flag.String( @@ -86,26 +88,26 @@ func PrintColoredBanner() { pterm.DefaultBigText.WithLetters(cyan, purple).Render() pterm.DefaultBulletList.WithItems([]pterm.BulletListItem{ - {Level: 0, Text: "ADDR : " + *config.Addr}, + {Level: 0, Text: "ADDR : " + fmt.Sprint(*config.Addr)}, {Level: 0, Text: "PORT : " + fmt.Sprint(*config.Port)}, - {Level: 0, Text: "DNS : " + *config.Dns}, + {Level: 0, Text: "DNS : " + fmt.Sprint(*config.Dns)}, {Level: 0, Text: "DEBUG : " + fmt.Sprint(*config.Debug)}, }).Render() - if allowedHosts != nil && len(allowedHosts) > 0 { - log.Info("White listed urls: ", allowedHosts) - } + if allowedHosts != nil && len(allowedHosts) > 0 { + log.Info("White listed urls: ", allowedHosts) + } - if *allowedPattern != "" { - log.Info("Regex Pattern: ", *allowedPattern) - } + 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("- ADDR : ", *config.Addr) + fmt.Println("- PORT : ", *config.Port) + fmt.Println("- DNS : ", *config.Dns) + fmt.Println("- DEBUG : ", *config.Debug) fmt.Println("") }