Code Monkey home page Code Monkey logo

go-policyd's Introduction

lock go-policyd : Postfix policyd daemon

Build Status Go Report Card release

go-policyd is an anti-spam plugin for Postfix (written in Golang) that does sasl-based throttling.

Project purpose is to rate limit postfix outgoing emails sent per user via 'authenticated' abused user when phishing succeeds.

This daemon has been inspired from a existing policy golang daemon : polka. Go language is easy to install, making this project easy to read and adapt to suit your needs.

go-policyd use postfix policy protocol (check Postfix SMTP Access Policy Delegation).

Based on recipients numbers cumulated by day it responds DUNNO (neutral)/ HOLD (store in quarantine)/ REJECT ( refuse mail.).

Using a centralized database, it may be used for multiple authenticated postfix relays or clustering.

Using this projects we successfully reduced our spam volume during phishing campaigns from 60.000 users spammed to 1500 per day.

Main features

accept.png Quota of total recipients by day for an authenticated sender.

accept.png Hold queue when over quota for mail analysis and requeue if whitelisting or errors.

accept.png Rejection when recipients sum is over 2x quota max (customizable)

accept.png Persistant Mysql/Mariadb storage of policyd events.

accept.png Easy upgrade of a Single binary serving as network daemon, allowing multiple remote postfix smtps (de)centralisation.

accept.png Whitelisting only during offices hours (not weekends). Blacklisted entries are permanent.

accept.png Default accept mode when encountering database issues.

Build

Usual go commands, such as go mod tidy, go build should download dependencies and build binary

Version tag is given from git tag , a simple makefile is :

NAME= $(notdir $(shell pwd))
TAG=$(shell git tag)

{NAME}:
  go build -ldflags '-w -s -X main.Version=${NAME}-${TAG}' -o ${NAME}

How to use go-policyd step by step

  • Create mariadb database,
  • copy binary in /local/bin/policyd,
  • Adapt config file contrib/policyd.cfg to /etc/postfix/policyd.cfg,
  • Enable and start (CentOS systemd) service /local/etc/policyd.service,
  • Configure postfix for policyd restrictions.

Mariadb SQL database creation

Mariadb should be enabled and running in order to create database.

> CREATE USER 'policyd_daemon'@'localhost' IDENTIFIED BY 'yourChoiceOfPassword';
Query OK, 0 rows affected (0.01 sec)

> CREATE DATABASE policyd;
Query OK, 1 row affected (0.00 sec)

> CREATE TABLE IF NOT EXISTS `events` (
  `ts` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `sasl_username` char(8) NOT NULL DEFAULT '',
  `sender` char(80) NOT NULL DEFAULT '',
  `client_address`char(80) NOT NULL DEFAULT '',
  `recipient_count` int(6) DEFAULT NULL,
  PRIMARY KEY (`ts`,`sasl_username`,`sender`,`client_address`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

> GRANT ALL PRIVILEGES ON policyd.* TO 'policyd_daemon'@'localhost';
Query OK, 0 rows affected (0.00 sec)

Nota :

  • DATETIME(3) avoid key collision when multiples connections occurs.
  • The cleaning of records older than 7 days is done daily every 24 hours.
  • A policyd top 20 usage display utility is available in contrib/policyd-top20.sh

warning : sasl_username length may be an issue for you if your logins length are over 8 chars

CentOS Systemd daemon setup

# mkdir -p /local/bin/
# cp policyd /local/bin
# cp contrib/unit.service /local/etc/policyd.service
# cp contrib/policyd.cfg /etc/postfix/policyd.cfg
# edit /etc/postfix/policyd.cfg

# systemctl daemon-reload
# systemctl enable /local/etc/policyd.service
# systemctl start policyd.service
# systemctl status  policyd.service

Binary and config file localisation may be modified

Postfix Configuration

Edit /etc/postfix/main.cf to add :

# Policyd restrictions ( at end_of_data stage for nbrcpt )
smtpd_end_of_data_restrictions = check_policy_service inet:127.0.0.1:9093

Then verify configuration with postfix check command

Monit check (optional)

The daemon once started by systemd is restarted in the event of an unexpected shutdown.

However the daemon is also monitored by monit via the lines

check program policyd with path "/usr/bin/systemctl --quiet is-active policyd"
   if status != 0 then restart
   start program = "/usr/bin/systemctl start policyd.service"
   stop  program = "/usr/bin/systemctl stop  policyd.service"

## When user is over quota, mail is stored to postfix HOLD Queue, send alert
check file daemon.info with path /var/log/daemon.info
    ignore content = "monit"
    if match "DEFERRING overquota" then alert

Logs examples

go-policyd use syslog "daemon.ERR|INFO" facility

# tail /var/log/daemon.err
Sep 23 11:08:56 smtps policyd[8168]: ERROR while UPDATING db :dial tcp 127.0.0.1:3306: connect: connection refused
Sep 23 11:09:03 smtps policyd[8168]: ERROR while UPDATING db :dial tcp 127.0.0.1:3306: connect: connection refused
Sep 25 11:19:55 smtps systemd: Failed to start Policyd go daemon for Postfix.
Sep 25 11:20:20 smtps systemd: Failed to start Policyd go daemon for Postfix.

Nov  9 04:28:46 smtps policyd[25479]: Skipping policyVerify db.Ping Error: driver: bad connection


# tail /var/log/daemon.info
Sep 26 16:23:34 smtps policyd[18771]: Updating db: nathxxx/[email protected]/192.168.39.7/1/6
Sep 26 16:24:22 smtps policyd[18771]: Updating db: anaxxx/[email protected]/192.168.39.96/1/46
Sep 26 16:28:15 smtps policyd[18771]: Updating db: marxxx/[email protected]/192.168.24.154/1/14

Nov  9 04:28:46 smtps policyd: [mysql] 2021/11/09 04:28:46 packets.go:123: closing bad idle connection: unexpected read from socket
Nov  9 04:28:46 smtps policyd[25479]: Skipping policyVerify db.Ping Error: driver: bad connection

The log format is identifier / email / ip / recipients / recipientssumforthelast24h.

Sep 26 16:27:53 smtps policyd[18771]: Updating db: anaxxx/[email protected]/192.168.39.96/2/50

indicates the sending of an email to 2 recipients, bringing the total of recipients over 24 hours to 50.

Postfix re-enqueuing, and mail queue cleaning

Legit messages can be re-enqueued after policyd user whitelisting reconfiguration and a restart of policyd daemon, with commands like :

# postqueue -p | grep legit-user | awk '{ print $1 }' | sed "s/\!//g" | xargs -n 1  postsuper -r

Cleaning of spam/phishing can be done with :

# cd /var/spool/postfix/hold ; ls | postsuper -d -

Additional internal Postfix rate limits

# tail /etc/postfix/main.cf 

# For denial of service mitigations (by ip) please read : 
# http://www.postfix.org/TUNING_README.html#conn_limit
# http://www.jonsblog.org/2011/11/30/stay-off-of-blacklists-limit-postfix-recipients/
# anvil_rate_time_unit (default: 60s).
anvil_rate_time_unit=1h
smtpd_client_connection_count_limit=10
smtpd_client_connection_rate_limit=120
smtpd_client_message_rate_limit=120
smtpd_client_recipient_rate_limit=1000
smtpd_client_event_limit_exceptions=127.0.0.1 <hosts> ...

Going further

Code is short and basic. It is intended to be adapted to suit your needs with few modifications.

So clone, fork, (star,) comment, adapt to your needs, and let me know what we can improve !

.

go-policyd's People

Contributors

thc2cat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

go-policyd's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.