init.lua 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. -- Vps Blocker
  2. local http = minetest.request_http_api()
  3. assert(http ~= nil, "You need to add vps_blocker to secure.http_mods")
  4. 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."
  5. vps_blocker = {}
  6. local cache = {}
  7. local storage = minetest.get_mod_storage()
  8. --[[
  9. cache of ip == nil not checked yet
  10. == 1 checked allow
  11. == 2 checked deny
  12. ]]
  13. local checkers = {}
  14. --[[
  15. vps_blocker.register_check(check):
  16. passed check is a array:
  17. getreq(ip) return req, callback or nil, err for failed
  18. callback func will get the result of the req and is supposed
  19. to return true for allow and false for denying the client
  20. nil, err for failed requests
  21. active = true
  22. If the checker is currently working is true by default
  23. The checker can store any other data inside this table.
  24. ]]
  25. function vps_blocker.register_checker(check)
  26. assert(type(check) == "table")
  27. check.active = true
  28. assert(type(check.getreq) == "function")
  29. -- Dummy testing function:
  30. local req, call = check.getreq("0.0.0.0")
  31. assert(type(req) == "table")
  32. assert(type(req.url == "string"))
  33. assert(type(call) == "function")
  34. table.insert(checkers, check)
  35. end
  36. -- Load checkers
  37. dofile(minetest.get_modpath(minetest.get_current_modname()).. "/checker.lua")
  38. -- Add the main ipcheckup function
  39. local function check_ip(name, ip, hash)
  40. -- Loop throught the list of checkers and use one
  41. local checked = false
  42. for _, check in pairs(checkers) do
  43. if check.active then
  44. local req, call = check.getreq(ip)
  45. if req then
  46. function callback(result)
  47. local pass, err = call(result)
  48. if pass then
  49. cache[hash] = 1
  50. minetest.log("action", "vps_blocker: Passing good-ip-player "..name.." ["..ip.."]")
  51. elseif pass == false then
  52. cache[hash] = 2
  53. minetest.log("action", "vps_blocker: Kicking bad-ip-player "..name.." ["..ip.."]")
  54. else minetest.log("error", "vps_blocker: Callback-Error "..err.." while checking "..name.." ["..ip.."]!")
  55. end
  56. end
  57. http.fetch(req, callback)
  58. checked = true
  59. break
  60. else minetest.log("error", "vps_blocker: Checker failed to create requests for "..name.." ["..ip.."]!")
  61. end
  62. end
  63. end
  64. -- Report error if no working was found
  65. if not checked then
  66. minetest.log("error", "vps_blocker: No working checker found!")
  67. end
  68. end
  69. -- Add a function which handels what do do(check, kick, nth...)
  70. function vps_blocker.handle_player(name, ip)
  71. if not ip or not name then
  72. return
  73. end
  74. local iphash = minetest.sha1(ip)
  75. if not iphash then
  76. return
  77. end
  78. if cache[iphash] == 1 or storage:get_int(name) == 1 then
  79. return
  80. end
  81. if not cache[iphash] then
  82. check_ip(name, ip, iphash)
  83. return
  84. end
  85. if cache[iphash] == 2 then
  86. local player = minetest.get_player_by_name(name)
  87. if player then
  88. -- Kick after a server step, to prevent other on_joinplayer to crash
  89. minetest.after(0, function()
  90. minetest.kick_player(name, kick_message)
  91. end)
  92. else return kick_message
  93. end
  94. end
  95. end
  96. -- Do handle_player on prejoin and normal join
  97. minetest.register_on_prejoinplayer(vps_blocker.handle_player)
  98. minetest.register_on_joinplayer(function(player)
  99. local name = player:get_player_name()
  100. local ip = minetest.get_player_ip(name)
  101. vps_blocker.handle_player(name, ip)
  102. end)
  103. -- Add a command to whitelist players
  104. minetest.register_chatcommand("vps_wl", {
  105. description = "Allow a player to use vps services.",
  106. params = "<add or remove> <name>",
  107. privs = {server=true},
  108. func = function(name, params)
  109. local p = string.split(params, " ")
  110. if p[1] == "add" then
  111. storage:set_int(p[2], 1)
  112. return true, "Added "..p[2].." to the whitelist."
  113. elseif p[1] == "remove" then
  114. storage:set_int(p[2], 0)
  115. return true, "Removed "..p[2].." from the whitelist."
  116. else return false, "Invalid Input"
  117. end
  118. end
  119. })