-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.lua
134 lines (119 loc) · 3.97 KB
/
init.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
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
-- Vps Blocker
local http = minetest.request_http_api()
assert(http ~= nil, "You need to add vps_blocker to secure.http_mods")
local kick_message = minetest.settings:get("vps_kick_message") or "You are using a proxy, vpn or other hosting services, please disable them to play on this server."
vps_blocker = {}
local cache = {}
local storage = minetest.get_mod_storage()
--[[
cache of ip == nil not checked yet
== 1 checked allow
== 2 checked deny
]]
local checkers = {}
--[[
vps_blocker.register_check(check):
passed check is a array:
getreq(ip) return req, callback or nil, err for failed
callback func will get the result of the req and is supposed
to return true for allow and false for denying the client
nil, err for failed requests
active = true
If the checker is currently working is true by default
The checker can store any other data inside this table.
]]
function vps_blocker.register_checker(check)
assert(type(check) == "table")
check.active = true
assert(type(check.getreq) == "function")
-- Dummy testing function:
local req, call = check.getreq("0.0.0.0")
assert(type(req) == "table")
assert(type(req.url == "string"))
assert(type(call) == "function")
table.insert(checkers, check)
end
-- Load checkers
dofile(minetest.get_modpath(minetest.get_current_modname()).. "/checker.lua")
-- Add the main ipcheckup function
local function check_ip(name, ip, hash)
-- Loop throught the list of checkers and use one
local checked = false
for _, check in pairs(checkers) do
if check.active then
local req, call = check.getreq(ip)
if req then
local function callback(result)
local pass, err = call(result)
if pass then
cache[hash] = 1
minetest.log("action", "vps_blocker: Passing good-ip-player "..name.." ["..ip.."]")
elseif pass == false then
cache[hash] = 2
minetest.log("action", "vps_blocker: Kicking bad-ip-player "..name.." ["..ip.."]")
else minetest.log("error", "vps_blocker: Callback-Error "..err.." while checking "..name.." ["..ip.."]!")
end
end
http.fetch(req, callback)
checked = true
break
else minetest.log("error", "vps_blocker: Checker failed to create requests for "..name.." ["..ip.."]!")
end
end
end
-- Report error if no working was found
if not checked then
minetest.log("error", "vps_blocker: No working checker found!")
end
end
-- Add a function which handels what do do(check, kick, nth...)
function vps_blocker.handle_player(name, ip)
if not ip or not name then
return
end
local iphash = minetest.sha1(ip)
if not iphash then
return
end
if cache[iphash] == 1 or storage:get_int(name) == 1 then
return
end
if not cache[iphash] then
check_ip(name, ip, iphash)
return
end
if cache[iphash] == 2 then
local player = minetest.get_player_by_name(name)
if player then
-- Kick after a server step, to prevent other on_joinplayer to crash
minetest.after(0, function()
minetest.kick_player(name, kick_message)
end)
else return kick_message
end
end
end
-- Do handle_player on prejoin and normal join
minetest.register_on_prejoinplayer(vps_blocker.handle_player)
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
local ip = minetest.get_player_ip(name)
vps_blocker.handle_player(name, ip)
end)
-- Add a command to whitelist players
minetest.register_chatcommand("vps_wl", {
description = "Allow a player to use vps services.",
params = "<add or remove> <name>",
privs = {server=true},
func = function(name, params)
local p = string.split(params, " ")
if p[1] == "add" then
storage:set_int(p[2], 1)
return true, "Added "..p[2].." to the whitelist."
elseif p[1] == "remove" then
storage:set_int(p[2], 0)
return true, "Removed "..p[2].." from the whitelist."
else return false, "Invalid Input"
end
end
})