-
Notifications
You must be signed in to change notification settings - Fork 38
/
router.go
156 lines (122 loc) · 3.49 KB
/
router.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package http
import (
"bufio"
"fmt"
"net/http"
"runtime"
"strings"
"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 {
return xrealip
}
return ctx.RemoteIP().String()
}
func hellPot(ctx *fasthttp.RequestCtx) {
path, pok := ctx.UserValue("path").(string)
if len(path) < 1 || !pok {
path = "/"
}
remoteAddr := getRealRemote(ctx)
slog := log.With().
Str("USERAGENT", string(ctx.UserAgent())).
Str("REMOTE_ADDR", remoteAddr).
Interface("URL", string(ctx.RequestURI())).Logger()
for _, denied := range config.UseragentBlacklistMatchers {
if strings.Contains(string(ctx.UserAgent()), denied) {
slog.Trace().Msg("Ignoring useragent")
ctx.Error("Not found", http.StatusNotFound)
return
}
}
if config.Trace {
slog = slog.With().Str("caller", path).Logger()
}
slog.Info().Msg("NEW")
s := time.Now()
var n int64
ctx.SetBodyStreamWriter(func(bw *bufio.Writer) {
var err error
var wn int64
for {
wn, err = heffalump.DefaultHeffalump.WriteHell(bw)
n += wn
if err != nil {
slog.Trace().Err(err).Msg("END_ON_ERR")
break
}
}
slog.Info().
Int64("BYTES", n).
Dur("DURATION", time.Since(s)).
Msg("FINISH")
})
}
func getSrv(r *router.Router) fasthttp.Server {
if !config.RestrictConcurrency {
config.MaxWorkers = fasthttp.DefaultConcurrency
}
log = config.GetLogger()
return 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: 10,
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 (in fact it probably will)
KeepHijackedConns: true,
CloseOnShutdown: true,
// No need to keepalive, our response is a sort of keep-alive ;)
DisableKeepalive: true,
Handler: r.Handler,
Logger: log,
}
}
// Serve starts our HTTP server and request router
func Serve() error {
log = config.GetLogger()
l := config.HTTPBind + ":" + config.HTTPPort
r := router.New()
if config.MakeRobots && !config.CatchAll {
r.GET("/robots.txt", robotsTXT)
}
if !config.CatchAll {
for _, p := range config.Paths {
log.Trace().Str("caller", "router").Msg(p)
r.GET(fmt.Sprintf("/%s", p), hellPot)
}
} else {
log.Trace().Msg("Catch-All mode enabled...")
r.GET("/", hellPot)
r.GET("/{path}", hellPot)
}
srv := getSrv(r)
//goland:noinspection GoBoolExpressions
if !config.UseUnixSocket || runtime.GOOS == "windows" {
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)
}