diff --git a/cmd/spoof-dpi/main.go b/cmd/spoof-dpi/main.go index 5fd39e3..bed9394 100644 --- a/cmd/spoof-dpi/main.go +++ b/cmd/spoof-dpi/main.go @@ -4,20 +4,30 @@ import ( "flag" "os" - "github.com/xvzc/SpoofDPI/proxy" + "github.com/pterm/pterm" "github.com/xvzc/SpoofDPI/config" + "github.com/xvzc/SpoofDPI/proxy" ) func main() { - src := flag.String("src", "localhost:8080", "source-ip:source-port") + src := flag.String("src", "127.0.0.1:8080", "source-ip:source-port") dns := flag.String("dns", "8.8.8.8", "DNS server") debug := flag.Bool("debug", false, "true | false") - mtu := flag.Int("mtu", 100, "int") + flag.Parse() - err := config.InitConfig(*src, *dns, *mtu, *debug) + err := config.InitConfig(*src, *dns, *debug) if err != nil { os.Exit(1) } + 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: "SRC : " + *src}, + {Level: 0, Text: "DNS : " + *dns}, + }).Render() + proxy.Start() } diff --git a/cmd/spoof-dpi/spoof-dpi b/cmd/spoof-dpi/spoof-dpi deleted file mode 100755 index a5264bd..0000000 Binary files a/cmd/spoof-dpi/spoof-dpi and /dev/null differ diff --git a/config/config.go b/config/config.go index 73f233d..0255ac0 100644 --- a/config/config.go +++ b/config/config.go @@ -4,15 +4,15 @@ import ( "errors" "log" "strings" - "fmt" "sync" + "runtime" ) type Config struct { SrcIp string SrcPort string DNS string - MTU int + OS string Debug bool } @@ -32,7 +32,7 @@ func tokenizeAddress(srcAddress string) (string, string, error) { return ip, port, nil } -func InitConfig(srcAddress string, dns string, mtu int, debug bool) error { +func InitConfig(srcAddress string, dns string, debug bool) error { err = nil once.Do(func() { @@ -46,21 +46,11 @@ func InitConfig(srcAddress string, dns string, mtu int, debug bool) error { SrcIp : ip, SrcPort : port, DNS : dns, - MTU : mtu, + OS : runtime.GOOS, Debug : debug, } }) - log.Println("source ip : " + config.SrcIp) - log.Println("source port : " + config.SrcPort) - log.Println("dns : " + config.DNS) - log.Println("mtu : " + fmt.Sprint(config.MTU)) - if config.Debug { - log.Println("debug : true") - } else { - log.Println("debug : false") - } - return err } diff --git a/go.mod b/go.mod index 71ac69d..476d243 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,17 @@ module github.com/xvzc/SpoofDPI go 1.17 -require github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 +require ( + github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 + github.com/pterm/pterm v0.12.33 +) + +require ( + github.com/atomicgo/cursor v0.0.1 // indirect + github.com/gookit/color v1.4.2 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + golang.org/x/sys v0.0.0-20211013075003-97ac67df715c // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect +) diff --git a/go.sum b/go.sum index 94a486b..bd3a7aa 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,45 @@ +github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= +github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= +github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= +github.com/MarvinJWendt/testza v0.2.10 h1:cX4zE9TofXxe72a6EPIYAxC+8cVWTsmmgsXTZIT+5bQ= +github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= +github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU= +github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= +github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= +github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= +github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= +github.com/pterm/pterm v0.12.33 h1:XiT50Pvdqn5O8FAiIqZMpXP6NkVEcmlUa+mkA1yWVCg= +github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c h1:taxlMj0D/1sOAuv/CbSD+MMDof2vbyPTqz5FNYKpXt8= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/proxy/http.go b/proxy/http.go index bcf0d2e..193265d 100644 --- a/proxy/http.go +++ b/proxy/http.go @@ -15,29 +15,12 @@ func HandleHttp(clientConn net.Conn, ip string, message []byte) { } defer remoteConn.Close() - _, write_err := remoteConn.Write(message) - if write_err != nil { - util.Debug("failed:", write_err) - return - } - defer remoteConn.(*net.TCPConn).CloseWrite() + util.Debug("[HTTP] Connected to the server.") - buf, err := util.ReadMessage(remoteConn) - if err != nil { - util.Debug("failed:", err) - return - } + go Serve(remoteConn, clientConn, "HTTP") - fmt.Println() - util.Debug() - fmt.Println("##### Response from the server: ") - fmt.Println(string(buf)) + util.Debug("[HTTP] Sending request to the server") + fmt.Fprintf(remoteConn, string(message)) - // Write to client - _, write_err = clientConn.Write(buf) - if write_err != nil { - util.Debug("failed:", write_err) - return - } - defer clientConn.(*net.TCPConn).CloseWrite() + Serve(clientConn, remoteConn, "HTTP") } diff --git a/proxy/https.go b/proxy/https.go index c8776f6..be27a00 100644 --- a/proxy/https.go +++ b/proxy/https.go @@ -4,77 +4,46 @@ import ( "fmt" "net" - // "time" - - "github.com/xvzc/SpoofDPI/config" "github.com/xvzc/SpoofDPI/util" ) func HandleHttps(clientConn net.Conn, ip string) { - remoteConn, err := net.Dial("tcp", ip+":443") // create connection to server + // Create a connection to the requested server + remoteConn, err := net.Dial("tcp", ip+":443") if err != nil { util.Debug(err) return } - defer clientConn.Close() defer remoteConn.Close() - util.Debug("Connected to the server.") + util.Debug("[HTTPS] Connected to the server.") - go func() { - for { - buf, err := util.ReadMessage(remoteConn) - if err != nil { - util.Debug("Error reading from the server", err, " Closing connection ", remoteConn.RemoteAddr()) - return - } - - util.Debug(remoteConn.RemoteAddr(), "Server sent data", len(buf)) - - _, write_err := clientConn.Write(buf) - if write_err != nil { - util.Debug("Error sending data to the client:", write_err) - return - } - } - }() - - util.Debug("Sending 200 Connection Estabalished") + // Send self generated response for connect request fmt.Fprintf(clientConn, "HTTP/1.1 200 Connection Established\r\n\r\n") + util.Debug("[HTTPS] Sent 200 Connection Estabalished") - clientHello, err := util.ReadMessage(clientConn) + // Read client hello + clientHello, err := ReadBytes(clientConn) if err != nil { - util.Debug("Error reading client hello", err, " Closing connection ", clientConn.RemoteAddr()) + util.Debug("[HTTPS] Error reading client hello: ", err) + util.Debug("Closing connection ", clientConn.RemoteAddr()) } - util.Debug(clientConn.RemoteAddr(), "Client sent hello", len(clientHello)) + util.Debug(clientConn.RemoteAddr(), "[HTTPS] Client sent hello", len(clientHello)) - chunks, err := util.SplitInChunks(clientHello, config.GetConfig().MTU) - if err != nil { - util.Debug("Error chunking client hello: ", err) - } + // Generate a go routine that reads from the server + go Serve(remoteConn, clientConn, "HTTPS") + // Send chunked request + chunks := util.BytesToChunks(clientHello) for i := 0; i < len(chunks); i++ { _, write_err := remoteConn.Write(chunks[i]) if write_err != nil { - util.Debug("Error writing to client:", write_err) + util.Debug("[HTTPS] Error writing to the client:", write_err) break } } - for { - buf, err := util.ReadMessage(clientConn) - if err != nil { - util.Debug("Error reading from the client", err, " Closing connection ", clientConn.RemoteAddr()) - break - } - - util.Debug(clientConn.RemoteAddr(), "Client sent data", len(buf)) - - _, write_err := remoteConn.Write(buf) - if write_err != nil { - util.Debug("Error writing to client:", write_err) - break - } - } + // Read from the client + Serve(clientConn, remoteConn, "HTTPS") } diff --git a/proxy/manager.go b/proxy/manager.go new file mode 100644 index 0000000..b933f06 --- /dev/null +++ b/proxy/manager.go @@ -0,0 +1,49 @@ +package proxy + +import( + "net" + "github.com/xvzc/SpoofDPI/util" +) + +const BUF_SIZE = 1024 + +func ReadBytes(conn net.Conn)([]byte, error) { + buf := make([]byte, 0) // big buffer + tmp := make([]byte, BUF_SIZE) // using small tmo buffer for demonstrating + + for { + n, err := conn.Read(tmp) + if err != nil { + return nil, err + } + buf = append(buf, tmp[:n]...) + + if n < BUF_SIZE { + break + } + } + + return buf, nil +} + + +func Serve(from net.Conn, to net.Conn, proto string) { + for { + buf, err := ReadBytes(from) + if err != nil { + util.Debug("["+ proto +"]" + "Error reading from ", from.RemoteAddr()) + util.Debug(err, " Closing the connection.. ") + break + } + + util.Debug(from.RemoteAddr(), "sent data", len(buf)) + + _, write_err := to.Write(buf) + if write_err != nil { + util.Debug("["+ proto +"]" + "Error reading from ", to.RemoteAddr()) + util.Debug(err, " Closing the connection.. ") + break + } + } +} + diff --git a/proxy/proxy.go b/proxy/proxy.go index fd8a5cc..e8d038c 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -16,7 +16,7 @@ func Start() { os.Exit(1) } - log.Println("Created a listener") + util.Debug("Created a listener") for { clientConn, err := listener.Accept() @@ -25,17 +25,17 @@ func Start() { continue } - log.Println("Accepted a new connection.", clientConn.RemoteAddr()) + util.Debug("Accepted a new connection.", clientConn.RemoteAddr()) go func() { defer clientConn.Close() - message , err := util.ReadMessage(clientConn) + message , err := ReadBytes(clientConn) if err != nil { return } - log.Println("Client sent data: ", len(message)) + util.Debug("Client sent data: ", len(message)) domain := util.ExtractDomain(&message) @@ -44,13 +44,13 @@ func Start() { return } - log.Println("ip: "+ ip) + util.Debug("ip: "+ ip) if util.ExtractMethod(&message) == "CONNECT" { util.Debug("HTTPS Requested") HandleHttps(clientConn, ip) }else { - log.Println("HTTP Requested.") + util.Debug("HTTP Requested.") HandleHttp(clientConn, ip, message) } }() diff --git a/readme.md b/readme.md index af3ef3e..c1d379c 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,10 @@ # SpoofDPI -currently alpha +███████ ██████ ██████ ██████ ███████ ██████ ██████ ██ +██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +███████ ██████ ██ ██ ██ ██ █████ ██ ██ ██████ ██ + ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +███████ ██ ██████ ██████ ██ ██████ ██ ██ ## Run diff --git a/spoof-dpi b/spoof-dpi index 4792e63..a0a3923 100755 Binary files a/spoof-dpi and b/spoof-dpi differ diff --git a/util/util.go b/util/util.go index 54a9f95..030e9bf 100644 --- a/util/util.go +++ b/util/util.go @@ -2,52 +2,12 @@ package util import ( "log" - "net" "strings" - "errors" "github.com/babolivier/go-doh-client" "github.com/xvzc/SpoofDPI/config" ) -const BUF_SIZE = 1024 - -func WriteAndRead(conn net.Conn, message []byte) ([]byte, error){ - _, err := conn.Write(message) - if err != nil { - log.Fatal("Error writing to client:", err) - return nil, err - } - // defer conn.(*net.TCPConn).CloseWrite() - - buf, err := ReadMessage(conn) - if err != nil { - log.Fatal("failed:", err) - return nil, err - } - - return buf, nil -} - -func ReadMessage(conn net.Conn)([]byte, error) { - buf := make([]byte, 0) // big buffer - tmp := make([]byte, BUF_SIZE) // using small tmo buffer for demonstrating - - for { - n, err := conn.Read(tmp) - if err != nil { - return nil, err - } - buf = append(buf, tmp[:n]...) - - if n < BUF_SIZE { - break - } - } - - return buf, nil -} - func ExtractDomain(message *[]byte) (string) { i := 0 for ; i < len(*message); i++ { @@ -83,7 +43,7 @@ func DnsLookupOverHttps(dns string, domain string)(string, error) { Class: doh.IN, } - log.Println(domain) + Debug(domain) a, _, err := resolver.LookupA(domain) if err != nil { log.Println("Error looking up dns. ", err) @@ -104,24 +64,11 @@ func ExtractMethod(message *[]byte) (string) { } method := strings.TrimSpace(string((*message)[:i])) - log.Println(method) + Debug(method) return strings.ToUpper(method) } -func SplitInChunks(a []byte, size int) ([][]byte, error) { - if size < 1 { - return nil, errors.New("chuckSize must be greater than zero") - } - chunks := make([][]byte, 0, (len(a)+size-1)/size) - - for size < len(a) { - a, chunks = a[size:], append(chunks, a[0:size:size]) - } - chunks = append(chunks, a) - return chunks, nil -} - func Debug(v ...interface{}) { if config.GetConfig().Debug == false { return @@ -129,3 +76,11 @@ func Debug(v ...interface{}) { log.Println(v...) } + +func BytesToChunks(buf []byte) ([][]byte) { + if len(buf) < 1 { + return [][]byte{buf} + } + + return [][]byte{buf[:1], buf[1:]} +}