Configure Socks5 Proxy in Lua policy extras sources helper?

When using the queue helper, is it possible to configure an IP Pool to use a Socks5 proxy?

The documentation shows examples of Socks5 usage via the socks5_proxy_server in Lua, but doesn’t specifically show doing the equivalent in TOML:

# init.lua

kumo.on('get_egress_source', function(source_name)
  if source_name == 'ip-2' then
    kumo.make_egress_source {
      name = 'ip-2',
      socks5_proxy_source_address = '10.0.0.1',
      socks5_proxy_server = '10.0.0.1:5000',
      ehlo_domain = 'mta2.examplecorp.com',
    }
  end
end)
# /opt/kumomta/etc/policy/sources.toml

[source."ip-1"]
source_address = "10.0.0.1"
ehlo_domain = 'mta1.examplecorp.com'

[source."ip-2"]
socks5_proxy_source_address = '10.0.0.1'
socks5_proxy_server = '10.0.0.1:5000'
ehlo_domain = 'mta2.examplecorp.com'

[pool."pool-2"]
[pool."pool-2"."ip-2"]

I’ve tried the second method (shown above), but encounter errors leading me to believe something is awry.

What errors?

The DEBUG error I get is:

e[2m2025-02-28T22:10:58.106257Ze[0m e[31mERRORe[0m  smtpsrv-20 e[1mrune[0me[1m{e[0me[3msockete[0me[2m=e[0mPollEvented { io: Some(TcpStream { addr: 127.0.0.1:25, peer: 127.0.0.1:53092, fd: 35 }) }e[1m}e[0me[2m:e[0m e[2mkumod::smtp_servere[0me[2m:e[0m Error in SmtpServer: QueueManager::insert failed for 1 messages: e31298a4f62011efac107a1ee9457203: resolving egress pool 'pool-2': runtime error: /opt/kumomta/share/policy-extras/sources.lua:75: /opt/kumomta/share/policy-extras/sources.lua:41 SourcesHelperConfig: invalid value for field 'source'

/opt/kumomta/share/policy-extras/sources.lua:41 Expected value of type 'map<string,SourceConfig>' and encountered an error during coercion
/opt/kumomta/share/policy-extras/sources.lua:41 /opt/kumomta/share/policy-extras/sources.lua:75: /opt/kumomta/share/policy-extras/sources.lua:41 map<string,SourceConfig>: invalid value for key 'ip-2'
/opt/kumomta/share/policy-extras/sources.lua:41 Expected value of type 'SourceConfig' and encountered an error during coercion
/opt/kumomta/share/policy-extras/sources.lua:41 /opt/kumomta/share/policy-extras/sources.lua:75: /opt/kumomta/share/policy-extras/sources.lua:41 SourceConfig: unknown field 'socks5_proxy_server'
stack traceback:
    [C]: in function 'error'
    /opt/kumomta/share/policy-extras/typing.lua:78: in method 'raise'
    /opt/kumomta/share/policy-extras/typing.lua:249: in metamethod 'newindex'
    /opt/kumomta/share/policy-extras/typing.lua:258: in function </opt/kumomta/share/policy-extras/typing.lua:253>
    (...tail calls...)
    /opt/kumomta/share/policy-extras/sources.lua:41: in upvalue 'load_data_from_file'
    /opt/kumomta/share/policy-extras/sources.lua:75: in function </opt/kumomta/share/policy-extras/sources.lua:68>
stack traceback:
    [C]: in local 'poll'
    [string "?"]:4: in upvalue 'cached_load_data'
    /opt/kumomta/share/policy-extras/sources.lua:153: in function </opt/kumomta/share/policy-extras/sources.lua:152>

FWIW, running kumod --validate can be helpful to detect errors before you start the server

I’m not sure why you’re seeing that error. If I modify the test case in assets/policy-extras/sources.lua and run make test-lua, it parses those options just fine:

diff --git a/assets/policy-extras/sources.lua b/assets/policy-extras/sources.lua
index 3a0827d3..2c70496c 100644
--- a/assets/policy-extras/sources.lua
+++ b/assets/policy-extras/sources.lua
@@ -221,7 +221,9 @@ source_address = "10.0.0.1"
 source_address = "10.0.0.2"

 [source."ip-3"]
-source_address = "10.0.0.3"
+socks5_proxy_source_address = '10.0.0.1'
+socks5_proxy_server = '10.0.0.1:5000'
+ehlo_domain = 'mta2.examplecorp.com'

 # Pool containing just ip-1, which has weight=1
 [pool."BestReputation"]

(that’s all the time I have to look into this just now)

Here’s the result of validating my local init.lua file:

root@kumomta:/# kumod --user root --validate

2025-03-01T00:14:23.437687Z DEBUG      main kumod::logging: Joined -> Some(Ok(()))
2025-03-01T00:14:23.437776Z  INFO      main kumod::spool: Shutting down spool
Error: Initialization raised an error: call validate_config callback: Attempting to register an event handler via `kumo.on('validate_config', ...)` from within the event handler 'validate_config'. You must move your event handler registration so that it is setup directly when the policy is loaded in order for it to consistently trigger and handle events.
stack traceback:
    [C]: in function 'kumo.on'
    /opt/kumomta/share/policy-extras/sources.lua:160: in main chunk
    [C]: in function 'require'
    /opt/kumomta/share/policy-extras/queue.lua:597: in function </opt/kumomta/share/policy-extras/queue.lua:550>

using --user kumod is recommended if you installed a .deb or .rpm package, in order to avoid breaking file/directory ownership

It’s running in a Docker container.

that error about validate_config is weird. What version are you running?

kumod -V

I believe our Docker compose is using the kumomta-dev:latest container, as shown below:

# docker-compose.yml

services:
  kumo:
    image: ghcr.io/kumocorp/kumomta-dev:latest
    ...

When I run that command it shows version: kumod 2025.01.29-833f82a8.

not crazy old then

weird; I suspect there’s something a bit off with the config and this is an unfortunately awful case of not showing you the root cause of the problem

Is this the correct understanding of these values?

socks5_proxy_source_address - ip that the message is going out on
socks5_proxy_server - ip/fqdn of proxy server with port

[source."ip-2"]
# Use Socks5 Proxy Server for outgoing SMTP Connection
socks5_proxy_source_address = 'actual.public.ip.addr'
socks5_proxy_server = 'kumo-proxy:5000'
ehlo_domain = 'smtp.example.com'

Yes.

You should be able to connect manually from your MTA node to that proxy to test it.
In your case, the proxy server lives at “Kumo-proxy:5000” and the egress ip is “actual.public.ip.addr” but there must be routing in the proxy server to enable that.

For instance, If your proxy has internal NAT from 10.1.1.1 to 200.50.50.1 , then you could use something like
socks5_proxy_source_address = '10.1.1.1', socks5_proxy_server = '10.1.1.1:5000', ehlo_domain = 'mta1.examplecorp.com',

Something like this should test it from your MTA node

nc -v -xkumo-proxy:5000 -Xconnect -s actual.public.ip.addr gmail.com 25

Note that I am doing this by memory on my phone, so you may need to massage that a bit :slightly_smiling_face: