slimta / python-slimta

Python libraries to send, receive, and queue email.
https://slimta.org/
MIT License
171 stars 43 forks source link

Support proxy-protocol #148

Closed frmdstryr closed 5 years ago

frmdstryr commented 5 years ago

When running behind a reverse-proxy, eg nginx, haproxy, the client IP can't be determined to check for spam. It would be nice to have a flag to enable the proxy protocol on the SmtpEdge like Postfix to get the actual client IP instead of the proxy itself.

I implemented it by extending the SmtpEdge as follows, would you be willing to accept a PR for this if it were added as a flag to the smtp edge (or a sublcass as done here)?

import re
from slimta.edge.smtp import SmtpEdge

class ProxiedSmtpEdge(SmtpEdge):

    def handle_proxy(self, socket, address):
        """ Check proxy protocol v1

        """
        proxy_line = socket.recv(108)

        # Check long case, proto, src_ip, dst_ip, src_port, dst_port
        m = re.match(rb'PROXY (TCP4|TCP6|UNKNOWN) (.+) (.+) (\d+) (\d+)\r\n',
                     proxy_line)
        if m:
            return (m.group(2).decode(), int(m.group(4)), 0, 0)

        # Check short case
        m = re.match(rb'PROXY (UNKNOWN)\r\n', proxy_line)
        if m:
            return address  # Local address

        # Any sequence which does not exactly match the protocol must be
        # discarded and cause the receiver to abort the connection.
        socket.close()
        return

    def handle(self, socket, address):
        # Read PROXY protocol
        address = self.handle_proxy(socket, address)
        if not address:
            return
        return super(ProxiedSmtpEdge, self).handle(socket, address)

Thanks for the great library!

thestick613 commented 5 years ago

This is already implemented, i think: https://github.com/slimta/python-slimta/issues/45

frmdstryr commented 5 years ago

Wow, didn't see that... Thank you!