Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Mar 2006 15:49:08 +1100 (EST)
From:      Maurice Castro <maurice@sphinx.clari.net.au>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   ports/94715: modification to mail/spamd port to use ipfw
Message-ID:  <200603200449.k2K4n8Tf018205@sphinx.clari.net.au>
Resent-Message-ID: <200603200450.k2K4oF15054881@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         94715
>Category:       ports
>Synopsis:       modification to mail/spamd port to use ipfw
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Mar 20 04:50:15 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Maurice Castro
>Release:        FreeBSD 5.4-RELEASE i386
>Organization:
Calrinet Internet Solutions
>Environment:
System: FreeBSD sphinx.clari.net.au 5.4-RELEASE FreeBSD 5.4-RELEASE #1: Wed Nov 30 11:05:23 EST 2005 mjb@sphinx.clari.net.au:/work/src/sys/i386/compile/sphinx i386


	All FreeBSD post 4.9
>Description:
	Patch for mail/spamd port to allow compilation with make -DIPFW to 
	generate a version of spamd that works without the need for pf.
>How-To-Repeat:
	Apply patch
>Fix:


diff -urN /usr/ports/mail/spamd/Makefile spamd_new/Makefile
--- /usr/ports/mail/spamd/Makefile	Mon Jul 18 13:24:33 2005
+++ spamd_new/Makefile	Fri Mar 17 16:40:03 2006
@@ -19,11 +19,19 @@
 
 .include <bsd.port.pre.mk>
 
+.if defined(IPFW)
+CFLAGS+= -DIPFW
+.if ${OSVERSION} < 490000
+IGNORE=		IPFW with Tables is required for this port to function properly
+.endif
+.else
 .if ${OSVERSION} < 502117
 IGNORE=		OpenBSD 3.5 pf/pfctl is necessary for this port to function properly.
 .else
 LOCAL_PFCTL=	/sbin/pfctl
 .endif
+.endif
+
 
 USE_RC_SUBR=	yes
 RC_SCRIPTS_SUB=	PREFIX=${PREFIX} RC_SUBR=${RC_SUBR}
@@ -46,7 +54,7 @@
 	@${REINPLACE_CMD} -e 's|/etc/spamd.conf|${PREFIX}/etc/spamd.conf|' \
 	    ${WRKSRC}/spamd/spamd.8 ${WRKSRC}/spamd-setup/spamd-setup.8
 	@${SED} ${RC_SCRIPTS_SUB:S/$/!g/:S/^/ -e s!%%/:S/=/%%!/} \
-		${FILESDIR}/pfspamd.sh > ${WRKDIR}/pfspamd.sh
+		${FILESDIR}/pfspamd.sh > ${WRKDIR}/pfspamd.sh 
 
 pre-su-install:
 .if !defined(BATCH) && !defined(PACKAGE_BUILDING)
@@ -63,11 +71,11 @@
 	${INSTALL_MAN} ${WRKSRC}/spamd-setup/spamd-setup.8 ${PREFIX}/man/man8
 	${INSTALL_MAN} ${WRKSRC}/spamdb/spamdb.8 ${PREFIX}/man/man8
 	${INSTALL_MAN} ${WRKSRC}/spamlogd/spamlogd.8 ${PREFIX}/man/man8
-	@${INSTALL_SCRIPT} -m 555 ${WRKDIR}/pfspamd.sh ${PREFIX}/etc/rc.d/pfspamd.sh
 	@if [ ! -f ${SAMPLE_SPAMD_CONF} ]; then			\
 		${ECHO_MSG} "Installing ${SAMPLE_SPAMD_CONF} file."; \
 		${INSTALL_DATA} ${WRKSRC}/doc/spamd.conf	\
 		${SAMPLE_SPAMD_CONF};				\
 	fi
+	@${INSTALL_SCRIPT} -m 555 ${WRKDIR}/pfspamd.sh ${PREFIX}/etc/rc.d/pfspamd.sh
 
 .include <bsd.port.post.mk>
diff -urN /usr/ports/mail/spamd/files/patch-greyc spamd_new/files/patch-greyc
--- /usr/ports/mail/spamd/files/patch-greyc	Thu Jan  1 10:00:00 1970
+++ spamd_new/files/patch-greyc	Mon Mar 20 15:33:11 2006
@@ -0,0 +1,131 @@
+--- spamd/grey.c	Wed Apr 13 03:22:17 2005
++++ spamd/grey.c	Mon Mar 20 15:26:18 2006
+@@ -39,6 +39,10 @@
+ #include <unistd.h>
+ #include <netdb.h>
+ 
++#ifdef IPFW
++#include <netinet/ip_fw.h>
++#endif
++
+ #include "grey.h"
+ 
+ extern time_t passtime, greyexp, whiteexp, trapexp;
+@@ -65,13 +69,17 @@
+ char *traplist_msg = "\"Your address %A has mailed to spamtraps here\\n\"";
+ 
+ pid_t db_pid = -1;
+-int pfdev;
+ int spamdconf;
+ 
++#ifdef IPFW
++extern int tabno;
++#else
++int pfdev;
+ static char *pargv[11]= {
+ 	"pfctl", "-p", "/dev/pf", "-q", "-t",
+ 	"spamd-white", "-T", "replace", "-f" "-", NULL
+ };
++#endif
+ 
+ /* If the parent gets a signal, kill off the children and exit */
+ /* ARGSUSED */
+@@ -104,6 +112,7 @@
+ 	return(0);
+ }
+ 
++#ifndef IPFW
+ int
+ configure_pf(char **addrs, int count)
+ {
+@@ -166,11 +175,54 @@
+ 	for (i = 0; i < count; i++)
+ 		if (addrs[i] != NULL)
+ 			fprintf(pf, "%s/32\n", addrs[i]);
++
+ 	fclose(pf);
+ 	waitpid(pid, NULL, 0);
+ 	sigaction(SIGCHLD, &sa, NULL);
+ 	return(0);
+ }
++#else
++int
++configure_pf(char **addrs, int count)
++{
++	int s = -1;
++	ipfw_table_entry ent;
++	int i;
++
++	if (s == -1)
++		s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
++	if (s < 0)
++	{
++		syslog_r(LOG_INFO, &sdata, "IPFW socket unavailable (%m)");
++		return(-1);
++	}
++
++	/* flush the table */	
++	ent.tbl = tabno;
++	if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_FLUSH,  &ent.tbl, sizeof(ent.tbl)) < 0)
++	{
++		syslog_r(LOG_INFO, &sdata, "IPFW setsockopt(IP_FW_TABLE_FLUSH) (%m)");
++		return(-1);
++	}
++
++	for (i = 0; i < count; i++)
++		if (addrs[i] != NULL)
++	{
++		/* add addrs[i] to tabno */
++		ent.tbl = tabno;
++		ent.masklen = 32;
++		ent.value = 0;
++		inet_aton(addrs[i], (struct in_addr *)&ent.addr);
++		if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_ADD,  &ent, sizeof(ent)) < 0)
++		{
++			syslog_r(LOG_INFO, &sdata, "IPFW setsockopt(IP_FW_TABLE_ADD) (%m)");
++			return(-1);
++		}
++	}
++
++	return(0);
++}
++#endif
+ 
+ void
+ freeaddrlists(void)
+@@ -590,11 +642,13 @@
+ 	int i;
+ 	struct sigaction sa;
+ 
++#ifndef IPFW
+ 	pfdev = open("/dev/pf", O_RDWR);
+ 	if (pfdev == -1) {
+ 		syslog_r(LOG_ERR, &sdata, "open of /dev/pf failed (%m)");
+ 		exit(1);
+ 	}
++#endif
+ 
+ 	/* check to see if /var/db/spamd exists, if not, create it */
+ 	if ((i = open(PATH_SPAMD_DB, O_RDWR, 0)) == -1 && errno == ENOENT) {
+@@ -636,7 +690,9 @@
+ 		 * child, talks to jailed spamd over greypipe,
+ 		 * updates db. has no access to pf.
+ 		 */
++#ifndef IPFW
+ 		close(pfdev);
++#endif
+ 		setproctitle("(%s update)", PATH_SPAMD_DB);
+ 		greyreader();
+ 		/* NOTREACHED */
+@@ -655,7 +711,11 @@
+ 	sigaction(SIGCHLD, &sa, NULL);
+ 	sigaction(SIGINT, &sa, NULL);
+ 
++#ifndef IPFW
+ 	setproctitle("(pf <spamd-white> update)");
++#else
++	setproctitle("(ipfw white table update)");
++#endif
+ 	greyscanner();
+ 	/* NOTREACHED */
+ 	exit(1);
diff -urN /usr/ports/mail/spamd/files/patch-greyh spamd_new/files/patch-greyh
--- /usr/ports/mail/spamd/files/patch-greyh	Thu Jan  1 10:00:00 1970
+++ spamd_new/files/patch-greyh	Thu Mar 16 21:18:51 2006
@@ -0,0 +1,10 @@
+--- spamd/grey.h	Thu Mar 16 19:55:33 2006
++++ spamd/grey.h	Thu Mar 16 19:55:56 2006
+@@ -22,6 +22,7 @@
+ #define WHITEEXP (60 * 60 * 24 * 36) /* remove white entries after 36 days */
+ #define TRAPEXP (60 * 60 * 24) /* hitting a spamtrap blacklists for a day */
+ #define PATH_PFCTL "/sbin/pfctl"
++#define PATH_IPFW "/sbin/ipfw"
+ #define DB_SCAN_INTERVAL 60
+ #define PATH_SPAMD_DB "/var/db/spamd"
+ 
diff -urN /usr/ports/mail/spamd/files/patch-spamd spamd_new/files/patch-spamd
--- /usr/ports/mail/spamd/files/patch-spamd	Thu Jan  1 10:00:00 1970
+++ spamd_new/files/patch-spamd	Fri Mar 17 08:20:06 2006
@@ -0,0 +1,48 @@
+--- spamd/spamd.c	Thu Mar 16 20:56:45 2006
++++ spamd/spamd.c	Thu Mar 16 21:07:11 2006
+@@ -123,6 +123,10 @@
+ pid_t jail_pid = -1;
+ u_short cfg_port;
+ 
++#ifdef IPFW
++int tabno=1;
++#endif
++
+ extern struct sdlist *blacklists;
+ 
+ int conffd = -1;
+@@ -153,6 +157,10 @@
+ 	    "             [-G mins:hours:hours] [-n name] [-p port]\n");
+ 	fprintf(stderr,
+ 	    "             [-r reply] [-s secs] [-w window]\n");
++#ifdef IPFW
++	fprintf(stderr,
++	    "             [-t table_no]\n");
++#endif
+ 	exit(1);
+ }
+ 
+@@ -958,7 +966,11 @@
+ 	if (gethostname(hostname, sizeof hostname) == -1)
+ 		err(1, "gethostname");
+ 
++#ifdef IPFW
++	while ((ch = getopt(argc, argv, "45b:c:B:p:dgG:r:s:n:vw:t:")) != -1) {
++#else
+ 	while ((ch = getopt(argc, argv, "45b:c:B:p:dgG:r:s:n:vw:")) != -1) {
++#endif
+ 		switch (ch) {
+ 		case '4':
+ 			nreply = "450";
+@@ -1015,6 +1027,11 @@
+ 		case 'v':
+ 			verbose = 1;
+ 			break;
++#ifdef IPFW
++		case 't':
++			tabno = atoi(optarg);
++			break;
++#endif
+ 		case 'w':
+ 			window = atoi(optarg);
+ 			if (window <= 0)
diff -urN /usr/ports/mail/spamd/files/patch-spamd-setup spamd_new/files/patch-spamd-setup
--- /usr/ports/mail/spamd/files/patch-spamd-setup	Thu Jan  1 10:00:00 1970
+++ spamd_new/files/patch-spamd-setup	Mon Mar 20 15:33:22 2006
@@ -0,0 +1,115 @@
+--- spamd-setup/spamd-setup.c	Wed Apr 13 03:18:59 2005
++++ spamd-setup/spamd-setup.c	Fri Mar 17 16:19:25 2006
+@@ -41,9 +41,14 @@
+ #include <netdb.h>
+ #include <zlib.h>
+ 
++#ifdef IPFW
++#include <net/if.h>
++#include <netinet/ip_fw.h>
++#endif
++
+ #define PATH_FTP		"/usr/bin/ftp"
+-#define PATH_PFCTL		"%%LOCAL_PFCTL%%"
+-#define PATH_SPAMD_CONF		"%%LOCAL_SPAMD_CONF%%"
++#define PATH_PFCTL		""
++#define PATH_SPAMD_CONF		"/usr/local/etc/spamd.conf"
+ #define SPAMD_ARG_MAX		256 /* max # of args to an exec */
+ 
+ struct cidr {
+@@ -93,6 +98,11 @@
+ int		debug;
+ int		dryrun;
+ 
++#ifdef IPFW
++int tabno=2;
++#endif
++
++
+ u_int32_t
+ imask(u_int8_t b)
+ {
+@@ -630,6 +640,7 @@
+ }
+ 
+ 
++#ifndef IPFW
+ int
+ configure_pf(struct cidr **blacklists)
+ {
+@@ -676,6 +687,51 @@
+ 	}
+ 	return(0);
+ }
++#else
++int
++configure_pf(struct cidr **blacklists)
++{
++	int s = -1;
++	ipfw_table_entry ent;
++
++	if (s == -1)
++		s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
++	if (s < 0)
++	{
++		err(1, "IPFW socket unavailable");
++		return(-1);
++	}
++
++	/* flush the table */   
++	ent.tbl = tabno;
++	if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_FLUSH,  &ent.tbl, sizeof(ent.tbl)) < 0)
++	{
++		err(1, "IPFW setsockopt(IP_FW_TABLE_FLUSH)");
++		return(-1);
++	}
++
++	while (*blacklists != NULL) {
++		struct cidr *b = *blacklists;
++
++		while (b->addr != 0) {
++			/* add b to tabno */
++			ent.tbl = tabno;
++			ent.masklen = b->bits;
++			ent.value = 0;
++			inet_aton(atop(b->addr), (struct in_addr *)&ent.addr);
++			if (setsockopt(s, IPPROTO_IP, IP_FW_TABLE_ADD,  &ent, sizeof(ent)) < 0)
++			{
++				err(1, "IPFW setsockopt(IP_FW_TABLE_ADD)");
++				return(-1);
++			}
++			b++;
++		}
++		blacklists++;
++	}
++
++	return(0);
++}
++#endif
+ 
+ int
+ getlist(char ** db_array, char *name, struct blacklist *blist,
+@@ -773,7 +829,11 @@
+ 	struct servent *ent;
+ 	int i, ch;
+ 
++#ifndef IPFW
+ 	while ((ch = getopt(argc, argv, "nd")) != -1) {
++#else
++	while ((ch = getopt(argc, argv, "ndt")) != -1) {
++#endif
+ 		switch (ch) {
+ 		case 'n':
+ 			dryrun = 1;
+@@ -781,6 +841,11 @@
+ 		case 'd':
+ 			debug = 1;
+ 			break;
++#ifdef IPFW
++		case 't':
++			tabno = atoi(optarg);
++			break;
++#endif
+ 		default:
+ 			break;
+ 		}
diff -urN /usr/ports/mail/spamd/files/patch-spamdm spamd_new/files/patch-spamdm
--- /usr/ports/mail/spamd/files/patch-spamdm	Thu Jan  1 10:00:00 1970
+++ spamd_new/files/patch-spamdm	Mon Mar 20 15:36:57 2006
@@ -0,0 +1,89 @@
+--- spamd/spamd.8	Wed Apr 13 03:21:48 2005
++++ spamd/spamd.8	Mon Mar 20 15:12:10 2006
+@@ -49,6 +49,8 @@
+ daemon which rejects false mail.
+ If the
+ .Xr pf 4
++or
++.Xr ipfw 4
+ packet filter is configured to redirect port 25 (SMTP) to this daemon,
+ it will attempt to waste the time and resources of the spam sender.
+ .Pp
+@@ -151,11 +153,15 @@
+ which processes a list of spammers' addresses, and applies appropriate
+ .Xr pfctl 8
+ .Em rdr
++or
++.Xr ipfw 8
++.Em fwd
+ rules.
+ .Xr spamd-setup 8
+ is run from
+ .Xr cron 8 .
+ .Sh REDIRECTING SMTP CONNECTIONS
++.Ss "When using PF"
+ With
+ .Xr pf 4 ,
+ connections to port 25 (SMTP) can be redirected to another host or port,
+@@ -189,6 +195,8 @@
+ can also be used to load addresses into the
+ .Em <spamd>
+ table.
++
++
+ .Xr spamd-setup 8
+ also has the added benefit of being able to remove addresses from
+ blacklists, and will connect to
+@@ -203,6 +211,52 @@
+ This is important as it allows legitimate mail
+ senders to pressure spam sources into behaving properly so that they
+ may be removed from the relevant blacklists.
++
++.Ss "If compiled with IPFW"
++With
++.Xr ipfw 4 ,
++the syntax for redirection of TCP sessions is quite different
++from that of
++.Xr pf 4 .
++The
++.Em fwd
++rule used for this purpose are described in
++.Xr ipfw 8 .
++The rules should be added to the ruleset called by /etc/rc.firewall
++to be present at boot time.
++.Bd -literal -offset 4n
++fwd 127.0.0.1,8025 tcp from table(2) to me 25 in
++allow tcp from table(1) to me 25 in
++fwd 127.0.0.1,8025 tcp from any to me 25 in
++.Ed
++.Pp
++Any addresses in the blacklist table
++.Em 2
++and not in the whitelist table
++.Em 1
++are then redirected to
++.Nm
++running on port 8025.
++Addresses can be loaded into the blacklist
++.Em table ,
++like:
++.Bd -literal -offset 4n
++# ipfw table 1 add a.b.c.d/x
++.Ed
++.Pp
++.Xr spamd-setup 8
++can also be used to load addresses into the blacklist table
++.Em 2 .
++.Pp
++The 
++.Op Fl t Ar table_no
++option to 
++.Em spamd 
++and 
++.Em spamd-setup 
++can be used to change the default table
++numbers.
++
+ .Sh CONFIGURATION CONNECTIONS
+ .Nm
+ listens for configuration connections on the port identified by the
diff -urN /usr/ports/mail/spamd/pkg-message spamd_new/pkg-message
--- /usr/ports/mail/spamd/pkg-message	Thu Jan 13 13:54:46 2005
+++ spamd_new/pkg-message	Mon Mar 20 10:44:13 2006
@@ -1,9 +1,18 @@
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-In order to use spamd greylisting feature you have to have a mounted fdescfs(5)
-at /dev/fd.  This is done by adding:
+In order to use spamd greylisting feature with pf firewall you have to have a 
+mounted fdescfs(5) at /dev/fd.  This is done by adding:
 
         fdescfs /dev/fd fdescfs rw 0 0
 
 to /etc/fstab.  You may need either a customised kernel, or kldload the fdescfs
 kernel module.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+To use spamd with ipfw firewall, simply include ipfw rules similar to the 
+following:
+
+00400 fwd tcp from table(2) to any dst-port 25
+00410 allow tcp from table(1) to any dst-port 25
+00420 fwd 127.0.0.1,8025 tcp from any to any dst-port 25 in
+
+Other table numbers can be used by using the -t option to spamd and spamd-setup
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603200449.k2K4n8Tf018205>