-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathsni.lua
80 lines (60 loc) · 1.67 KB
/
sni.lua
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
--
-- SPDX-FileCopyrightText: (c) 2024 Ring Zero Desenvolvimento de Software LTDA
-- SPDX-License-Identifier: MIT OR GPL-2.0-only
--
local xdp = require("xdp")
local action = xdp.action
local function set(t)
local s = {}
for _, key in ipairs(t) do s[key] = true end
return s
end
local blacklist = set{
"ebpf.io",
}
local function log(sni, verdict)
print(string.format("filter_sni: %s %s", sni, verdict))
end
local function unpacker(packet, base)
local byte = function (offset)
return packet:getbyte(base + offset)
end
local short = function (offset)
local offset = base + offset
return packet:getbyte(offset) << 8 | packet:getbyte(offset + 1)
end
local str = function (offset, length)
return packet:getstring(base + offset, length)
end
return byte, short, str
end
local function offset(argument)
return select(2, unpacker(argument, 0))(0)
end
local client_hello = 0x01
local handshake = 0x16
local server_name = 0x00
local session = 43
local max_extensions = 17
local function filter_sni(packet, argument)
local byte, short, str = unpacker(packet, offset(argument))
if byte(0) ~= handshake or byte(5) ~= client_hello then
return action.PASS
end
local cipher = (session + 1) + byte(session)
local compression = cipher + 2 + short(cipher)
local extension = compression + 3 + byte(compression)
for i = 1, max_extensions do
local data = extension + 4
if short(extension) == server_name then
local length = short(data + 3)
local sni = str(data + 5, length)
verdict = blacklist[sni] and "DROP" or "PASS"
log(sni, verdict)
return action[verdict]
end
extension = data + short(extension + 2)
end
return action.PASS
end
xdp.attach(filter_sni)