mirror of
https://github.com/xvzc/SpoofDPI.git
synced 2025-01-03 04:50:11 +00:00
refactor
This commit is contained in:
parent
83326a0a66
commit
2d8b9103db
@ -15,7 +15,7 @@ func main() {
|
||||
util.ParseArgs()
|
||||
config := util.GetConfig()
|
||||
|
||||
p := proxy.New(config)
|
||||
pxy := proxy.New(config)
|
||||
if *config.Debug {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
} else {
|
||||
@ -36,7 +36,7 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
go p.Start()
|
||||
go pxy.Start()
|
||||
|
||||
// Handle signals
|
||||
sigs := make(chan os.Signal, 1)
|
||||
|
112
net/conn.go
112
net/conn.go
@ -7,8 +7,6 @@ import (
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/xvzc/SpoofDPI/dns"
|
||||
"github.com/xvzc/SpoofDPI/packet"
|
||||
)
|
||||
|
||||
const BUF_SIZE = 1024
|
||||
@ -59,116 +57,6 @@ func (conn *Conn) ReadBytes() ([]byte, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (lConn *Conn) HandleHttp(p *packet.HttpPacket, timeout int, resolver *dns.DnsResolver) {
|
||||
p.Tidy()
|
||||
|
||||
ip, err := resolver.Lookup(p.Domain())
|
||||
if err != nil {
|
||||
log.Error("[HTTP] Error looking up for domain with ", p.Domain(), " ", err)
|
||||
lConn.Write([]byte(p.Version() + " 502 Bad Gateway\r\n\r\n"))
|
||||
return
|
||||
}
|
||||
|
||||
// Create connection to server
|
||||
var port = "80"
|
||||
if p.Port() != "" {
|
||||
port = p.Port()
|
||||
}
|
||||
|
||||
rConn, err := DialTCP("tcp", ip, port)
|
||||
if err != nil {
|
||||
log.Debug("[HTTP] ", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
lConn.Close()
|
||||
log.Debug("[HTTP] Closing client Connection.. ", lConn.RemoteAddr())
|
||||
|
||||
rConn.Close()
|
||||
log.Debug("[HTTP] Closing server Connection.. ", p.Domain(), " ", rConn.LocalAddr())
|
||||
}()
|
||||
|
||||
log.Debug("[HTTP] New connection to the server ", p.Domain(), " ", rConn.LocalAddr())
|
||||
|
||||
go rConn.Serve(lConn, "[HTTP]", lConn.RemoteAddr().String(), p.Domain(), timeout)
|
||||
|
||||
_, err = rConn.Write(p.Raw())
|
||||
if err != nil {
|
||||
log.Debug("[HTTP] Error sending request to ", p.Domain(), err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("[HTTP] Sent a request to ", p.Domain())
|
||||
|
||||
lConn.Serve(rConn, "[HTTP]", lConn.RemoteAddr().String(), p.Domain(), timeout)
|
||||
|
||||
}
|
||||
|
||||
func (lConn *Conn) HandleHttps(p *packet.HttpPacket, timeout int, resolver *dns.DnsResolver) {
|
||||
ip, err := resolver.Lookup(p.Domain())
|
||||
|
||||
if err != nil {
|
||||
log.Error("[HTTPS] Error looking up for domain: ", p.Domain(), " ", err)
|
||||
lConn.Write([]byte(p.Version() + " 502 Bad Gateway\r\n\r\n"))
|
||||
return
|
||||
}
|
||||
|
||||
// Create a connection to the requested server
|
||||
var port = "443"
|
||||
if p.Port() != "" {
|
||||
port = p.Port()
|
||||
}
|
||||
|
||||
rConn, err := DialTCP("tcp4", ip, port)
|
||||
if err != nil {
|
||||
log.Debug("[HTTPS] ", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
lConn.Close()
|
||||
log.Debug("[HTTPS] Closing client Connection.. ", lConn.RemoteAddr())
|
||||
|
||||
rConn.Close()
|
||||
log.Debug("[HTTPS] Closing server Connection.. ", p.Domain(), " ", rConn.LocalAddr())
|
||||
}()
|
||||
|
||||
log.Debug("[HTTPS] New connection to the server ", p.Domain(), " ", rConn.LocalAddr())
|
||||
|
||||
_, err = lConn.Write([]byte(p.Version() + " 200 Connection Established\r\n\r\n"))
|
||||
if err != nil {
|
||||
log.Debug("[HTTPS] Error sending 200 Connection Established to the client", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("[HTTPS] Sent 200 Connection Estabalished to ", lConn.RemoteAddr())
|
||||
|
||||
// Read client hello
|
||||
clientHello, err := lConn.ReadBytes()
|
||||
if err != nil {
|
||||
log.Debug("[HTTPS] Error reading client hello from the client", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("[HTTPS] Client sent hello ", len(clientHello), "bytes")
|
||||
|
||||
// Generate a go routine that reads from the server
|
||||
|
||||
pkt := packet.NewHttpsPacket(clientHello)
|
||||
|
||||
chunks := pkt.SplitInChunks()
|
||||
|
||||
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(), timeout)
|
||||
}
|
||||
|
||||
func (from *Conn) Serve(to *Conn, proto string, fd string, td string, timeout int) {
|
||||
proto += " "
|
||||
|
||||
|
@ -1,9 +1,5 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"github.com/xvzc/SpoofDPI/util"
|
||||
)
|
||||
|
||||
type HttpsPacket struct {
|
||||
raw []byte
|
||||
}
|
||||
@ -17,21 +13,3 @@ func NewHttpsPacket(raw []byte) HttpsPacket {
|
||||
func (p *HttpsPacket) Raw() []byte {
|
||||
return p.raw
|
||||
}
|
||||
|
||||
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 config.PatternExists() {
|
||||
if (config.PatternMatches(p.Raw())) {
|
||||
return [][]byte{(p.Raw())[:1], (p.Raw())[1:]}
|
||||
}
|
||||
|
||||
return [][]byte{p.Raw()}
|
||||
}
|
||||
|
||||
return [][]byte{(p.Raw())[:1], (p.Raw())[1:]}
|
||||
}
|
||||
|
46
proxy/http.go
Normal file
46
proxy/http.go
Normal file
@ -0,0 +1,46 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/xvzc/SpoofDPI/net"
|
||||
"github.com/xvzc/SpoofDPI/packet"
|
||||
)
|
||||
|
||||
func (pxy *Proxy) HandleHttp(lConn *net.Conn, pkt *packet.HttpPacket, ip string) {
|
||||
pkt.Tidy()
|
||||
|
||||
// Create connection to server
|
||||
var port = "80"
|
||||
if pkt.Port() != "" {
|
||||
port = pkt.Port()
|
||||
}
|
||||
|
||||
rConn, err := net.DialTCP("tcp", ip, port)
|
||||
if err != nil {
|
||||
lConn.Close()
|
||||
log.Debug("[HTTP] ", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
lConn.Close()
|
||||
log.Debug("[HTTP] Closing client Connection.. ", lConn.RemoteAddr())
|
||||
|
||||
rConn.Close()
|
||||
log.Debug("[HTTP] Closing server Connection.. ", pkt.Domain(), " ", rConn.LocalAddr())
|
||||
}()
|
||||
|
||||
log.Debug("[HTTP] New connection to the server ", pkt.Domain(), " ", rConn.LocalAddr())
|
||||
|
||||
go rConn.Serve(lConn, "[HTTP]", lConn.RemoteAddr().String(), pkt.Domain(), pxy.timeout)
|
||||
|
||||
_, err = rConn.Write(pkt.Raw())
|
||||
if err != nil {
|
||||
log.Debug("[HTTP] Error sending request to ", pkt.Domain(), err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("[HTTP] Sent a request to ", pkt.Domain())
|
||||
|
||||
lConn.Serve(rConn, "[HTTP]", lConn.RemoteAddr().String(), pkt.Domain(), pxy.timeout)
|
||||
}
|
106
proxy/https.go
Normal file
106
proxy/https.go
Normal file
@ -0,0 +1,106 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/xvzc/SpoofDPI/net"
|
||||
"github.com/xvzc/SpoofDPI/packet"
|
||||
)
|
||||
|
||||
func (pxy *Proxy) HandleHttps(lConn *net.Conn, initPkt *packet.HttpPacket, ip string) {
|
||||
// Create a connection to the requested server
|
||||
var port = "443"
|
||||
if initPkt.Port() != "" {
|
||||
port = initPkt.Port()
|
||||
}
|
||||
|
||||
rConn, err := net.DialTCP("tcp4", ip, port)
|
||||
if err != nil {
|
||||
lConn.Close()
|
||||
log.Debug("[HTTPS] ", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
lConn.Close()
|
||||
log.Debug("[HTTPS] Closing client Connection.. ", lConn.RemoteAddr())
|
||||
|
||||
rConn.Close()
|
||||
log.Debug("[HTTPS] Closing server Connection.. ", initPkt.Domain(), " ", rConn.LocalAddr())
|
||||
}()
|
||||
|
||||
log.Debug("[HTTPS] New connection to the server ", initPkt.Domain(), " ", rConn.LocalAddr())
|
||||
|
||||
_, err = lConn.Write([]byte(initPkt.Version() + " 200 Connection Established\r\n\r\n"))
|
||||
if err != nil {
|
||||
log.Debug("[HTTPS] Error sending 200 Connection Established to the client", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("[HTTPS] Sent 200 Connection Estabalished to ", lConn.RemoteAddr())
|
||||
|
||||
// Read client hello
|
||||
clientHello, err := lConn.ReadBytes()
|
||||
if err != nil {
|
||||
log.Debug("[HTTPS] Error reading client hello from the client", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("[HTTPS] Client sent hello ", len(clientHello), "bytes")
|
||||
|
||||
// Generate a go routine that reads from the server
|
||||
|
||||
chPkt := packet.NewHttpsPacket(clientHello)
|
||||
|
||||
go rConn.Serve(lConn, "[HTTPS]", rConn.RemoteAddr().String(), initPkt.Domain(), pxy.timeout)
|
||||
|
||||
if pxy.patternExists() && !pxy.patternMatches([]byte(initPkt.Domain())) {
|
||||
if _, err := rConn.Write(chPkt.Raw()); err != nil {
|
||||
log.Debug("[HTTPS] Error writing client hello to ", initPkt.Domain(), err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
chunks := pxy.splitInChunks(chPkt.Raw(), pxy.windowSize)
|
||||
if _, err := rConn.WriteChunks(chunks); err != nil {
|
||||
log.Debug("[HTTPS] Error writing client hello to ", initPkt.Domain(), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
lConn.Serve(rConn, "[HTTPS]", lConn.RemoteAddr().String(), initPkt.Domain(), pxy.timeout)
|
||||
}
|
||||
|
||||
func (pxy *Proxy) splitInChunks(bytes []byte, size int) [][]byte {
|
||||
// If the packet matches the pattern or the URLs, we don't split it
|
||||
if pxy.patternExists() && !pxy.patternMatches(bytes) {
|
||||
return [][]byte{bytes}
|
||||
}
|
||||
|
||||
var chunks [][]byte
|
||||
var raw []byte = bytes
|
||||
|
||||
for {
|
||||
if len(raw) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// necessary check to avoid slicing beyond
|
||||
// slice capacity
|
||||
if len(raw) < size {
|
||||
size = len(raw)
|
||||
}
|
||||
|
||||
chunks = append(chunks, raw[0:size])
|
||||
raw = raw[size:]
|
||||
}
|
||||
|
||||
return chunks
|
||||
}
|
||||
|
||||
func (pxy *Proxy) patternExists() bool {
|
||||
return pxy.allowedPattern != nil || pxy.allowedUrls != nil
|
||||
}
|
||||
|
||||
func (p *Proxy) patternMatches(bytes []byte) bool {
|
||||
return (p.allowedPattern != nil && p.allowedPattern.Match(bytes)) ||
|
||||
(p.allowedUrls != nil && p.allowedUrls.Match(bytes))
|
||||
}
|
@ -3,6 +3,7 @@ package proxy
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/xvzc/SpoofDPI/dns"
|
||||
@ -16,6 +17,9 @@ type Proxy struct {
|
||||
port int
|
||||
timeout int
|
||||
resolver *dns.DnsResolver
|
||||
windowSize int
|
||||
allowedPattern *regexp.Regexp
|
||||
allowedUrls *regexp.Regexp
|
||||
}
|
||||
|
||||
func New(config *util.Config) *Proxy {
|
||||
@ -23,28 +27,31 @@ func New(config *util.Config) *Proxy {
|
||||
addr: *config.Addr,
|
||||
port: *config.Port,
|
||||
timeout: *config.Timeout,
|
||||
windowSize: *config.WindowSize,
|
||||
allowedPattern: config.AllowedPattern,
|
||||
allowedUrls: config.AllowedUrls,
|
||||
resolver: dns.NewResolver(config),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) TcpAddr() *net.TCPAddr {
|
||||
return net.TcpAddr(p.addr, p.port)
|
||||
func (pxy *Proxy) TcpAddr() *net.TCPAddr {
|
||||
return net.TcpAddr(pxy.addr, pxy.port)
|
||||
}
|
||||
|
||||
func (p *Proxy) Port() int {
|
||||
return p.port
|
||||
func (pxy *Proxy) Port() int {
|
||||
return pxy.port
|
||||
}
|
||||
|
||||
func (p *Proxy) Start() {
|
||||
l, err := net.ListenTCP("tcp4", p.TcpAddr())
|
||||
func (pxy *Proxy) Start() {
|
||||
l, err := net.ListenTCP("tcp4", pxy.TcpAddr())
|
||||
if err != nil {
|
||||
log.Fatal("Error creating listener: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
log.Println(fmt.Sprintf("Connection timeout is set to %dms", p.timeout))
|
||||
log.Println(fmt.Sprintf("Connection timeout is set to %dms", pxy.timeout))
|
||||
|
||||
log.Println("Created a listener on port", p.Port())
|
||||
log.Println("Created a listener on port", pxy.Port())
|
||||
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
@ -64,20 +71,30 @@ func (p *Proxy) Start() {
|
||||
pkt, err := packet.NewHttpPacket(b)
|
||||
if err != nil {
|
||||
log.Debug("Error while parsing request: ", string(b))
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
if !pkt.IsValidMethod() {
|
||||
log.Debug("Unsupported method: ", pkt.Method())
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
ip, err := pxy.resolver.Lookup(pkt.Domain())
|
||||
if err != nil {
|
||||
log.Error("[HTTP] Error looking up for domain with ", pkt.Domain(), " ", err)
|
||||
conn.Write([]byte(pkt.Version() + " 502 Bad Gateway\r\n\r\n"))
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
if pkt.IsConnectMethod() {
|
||||
log.Debug("[HTTPS] Start")
|
||||
conn.HandleHttps(pkt, p.timeout, p.resolver)
|
||||
pxy.HandleHttps(conn, pkt, ip)
|
||||
} else {
|
||||
log.Debug("[HTTP] Start")
|
||||
conn.HandleHttp(pkt, p.timeout, p.resolver)
|
||||
pxy.HandleHttp(conn, pkt, ip)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ type Config struct {
|
||||
Timeout *int
|
||||
AllowedPattern *regexp.Regexp
|
||||
AllowedUrls *regexp.Regexp
|
||||
WindowSize *int
|
||||
}
|
||||
|
||||
type ArrayFlags []string
|
||||
@ -43,15 +44,6 @@ 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")
|
||||
@ -62,6 +54,7 @@ func ParseArgs() {
|
||||
config.Debug = flag.Bool("debug", false, "Enable debug output")
|
||||
config.NoBanner = flag.Bool("no-banner", false, "Disable banner")
|
||||
config.Timeout = flag.Int("timeout", 2000, "timeout in milliseconds")
|
||||
config.WindowSize = flag.Int("window-size", 50, "window-size for fragmented client hello")
|
||||
|
||||
flag.Var(&allowedHosts, "url", "Bypass DPI only on this url, can be passed multiple times")
|
||||
allowedPattern = flag.String(
|
||||
|
Loading…
Reference in New Issue
Block a user