sqlgrey(1)

πŸ’– sqlgrey(1) β€” the Postfix Greylisting Policy Server πŸ’–

okay bestie, sit down, hydrate, because we're about to talk about sqlgrey β€” the little policy server that makes spammers cry. this is a page from the User Contributed Perl Documentation collection, and yes, it's giving very much "I run your mail server and I know it". πŸŽ€


✨ NAME ✨

sqlgrey β€” Postfix Greylisting Policy Server πŸ‘‘


🌸 SYNOPSIS 🌸

sqlgrey [options...]

 -h, --help                 display this help and exit
     --man                  display man page
     --version              output version information and exit
 -d, --daemonize            run in the background
 -p, --pidfile=FILE         write process ID to FILE
                            (overrides 'pidfile' in configfile)
 -k, --kill                 kill a running sqlgrey
                            (identified by 'pidfile' content)
 -f, --configfile=FILE      read config from FILE
                            (default /etc/sqlgrey/sqlgrey.conf)
                            expecting config_param=value lines,
                            - spaces are ignored,
                            - '#' is used for comments

so here's the vibe check on each one, one by one, no skips, periodt:

  • -h, --help β€” shows you this help and then dips. bye! πŸ‘‹
  • --man β€” displays the man page. meta, iconic, obsessed.
  • --version β€” spits out the version info and exits. πŸ’…
  • -d, --daemonize β€” runs it in the background, main character energy but make it lowkey. πŸŒ™
  • -p, --pidfile=FILE β€” writes the process ID to FILE. note: this overrides pidfile in the configfile, so it wins the argument fr.
  • -k, --kill β€” kills a running sqlgrey, and it figures out which one by reading the pidfile content. πŸ”ͺ
  • -f, --configfile=FILE β€” reads config from FILE. default is /etc/sqlgrey/sqlgrey.conf. it expects config_param=value lines, and heads up: spaces are ignored, and # is what you use for comments. 🫢
real talk: the runtime parameters live in the default config file at /etc/sqlgrey/sqlgrey.conf. if you got sqlgrey from sources, go read the HOWTO file inside the compressed archive. if it came prepackaged, look into the documentation tree for this file: /usr/share/doc/sqlgrey-<version>/ on most Linux distributions, for example. ✨

πŸ¦‹ DESCRIPTION πŸ¦‹

Sqlgrey is a Postfix policy server implementing greylisting. say it with me: grey-list-ing. it's the art of being slightly annoying on purpose. 😌

When a request for delivery of a mail is received by Postfix via SMTP, the triplet "CLIENT_IP" / "SENDER" / "RECIPIENT" is built. If it is the first time that this triplet is seen, or if the triplet was first seen less than reconnect-delay minutes (1 is the default), then the mail gets rejected with a temporary error. Hopefully spammers or viruses will not try again later, as it is however required per RFC. πŸ’€ (not them being required to retry, literally handing us the win)

In order to alleviate the reconnect delay, sqlgrey uses a 2-level auto-white-list (AWL) system:

  • As soon as a "CLIENT IP" / "SENDER" is accepted, it is added to an AWL. The couple expires when it isn't seen for more than awl-age days (60 is the default).
  • If group-domain-level "SENDER"s (2 is the default) from the same domain or more use the same "CLIENT IP", another AWL is used based on a "CLIENT IP" / "DOMAIN" couple. This couple expires after awl-age days too. This AWL is meant to be used on high throughput sites in order to:
    • minimize the amount of data stored in database,
    • minimize the amount of processing required to find an entry in the AWL.
    • don't impose any further mail delay when a "CLIENT IP" / "DOMAIN" couple is known.

It can be disabled by setting group-domain-level to 0.

General idea: 🧠

When a SMTP client has been accepted once, if the IP isn't dynamic, greylisting the IP again is only a waste of time when it sends another e-mail. As we already know that this IP runs an RFC-compliant MTA (at least the 4xx error code handling) and will get the new e-mail through anyway.

In the case of mail relays, these AWLs works very well as the same senders and mail domains are constantly coming through the same IP addresses -> the e-mails are quickly accepted on the first try. In the case of individual SMTP servers, this works well if the IP is fixed too. When using a floating IP address, the AWLs are defeated, but it should be the least common case by far.

Why do we put the domain in the AWL and not the IP only? If we did only store IP addresses, polluting the AWL would be far too easy. It would only take one correctly configured MTA sending one e-mail from one IP one single time to put it in a whitelist used whatever future mails from this IP look like.

With this AWL system, one single mail can only allow whitelisting of mails from a single sender from the same IP... balance restored ✨


πŸ’… INSTALLATION πŸ’…

  • Create a "sqlgrey" user. This will be the user the daemon runs as. (yes, the daemon has its own identity, slay)
  • When using a full-fledge SGBD (MySQL and PostgreSQL, not SQLite), create a 'sqlgrey' db user and a 'sqlgrey' database. Grant access to the newly created database to sqlgrey. πŸ—„οΈ
  • Use the packaged init script to start sqlgrey at boot and start it manually.

πŸŽ€ CONFIGURATION πŸŽ€

🌈 General 🌈

  • Start by adding check_policy_service after reject_unauth_destination in /etc/postfix/main.cf:
smtpd_recipient_restrictions =
              ...
              reject_unauth_destination
              check_policy_service inet:127.0.0.1:2501
  • Be aware that some servers do not behave correctly and do not resend mails (as required by the standard) or use unique return addresses. This is the reason why you should maintain whitelists for them. 😭

SQLgrey comes with a comprehensive whitelisting system. It can even be configured to fetch up-to-date whitelists from a repository. See the HOWTO for the details.

πŸ™ˆ Disabling greylisting for some users πŸ™ˆ

If you want to disable greylisting for some users you can configure Postfix like this:

/etc/postfix/sqlgrey_recipient_access:
  i_like_spam@ee.ethz.ch                OK

Then you'll add a check_recipient_access in main.cf before the check_policy_service:

 smtpd_recipient_restrictions =
       ...
       reject_unauth_destination
       check_client_access    hash:/etc/postfix/sqlgrey_client_access
       check_recipient_access hash:/etc/postfix/sqlgrey_recipient_access
       check_policy_service inet:127.0.0.1:10023

⭐ SEE ALSO ⭐

See <http://www.greylisting.org/> for a description of what greylisting is and <http://www.postfix.org/SMTPD_POLICY_README.html> for a description of how Postfix policy servers work. go read, bestie, iykyk πŸ“š


Copyright (c) 2004 by Lionel Bouton.


🧚 LICENSE 🧚

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


πŸ’œ AUTHOR πŸ’œ

Lionel Bouton <lionel-dev@bouton.name>


and that's the whole page, bestie 🫢 this one shipped as part of perl v5.30.0 and got its lil timestamp on 2020-02-16 β€” so go forth, greylist responsibly, and remember: it's not a rejection, it's a vibe check with a 4xx code. πŸ’–βœ¨

πŸ“¦ where this page comes from