block_vps/init.lua

148 lines
5.2 KiB
Lua

block_vps = {}
local http_api = minetest.request_http_api()
assert(http_api ~= nil, "Add 'block_vps' to secure.http_mods and restart server")
local mod_path = core.get_modpath(core.get_current_modname())
local mod_storage
-- support older minetest versions
if minetest.get_mod_storage then
mod_storage = minetest.get_mod_storage()
end
-- support older minetest versions
function block_vps.get_setting(name)
if core.settings then
return core.settings:get(name)
else
return core.setting_get(name)
end
end
local block_type = block_vps.get_setting("block_vps_type") or "activation"
assert(loadfile(mod_path .. "/api.lua"))(http_api)
dofile(mod_path .. "/iphub.lua")
dofile(mod_path .. "/iphub_legacy.lua")
dofile(mod_path .. "/nastyhosts.lua")
-- block other mods from register data source till better security code can be written
block_vps.register_datasource = nil
local function create_reject_message(ip, isp)
local message
if block_type ~= "kick" then
message = "\nCreating new accounts "
else
message = "\nConnecting "
end
message = message .. "from this IP address (%s) is blocked,\nas it appears to be belong to a hosting/VPN/proxy provider (%s)" ..
"%s\nplease contact the server owner if this is an error."
local note = ","
if block_type == "activation" then
note = ".\nConnect from an unblocked IP address to be able to use this account,"
end
return string.format(message, ip, isp, note)
end
local function log_block(name, ip, isp, datasource, kicked)
local prefix = "Blocking %q connecting"
if kicked then prefix = "Kicked %q connected" end
core.log("action", string.format("[block_vps] " .. prefix .. " from %q as the IP address appears to belong to %q (datasource = %q).", name, ip, isp, datasource))
end
if block_type == "creation" then
core.register_on_prejoinplayer(function(name, ip)
if not core.player_exists(name) then
local ip_info = block_vps.get_ip_info_sync(ip)
if ip_info and ip_info.is_blocked then
log_block(name, ip, ip_info.isp, ip_info.api)
return create_reject_message(ip, ip_info.isp)
end
end
end)
elseif block_type == "activation" then
-- support older minetest versions
assert(mod_storage ~= nil, "Your minetest version doesn't support mod storage, " ..
"it is required if 'block_vps_type' is set to 'activation' please change it to any other support setting ('none', 'kick', 'creation')")
local default_privs = core.string_to_privs(core.settings:get("default_privs"))
core.register_on_joinplayer(function(player)
local name = player:get_player_name()
-- Check if the account has yet to connect from a valid IP
if mod_storage:get_int(name) == 1 then
block_vps.get_ip_info(core.get_player_ip(name), function(ip, info)
if info and info.is_blocked then
-- if the player tries to connect from another banned IP kick and log.
log_block(name, ip, info.isp, info.api, true)
minetest.kick_player(name, create_reject_message(ip, info.isp))
else
-- give the player back the default privs we took
core.set_player_privs(name, default_privs)
mod_storage:set_string(name, "") -- only way to erase a mod storage key
end
end)
end
end)
core.register_on_newplayer(function(player)
local name = player:get_player_name()
-- revoke all of the players privs so they don't try to exploit the small delay between connection and IP lookup end.
core.set_player_privs(name, {})
block_vps.get_ip_info(core.get_player_ip(name), function(ip, info)
if info and info.is_blocked then
--[[
If the IP the player created the account with is banned,
kick them, log the event and record that they need to login with a normal IP to use the account in mod storage
--]]
mod_storage:set_int(name, 1)
log_block(name, ip, info.isp, info.api, true)
minetest.kick_player(name, create_reject_message(ip, info.isp, true))
else
-- give the player back the default privs we took
core.set_player_privs(name, default_privs)
end
end)
end)
elseif block_type == "kick" then
core.register_on_joinplayer(function(player)
local name = player:get_player_name()
if core.check_player_privs(name, {bypass_ip_check=true}) then
return
end
block_vps.get_ip_info(core.get_player_ip(name), function(ip, info)
if info and info.is_blocked then
log_block(name, ip, info.isp, info.api, true)
minetest.kick_player(name, create_reject_message(ip, info.isp))
end
end)
end)
end
core.register_privilege("bypass_ip_check", "Stops the users IP from being check on join by block_vps")
core.register_chatcommand("get_ip_info", {
params = "<ip_address>",
description = "Display IP address information",
privs = {server=true},
func = function(name, param)
param = param:trim()
if param == "" then
return false, "IP address needed"
end
local ip = param:match("^([^ ]+)")
block_vps.get_ip_info(ip, function(ip, info)
if not info then
core.chat_send_player(name, string.format("Failed to get IP info for %q", ip))
else
local message = string.format("\nIP Info for %q\nData Source: %s\nBlocked: %s\nISP: %q\nASN: %d\nHost Name: %s\n",
ip, info.api, tostring(info.is_blocked), info.isp, info.asn, info.hostname)
if info.country then
message = message .. "Country: " .. info.country .. "\n"
end
core.chat_send_player(name, message)
end
end)
end,
})