Mercurial > prosody-modules
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 |
