📜 ⬆️ ⬇️

Limiting outgoing messages on a server with postfix and postfwd

On the server where the sites of different users are located, the possibility of sending messages through a local mail server is most often provided. In the case of hacking one of the sites there is the possibility of sending spam messages, which can lead to serious consequences, such as entering the IP address of the mail server in the block lists.

In order to prevent the possibility of discrediting the mail server, it is necessary to limit the maximum number of outgoing messages that each user can send in a certain period of time.

The problem is not completely trivial, and the purpose of this article is to demonstrate a ready-made solution that can be used in production.

Baseline: Debian 8 OS ("Jessie"), Postfix mail server.
')

Install and configure the postfwd package


Install the postfwd package with apt:

apt-get install postfwd 

The package does not have a configuration file and does not run by default. Create a /etc/postfix/postfwd.cf configuration file and add a rule (sending no more than 50 messages per hour for one user):

 id=R001; action=rcpt(sender/50/3600/REJECT limit of 50 recipients per hour for sender $$sender exceeded) 

More information about the configuration of postfwd can be found in the documentation on the project website .

Edit the / etc / default / postfwd file :

 #    STARTUP=1 #   ,    CONF=/etc/postfix/postfwd.cf # IP ,        INET=127.0.0.1 # ,        PORT=10040 # ,     RUNAS="nobody" # ,      ARGS="--summary=600 --cache=600 --cache-rdomain-only --cache-no-size" 

Restart the postfwd service:

 service postfwd restart 

And check that everything works as it should:

 srv1:~# tail /var/log/mail.log Jun 9 14:14:18 srv1 postfwd2/master[37242]: postfwd2 1.35 starting Jun 9 14:14:18 srv1 postfwd2/master[37244]: Started cache at pid 37245 Jun 9 14:14:18 srv1 postfwd2/master[37244]: Started server at pid 37246 Jun 9 14:14:18 srv1 postfwd2/cache[37245]: ready for input Jun 9 14:14:18 srv1 postfwd2/policy[37246]: ready for input 

Postfix and postfwd integration


In order to integrate the Postfix mail server and the postfwd service, you need to change the configuration file /etc/postfix/main.cf , adding the following parameters to it:

 #   policy service - postfwd       smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10040, permit_sasl_authenticated, reject_unauth_destination #   policy service - postfwd smtpd_end_of_data_restrictions = check_policy_service inet:127.0.0.1:10040 

The posftwd connection should be made at the beginning, this is due to the feature of the parameters interpretation by the Postfix mail server. If the smtpd_recipient_restrictions and smtpd_end_of_data_restrictions parameters are already set in the configuration file, you must change them so that check_policy_service inet: 127.0.0.1: 10040 and permit_sasl_authenticated are located at the beginning.

Reboot configuration:

 srv1:~# postfix reload postfix/postfix-script: refreshing the Postfix mail system 

After rebooting, postfwd starts its work and periodically displays statistics in the mail log (/var/log/mail.log):

 srv1:~# tail /var/log/mail.log | grep postfwd Jun 9 14:24:18 srv1 postfwd2/master[37244]: [STATS] postfwd2::policy 1.35: 1 requests since 0 days, 00:09:59 hours Jun 9 14:24:18 srv1 postfwd2/master[37244]: [STATS] Requests: 0.10/min last, 0.10/min overall, 0.10/min top Jun 9 14:24:18 srv1 postfwd2/master[37244]: [STATS] Dnsstats: 0.00/min last, 0.00/min overall, 0.00/min top Jun 9 14:24:18 srv1 postfwd2/master[37244]: [STATS] Hitrates: 0.0% ruleset, 0.0% parent, 0.0% child, 0.0% rates Jun 9 14:24:18 srv1 postfwd2/master[37244]: [STATS] Timeouts: 0.0% (0 of 0 dns queries) Jun 9 14:24:18 srv1 postfwd2/master[37244]: [STATS] 1 matches for id: R001 

Now all users who send emails via an SMTP server will be set to the limits corresponding to the rules specified in postfwd (in our case, only one rule is set). However, all messages sent via / usr / sbin / sendmail will not be filtered, since Postfix sends them directly to the queue, bypassing postfwd.

Stub settings for / usr / sbin / sendmail


