On Sat, Dec 24, 2022 at 07:51:42AM +0400, Samer Afach <samer.af...@msn.com> wrote:
> Dear Raf: > > Thank you very much. I just tested my server with mxtoolbox, and all seems > good. I didn't realize mxtoolbox works without MX records, thanks for that > hint. > > I applied 90% of your suggestions, and some I didn't out of fear. I'm > working on understanding them more. Good decision. :-) > I have two questions if you don't mind. > > 1. I see you're telling me to remove smtpd_client_restrictions (for both 465 > and 587?) and only keep smtpd_recipient_restrictions. Can you please > elaborate on the difference? I thought clients connecting to the server are > what we need to restrict. I kind of failed to understand why > smtpd_recipient_restrictions even exists. The reason is that the only important restriction that you need (In my opinion) for ports 465/587 is SASL-authentication. It doesn't matter what the source IP address is if the authentication succeeds (that's assuming that you are certain that brute-force guessing of passwords from around the world won't succeed). The main purpose for smtpd_client_restrictions is to be able to reject connections at the very earliest stage of an SMTP connection: when the connection first happens, and the only information that is available to Postfix is the IP address of the client. So it makes sense to only put criteria there that are based on the source IP address (i.e., things like permit_mynetworks and RBL checks). If you put anything else in smtpd_client_restrictions, its evaluation has to wait until later in the connection. It'll still work, it's just not the "ideal" place for other criteria. The reason that there are many smtpd_*_restrictions parameters is that they each apply to a particular point in time during the SMTP protocol (e.g., HELO/EHLO, MAIL FROM, RCPT TO, DATA). So, you can specify checks that make sense at each point in time. However, for the most part, you can actually put all of the restrictions in a single smtpd_*_restrictions parameter and it will be fine. By default, the decisions are delayed until it's possible to evaluate the restrictions. The only real advantage to splitting up the criteria into separate restrictions parameters is that it makes it possible to reject connections at the earliest possible time. But that probably only matters when the mail volume is very high, and you want to maximise efficiency when rejecting connections (i.e., why wait until the RCPT TO command or DATA command if the HELO/EHLO command is unacceptable). The only real requirement is that you either use smtpd_recipient_restrictions or smtpd_relay_restrictions, and one of a certain set of items must appear in either (or both) of them, or Postfix won't accept that you have tried to prevent being an open relay. See http://www.postfix.org/SMTPD_ACCESS_README.html and the entries in postconf(5) for all of the smtpd_*_restrictions parameters. > With that logic, I only removed > the smtp_* part of the enforced protocols. My fear, which is very paranoid, > is that a peer of mine gets hacked, and then their email server uses nothing > but unencrypted connection. Forcing encryption basically means this issue > will be noticeable. (and if you're wondering why port 25's encryption is > `may` in main.cf, it's because I still don't know how to get fetchmail to > deliver emails without that... another issue to be solved). The restrictions and whether or not encryption happens are not related to each other. Port 25's encryption should definitely be "may". I said that SASL-authentication shouldn't be enabled on port 25. That's not the same thing. Encryption/STARTTLS for incoming connections on port 25 is enabled with smtpd_tls_security_level=may in main.cf. That's great. Keep that. SASL-authenticated for incoming connections on port 25 is enabled with smtpd_sasl_auth_enable=yes in main.cf. That's not useful (other MTAs won't SASL-authenticate with your server on port 25), so it can be removed. The only place that smtpd_sasl_auth_enable=yes is useful is in master.cf when defining the services for ports 465 and 587. Also, you weren't forcing encryption. You you just excluding certain TLS versions from being used when encryption was used. The parameters with "mandatory" in their names excluded certain versions of TLS when *mandatory* encryption was in place. But there was nothing in your configuration that made encryption mandatory. Making encryption mandatory requires something like smtpd_tls_security_level=encrypt or smtpd_tls_wrappermode=yes but you can't do that for port 25. It's important to realise that for email, encryption is almost always opportunistic, not mandatory. Any encryption is better than none when it comes to opportunistic encryption. There can be cases where you are required to encrypt mail sent to particular peers, but that will be by prior arrangement, and you will need to set up a different "transport" in Postfix for that peer, and that transport can have different properties such as mandatory encryption. Often, what that looks like is a peer that you connect to over port 587 rather than port 25. And your transport table specifies this. It can get much more complicated, but that's enough for now. :-) Read the TLS_README if you want more details. If you are concerned about a peer getting hacked (or a MITM attack), you could investigate DANE (DNS-based Authentication of Named Entities). If a domain uses DNSSEC, it's possible to publish the fingerprint of that domain's mail server's TLS key in the DNS. Then, mail clients (other MTAs) can check and make sure not only that when they send an email to that domain, they get a key to encrypt to, but that it's the correct key owned by the domain, and not some other key owned by a MITM attacker. Actually, if the mail server is hacked, they'd keep using the correct key any way. This is really to prevent MITM attacks. If a domain is using DANE to publish its legitimate key, then clients can be configured to only send mail when they see the correct key. The way to do this is that instead of having this in main.cf: smtp_tls_security_level = yes You have this: smtp_dns_support_level = dnssec smtp_tls_security_level = dane AND (very important) you run a DNSSEC-validating DNS resolver like Bind9 or Unbound on the localhost, and put this in /etc/resolv.conf: nameserver 127.0.0.1 options trust-ad That tells Postfix that it can trust DNSSEC lookups, and that it should check if remote MTAs have published their TLS keys and if so, only accept keys that match the published TLSA DNS records when making outgoing SMTP connections. And of course, if your own domain uses DNSSEC (much easier nowadays than it used to be), you can publish TLSA records for your own TLS keys, and just hope that other MTAs that send you email have been configured to check for them. Most probably won't, but the number should be increasing. However, setting that up doesn't have anything to do with Postfix itself. But there are tools that can help with the setup such as LetsDNS (https://letsdns.org/) and (my) danectl (https://raf.org/danectl). > 2. It's been too long and I'm too afraid to ask (Chris Pratt meme goes > here): Is smtp strictly for outgoing connections, no matter what port, and > smtpd for incoming connections, no matter what port? That's right. smtpd_* is for incoming connections. When it's in main.cf, it applies to port 25. When it's in master.cf, it applies to the port of the particular service definition where it appears. smtp_* is for outgoing connections whether it's going to a peer's port 25, or to a peer's port 465/587 (which would only happen if there's an entry for a particular domain in the transport table that tells Postfix to connect via one of those ports - some peers might require authentication and encryption). > Btw, just a note since you mentioned it, while using one file for keys + > certificates has an advantage, I have to say that letsencrypt really annoys > me that it doesn't do that automatically. I have a to run cron jobs to > recreate this for HAProxy... because HAProxy only accepts one file with > everything in it. Your comment explained to me why HAProxy enforces this, > but doesn't explain why letsencrypt cannot add a `cat` call after recreating > the certificates. Cron isn't the best choice because it doesn't know when the certificate renews. You can automate this with LetsEncrypt's deploy hooks. You can run a script that performs the cat as soon as the key and certificate are renewed (rather than waiting for the cronjob to happen). If you set up a deploy hook that runs the following script, there will always be a single file containing the privkey and fullchain that matches the underlying files: /etc/postfix/mktlschain: #!/bin/sh -e # Postfix recommends a single file, containing both the private key # and the certificate chain, as that makes it possible to rollover # keys atomically and avoid race conditions. # http://www.postfix.org/TLS_README.html # This is run automatically when the LetsEncrypt certificate is renewed. # Note: a Postfix reload is not required after this. # Note: this puts the file in $RENEWED_LINEAGE (i.e., /etc/letsencrypt/live/CERTNAME) # so that multiple lineages for the same domain can coexist. This is needed for use # with danectl(1). When using danectl, refer to /etc/letsencrypt/current rather # than /etc/letsencrypt/live in main.cf. [ -n "$RENEWED_LINEAGE" -a -d "$RENEWED_LINEAGE" ] || exit 1 cd "$RENEWED_LINEAGE" chain=privkey-then-fullchain-for-postfix.pem umask 077 touch $chain.tmp chmod 600 $chain.tmp cat privkey.pem fullchain.pem > $chain.tmp mv $chain.tmp $chain chmod 600 $chain Installing this as a LetEncrypt deploy hook depends on whether or not you only have a single domain. If so, you can put the script file in the /etc/letsencrypt/renewal-hooks/deploy directory. It's more complicated if you have LetsEncrypt handling multiple domains on the same host because LetsEncrypt wants to run the same hook script for every domain, and you probably only need this for one of them. But it should be easy to adapt. I have a setup that has distinct per-domain hooks. > Thanks a lot for looking into my configuration. That's very generous of you. No worries. I hope you're having fun with Postfix! > Cheers, > Sam cheers, raf