mirror of
https://github.com/xvzc/SpoofDPI.git
synced 2024-12-22 14:26:31 +00:00
Remove net package and refactor
This commit is contained in:
parent
2d8b9103db
commit
ed70bde7e7
@ -11,9 +11,16 @@ import (
|
||||
"github.com/xvzc/SpoofDPI/util"
|
||||
)
|
||||
|
||||
var VERSION = "v0.0.0(dev)"
|
||||
func main() {
|
||||
util.ParseArgs()
|
||||
config := util.GetConfig()
|
||||
config := util.GetConfig()
|
||||
if *config.Version {
|
||||
println("spoog-dpi", VERSION)
|
||||
println("\nA simple and fast anti-censorship tool written in Go.")
|
||||
println("https://github.com/xvzc/SpoofDPI")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
pxy := proxy.New(config)
|
||||
if *config.Debug {
|
||||
|
31
net/dial.go
31
net/dial.go
@ -1,31 +0,0 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func ListenTCP(network string, addr *TCPAddr) (Listener, error) {
|
||||
l, err := net.ListenTCP(network, addr.Addr)
|
||||
if err != nil {
|
||||
return Listener{}, err
|
||||
}
|
||||
|
||||
return Listener{listener: l}, nil
|
||||
}
|
||||
|
||||
func DialTCP(network string, ip string, port string) (*Conn, error) {
|
||||
p, _ := strconv.Atoi(port)
|
||||
|
||||
addr := &net.TCPAddr{
|
||||
IP: net.ParseIP(ip),
|
||||
Port: p,
|
||||
}
|
||||
|
||||
conn, err := net.DialTCP(network, nil, addr)
|
||||
if err != nil {
|
||||
return &Conn{}, err
|
||||
}
|
||||
|
||||
return &Conn{*conn}, nil
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
type Listener struct {
|
||||
listener *net.TCPListener
|
||||
}
|
||||
|
||||
func (l *Listener) Accept() (*Conn, error) {
|
||||
conn, err := l.listener.AcceptTCP()
|
||||
if err != nil {
|
||||
return &Conn{}, err
|
||||
}
|
||||
|
||||
return &Conn{*conn}, nil
|
||||
}
|
20
net/tcp.go
20
net/tcp.go
@ -1,20 +0,0 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
type TCPAddr struct {
|
||||
Addr *net.TCPAddr
|
||||
}
|
||||
|
||||
func TcpAddr(ip string, port int) *TCPAddr {
|
||||
addr := &net.TCPAddr{
|
||||
IP: net.ParseIP(ip),
|
||||
Port: port,
|
||||
}
|
||||
|
||||
return &TCPAddr{
|
||||
Addr: addr,
|
||||
}
|
||||
}
|
@ -1,23 +1,30 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
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) {
|
||||
func (pxy *Proxy) HandleHttp(lConn *net.TCPConn, pkt *packet.HttpPacket, ip string) {
|
||||
pkt.Tidy()
|
||||
|
||||
// Create connection to server
|
||||
var port = "80"
|
||||
// Create a connection to the requested server
|
||||
var port int = 80
|
||||
var err error
|
||||
if pkt.Port() != "" {
|
||||
port = pkt.Port()
|
||||
port, err = strconv.Atoi(pkt.Port())
|
||||
if err != nil {
|
||||
log.Debug("[HTTPS] Error while parsing port for ", pkt.Domain(), " aborting..")
|
||||
}
|
||||
}
|
||||
|
||||
rConn, err := net.DialTCP("tcp", ip, port)
|
||||
rConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: net.ParseIP(ip), Port: port})
|
||||
if err != nil {
|
||||
lConn.Close()
|
||||
lConn.Close()
|
||||
log.Debug("[HTTP] ", err)
|
||||
return
|
||||
}
|
||||
@ -32,7 +39,7 @@ func (pxy *Proxy) HandleHttp(lConn *net.Conn, pkt *packet.HttpPacket, ip string)
|
||||
|
||||
log.Debug("[HTTP] New connection to the server ", pkt.Domain(), " ", rConn.LocalAddr())
|
||||
|
||||
go rConn.Serve(lConn, "[HTTP]", lConn.RemoteAddr().String(), pkt.Domain(), pxy.timeout)
|
||||
go Serve(rConn, lConn, "[HTTP]", lConn.RemoteAddr().String(), pkt.Domain(), pxy.timeout)
|
||||
|
||||
_, err = rConn.Write(pkt.Raw())
|
||||
if err != nil {
|
||||
@ -42,5 +49,5 @@ func (pxy *Proxy) HandleHttp(lConn *net.Conn, pkt *packet.HttpPacket, ip string)
|
||||
|
||||
log.Debug("[HTTP] Sent a request to ", pkt.Domain())
|
||||
|
||||
lConn.Serve(rConn, "[HTTP]", lConn.RemoteAddr().String(), pkt.Domain(), pxy.timeout)
|
||||
Serve(lConn, rConn, "[HTTP]", lConn.RemoteAddr().String(), pkt.Domain(), pxy.timeout)
|
||||
}
|
||||
|
@ -1,21 +1,27 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
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) {
|
||||
func (pxy *Proxy) HandleHttps(lConn *net.TCPConn, initPkt *packet.HttpPacket, ip string) {
|
||||
// Create a connection to the requested server
|
||||
var port = "443"
|
||||
var port int = 443
|
||||
var err error
|
||||
if initPkt.Port() != "" {
|
||||
port = initPkt.Port()
|
||||
port, err = strconv.Atoi(initPkt.Port())
|
||||
if err != nil {
|
||||
log.Debug("[HTTPS] Error while parsing port for ", initPkt.Domain(), " aborting..")
|
||||
}
|
||||
}
|
||||
|
||||
rConn, err := net.DialTCP("tcp4", ip, port)
|
||||
rConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: net.ParseIP(ip), Port: port})
|
||||
if err != nil {
|
||||
lConn.Close()
|
||||
lConn.Close()
|
||||
log.Debug("[HTTPS] ", err)
|
||||
return
|
||||
}
|
||||
@ -39,7 +45,7 @@ func (pxy *Proxy) HandleHttps(lConn *net.Conn, initPkt *packet.HttpPacket, ip st
|
||||
log.Debug("[HTTPS] Sent 200 Connection Estabalished to ", lConn.RemoteAddr())
|
||||
|
||||
// Read client hello
|
||||
clientHello, err := lConn.ReadBytes()
|
||||
clientHello, err := ReadBytes(lConn)
|
||||
if err != nil {
|
||||
log.Debug("[HTTPS] Error reading client hello from the client", err)
|
||||
return
|
||||
@ -51,22 +57,27 @@ func (pxy *Proxy) HandleHttps(lConn *net.Conn, initPkt *packet.HttpPacket, ip st
|
||||
|
||||
chPkt := packet.NewHttpsPacket(clientHello)
|
||||
|
||||
go rConn.Serve(lConn, "[HTTPS]", rConn.RemoteAddr().String(), initPkt.Domain(), pxy.timeout)
|
||||
lConn.SetLinger(3)
|
||||
rConn.SetLinger(3)
|
||||
|
||||
go Serve(rConn, 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
|
||||
}
|
||||
log.Debug("[HTTPS] Writing plain client hello to ", initPkt.Domain())
|
||||
if _, err := rConn.Write(chPkt.Raw()); err != nil {
|
||||
log.Debug("[HTTPS] Error writing plain 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
|
||||
}
|
||||
}
|
||||
log.Debug("[HTTPS] Writing chunked client hello to ", initPkt.Domain())
|
||||
chunks := pxy.splitInChunks(chPkt.Raw(), pxy.windowSize)
|
||||
if _, err := WriteChunks(rConn, chunks); err != nil {
|
||||
log.Debug("[HTTPS] Error writing chunked client hello to ", initPkt.Domain(), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
lConn.Serve(rConn, "[HTTPS]", lConn.RemoteAddr().String(), initPkt.Domain(), pxy.timeout)
|
||||
Serve(lConn, rConn, "[HTTPS]", lConn.RemoteAddr().String(), initPkt.Domain(), pxy.timeout)
|
||||
}
|
||||
|
||||
func (pxy *Proxy) splitInChunks(bytes []byte, size int) [][]byte {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -11,11 +11,7 @@ import (
|
||||
|
||||
const BUF_SIZE = 1024
|
||||
|
||||
type Conn struct {
|
||||
net.TCPConn
|
||||
}
|
||||
|
||||
func (conn *Conn) WriteChunks(c [][]byte) (n int, err error) {
|
||||
func WriteChunks(conn *net.TCPConn, c [][]byte) (n int, err error) {
|
||||
total := 0
|
||||
for i := 0; i < len(c); i++ {
|
||||
b, err := conn.Write(c[i])
|
||||
@ -29,7 +25,7 @@ func (conn *Conn) WriteChunks(c [][]byte) (n int, err error) {
|
||||
return total, nil
|
||||
}
|
||||
|
||||
func (conn *Conn) ReadBytes() ([]byte, error) {
|
||||
func ReadBytes(conn *net.TCPConn) ([]byte, error) {
|
||||
ret := make([]byte, 0)
|
||||
buf := make([]byte, BUF_SIZE)
|
||||
|
||||
@ -57,15 +53,15 @@ func (conn *Conn) ReadBytes() ([]byte, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (from *Conn) Serve(to *Conn, proto string, fd string, td string, timeout int) {
|
||||
func Serve(from *net.TCPConn, to *net.TCPConn, proto string, fd string, td string, timeout int) {
|
||||
proto += " "
|
||||
|
||||
for {
|
||||
from.SetReadDeadline(
|
||||
time.Now().Add(time.Millisecond * time.Duration(timeout)),
|
||||
)
|
||||
from.SetReadDeadline(
|
||||
time.Now().Add(time.Millisecond * time.Duration(timeout)),
|
||||
)
|
||||
|
||||
buf, err := from.ReadBytes()
|
||||
buf, err := ReadBytes(from)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
log.Debug(proto, "Finished ", fd)
|
@ -2,12 +2,13 @@ package proxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/xvzc/SpoofDPI/dns"
|
||||
"github.com/xvzc/SpoofDPI/net"
|
||||
"github.com/xvzc/SpoofDPI/packet"
|
||||
"github.com/xvzc/SpoofDPI/util"
|
||||
)
|
||||
@ -34,34 +35,26 @@ func New(config *util.Config) *Proxy {
|
||||
}
|
||||
}
|
||||
|
||||
func (pxy *Proxy) TcpAddr() *net.TCPAddr {
|
||||
return net.TcpAddr(pxy.addr, pxy.port)
|
||||
}
|
||||
|
||||
func (pxy *Proxy) Port() int {
|
||||
return pxy.port
|
||||
}
|
||||
|
||||
func (pxy *Proxy) Start() {
|
||||
l, err := net.ListenTCP("tcp4", pxy.TcpAddr())
|
||||
l, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.ParseIP(pxy.addr), Port: pxy.port})
|
||||
if err != nil {
|
||||
log.Fatal("Error creating listener: ", err)
|
||||
log.Fatal("[PROXY] Error creating listener: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
log.Println(fmt.Sprintf("Connection timeout is set to %dms", pxy.timeout))
|
||||
log.Println(fmt.Sprintf("[PROXY] Connection timeout is set to %dms", pxy.timeout))
|
||||
|
||||
log.Println("Created a listener on port", pxy.Port())
|
||||
log.Println("[PROXY] Created a listener on port", pxy.port)
|
||||
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Fatal("Error accepting connection: ", err)
|
||||
log.Fatal("[PROXY] Error accepting connection: ", err)
|
||||
continue
|
||||
}
|
||||
|
||||
go func() {
|
||||
b, err := conn.ReadBytes()
|
||||
b, err := ReadBytes(conn.(*net.TCPConn))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -70,32 +63,68 @@ func (pxy *Proxy) Start() {
|
||||
|
||||
pkt, err := packet.NewHttpPacket(b)
|
||||
if err != nil {
|
||||
log.Debug("Error while parsing request: ", string(b))
|
||||
conn.Close()
|
||||
log.Debug("[PROXY] Error while parsing request: ", string(b))
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
if !pkt.IsValidMethod() {
|
||||
log.Debug("Unsupported method: ", pkt.Method())
|
||||
conn.Close()
|
||||
log.Debug("[PROXY] 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)
|
||||
log.Error("[PROXY] Error looking up for domain with ", pkt.Domain(), " ", err)
|
||||
conn.Write([]byte(pkt.Version() + " 502 Bad Gateway\r\n\r\n"))
|
||||
conn.Close()
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// Avoid recursively querying self
|
||||
if pkt.Port() == strconv.Itoa(pxy.port) && isLoopedRequest(net.ParseIP(ip)) {
|
||||
log.Error("[HTTP] Invalid request: final target has the same IP and port as our proxy")
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
if pkt.IsConnectMethod() {
|
||||
log.Debug("[HTTPS] Start")
|
||||
pxy.HandleHttps(conn, pkt, ip)
|
||||
log.Debug("[PROXY] Start HTTPS")
|
||||
pxy.HandleHttps(conn.(*net.TCPConn), pkt, ip)
|
||||
} else {
|
||||
log.Debug("[HTTP] Start")
|
||||
pxy.HandleHttp(conn, pkt, ip)
|
||||
log.Debug("[PROXY] Start HTTP")
|
||||
pxy.HandleHttp(conn.(*net.TCPConn), pkt, ip)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func isLoopedRequest(ip net.IP) bool {
|
||||
// we don't handle IPv6 at all it seems
|
||||
if ip.To4() == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if ip.IsLoopback() {
|
||||
return true
|
||||
}
|
||||
|
||||
// Get list of available addresses
|
||||
// See `ip -4 addr show`
|
||||
addr, err := net.InterfaceAddrs() // needs AF_NETLINK on linux
|
||||
if err != nil {
|
||||
log.Error("[PROXY] Error while getting addresses of our network interfaces: ", err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, addr := range addr {
|
||||
if ipnet, ok := addr.(*net.IPNet); ok {
|
||||
if ipnet.IP.To4() != nil && ipnet.IP.To4().Equal(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ type Config struct {
|
||||
AllowedPattern *regexp.Regexp
|
||||
AllowedUrls *regexp.Regexp
|
||||
WindowSize *int
|
||||
Version *bool
|
||||
}
|
||||
|
||||
type ArrayFlags []string
|
||||
@ -55,6 +56,7 @@ func ParseArgs() {
|
||||
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")
|
||||
config.Version = flag.Bool("v", false, "print version")
|
||||
|
||||
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