albertito / chasquid

SMTP (email) server with a focus on simplicity, security, and ease of operation [mirror]

Home Page:https://blitiri.com.ar/p/chasquid/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add support for specifying outbound source IP address (i.e. for multi-homed servers)

cipriancraciun opened this issue · comments

In case of multi-homed servers (having multiple public interfaces, with multiple default routes but using routing policies) it would be useful to have an option to specify the local IP address that should be used to connect from (i.e. bind(local_address) then connect(remote_address)).

This should be configurable through the configuration file, for example: smtp_local_address = "9.9.9.9".

In fact, by default this IP address should be initialized with the IP from smtp_address, as most likely the IP used to accept inbound SMTP connections should also be used for outbound SMTP connections. (And in case that is missing, just use 0.0.0.0 as it currently is.)


Looking at the source code, I assume that one could just change:
https://github.com/albertito/chasquid/blob/master/internal/courier/smtp.go#L128

	conn, err := net.DialTimeout("tcp", mx+":"+*smtpPort, smtpDialTimeout)

with

        localAddress = ...
        remoteAddress, err := net.ResolveTCPAddr("tcp", mx+":"+*smtpPort)
        ...
	conn, err := net.DialTcp("tcp", localAddress, remoteAddress)
        ...

However that loses the smtpDialTimeout functionality.

Or perhaps using the net.Dialer type, although that might be somewhat more complex.

Sorry I didn't reply before, I thought I had :(

Thanks for the suggestion!

I need to read up/refresh my knowledge on route policies a bit, think about the implications of this more carefully. It's not clear to me this is worth the complexity, but it definitely could be.

If there's more information that would help prioritize this higher, (e.g. more folks running into this, no possible workarounds, etc.) please let me know.

Thank you!

I need to read up/refresh my knowledge on route policies a bit, think about the implications of this more carefully. It's not clear to me this is worth the complexity, but it definitely could be.

In essence chasquid shouldn't care at all about the routing; using (Linux) routing policies was just an example how one could achieve this (and doesn't directly involve chasquid), there are also other techniques (such as a router downstream switching the provider based on the source IP).

Just bind-ing on a given IP (as opposed to the default 0.0.0.0) should be enough to implement this feature.

If there's more information that would help prioritize this higher, (e.g. more folks running into this, no possible workarounds, etc.) please let me know.

I'm not sure many would use this feature (as many servers have one IP and one default route). Regarding work-arounds there are, but they aren't as straight-forward as having chasquid bind on the desired IP.

I think this should work to implement it with a context timeout:

d := net.Dialer{
	// LocalAddr = ...,
	Timeout: smtpDialTimeout,
}

conn, err := d.Dial("tcp", mx+":"+*smtpPort)
if err != nil {
	return a.tr.Errorf("Could not dial: %v", err), false
}
defer conn.Close()

EDIT: replaced the context with Dialer.Timeout