1
4
mirror of https://github.com/yunginnanet/HellPot synced 2024-06-24 23:08:03 +00:00

Continue: fasthttp implementation

This commit is contained in:
kayos@tcp.direct 2021-09-15 09:13:16 -07:00
parent 4f98911b65
commit 234be70893
6 changed files with 138 additions and 88 deletions

@ -1,6 +1,10 @@
package main
import (
"os"
"os/signal"
"syscall"
"github.com/rs/zerolog"
"github.com/yunginnanet/HellPot/config"
@ -17,9 +21,19 @@ func init() {
if config.Debug {
log.Debug().Msg("debug enabled")
}
log.Info().Str("config", config.Filename).Msg("initialization finished")
log.Info().Str("file", config.Filename).Msg("current config")
log.Info().Str("file", config.CurrentLogFile).Msg("current log")
}
func main() {
log.Error().Err(http.Serve()).Msg("HTTP err")
stopChan := make(chan os.Signal, 1)
signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
log.Error().Err(http.Serve()).Msg("HTTP err")
}()
<-stopChan // wait for SIGINT
log.Warn().Msg("Shutting down server...")
}

@ -16,6 +16,7 @@ const (
Title = "HellPot"
)
// "http"
var (
// BindAddr is defined via our toml configuration file. It is the address that HellPot listens on.
BindAddr string
@ -24,6 +25,21 @@ var (
// Paths are defined via our toml configuration file. These are the paths that HellPot will present for "robots.txt"
// These are also the paths that HellPot will respond for. Other paths will throw a warning and will serve a 404.
Paths []string
UseUnixSocket bool
UnixSocketPath = ""
)
// "performance"
var (
RestrictConcurrency bool
MaxWorkers int
)
// "diception"
var (
// FakeServerName is our configured value for the "Server: " response header when serving HTTP clients
FakeServerName string
)
var (
@ -124,7 +140,7 @@ func Init() {
func setDefaults() {
var (
configSections = []string{"logger", "http"}
configSections = []string{"logger", "http", "performance", "diception"}
deflogdir = home + "/.config/" + Title + "/logs/"
defNoColor = false
)
@ -141,13 +157,22 @@ func setDefaults() {
"use_date_filename": true,
}
Opt["http"] = map[string]interface{}{
"bind_addr": "127.0.0.1",
"bind_port": "8080",
"use_unix_socket": false,
"unix_socket": "/var/run/hellpot",
"bind_addr": "127.0.0.1",
"bind_port": "8080",
"paths": []string{
"wp-login.php",
"wp-login",
},
}
Opt["performance"] = map[string]interface{}{
"restrict_concurrency": false,
"max_workers": 256,
}
Opt["diception"] = map[string]interface{}{
"server_name": "nginx",
}
for _, def := range configSections {
snek.SetDefault(def, Opt[def])
@ -221,6 +246,14 @@ func associate() {
BindAddr = snek.GetString("http.bind_addr")
BindPort = snek.GetString("http.bind_port")
Paths = snek.GetStringSlice("http.paths")
UseUnixSocket = snek.GetBool("http.use_unix_socket")
FakeServerName = snek.GetString("diception.server_name")
RestrictConcurrency = snek.GetBool("performance.restrict_concurrency")
MaxWorkers = snek.GetInt("performance.max_workers")
if UseUnixSocket {
UnixSocketPath = snek.GetString("http.unix_socket_path")
}
if Debug {
zerolog.SetGlobalLevel(zerolog.DebugLevel)

@ -49,6 +49,12 @@ func (h *Heffalump) putBuffer(buf []byte) {
// WriteHell writes markov chain heffalump hell to the provided io.Writer
// https://github.com/carlmjohnson/heffalump
func (h *Heffalump) WriteHell(w io.Writer) int64 {
defer func() {
if r := recover(); r != nil {
log.Error().Interface("caller", r).Msg("panic recovered!")
}
}()
buf := h.getBuffer()
defer h.putBuffer(buf)

@ -1,81 +0,0 @@
package http
import (
"net"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"github.com/yunginnanet/HellPot/config"
)
var log = config.GetLogger()
func listenOnUnixSocket(addr string, srv *http.Server) error {
var err error
var unixAddr *net.UnixAddr
var unixListener *net.UnixListener
socketPath := strings.TrimPrefix(addr, "unix:")
unixAddr, err = net.ResolveUnixAddr("unix", socketPath)
if err == nil {
// Always unlink sockets before listening on them
_ = syscall.Unlink(socketPath)
unixListener, err = net.ListenUnix("unix", unixAddr)
if err == nil {
err = srv.Serve(unixListener)
}
}
return err
}
func listen() {
addr := config.BindAddr
port := config.BindPort
//listenOnUnixDomain := true
log.Info().Str("bind_addr", addr).Str("bind_port", port).
Msg("Listening and serving HTTP...")
/* if !strings.HasPrefix(addr, "unix:") {
listenOnUnixDomain = false
}
if listenOnUnixDomain {
err = listenOnUnixSocket(addr, srv)
} else {
err = srv.ListenAndServe()
}*/
// log.Warn().Err(err).Msg("HTTP_STOP")
}
func StartPot() {
// subscribe to SIGINT signals
stopChan := make(chan os.Signal, 1)
signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)
/*r := mux.NewRouter()
r.HandleFunc("/{path}", heffalump.DefaultHoneypot)
srv := &http.Server{Handler: r}
*/
go listen()
<-stopChan // wait for SIGINT
log.Warn().Msg("Shutting down server...")
/*
// shut down gracefully, but wait no longer than 5 seconds before halting
ctx, c := context.WithTimeout(context.Background(), 5*time.Second)
defer c()
if err := srv.Shutdown(ctx); err != nil {
log.Debug().Caller().Err(err)
}
log.Info().Msg("Server gracefully stopped")
*/
}

@ -23,5 +23,4 @@ func robotsTXT(ctx *fasthttp.RequestCtx) {
if _, err := fmt.Fprintf(ctx, robotsTxt+paths+"\r\n"); err != nil {
log.Error().Err(err).Msg("SERVE_ROBOTS_ERROR")
}
return
}

@ -1,15 +1,21 @@
package http
import (
"fmt"
"net"
"syscall"
"time"
"github.com/fasthttp/router"
"github.com/rs/zerolog"
"github.com/valyala/fasthttp"
"github.com/yunginnanet/HellPot/config"
"github.com/yunginnanet/HellPot/heffalump"
)
var log zerolog.Logger
func getRealRemote(ctx *fasthttp.RequestCtx) string {
xrealip := string(ctx.Request.Header.Peek("X-Real-IP"))
if len(xrealip) > 0 {
@ -53,10 +59,83 @@ func scopeCheck(ctx *fasthttp.RequestCtx) {
}
func listenOnUnixSocket(addr string, r *router.Router) error {
var err error
var unixAddr *net.UnixAddr
var unixListener *net.UnixListener
unixAddr, err = net.ResolveUnixAddr("unix", addr)
if err == nil {
// Always unlink sockets before listening on them
if err2 := syscall.Unlink(addr); err2 != nil {
panic(err2)
}
unixListener, err = net.ListenUnix("unix", unixAddr)
if err == nil {
err = fasthttp.Serve(unixListener, r.Handler)
}
}
return err
}
// Serve starts our HTTP server and request router
func Serve() error {
log = config.GetLogger()
l := fmt.Sprintf("%s:%s", config.BindAddr, config.BindPort)
r := router.New()
r.GET("/robots.txt", robotsTXT)
r.GET("/{path}", scopeCheck)
return fasthttp.ListenAndServe(":8080", r.Handler)
if !config.RestrictConcurrency {
config.MaxWorkers = fasthttp.DefaultConcurrency
}
srv := fasthttp.Server{
// User defined server name
// Likely not useful if behind a reverse proxy without additional configuration of the proxy server.
Name: config.FakeServerName,
/*
from fasthttp docs: "By default request read timeout is unlimited."
My thinking here is avoiding some sort of weird oversized GET query just in case.
*/
ReadTimeout: 5 * time.Second,
MaxRequestBodySize: 1 * 1024 * 1024,
// Help curb abuse of HellPot (we've always needed this badly)
MaxConnsPerIP: 1,
MaxRequestsPerConn: 2,
Concurrency: config.MaxWorkers,
// only accept GET requests
GetOnly: true,
// we don't care if a request ends up being handled by a different handler
// it shouldn't for now, but this may prevent future bugs
KeepHijackedConns: true,
CloseOnShutdown: true,
// No need to keepalive, our response is a sort of keep-alive ;)
DisableKeepalive: true,
Handler: r.Handler,
}
if !config.UseUnixSocket {
log.Info().Str("caller", l).Msg("Listening and serving HTTP...")
return srv.ListenAndServe(l)
}
if len(config.UnixSocketPath) < 1 {
log.Fatal().Msg("unix_socket_path configuration directive appears to be empty")
}
log.Info().Str("caller", config.UnixSocketPath).Msg("Listening and serving HTTP...")
return listenOnUnixSocket(config.UnixSocketPath, r)
}