diff --git a/modules/zerogod/zerogod_acceptor.go b/modules/zerogod/zerogod_acceptor.go index 09679cca..ccb956ef 100644 --- a/modules/zerogod/zerogod_acceptor.go +++ b/modules/zerogod/zerogod_acceptor.go @@ -25,7 +25,13 @@ var TCP_HANDLERS = map[string]Handler{ TLS: true, Handle: ippClientHandler, }, - // TODO: _http at least + "_http": { + Handle: httpClientHandler, + }, + "_https": { + TLS: true, + Handle: httpClientHandler, + }, } type Acceptor struct { @@ -42,6 +48,7 @@ type Acceptor struct { ctxCancel context.CancelFunc handler Handler ippAttributes map[string]string + httpPaths map[string]string } type HandlerContext struct { @@ -52,9 +59,10 @@ type HandlerContext struct { srvPort int srvTLS bool ippAttributes map[string]string + httpPaths map[string]string } -func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsConfig *tls.Config, ippAttributes map[string]string) *Acceptor { +func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsConfig *tls.Config, ippAttributes map[string]string, httpPaths map[string]string) *Acceptor { context, ctcCancel := context.WithCancel(context.Background()) proto := ops.Ternary(strings.Contains(service, "_tcp"), "tcp", "udp").(string) @@ -67,11 +75,14 @@ func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsC ctxCancel: ctcCancel, srvHost: srvHost, ippAttributes: ippAttributes, + httpPaths: httpPaths, } for svcName, svcHandler := range TCP_HANDLERS { if strings.Contains(service, svcName) { - acceptor.tlsConfig = tlsConfig + if svcHandler.TLS { + acceptor.tlsConfig = tlsConfig + } acceptor.handler = svcHandler break } @@ -81,7 +92,7 @@ func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsC mod.Warning("no protocol handler found for service %s, using generic %s dump handler", tui.Yellow(service), proto) acceptor.handler.Handle = handleGenericTCP } else { - mod.Info("found %s %s protocol handler", proto, tui.Green(service)) + mod.Info("found %s %s protocol handler (tls=%v)", proto, tui.Green(service), acceptor.tlsConfig != nil) } return &acceptor @@ -114,6 +125,7 @@ func (a *Acceptor) startTCP() (err error) { srvPort: int(a.port), srvTLS: a.tlsConfig != nil, ippAttributes: a.ippAttributes, + httpPaths: a.httpPaths, }) } } diff --git a/modules/zerogod/zerogod_advertise.go b/modules/zerogod/zerogod_advertise.go index 82eb9dd3..2b350173 100644 --- a/modules/zerogod/zerogod_advertise.go +++ b/modules/zerogod/zerogod_advertise.go @@ -172,7 +172,7 @@ func (mod *ZeroGod) startAdvertiser(fileName string) error { for _, svc := range advertiser.Services { // if no external responder has been specified if svc.Responder == "" { - acceptor := NewAcceptor(mod, svc.FullName(), hostName, uint16(svc.Port), tlsConfig, svc.IPP) + acceptor := NewAcceptor(mod, svc.FullName(), hostName, uint16(svc.Port), tlsConfig, svc.IPP, svc.HTTP) if err := acceptor.Start(); err != nil { return err } diff --git a/modules/zerogod/zerogod_http_handler.go b/modules/zerogod/zerogod_http_handler.go new file mode 100644 index 00000000..45ad0893 --- /dev/null +++ b/modules/zerogod/zerogod_http_handler.go @@ -0,0 +1,104 @@ +package zerogod + +import ( + "bufio" + "bytes" + "fmt" + "io" + "net/http" + "strings" + + "github.com/evilsocket/islazy/tui" +) + +func httpGenericHandler(ctx *HandlerContext) (shouldQuit bool, clientIP string, req *http.Request, err error) { + clientIP = strings.SplitN(ctx.client.RemoteAddr().String(), ":", 2)[0] + + buf := make([]byte, 4096) + // read raw request + read, err := ctx.client.Read(buf) + if err != nil { + if err == io.EOF { + ctx.mod.Debug("EOF, client %s disconnected", clientIP) + return true, clientIP, nil, nil + } + ctx.mod.Warning("error while reading from %v: %v", clientIP, err) + return true, clientIP, nil, err + } else if read == 0 { + ctx.mod.Warning("error while reading from %v: no data", clientIP) + return true, clientIP, nil, err + } + + raw_req := buf[0:read] + + ctx.mod.Debug("read %d bytes from %v:\n%s\n", read, clientIP, Dump(raw_req)) + + // parse as http + reader := bufio.NewReader(bytes.NewReader(raw_req)) + httpRequest, err := http.ReadRequest(reader) + if err != nil { + ctx.mod.Error("error while parsing http request from %v: %v\n%s", clientIP, err, Dump(raw_req)) + return true, clientIP, nil, err + } + + return false, clientIP, httpRequest, nil +} + +func httpLogRequest(ctx *HandlerContext, clientIP string, httpRequest *http.Request) { + clientUA := httpRequest.UserAgent() + ctx.mod.Info("%v (%s) > %s %s", + clientIP, + tui.Green(clientUA), + tui.Bold(httpRequest.Method), + tui.Yellow(httpRequest.RequestURI)) +} + +func httpClientHandler(ctx *HandlerContext) { + defer ctx.client.Close() + + shouldQuit, clientIP, httpRequest, err := httpGenericHandler(ctx) + if shouldQuit { + return + } else if err != nil { + ctx.mod.Error("%v", err) + } + + httpLogRequest(ctx, clientIP, httpRequest) + + respStatusCode := 404 + respStatus := "Not Found" + respBody := ` +