# HG changeset patch # User moparisthebest # Date 1650859121 14400 # Node ID f4a9e804c4577657c7a69c754b77a7cfdadec4fd # Parent 13070c6a7ce866fc4c53f57cebfac63ae0ad314f mod_s2soutinjection: Rewrite based on mod_onions for 0.12 compat (thanks Zash) diff -r 13070c6a7ce8 -r f4a9e804c457 mod_s2soutinjection/README.markdown --- a/mod_s2soutinjection/README.markdown Fri Apr 22 14:29:32 2022 +0200 +++ b/mod_s2soutinjection/README.markdown Sun Apr 24 23:58:41 2022 -0400 @@ -16,15 +16,16 @@ "s2soutinjection"; } +-- targets must be IPs, not hostnames s2s_connect_overrides = { -- This one will use the default port, 5269 - ["example.com"] = "xmpp.server.local"; + ["example.com"] = "1.2.3.4"; -- To set a different port: - ["another.example"] = { "non-standard-port.example", 9999 }; + ["another.example"] = { "127.0.0.1", 9999 }; } ``` # Compatibility -Requires 0.9.x or later. +Requires 0.9.x or later. Tested on 0.12.0 diff -r 13070c6a7ce8 -r f4a9e804c457 mod_s2soutinjection/mod_s2soutinjection.lua --- a/mod_s2soutinjection/mod_s2soutinjection.lua Fri Apr 22 14:29:32 2022 +0200 +++ b/mod_s2soutinjection/mod_s2soutinjection.lua Sun Apr 24 23:58:41 2022 -0400 @@ -2,12 +2,69 @@ local new_ip = require"util.ip".new_ip; local new_outgoing = require"core.s2smanager".new_outgoing; local bounce_sendq = module:depends"s2s".route_to_new_session.bounce_sendq; -local s2sout = module:depends"s2s".route_to_new_session.s2sout; +local initialize_filters = require "util.filters".initialize; +local st = require "util.stanza"; + +local portmanager = require "core.portmanager"; + +local addclient = require "net.server".addclient; + +module:depends("s2s"); + +local sessions = module:shared("sessions"); local injected = module:get_option("s2s_connect_overrides"); -local function isip(addr) - return not not (addr and addr:match("^%d+%.%d+%.%d+%.%d+$") or addr:match("^[%x:]*:[%x:]-:[%x:]*$")); +-- The proxy_listener handles connection while still connecting to the proxy, +-- then it hands them over to the normal listener (in mod_s2s) +local proxy_listener = { default_port = port, default_mode = "*a", default_interface = "*" }; + +function proxy_listener.onconnect(conn) + local session = sessions[conn]; + + -- Now the real s2s listener can take over the connection. + local listener = portmanager.get_service("s2s").listener; + + local w, log = conn.send, session.log; + + local filter = initialize_filters(session); + + session.version = 1; + + session.sends2s = function (t) + log("debug", "sending (s2s over proxy): %s", (t.top_tag and t:top_tag()) or t:match("^[^>]*>?")); + if t.name then + t = filter("stanzas/out", t); + end + if t then + t = filter("bytes/out", tostring(t)); + if t then + return conn:write(tostring(t)); + end + end + end + + session.open_stream = function () + session.sends2s(st.stanza("stream:stream", { + xmlns='jabber:server', ["xmlns:db"]='jabber:server:dialback', + ["xmlns:stream"]='http://etherx.jabber.org/streams', + from=session.from_host, to=session.to_host, version='1.0', ["xml:lang"]='en'}):top_tag()); + end + + conn.setlistener(conn, listener); + + listener.register_outgoing(conn, session); + + listener.onconnect(conn); +end + +function proxy_listener.register_outgoing(conn, session) + session.direction = "outgoing"; + sessions[conn] = session; +end + +function proxy_listener.ondisconnect(conn, err) + sessions[conn] = nil; end module:hook("route/remote", function(event) @@ -16,34 +73,18 @@ if not inject then return end log("debug", "opening a new outgoing connection for this stanza"); local host_session = new_outgoing(from_host, to_host); - host_session.version = 1; -- Store in buffer host_session.bounce_sendq = bounce_sendq; host_session.sendq = { {tostring(stanza), stanza.attr.type ~= "error" and stanza.attr.type ~= "result" and st.reply(stanza)} }; log("debug", "stanza [%s] queued until connection complete", tostring(stanza.name)); - local ip_hosts, srv_hosts = {}, {}; - host_session.srv_hosts = srv_hosts; - host_session.srv_choice = 0; + local host, port = inject[1] or inject, tonumber(inject[2]) or 5269; - if type(inject) == "string" then inject = { inject } end + local conn = addclient(host, port, proxy_listener, "*a"); - for _, item in ipairs(inject) do - local host, port = item[1] or item, tonumber(item[2]) or 5269; - if isip(host) then - ip_hosts[#ip_hosts+1] = { ip = new_ip(host), port = port } - else - srv_hosts[#srv_hosts+1] = { target = host, port = port } - end - end - if #ip_hosts > 0 then - host_session.ip_hosts = ip_hosts; - host_session.ip_choice = 0; -- Incremented by try_next_ip - s2sout.try_next_ip(host_session); - return true; - end + proxy_listener.register_outgoing(conn, host_session); - return s2sout.try_connect(host_session, host_session.srv_hosts[1].target, host_session.srv_hosts[1].port); + host_session.conn = conn; + return true; end, -2); -