Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
cipriancraciun opened this issue Oct 21, 2021 · 3 comments
Assignees

Comments

@cipriancraciun
Copy link

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.

@albertito albertito self-assigned this Oct 22, 2021
@albertito
Copy link
Owner

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!

@cipriancraciun
Copy link
Author

cipriancraciun commented Jun 19, 2022

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.

@ThinkChaos
Copy link
Contributor

ThinkChaos commented Jun 19, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants