Hello folks,
Here's a suggested improvement to spamd(8) that keeps blacklisted entries
tarpitted while they keep trying. Rationale: often blacklists like
uatraps will remove hosts because they have stopped trying there, but will
continue elsewhere. If your host is 'elsewhere', and a blacklisted
spammer has tried to deliver mail to you, then you will want to keep this
spammer trapped for a while even though it has vanished from the blacklist.
With this diff, a tarpitted host is inserted or updated as a TRAPPED entry
in /var/db/spamd on every incoming tarpit connection. A downside is that
the jailed process is no longer chrooted. If that is unacceptable, it
could perhaps chroot to dirname(PATH_SPAMD_DB) instead.
--- /usr/src/libexec/spamd/spamd.c Sat Feb 20 18:59:32 2010
+++ /usr/src/libexec/spamd/spamd.c Mon Jun 4 10:01:10 2012
@@ -45,6 +45,7 @@
extern int server_lookup(struct sockaddr *, struct sockaddr *,
struct sockaddr *);
+extern int trapupdate(char *, char *);
struct con {
int fd;
@@ -660,6 +661,7 @@
if (greylist && blackcount > maxblack)
cp->stutter = 0;
cp->lists = strdup(loglists(cp));
+ trapupdate(PATH_SPAMD_DB, cp->addr);
}
else
cp->lists = NULL;
@@ -1306,11 +1308,6 @@
}
jail:
- if (chroot("/var/empty") == -1 || chdir("/") == -1) {
- syslog(LOG_ERR, "cannot chdir to /var/empty.");
- exit(1);
- }
-
if (pw)
if (setgroups(1, &pw->pw_gid) ||
setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
--- /dev/null Mon Jun 4 09:52:51 2012
+++ /usr/src/libexec/spamd/trapupdate.c Wed Mar 7 09:54:38 2012
@@ -0,0 +1,89 @@
+/* update trapped entries. */
+
+#include <sys/types.h> /* inet_pton, dbopen */
+#include <sys/socket.h> /* inet_pton */
+
+#include <netinet/in.h> /* inet_pton */
+#include <arpa/inet.h> /* inet_pton */
+
+#include <db.h> /* dbopen */
+#include <errno.h> /* errno */
+#include <fcntl.h> /* dbopen */
+#include <syslog.h> /* syslog_r */
+#include <string.h> /* memset, strerror */
+
+#include "grey.h"
+#include "sync.h"
+
+extern int debug;
+extern struct syslog_data sdata;
+extern int syncsend;
+extern time_t trapexp;
+
+int
+trapupdate(char *dbname, char *ip)
+{
+ HASHINFO hashinfo;
+ DBT dbk, dbd;
+ DB *db;
+ struct gdata gd;
+ time_t now;
+ int r;
+
+ now = time(NULL);
+ memset(&hashinfo, 0, sizeof(hashinfo));
+ db = dbopen(dbname, O_EXLOCK|O_RDWR, 0600, DB_HASH, &hashinfo);
+ if (db == NULL) {
+ syslog_r(LOG_ERR, &sdata, "Can not open db %s: %s", dbname,
+ strerror(errno));
+ return -1;
+ }
+ memset(&dbk, 0, sizeof(dbk));
+ dbk.size = strlen(ip);
+ dbk.data = ip;
+ memset(&dbd, 0, sizeof(dbd));
+
+ /* add or update trapped entry */
+ r = db->get(db, &dbk, &dbd, 0);
+ if (r == -1) {
+ syslog_r(LOG_NOTICE, &sdata, "db->get failed (%m)");
+ goto bad;
+ }
+
+ if (r) {
+ /* new entry */
+ memset(&gd, 0, sizeof(gd));
+ gd.first = now;
+ gd.pass = now;
+ gd.bcount = 1;
+ } else {
+ if (dbd.size != sizeof(gd)) {
+ /* whatever this is, it doesn't belong */
+ db->del(db, &dbk, 0);
+ goto bad;
+ }
+ memcpy(&gd, dbd.data, sizeof(gd));
+ gd.bcount++;
+ }
+ gd.pcount = -1;
+ gd.expire = now + trapexp;
+ memset(&dbk, 0, sizeof(dbk));
+ dbk.size = strlen(ip);
+ dbk.data = ip;
+ memset(&dbd, 0, sizeof(dbd));
+ dbd.size = sizeof(gd);
+ dbd.data = &gd;
+ r = db->put(db, &dbk, &dbd, 0);
+ db->close(db);
+ if (r) {
+ syslog_r(LOG_NOTICE, &sdata, "db->put failed (%m)");
+ return -1;
+ }
+ if (syncsend)
+ sync_trapped(now, now + trapexp, ip);
+ return 0;
+bad:
+ db->close(db);
+ return -1;
+}
+
--
Gemaakt met Opera's revolutionaire e-mailprogramma:
http://www.opera.com/mail/
(Remove the obvious prefix to reply privately.)