SpoofDPI/proxy/handler/http.go
2024-09-03 16:16:15 +09:00

124 lines
2.9 KiB
Go

package handler
import (
"context"
"net"
"strconv"
"github.com/xvzc/SpoofDPI/packet"
"github.com/xvzc/SpoofDPI/util"
"github.com/xvzc/SpoofDPI/util/log"
)
type HttpHandler struct {
bufferSize int
protocol string
port int
timeout int
}
func NewHttpHandler(timeout int) *HttpHandler {
return &HttpHandler{
bufferSize: 1024,
protocol: "HTTP",
port: 80,
timeout: timeout,
}
}
func (h *HttpHandler) Serve(ctx context.Context, lConn *net.TCPConn, pkt *packet.HttpRequest, ip string) {
ctx = util.GetCtxWithScope(ctx, h.protocol)
logger := log.GetCtxLogger(ctx)
// Create a connection to the requested server
var port int = 80
var err error
if pkt.Port() != "" {
port, err = strconv.Atoi(pkt.Port())
if err != nil {
logger.Debug().Msgf("error while parsing port for %s aborting..", pkt.Domain())
}
}
rConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: net.ParseIP(ip), Port: port})
if err != nil {
lConn.Close()
logger.Debug().Msgf("%s", err)
return
}
logger.Debug().Msgf("new connection to the server %s -> %s", rConn.LocalAddr(), pkt.Domain())
go h.deliverResponse(ctx, rConn, lConn, pkt.Domain(), lConn.RemoteAddr().String())
go h.deliverRequest(ctx, lConn, rConn, lConn.RemoteAddr().String(), pkt.Domain())
_, err = rConn.Write(pkt.Raw())
if err != nil {
logger.Debug().Msgf("error sending request to %s: %s", pkt.Domain(), err)
return
}
}
func (h *HttpHandler) deliverRequest(ctx context.Context, from *net.TCPConn, to *net.TCPConn, fd string, td string) {
ctx = util.GetCtxWithScope(ctx, h.protocol)
logger := log.GetCtxLogger(ctx)
defer func() {
from.Close()
to.Close()
logger.Debug().Msgf("closing proxy connection: %s -> %s", fd, td)
}()
for {
err := setConnectionTimeout(from, h.timeout)
if err != nil {
logger.Debug().Msgf("error while setting connection deadline for %s: %s", fd, err)
}
pkt, err := packet.ReadHttpRequest(from)
if err != nil {
logger.Debug().Msgf("error reading from %s: %s", fd, err)
return
}
pkt.Tidy()
if _, err := to.Write(pkt.Raw()); err != nil {
logger.Debug().Msgf("error Writing to %s", td)
return
}
}
}
func (h *HttpHandler) deliverResponse(ctx context.Context, from *net.TCPConn, to *net.TCPConn, fd string, td string) {
ctx = util.GetCtxWithScope(ctx, h.protocol)
logger := log.GetCtxLogger(ctx)
defer func() {
from.Close()
to.Close()
logger.Debug().Msgf("closing proxy connection: %s -> %s", fd, td)
}()
buf := make([]byte, h.bufferSize)
for {
err := setConnectionTimeout(from, h.timeout)
if err != nil {
logger.Debug().Msgf("error while setting connection deadline for %s: %s", fd, err)
}
bytesRead, err := ReadBytes(ctx, from, buf)
if err != nil {
logger.Debug().Msgf("error reading from %s: %s", fd, err)
return
}
if _, err := to.Write(bytesRead); err != nil {
logger.Debug().Msgf("error Writing to %s", td)
return
}
}
}