srctree

Gregory Mullen parent 8c57610b 3574f20d
detect 99% of bots with this one weird trick

inlinesplit
src/bot-detection.zig added: 34, removed: 3, total 31
@@ -41,6 +41,9 @@ pub fn init(r: *const Request) BotDetection {
}
},
.browser => |browser| {
inline for (rules.browser) |rule| {
rule(ua, r, &bot.score) catch @panic("not implemented");
}
// Any bot that masqurades as a browser is by definition malign
if (bot.score >= ANOMALY_MAX) {
bot.bot = true;
@@ -71,6 +74,9 @@ const rules = struct {
const global = [_]RuleFn{
browsers.Rules.age,
};
const browser = [_]RuleFn{
browsers.Rules.protocolVer,
};
const bots = [_]RuleFn{
//
};
 
src/bot-detection/browsers.zig added: 34, removed: 3, total 31
@@ -240,6 +240,21 @@ pub const Rules = struct {
} }, undefined, &score);
try std.testing.expectEqual(score, 0.0);
}
 
pub fn protocolVer(_: UA, r: *const Request, score: *f16) !void {
if (!r.secure) return;
 
// TODO To actually be correct, this should do a browser version check as well
 
switch (r.protocol) {
.http => |http| switch (http) {
.@"1.0" => score.* += 1.0,
.@"1.1" => score.* += 1.0,
.@"2.0" => {},
},
.malformed => |_| {},
}
}
};
 
const browsers = @This();
@@ -250,3 +265,5 @@ test browsers {
const std = @import("std");
const UA = @import("../user-agent.zig");
const Request = @import("../request.zig");
 
const eql = std.mem.eql;
 
src/request.zig added: 34, removed: 3, total 31
@@ -9,6 +9,7 @@ accept: ?Accept,
accept_encoding: Encoding = .default,
authorization: ?Authorization,
protocol: Protocol,
secure: bool,
 
headers: Headers,
/// Default API, still unstable, but unlike to drastically change
@@ -135,6 +136,7 @@ fn initCommon(
proto: []const u8,
data: Data,
raw: RawReq,
secure: bool,
) !Request {
var method = _method;
if (headers.getCustom("Upgrade")) |val| {
@@ -157,6 +159,7 @@ fn initCommon(
.uri = uri,
.user_agent = if (ua) |u| .init(u) else null,
.protocol = .parse(proto),
.secure = secure,
};
}
 
@@ -173,6 +176,7 @@ pub fn initZWSGI(a: Allocator, zwsgi: *zWSGIRequest, data: Data) !Request {
var authorization: ?Authorization = null;
var cookie_header: ?[]const u8 = null;
var proto: []const u8 = "ERROR";
var secure: bool = false;
 
for (zwsgi.vars) |v| {
try headers.addCustom(v.key, v.val);
@@ -201,6 +205,8 @@ pub fn initZWSGI(a: Allocator, zwsgi: *zWSGIRequest, data: Data) !Request {
cookie_header = v.val;
} else if (eqlIgnoreCase("SERVER_PROTOCOL", v.key)) {
proto = v.val;
} else if (eqlIgnoreCase("REQUEST_SCHEME", v.key)) {
secure = eqlIgnoreCase("https", v.val);
}
}
 
@@ -220,6 +226,7 @@ pub fn initZWSGI(a: Allocator, zwsgi: *zWSGIRequest, data: Data) !Request {
proto,
data,
.{ .zwsgi = zwsgi },
secure,
);
}
 
@@ -279,6 +286,7 @@ pub fn initHttp(a: Allocator, http: *std.http.Server.Request, data: Data) !Reque
proto,
data,
.{ .http = http },
false, // https isn't currently supported using verse internal http
);
}