forked from comotion/VSF
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vsf.vcl
221 lines (198 loc) · 7.13 KB
/
vsf.vcl
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
vcl 4.0;
/* VSF main VCL file
* XXX: Paths are hardcoded, otherwise they don't resolve. sorry.
*/
import std;
import vsf;
# clear all internal variables
include "security/build/variables.vcl";
include "security/local.vcl";
/* the honeypot backend...
* presently defined to give no service
* possible uses:
* send to less critical server
* log evil traffic
* sandbox request
* execute CGI scripts based on traffic
* ... ie to firewall client
* ... other active responses?
*/
backend sec_honey {
.host = "127.0.1.2";
.port = "3";
}
sub vcl_recv {
if (req.restarts > 0 && req.http.X-VSF-Response ~ "honeypot me") {
set req.backend_hint = sec_honey;
return (pass);
}
set req.http.X-VSF-Actual-IP = regsub(req.http.X-Forwarded-For, "[, ].*$", "");
set req.http.X-VSF-ClientIP = client.ip;
set req.http.X-VSF-Method = req.method;
set req.http.X-VSF-Proto = req.proto;
set req.http.X-VSF-UA = req.http.user-agent;
#STABLE | COMPAT | COMPOSE | IGNORE | NLF2LF | LUMP | STRIPMARK
set req.http.X-VSF-URL = vsf.normalize(vsf.urldecode(req.url));
set req.http.X-VSF-Body = vsf.normalize(vsf.body(512KB));
if (req.url ~ "(i)^/[^?]+\.(css|js|jp(e)?g|ico|png|gif|txt|gz(ip)?|zip|rar|iso|lzma|bz(2)?|t(ar\.)?gz|t(ar\.)?bz)(\?.*)?$") {
set req.http.X-VSF-Static = "y";
}
# gather info about client
# this is one of the vars guaranteed to be present
# if and only if your request is inside security.vcl
set req.http.X-VSF-Client = "[" + client.ip + "] "
+ req.http.host + req.url
+ " (" + req.http.user-agent + ")";
}
# which modules to use, what to log, how to handle events and honeypot
# backend definition
include "security/config.vcl";
# fallthrough: clear all internal variables on security.vcl_recv exit
include "security/build/variables.vcl";
# define all the event handlers
include "security/handlers.vcl";
/* The value of '800' and up is used because it is not actual HTTP error
* codes. They should not be exposed.
*
* The list thus far:
* 800 - Debug
* 801 - Plain error (403-forbidden might be a bad rewrite here)
* 802 - Redirect
* 803 - Restart, forward to backend honey
* 804 - Synthetic response
* 805 - Attempt to drop or reset the request (not implemented yet)
* 808 - Raw synthetic deliver
*/
sub vcl_synth {
if (req.restarts == 0 && req.http.X-VSF-Client ) {
call sec_log;
if (resp.status == 800) {
set resp.http.X-VSF-Rule = req.http.X-VSF-Rule;
set resp.status = 200;
} elsif (resp.status == 801) {
set resp.status = 403;
if (req.http.X-VSF-Response ) {
set resp.reason = req.http.X-VSF-Response;
} else {
set resp.reason = "Forbidden";
}
} elsif (resp.status == 802) {
set resp.status = 302;
#set resp.reason = "Redirected for fun and profit";
if (resp.http.X-VSF-Response ) {
set resp.http.Location = resp.http.X-VSF-Response;
} else {
set resp.http.Location =
"http://images.google.com/images?q=llama";
}
return (deliver);
} elsif (resp.status == 803) {
# restart on 2nd backend
set req.http.X-VSF-Response = "honeypot me";
set req.backend_hint = sec_honey;
return (restart);
} elsif (resp.status == 804) {
set resp.status = 200;
set resp.reason = "OK";
set resp.http.content-type = "text/html";
if (! resp.http.X-VSF-Response ) {
set resp.http.X-VSF-Response = "Synthetic";
}
synthetic({"<html><body>
"} + resp.http.X-VSF-Response + {"
</body></html>
"});
return (deliver);
} elsif (resp.status == 805) {
set resp.status = 501;
set resp.reason = "Get outta here";
} elsif (resp.status == 808) {
set resp.status = 200;
set resp.reason = "OK";
synthetic(req.http.X-VSF-Response);
}
# fallthrough to other vcl_synth's
}
}
/* Call this one to just log rule hits and pass to backend
* without calling error.
* This effectively *DISABLES* security.vcl protectionism */
sub sec_passthru {
call sec_log;
}
/* Call this one for a catch-all */
sub sec_general {
return (synth(800, "Naughty, not nice!"));
}
/* 403 rejected */
sub sec_reject {
return (synth(801, "Rejected"));
}
/* call this one for a redirect */
sub sec_redirect {
return (synth(802, "Redirect"));
}
sub sec_honeypot {
return (synth(803, "Sexy Honey"));
}
/* call this one for synthetic html */
sub sec_synthtml {
return (synth(804, "Synthetic"));
}
sub sec_drop {
call sec_log;
vsf.conn_reset();
}
sub sec_magichandler {
if (!req.http.X-VSF-Response ) {
## The default attack response message, can be overridden by rules.
set req.http.X-VSF-Response = "Naughty, not nice!";
}
if (req.http.X-VSF-Response ~ "^honeypot me$") {
# we have restarted and our request is on the honeypot backend
# pass the request;
return (pass);
}
}
/* You can define how to handle the different severity levels. */
sub sec_handler {
## retrieve the rule info
set req.http.X-VSF-Rule = req.http.X-VSF-Module + "-" +
req.http.X-VSF-RuleID;
if (req.http.X-VSF-Rule ~ "^(fooobs)$") {
# squelch this rule
} else {
## magichandler handles restarts should always be called!
call sec_magichandler;
if (req.http.X-VSF-Severity == "1") {
/* we have only one severity for now: this is the default rule */
call sec_default_handler;
} else {
# fallback attack response when severity is off the charts
call sec_default_handler;
}
# this variable always present, so rule always false
if (!req.http.X-VSF-Client ) {
# all functions must be used in vcl, fool compiler by putting
# them here
std.log("security.vcl WONTREACH: available sec handlers");
# the handlers are defined in main.vcl along with the error codes
# handler name # code # purpose
call sec_general; # 800 # debug handler - delivers
# X-VSF-Rule to client
call sec_reject; # 801 # 403 reject with message
call sec_redirect; # 802 # 302 redirect
call sec_honeypot; # 803 # restart request with honeypot
# backend
call sec_synthtml; # 804 # synthesize a response
call sec_drop; # 805 # drop the request (not implemented)
call sec_myhandler; # any # do your own thing
call sec_default_handler; # fallback handler
## note! the passthru handler really does pass thru
# - you must make sure it is the last thing called
call sec_passthru; # n/a # log client and pass thru to
# default error logic
}
}
}
/* vim: set syntax=c tw=76: */