This commit is contained in:
xvzc 2022-01-04 00:13:42 +09:00
parent 7efe71ef4c
commit aa9c47271a
12 changed files with 167 additions and 151 deletions

View File

@ -4,20 +4,30 @@ import (
"flag" "flag"
"os" "os"
"github.com/xvzc/SpoofDPI/proxy" "github.com/pterm/pterm"
"github.com/xvzc/SpoofDPI/config" "github.com/xvzc/SpoofDPI/config"
"github.com/xvzc/SpoofDPI/proxy"
) )
func main() { 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") dns := flag.String("dns", "8.8.8.8", "DNS server")
debug := flag.Bool("debug", false, "true | false") 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 { if err != nil {
os.Exit(1) 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() proxy.Start()
} }

Binary file not shown.

View File

@ -4,15 +4,15 @@ import (
"errors" "errors"
"log" "log"
"strings" "strings"
"fmt"
"sync" "sync"
"runtime"
) )
type Config struct { type Config struct {
SrcIp string SrcIp string
SrcPort string SrcPort string
DNS string DNS string
MTU int OS string
Debug bool Debug bool
} }
@ -32,7 +32,7 @@ func tokenizeAddress(srcAddress string) (string, string, error) {
return ip, port, nil 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 err = nil
once.Do(func() { once.Do(func() {
@ -46,21 +46,11 @@ func InitConfig(srcAddress string, dns string, mtu int, debug bool) error {
SrcIp : ip, SrcIp : ip,
SrcPort : port, SrcPort : port,
DNS : dns, DNS : dns,
MTU : mtu, OS : runtime.GOOS,
Debug : debug, 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 return err
} }

15
go.mod
View File

@ -2,4 +2,17 @@ module github.com/xvzc/SpoofDPI
go 1.17 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
)

43
go.sum
View File

@ -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 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg= 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=

View File

@ -15,29 +15,12 @@ func HandleHttp(clientConn net.Conn, ip string, message []byte) {
} }
defer remoteConn.Close() defer remoteConn.Close()
_, write_err := remoteConn.Write(message) util.Debug("[HTTP] Connected to the server.")
if write_err != nil {
util.Debug("failed:", write_err)
return
}
defer remoteConn.(*net.TCPConn).CloseWrite()
buf, err := util.ReadMessage(remoteConn) go Serve(remoteConn, clientConn, "HTTP")
if err != nil {
util.Debug("failed:", err)
return
}
fmt.Println() util.Debug("[HTTP] Sending request to the server")
util.Debug() fmt.Fprintf(remoteConn, string(message))
fmt.Println("##### Response from the server: ")
fmt.Println(string(buf))
// Write to client Serve(clientConn, remoteConn, "HTTP")
_, write_err = clientConn.Write(buf)
if write_err != nil {
util.Debug("failed:", write_err)
return
}
defer clientConn.(*net.TCPConn).CloseWrite()
} }

View File

@ -4,77 +4,46 @@ import (
"fmt" "fmt"
"net" "net"
// "time"
"github.com/xvzc/SpoofDPI/config"
"github.com/xvzc/SpoofDPI/util" "github.com/xvzc/SpoofDPI/util"
) )
func HandleHttps(clientConn net.Conn, ip string) { 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 { if err != nil {
util.Debug(err) util.Debug(err)
return return
} }
defer clientConn.Close()
defer remoteConn.Close() defer remoteConn.Close()
util.Debug("Connected to the server.") util.Debug("[HTTPS] Connected to the server.")
go func() { // Send self generated response for connect request
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")
fmt.Fprintf(clientConn, "HTTP/1.1 200 Connection Established\r\n\r\n") 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 { 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) // Generate a go routine that reads from the server
if err != nil { go Serve(remoteConn, clientConn, "HTTPS")
util.Debug("Error chunking client hello: ", err)
}
// Send chunked request
chunks := util.BytesToChunks(clientHello)
for i := 0; i < len(chunks); i++ { for i := 0; i < len(chunks); i++ {
_, write_err := remoteConn.Write(chunks[i]) _, write_err := remoteConn.Write(chunks[i])
if write_err != nil { if write_err != nil {
util.Debug("Error writing to client:", write_err) util.Debug("[HTTPS] Error writing to the client:", write_err)
break break
} }
} }
for { // Read from the client
buf, err := util.ReadMessage(clientConn) Serve(clientConn, remoteConn, "HTTPS")
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
}
}
} }