The simplest and most effective solution is to use a “stub” for the / usr / sbin / sendmail script, which would send all correspondence through an SMTP server with authorization. Accordingly, it is also necessary to prohibit sending messages via SMTP to unauthorized local users. We check that in the configuration file /etc/postfix/main.cf there is no parameter permit_mynetworks in smtpd_recipient_restrictions - in this case, authorization will be required even for local users.
In order to apply the solution with a “stub” in practice, you need to create mailboxes on the mail server that will correspond to users, as well as a “default” box, for example:


You must set one password for all mailboxes (site1, site2, etc.), and another password for default@myserver.org. There is no need to save letters in these boxes, so you can configure forwarding in / dev / null.
A similar configuration for the above rule allows postfwd sending up to 50 emails per hour to all users with a “separate” account, and sending 50 messages “for all” for users who do not have a separate account.
The stub will work as follows:

  1. Identify the name of the user who launched our script
  2. Try to log in to the mail server using the username obtained in paragraph 1
  3. In case of an error, autorize as default
  4. Forward a letter

The code is written in Perl and requires the installation of additional modules, install them through CPAN:

 srv1:~# cpan Net::SMTP_auth Email::Address 

Create a directory in which we will store the script (for example, / usr / local / bin / private), as well as an unprivileged user who becomes the "owner" of the directory and script:

 srv1:~# mkdir /usr/local/bin/private srv1:~# useradd sendmail 

Add a “stub” script to the created directory (/usr/local/bin/private/sendmail.pl), replacing the variables $ smtp_password, $ smtp_default_password and $ server, respectively, with the password of user boxes, the password of the box “by default” and your address the host on which the boxes are created:

 #!/usr/bin/perl use strict; use warnings; use Net::SMTP_auth; use Email::Address; my $user = getpwuid( $< ); my $smtp_password = 'password'; my $smtp_default_password = 'password'; my $server = 'srv1.re-hash.org'; my $input = ''; my $to_string = ''; foreach my $line ( <STDIN> ) { $input .= $line; if ($line =~ /^To:/) { $to_string = $line; } } my @addrs = Email::Address->parse($to_string); if (0+@addrs eq 0) { die "No recipients"; } my $rec = $addrs[0]; $rec =~ s/\@/\\@/; my $smtp = Net::SMTP_auth->new('127.0.0.1', Port => 25, Timeout => 10, Debug => 0); die "Could not connect to SMTP server!\n" unless $smtp; if (!$smtp->auth('PLAIN', $user.'@'.$server, $smtp_password)) { $smtp->auth('PLAIN', 'default@'.$server, $smtp_default_password) or die "Auth failed!\n"; } $smtp->mail($user.'\@'.$server); $smtp->to($rec); $smtp->data(); $smtp->datasend($input); $smtp->dataend(); $smtp->quit; 

Set the rights to the directory and script. You need to make sure that users can execute the script, but not read it:

 srv1:~# chown -R sendmail:sendmail /usr/local/bin/private srv1:~# chmod -R 4711 /usr/local/bin/private 

You can rename the old file / usr / sbin / sendmail (for example, sendmail-postfix), or remove its permissions to execute.
In principle, now instead of / usr / sbin / sendmail you can use the path /usr/local/bin/private/sendmail.pl (or immediately save the script as / usr / sbin / sendmail), but I wanted to do it differently. So I decided to write another wrapper (yes, wrapper over the wrapper), which will replace / usr / sbin / sendmail. The wrapper code (wrapper.c) is written in C and looks like this:

 /* wrapper.c */ #define REAL_PATH "/usr/local/bin/private/sendmail.pl" main(ac, av) char **av; { execv(REAL_PATH, av); } 

Compile this file, copy it to / usr / sbin and set the appropriate rights:

 srv1:~# cc -o sendmail wrapper.c srv1:~# cp -a ./sendmail /usr/sbin/sendmail srv1:~# chown -R sendmail:sendmail /usr/sbin/sendmail srv1:~# chmod -R 4711 /usr/sbin/sendmail 

After completing the above steps, all sites should send email messages in the same way as before, but limits and rules set in the postfwd configuration will be applied to the sent messages.

Wrapper source code is available at GitHub: github.com/xtremespb/sendmail-wrapper .
I would be happy to receive comments and suggestions for improving the limiting mechanism in the comments.

Source: https://habr.com/ru/post/259937/


All Articles