comparison mod_net_proxy/mod_net_proxy.lua @ 2963:504bb330e910

mod_net_proxy: Added proxy_trusted_proxies for whitelisting incoming connections
author Pascal Mathis <mail@pascalmathis.com>
date Wed, 28 Mar 2018 20:47:41 +0200
parents 6b01600b9c02
children 7eb6fa9b03fd
comparison
equal deleted inserted replaced
2962:6b01600b9c02 2963:504bb330e910
65 PROXYv1 = { signature = hex.from("50524F5859"), callback = nil }, 65 PROXYv1 = { signature = hex.from("50524F5859"), callback = nil },
66 PROXYv2 = { signature = hex.from("0D0A0D0A000D0A515549540A"), callback = nil } 66 PROXYv2 = { signature = hex.from("0D0A0D0A000D0A515549540A"), callback = nil }
67 }; 67 };
68 local PROTO_HANDLER_STATUS = { SUCCESS = 0, POSTPONE = 1, FAILURE = 2 }; 68 local PROTO_HANDLER_STATUS = { SUCCESS = 0, POSTPONE = 1, FAILURE = 2 };
69 69
70 -- Configuration Variables
71 local config_mappings = module:get_option("proxy_port_mappings", {});
72 local config_ports = module:get_option_set("proxy_ports", {});
73 local config_trusted_proxies = module:get_option_set("proxy_trusted_proxies", {"127.0.0.1", "::1"});
74
70 -- Persistent In-Memory Storage 75 -- Persistent In-Memory Storage
71 local sessions = {}; 76 local sessions = {};
72 local mappings = {}; 77 local mappings = {};
78 local trusted_networks = set.new();
73 79
74 -- Proxy Data Methods 80 -- Proxy Data Methods
75 local proxy_data_mt = {}; proxy_data_mt.__index = proxy_data_mt; 81 local proxy_data_mt = {}; proxy_data_mt.__index = proxy_data_mt;
76 82
77 function proxy_data_mt:describe() 83 function proxy_data_mt:describe()
312 service_listener.onconnect(conn); 318 service_listener.onconnect(conn);
313 end 319 end
314 return service_listener.onincoming(conn, session.buffer); 320 return service_listener.onincoming(conn, session.buffer);
315 end 321 end
316 322
323 local function is_trusted_proxy(conn)
324 -- If no trusted proxies were configured, trust any incoming connection
325 -- While this may seem insecure, the module defaults to only trusting 127.0.0.1 and ::1
326 if trusted_networks:empty() then
327 return true;
328 end
329
330 -- Iterate through all trusted proxies and check for match against connected IP address
331 local conn_ip = ip.new_ip(conn:ip());
332 for trusted_network in trusted_networks:items() do
333 if ip.match(trusted_network.ip, conn_ip, trusted_network.cidr) then
334 return true;
335 end
336 end
337
338 -- Connection does not match any trusted proxy
339 return false;
340 end
341
317 -- Network Listener Methods 342 -- Network Listener Methods
318 local listener = {}; 343 local listener = {};
319 344
320 function listener.onconnect(conn) 345 function listener.onconnect(conn)
346 -- Check if connection is coming from a trusted proxy
347 if not is_trusted_proxy(conn) then
348 conn:close();
349 module:log("warn", "Dropped connection from untrusted proxy: %s", conn:ip());
350 return;
351 end
352
353 -- Initialize session variables
321 sessions[conn] = { 354 sessions[conn] = {
322 handler = nil; 355 handler = nil;
323 buffer = nil; 356 buffer = nil;
324 }; 357 };
325 end 358 end
386 sessions[conn] = nil; 419 sessions[conn] = nil;
387 end 420 end
388 421
389 listener.ondetach = listener.ondisconnect; 422 listener.ondetach = listener.ondisconnect;
390 423
424 -- Parse trusted proxies which can either contain single hosts or networks
425 if not config_trusted_proxies:empty() then
426 for trusted_proxy in config_trusted_proxies:items() do
427 local network = {};
428 network.ip, network.cidr = ip.parse_cidr(trusted_proxy);
429 trusted_networks:add(network);
430 end
431 else
432 module:log("warn", "No trusted proxies configured, all connections will be accepted - this might be dangerous");
433 end
434
391 -- Process all configured port mappings and generate a list of mapped ports 435 -- Process all configured port mappings and generate a list of mapped ports
392 local mapped_ports = {}; 436 local mapped_ports = {};
393 local config_mappings = module:get_option("proxy_port_mappings", {});
394 for port, mapping in pairs(config_mappings) do 437 for port, mapping in pairs(config_mappings) do
395 table.insert(mapped_ports, port); 438 table.insert(mapped_ports, port);
396 mappings[port] = { 439 mappings[port] = {
397 service_name = mapping, 440 service_name = mapping,
398 service = nil, 441 service = nil,
399 }; 442 };
400 end 443 end
401 444
402 -- Log error message when user manually specifies ports without configuring the necessary port mappings 445 -- Log error message when user manually specifies ports without configuring the necessary port mappings
403 local config_ports = module:get_option_set("proxy_ports", {});
404 if not config_ports:empty() then 446 if not config_ports:empty() then
405 local missing_ports = config_ports - set.new(mapped_ports); 447 local missing_ports = config_ports - set.new(mapped_ports);
406 if not missing_ports:empty() then 448 if not missing_ports:empty() then
407 module:log("error", "Missing port<>service mappings for these ports: %s", tostring(missing_ports)); 449 module:log("error", "Missing port<>service mappings for these ports: %s", tostring(missing_ports));
408 end 450 end