49
proxy/manager.go Normal file
View File

@ -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
}
}
}

View File

@ -16,7 +16,7 @@ func Start() {
os.Exit(1) os.Exit(1)
} }
log.Println("Created a listener") util.Debug("Created a listener")
for { for {
clientConn, err := listener.Accept() clientConn, err := listener.Accept()
@ -25,17 +25,17 @@ func Start() {
continue continue
} }
log.Println("Accepted a new connection.", clientConn.RemoteAddr()) util.Debug("Accepted a new connection.", clientConn.RemoteAddr())
go func() { go func() {
defer clientConn.Close() defer clientConn.Close()
message , err := util.ReadMessage(clientConn) message , err := ReadBytes(clientConn)
if err != nil { if err != nil {
return return
} }
log.Println("Client sent data: ", len(message)) util.Debug("Client sent data: ", len(message))
domain := util.ExtractDomain(&message) domain := util.ExtractDomain(&message)
@ -44,13 +44,13 @@ func Start() {
return return
} }
log.Println("ip: "+ ip) util.Debug("ip: "+ ip)
if util.ExtractMethod(&message) == "CONNECT" { if util.ExtractMethod(&message) == "CONNECT" {
util.Debug("HTTPS Requested") util.Debug("HTTPS Requested")
HandleHttps(clientConn, ip) HandleHttps(clientConn, ip)
}else { }else {
log.Println("HTTP Requested.") util.Debug("HTTP Requested.")
HandleHttp(clientConn, ip, message) HandleHttp(clientConn, ip, message)
} }
}() }()

View File

@ -1,6 +1,10 @@
# SpoofDPI # SpoofDPI
currently alpha ███████ ██████ ██████ ██████ ███████ ██████ ██████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████ ██████ ██ ██ ██ ██ █████ ██ ██ ██████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████ ██ ██████ ██████ ██ ██████ ██ ██
## Run ## Run

BIN
spoof-dpi

Binary file not shown.

View File

@ -2,52 +2,12 @@ package util
import ( import (
"log" "log"
"net"
"strings" "strings"
"errors"
"github.com/babolivier/go-doh-client" "github.com/babolivier/go-doh-client"
"github.com/xvzc/SpoofDPI/config" "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) { func ExtractDomain(message *[]byte) (string) {
i := 0 i := 0
for ; i < len(*message); i++ { for ; i < len(*message); i++ {
@ -83,7 +43,7 @@ func DnsLookupOverHttps(dns string, domain string)(string, error) {
Class: doh.IN, Class: doh.IN,
} }
log.Println(domain) Debug(domain)
a, _, err := resolver.LookupA(domain) a, _, err := resolver.LookupA(domain)
if err != nil { if err != nil {
log.Println("Error looking up dns. ", err) log.Println("Error looking up dns. ", err)
@ -104,24 +64,11 @@ func ExtractMethod(message *[]byte) (string) {
} }
method := strings.TrimSpace(string((*message)[:i])) method := strings.TrimSpace(string((*message)[:i]))
log.Println(method) Debug(method)
return strings.ToUpper(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{}) { func Debug(v ...interface{}) {
if config.GetConfig().Debug == false { if config.GetConfig().Debug == false {
return return
@ -129,3 +76,11 @@ func Debug(v ...interface{}) {
log.Println(v...) log.Println(v...)
} }
func BytesToChunks(buf []byte) ([][]byte) {
if len(buf) < 1 {
return [][]byte{buf}
}
return [][]byte{buf[:1], buf[1:]}
}