[Mimedefang] Fwd: Re: Accessing the source/destination port #'s at filter_relay
Philip Prindeville
philipp_subx at redfish-solutions.com
Thu Sep 30 23:36:56 EDT 2010
So we concluded that Postfix can't generate the queue id early enough to make read_commands_file() work from filter_relay()...
Can we consider my patch as the next best thing?
Thanks.
Oh, for what it's worth, I've been running this in-house for 4 months and it works fine.
-------- Original Message --------
Subject: Re: [Mimedefang] Accessing the source/destination port #'s at filter_relay
Date: Tue, 04 May 2010 11:40:40 -0600
From: Philip A. Prindeville <philipp_subx at redfish-solutions.com>
Reply-To: mimedefang at lists.roaringpenguin.com
To: mimedefang at lists.roaringpenguin.com
Decided it was cleaner to use globals than to change the signature
(prototype) of filter_relay() and filter_helo().
Introduced therefore 3 new globals:
$RelayPort
$OurAddr
$OurPort
which are set in the context of both of these hooks.
As a side-effect of introducing these variables, I can make tests now in
filter_relay() like:
if ($hostname eq "[$hostip]"&& $OurPort != 587) {
md_syslog('debug', "no rDNS: reject [$hostip]");
return ('TEMPFAIL', "No rDNS records found; try again when you've properly configured your DNS.");
}
i.e. require rDNS for relays (but not for clients that are submitting locally).
Another test I can do in filter_helo():
if ($helo =~ /^\[(\d{1,3}\.\d{1,3}.\d{1,3}\.\d{1,3})\]$/) {
my $inet = inet_aton($1);
# check for a valid dotted-quad.
# use the same error message as above... don't make it too easy
# to guess what our checks are.
if (!defined($inet) || $inet eq INADDR_NONE) {
md_syslog('debug', "badquad: $helo ($hostname [$hostip])");
return ('REJECT', "Incorrect format for address-literal");
}
...
# lastly, check to see if what he thinks is his address is
# what we think is his address. Hosts behind NATting gateways
# or that are multi-homed might get this wrong, so don't be
# surprised if you need to yank this test.
if ($helo ne "[$hostip]"&& $OurPort != 587) {
md_syslog('debug', "wrong ip: [$hostip] claims to be $helo");
return ('REJECT',
"Address forgery attempt, [$hostip] claims to be $helo");
}
# we could do more tests... For instance, only allow
# bracketed quads for local connections...
return ('CONTINUE', "OK");
}
A common attempt to subvert our filters is to either say "HELO
[192.168.x.x]" from outside, or else to say "HELO [66.232.79.143]" which
is of course my own IP address.
Relays should know their own addresses (and indeed, be using names, not
dotted-quads).
Clients, on the other hand, are often laptops or phones in hotspots
behind a NATting Wifi/DSL router, and hence will get this wrong. But
that's ok, since we require authentication on port 587.
Indeed, if you have an iPhone on AT&T's 3G network, you'll have a
10.x.x.x address, but their NATting gateway will *not* rewrite your HELO
string with your public address.
-------------- next part --------------
--- mimedefang-2.68/Changelog.orig 2010-05-03 18:51:03.000000000 -0600
+++ mimedefang-2.68/Changelog 2010-05-03 17:30:04.000000000 -0600
@@ -2,6 +2,12 @@ WARNING: Before upgrading MIMEDefang, pl
*** NOTE INCOMPATIBILITY ** to see if anything has changed that might
affect your filter.
+2010-05-03 Philip A. Prindeville <philipp at redfish-solutions.com>
+
+ * Add remote port, local address, local port as args to
+ filter_relay(). Useful if you're using IPTables::libiptc to
+ perform tarpitting for example.
+
2010-02-24 David F. Skoll <dfs at roaringpenguin.com>
* MIMEDefang 2.68 RELEASED
--- mimedefang-2.68/mimedefang.pl.in.orig 2010-02-24 07:55:03.000000000 -0700
+++ mimedefang-2.68/mimedefang.pl.in 2010-05-04 11:15:43.000000000 -0600
@@ -36,8 +36,9 @@ use vars qw($AddWarningsInline @StatusTa
$DefangCounter $Domain $EntireMessageQuarantined
$MessageID $Rebuild $QuarantineCount
$QuarantineSubdir $QueueID $MsgID $MIMEDefangID
- $RelayAddr $WasResent $RelayHostname
+ $RelayAddr $WasResent $RelayHostname $RelayPort
$RealRelayAddr $RealRelayHostname
+ $OurAddr $OurPort
$ReplacementEntity $Sender $ServerMode $Subject $SubjectCount
$ClamdSock $SophieSock $TrophieSock
$SuspiciousCharsInHeaders
@@ -5640,7 +5641,8 @@ sub md_get_bogus_mx_hosts {
sub do_main_loop () {
# Infinite server loop... well, not quite infinite; we stop on EOF
# from STDIN.
- my ($workdir, $map, $key, $ip, $name, $helo, $sender, $recip, $firstRecip);
+ my ($workdir, $map, $key, $ip, $name, $helo, $sender, $recip, $firstRecip,
+ $port, $myip, $myport);
# Try to open the status descriptor
if ($DoStatusTags) {
@@ -5725,18 +5727,24 @@ sub do_main_loop () {
next;
}
- if ($_ =~ /^relayok (\S*)\s+(\S*)/) {
+ if ($_ =~ /^relayok (\S*)\s+(\S*)\s+(\S*)\s+(\S*)\s+(\S*)/) {
$ip = percent_decode($1);
$name = percent_decode($2);
- relay_ok($ip, $name);
+ $port = percent_decode($3);
+ $myip = percent_decode($4);
+ $myport = percent_decode($5);
+ relay_ok($ip, $name, $port, $myip, $myport);
chdir($Features{'Path:SPOOLDIR'});
next;
}
- if ($_ =~ /^helook (\S*)\s+(\S*)\s+(\S*)/) {
+ if ($_ =~ /^helook (\S*)\s+(\S*)\s+(\S*)\s+(\S*)\s+(\S*)\s+(\S*)/) {
$ip = percent_decode($1);
$name = percent_decode($2);
$helo = percent_decode($3);
- helo_ok($ip, $name, $helo);
+ $port = percent_decode($4);
+ $myip = percent_decode($5);
+ $myport = percent_decode($6);
+ helo_ok($ip, $name, $helo, $port, $myip, $myport);
chdir($Features{'Path:SPOOLDIR'});
next;
}
@@ -5859,12 +5867,15 @@ sub init_globals () {
$MsgID = "NOQUEUE";
$MessageID = "NOQUEUE";
$Helo = "";
+ $OurAddr = "";
+ $OurPort = 0;
$QueueID = "NOQUEUE";
$QuarantineCount = 0;
$Rebuild = 0;
$EntireMessageQuarantined = 0;
$QuarantineSubdir = "";
$RelayAddr = "";
+ $RelayPort = 0;
$RealRelayAddr = "";
$WasResent = 0;
$RelayHostname = "";
@@ -7066,11 +7077,14 @@ sub send_filter_answer ($$$$;$$$) {
# %ARGUMENTS:
# hostip -- IP address of relay host
# hostname -- name of relay host
+# port -- TCP port of relay host
+# myip -- IP address of server
+# myport -- TCP port of server
# %RETURNS:
# Nothing, but prints "ok 1" if we accept connection, "ok 0" if not.
#***********************************************************************
sub relay_ok ($$) {
- my($hostip, $hostname) = @_;
+ my($hostip, $hostname, $port, $myip, $myport) = @_;
if (!defined(&filter_relay)) {
send_filter_answer('CONTINUE', "ok",
"filter_relay", "host $hostip ($hostname)");
@@ -7080,6 +7094,10 @@ sub relay_ok ($$) {
# Set up globals
$RelayAddr = $hostip;
$RelayHostname = $hostname;
+ $RelayPort = $port;
+ $OurAddr = $myip;
+ $OurPort = $myport;
+
my($ok, $msg, $code, $dsn, $delay) = filter_relay($hostip, $hostname);
send_filter_answer($ok, $msg, "filter_relay", "host $hostip ($hostname)", $code, $dsn, $delay);
}
@@ -7090,12 +7108,15 @@ sub relay_ok ($$) {
# ip -- IP address of relay host
# name -- name of relay host
# helo -- arg to SMTP HELO command
+# port -- TCP port of relay host
+# myip -- IP address of server
+# myport -- TCP port of server
# %RETURNS:
# Nothing, but prints "ok 1" if we accept connections from this host.
# "ok 0" if not.
#***********************************************************************
-sub helo_ok ($$$) {
- my($ip, $name, $helo) = @_;
+sub helo_ok ($$$$$$) {
+ my($ip, $name, $helo, $port, $myip, $myport) = @_;
if (!defined(&filter_helo)) {
send_filter_answer('CONTINUE', "ok",
"filter_helo", "helo $helo");
@@ -7106,6 +7127,9 @@ sub helo_ok ($$$) {
$RelayAddr = $ip;
$RelayHostname = $name;
$Helo = $helo;
+ $RelayPort = $port;
+ $OurAddr = $myip;
+ $OurPort = $myport;
my($ok, $msg, $code, $dsn, $delay) = filter_helo($ip, $name, $helo);
send_filter_answer($ok, $msg, "filter_helo", "helo $helo",
--- mimedefang-2.68/mimedefang.h.orig 2009-09-03 14:59:15.000000000 -0600
+++ mimedefang-2.68/mimedefang.h 2010-05-04 10:41:25.000000000 -0600
@@ -29,9 +29,11 @@ extern int MXCheckFreeSlaves(char const
extern int MXScanDir(char const *sockname, char const *dir);
extern int MXCommand(char const *sockname, char const *cmd, char *buf, int len);
extern int MXRelayOK(char const *sockname, char *msg,
- char const *ip, char const *name);
+ char const *ip, char const *name,
+ int port, char const *myip, int myport);
extern int MXHeloOK(char const *sockname, char *msg,
- char const *helo, char const *ip, char const *name);
+ char const *helo, char const *ip, char const *name,
+ int port, char const *myip, int myport);
extern int MXSenderOK(char const *sockname, char *msg,
char const **sender_argv, char const *ip, char const *name,
char const *helo, char const *dir, char const *qid);
--- mimedefang-2.68/mimedefang.c.orig 2010-02-03 08:11:32.000000000 -0700
+++ mimedefang-2.68/mimedefang.c 2010-05-04 11:07:08.000000000 -0600
@@ -159,7 +159,9 @@ static int NumAdditionalMacros = 0;
struct privdata {
char *hostname; /* Name of connecting host */
char *hostip; /* IP address of connecting host */
+ int hostport; /* TCP port of connecting host */
char *myip; /* My IP address, from Sendmail macro */
+ int myport; /* My TCP port, from Sendmail macro */
char *sender; /* Envelope sender */
char *firstRecip; /* Address of first recipient */
char *dir; /* Work directory */
@@ -504,6 +506,9 @@ mfconnect(SMFICTX *ctx, char *hostname,
#if defined(AF_INET6) && defined(HAVE_INET_NTOP)
struct sockaddr_in6 *in6sa = (struct sockaddr_in6 *) sa;
#endif
+ char *me;
+ char *val;
+ unsigned n;
DEBUG_ENTER("mfconnect");
@@ -555,7 +560,9 @@ mfconnect(SMFICTX *ctx, char *hostname,
}
data->hostname = NULL;
data->hostip = NULL;
+ data->hostport = -1;
data->myip = NULL;
+ data->myport = -1;
data->sender = NULL;
data->firstRecip = NULL;
data->dir = NULL;
@@ -621,10 +628,12 @@ mfconnect(SMFICTX *ctx, char *hostname,
}
}
}
+ data->hostport = ntohs(in6sa->sin6_port);
} else
#endif
if (sa->sa_family == AF_INET) {
tmp = inet_ntop(AF_INET, &insa->sin_addr, data->hostip, 65);
+ data->hostport = ntohs(insa->sin_port);
} else if (sa->sa_family == AF_LOCAL) {
tmp = "127.0.0.1";
strcpy(data->hostip, tmp);
@@ -658,6 +667,23 @@ mfconnect(SMFICTX *ctx, char *hostname,
strcpy(data->hostip, "127.0.0.1");
}
+ /* Get my IP address */
+ me = smfi_getsymval(ctx, "{if_addr}");
+ if (me && *me && MyIPAddress && !strcmp(me, MyIPAddress)) {
+ data->myip = MyIPAddress;
+ } else if (me && *me && strcmp(me, "127.0.0.1")) {
+ data->myip = strdup_with_log(me);
+ } else {
+ /* Sigh... use our computed address */
+ data->myip = MyIPAddress;
+ }
+
+ /* get our local port */
+ val = smfi_getsymval(ctx, "{daemon_port}");
+ if (val && *val && (sscanf(val, "%u", &n) == 1)) {
+ data->myport = n;
+ }
+
data->dir = NULL;
data->fd = -1;
data->headerFD = -1;
@@ -668,7 +694,7 @@ mfconnect(SMFICTX *ctx, char *hostname,
if (doRelayCheck) {
char buf2[SMALLBUF];
int n = MXRelayOK(MultiplexorSocketName, buf2, data->hostip,
- data->hostname);
+ data->hostname, data->hostport, data->myip, data->myport);
if (n == MD_REJECT) {
/* Can't call smfi_setreply from connect callback */
/* set_dsn(ctx, buf2, 5); */
@@ -731,7 +757,8 @@ helo(SMFICTX *ctx, char *helohost)
if (doHeloCheck) {
char buf2[SMALLBUF];
int n = MXHeloOK(MultiplexorSocketName, buf2, data->hostip,
- data->hostname, data->heloArg);
+ data->hostname, data->heloArg, data->hostport,
+ data->myip, data->myport);
if (n == MD_REJECT) {
set_dsn(ctx, buf2, 5);
cleanup(ctx);
@@ -788,7 +815,6 @@ envfrom(SMFICTX *ctx, char **from)
time_t now = time(NULL);
unsigned long ulnow = (unsigned long) now;
char *queueid;
- char *me;
dynamic_buffer dbuf;
char mxid[MX_ID_LEN+1];
@@ -944,7 +970,9 @@ envfrom(SMFICTX *ctx, char **from)
append_macro_value(&dbuf, ctx, "cert_subject");
append_macro_value(&dbuf, ctx, "cipher");
append_macro_value(&dbuf, ctx, "cipher_bits");
+ append_macro_value(&dbuf, ctx, "client_port");
append_macro_value(&dbuf, ctx, "daemon_name");
+ append_macro_value(&dbuf, ctx, "daemon_port");
append_macro_value(&dbuf, ctx, "i");
append_macro_value(&dbuf, ctx, "if_addr");
append_macro_value(&dbuf, ctx, "if_name");
@@ -998,18 +1026,6 @@ envfrom(SMFICTX *ctx, char **from)
data->cmdFD = put_fd(data->cmdFD);
- /* Get my IP address */
- me = smfi_getsymval(ctx, "{if_addr}");
- if (me && *me && MyIPAddress && !strcmp(me, MyIPAddress)) {
- data->myip = MyIPAddress;
- } else if (me && *me && strcmp(me, "127.0.0.1")) {
- data->myip = strdup_with_log(me);
- } else {
- /* Sigh... use our computed address */
- data->myip = MyIPAddress;
- }
-
-
if (doSenderCheck) {
int n = MXSenderOK(MultiplexorSocketName, buf2,
(char const **) from, data->hostip, data->hostname,
--- mimedefang-2.68/utils.c.orig 2009-05-04 09:34:32.000000000 -0600
+++ mimedefang-2.68/utils.c 2010-05-04 10:43:22.000000000 -0600
@@ -547,6 +547,9 @@ munch_mx_return(char *ans, char *msg)
* msg -- buffer for holding error message, at least SMALLBUF chars
* ip -- relay IP address
* name -- relay name
+* port -- relay TCP port
+* myip -- server's IP address
+* myport -- server's TCP port
* %RETURNS:
* 1 if it's OK to accept connections from this host; 0 if not, -1 if error.
* If connection is rejected, error message *may* be set.
@@ -555,20 +558,30 @@ int
MXRelayOK(char const *sockname,
char *msg,
char const *ip,
- char const *name)
+ char const *name,
+ int port,
+ char const *myip,
+ int myport
+)
{
char cmd[SMALLBUF];
char ans[SMALLBUF];
+ char remport[6];
+ char localport[6];
*msg = 0;
+ snprintf(remport, sizeof(remport), "%d", port);
+ snprintf(localport, sizeof(localport), "%d", myport);
+
if (!ip || !*ip) {
ip = "UNKNOWN";
}
if (!name || !*name) {
name = ip;
}
- if (percent_encode_command(1, cmd, sizeof(cmd), "relayok", ip, name, NULL) < 0) {
+ if (percent_encode_command(1, cmd, sizeof(cmd), "relayok", ip, name,
+ remport, myip, localport, NULL) < 0) {
return MD_TEMPFAIL;
}
if (MXCommand(sockname, cmd, ans, SMALLBUF-1) < 0) return MD_TEMPFAIL;
@@ -590,13 +603,21 @@ MXHeloOK(char const *sockname,
char *msg,
char const *ip,
char const *name,
- char const *helo)
+ char const *helo,
+ int port,
+ char const *myip,
+ int myport)
{
char cmd[SMALLBUF];
char ans[SMALLBUF];
+ char remport[6];
+ char localport[6];
*msg = 0;
+ snprintf(remport, sizeof(remport), "%d", port);
+ snprintf(localport, sizeof(localport), "%d", myport);
+
if (!ip || !*ip) {
ip = "UNKNOWN";
}
@@ -606,7 +627,8 @@ MXHeloOK(char const *sockname,
if (!helo) {
helo = "UNKNOWN";
}
- if (percent_encode_command(1, cmd, sizeof(cmd), "helook", ip, name, helo, NULL) < 0) {
+ if (percent_encode_command(1, cmd, sizeof(cmd), "helook", ip, name, helo,
+ remport, myip, localport, NULL) < 0) {
return MD_TEMPFAIL;
}
if (MXCommand(sockname, cmd, ans, SMALLBUF-1) < 0) return MD_TEMPFAIL;
-------------- next part --------------
_______________________________________________
NOTE: If there is a disclaimer or other legal boilerplate in the above
message, it is NULL AND VOID. You may ignore it.
Visit http://www.mimedefang.org and http://www.roaringpenguin.com
MIMEDefang mailing list MIMEDefang at lists.roaringpenguin.com
http://lists.roaringpenguin.com/mailman/listinfo/mimedefang
More information about the MIMEDefang
mailing list