Last active
September 27, 2022 16:58
-
-
Save Earu/a3ede23bb5600f8cb980ac8b815ed6ed to your computer and use it in GitHub Desktop.
Find IPs that match known VPNs and proxy servers in Garry's Mod.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local BASE_URL = "https://raw.githubusercontent.com/X4BNet/lists_vpn/main/ipv4.txt" | |
local IP_PATTERN = "(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)" | |
local IP_RANGE_PATTERN = "(%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?)/(%d+)" | |
local function str_to_ip(str) | |
local o1, o2, o3, o4 = str:match(IP_PATTERN) | |
o1, o2, o3, o4 = tonumber(o1), tonumber(o2), tonumber(o3), tonumber(o4) | |
return bit.bor( | |
o1 * 2 ^ 24, | |
o2 * 2 ^ 16, | |
o3 * 2 ^ 8, | |
o4 | |
) | |
end | |
local lookup = {} | |
local lookup_count = 0 | |
http.Fetch(BASE_URL, function(body) | |
for str_ip, net_mask_str in body:gmatch(IP_RANGE_PATTERN) do | |
local ip = str_to_ip(str_ip) | |
if not lookup[ip] then | |
lookup[ip] = {} | |
lookup_count = lookup_count + 1 | |
end | |
local net_mask = tonumber(net_mask_str) | |
if not net_mask then continue end | |
table.insert(lookup[ip], net_mask) | |
end | |
end) | |
local function compare_ips(source_ip, net_ip, net_mask) | |
local mask = bit.bnot(2 ^ (32 - net_mask) - 1) | |
return bit.band(source_ip, mask) == bit.band(net_ip, mask) | |
end | |
local function check_vpn(ip_str, callback) | |
return coroutine.create(function() | |
if lookup_count == 0 then | |
callback(false, -1, -1) | |
return | |
end | |
local i = 0 | |
local source_ip = str_to_ip(ip_str) | |
for target_ip, net_masks in pairs(lookup) do | |
for _, net_mask in ipairs(net_masks) do | |
local is_in_range = compare_ips(source_ip, target_ip, net_mask) | |
if is_in_range then | |
callback(true, target_ip, net_mask) | |
return | |
end | |
i = i + 1 | |
if i % 1000 == 0 then | |
coroutine.yield() | |
end | |
end | |
end | |
callback(false, -1, -1) | |
end) | |
end | |
local callback_id = 0 | |
function util.CheckVPN(ip_addr, callback) | |
local co = check_vpn(ip_addr, callback) | |
local hook_name = ("CheckVPN_[%d]"):format(callback_id) | |
hook.Add("Think", hook_name, function() | |
local status, result = coroutine.resume(co) | |
if not status then | |
hook.Remove("Think", hook_name) | |
error(result) | |
end | |
if result or coroutine.status(co) == "dead" then | |
hook.Remove("Think", hook_name) | |
end | |
end) | |
callback_id = callback_id + 1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment