1 |
stephdl |
1.1 |
From cc2d8ccca6a7fafe2c08b7d180e81aeae8eb1b35 Mon Sep 17 00:00:00 2001 |
2 |
|
|
From: Matt Simerson <matt@tnpi.net> |
3 |
|
|
Date: Tue, 11 May 2010 01:06:54 -0400 |
4 |
|
|
Subject: added local_ip option to p0f plugin |
5 |
|
|
|
6 |
|
|
(updated patch against rspier/qpsmtpd) |
7 |
|
|
|
8 |
|
|
The p0f plugin defaulted to binding to TCPLOCALIP, which doesn't work |
9 |
|
|
when the mail server is running behind a firewall with a private IP. If |
10 |
|
|
the local_ip option is set in the config file, it overrides TCPLOCALIP. |
11 |
|
|
|
12 |
|
|
Added POD documentation for local_ip option and p0f general usage |
13 |
|
|
|
14 |
|
|
Signed-off-by: Robert <rspier@pobox.com> |
15 |
|
|
--- |
16 |
|
|
plugins/ident/p0f | 87 ++++++++++++++++++++++++++++++++++++++++++++-------- |
17 |
|
|
1 files changed, 73 insertions(+), 14 deletions(-) |
18 |
|
|
|
19 |
|
|
diff --git a/plugins/ident/p0f b/plugins/ident/p0f |
20 |
|
|
index 98b56ec..c92634e 100644 |
21 |
|
|
--- a/plugins/ident/p0f |
22 |
|
|
+++ b/plugins/ident/p0f |
23 |
|
|
@@ -1,20 +1,68 @@ |
24 |
|
|
# -*- perl -*- |
25 |
|
|
|
26 |
|
|
-=pod |
27 |
|
|
+=head1 NAME |
28 |
|
|
|
29 |
|
|
-An Identification Plugin |
30 |
|
|
+p0f - A TCP Fingerprinting Identification Plugin |
31 |
|
|
|
32 |
|
|
- ./p0f -u qpsmtpd -d -q -Q /tmp/.p0f_socket 'dst port 25' -o /dev/null && \ |
33 |
|
|
- chown qpsmtpd /tmp/.p0f_socket |
34 |
|
|
+=head1 SYNOPSIS |
35 |
|
|
|
36 |
|
|
-and add |
37 |
|
|
+Use TCP fingerprint info (remote computer OS, network distance, etc) to |
38 |
|
|
+implement more sophisticated anti-spam policies. |
39 |
|
|
+ |
40 |
|
|
+=head1 DESCRIPTION |
41 |
|
|
+ |
42 |
|
|
+This p0f module inserts a 'p0f' note that other qpsmtpd plugins can inspect. |
43 |
|
|
+It includes the following information about the TCP fingerprint (link, |
44 |
|
|
+detail, distance, uptime, genre). Here's an example connection note: |
45 |
|
|
+ |
46 |
|
|
+ genre => FreeBSD |
47 |
|
|
+ detail => 6.x (1) |
48 |
|
|
+ uptime => 1390 |
49 |
|
|
+ link => ethernet/modem |
50 |
|
|
+ distance => 17 |
51 |
|
|
+ |
52 |
|
|
+Which was parsed from this p0f fingerprint: |
53 |
|
|
+ |
54 |
|
|
+ 24.18.227.2:39435 - FreeBSD 6.x (1) (up: 1390 hrs) |
55 |
|
|
+ -> 208.75.177.101:25 (distance 17, link: ethernet/modem) |
56 |
|
|
+ |
57 |
|
|
+=head1 MOTIVATION |
58 |
|
|
+ |
59 |
|
|
+This p0f plugin provides a way to make sophisticated policies for email |
60 |
|
|
+messages. For example, the vast majority of email connections to my server |
61 |
|
|
+from Windows computers are spam (>99%). But, I have a few clients that use |
62 |
|
|
+Exchange servers so I can't just block email from all Windows computers. |
63 |
|
|
+ |
64 |
|
|
+Same goes for greylisting. Finance companies (AmEx, BoA, etc) just love to |
65 |
|
|
+send notices that they won't queue and retry. Either they deliver at that |
66 |
|
|
+instant or never. When I enable greylisting, I lose valid messages. Grrr. |
67 |
|
|
+ |
68 |
|
|
+So, while I'm not willing to use greylisting, and I'm not willing to block |
69 |
|
|
+connections from Windows computers, I am quite willing to greylist all email |
70 |
|
|
+from Windows computers. |
71 |
|
|
+ |
72 |
|
|
+=head1 CONFIGURATION |
73 |
|
|
+ |
74 |
|
|
+Create a startup script for PF that creates a communication socket when your |
75 |
|
|
+server starts up. |
76 |
|
|
+ |
77 |
|
|
+ p0f -u qpsmtpd -d -q -Q /tmp/.p0f_socket 'dst port 25' -o /dev/null |
78 |
|
|
+ chown qpsmtpd /tmp/.p0f_socket |
79 |
|
|
+ |
80 |
|
|
+add an entry to config/plugins to enable p0f: |
81 |
|
|
|
82 |
|
|
ident/p0f /tmp/.p0f_socket |
83 |
|
|
|
84 |
|
|
-to config/plugins |
85 |
|
|
+=head2 local_ip |
86 |
|
|
+ |
87 |
|
|
+Use the local_ip option to override the IP address of your mail server. This |
88 |
|
|
+is useful if your mail server has a private IP because it is running behind |
89 |
|
|
+a firewall. For example, my mail server has the IP 127.0.0.6, but the world |
90 |
|
|
+knows my mail server as 208.75.177.101. |
91 |
|
|
+ |
92 |
|
|
+Example config/plugins entry with local_ip override: |
93 |
|
|
|
94 |
|
|
-it puts things into the 'p0f' connection notes so other plugins can do |
95 |
|
|
-things based on source OS. |
96 |
|
|
+ ident/p0f /tmp/.p0f_socket local_ip 208.75.177.101 |
97 |
|
|
|
98 |
|
|
All code heavily based upon the p0fq.pl included with the p0f distribution. |
99 |
|
|
|
100 |
|
|
@@ -26,6 +74,15 @@ has been updated to provide that information when running under djb's |
101 |
|
|
tcpserver. The async, forkserver, and prefork models will likely require |
102 |
|
|
some additional changes to make sure these fields are populated. |
103 |
|
|
|
104 |
|
|
+=head1 ACKNOWLEDGEMENTS |
105 |
|
|
+ |
106 |
|
|
+Heavily based upon the p0fq.pl included with the p0f distribution. |
107 |
|
|
+ |
108 |
|
|
+=head1 AUTHORS |
109 |
|
|
+ |
110 |
|
|
+ Matt Simerson <msimerson@cpan.org> - 5/1/2010 |
111 |
|
|
+ previous unnamed author |
112 |
|
|
+ |
113 |
|
|
=cut |
114 |
|
|
|
115 |
|
|
use IO::Socket; |
116 |
|
|
@@ -34,22 +91,24 @@ use Net::IP; |
117 |
|
|
my $QUERY_MAGIC = 0x0defaced; |
118 |
|
|
|
119 |
|
|
sub register { |
120 |
|
|
- my ($self, $qp, $p0f_socket) = @_; |
121 |
|
|
+ my ($self, $qp, $p0f_socket, %args) = @_; |
122 |
|
|
|
123 |
|
|
- $p0f_socket =~ /(.*)/; # untaint |
124 |
|
|
- $self->{_args}->{p0f_socket} = $1; |
125 |
|
|
+ $p0f_socket =~ /(.*)/; # untaint |
126 |
|
|
+ $self->{_args}->{p0f_socket} = $1; |
127 |
|
|
+ foreach (keys %args) { |
128 |
|
|
+ $self->{_args}->{$_} = $args{$_}; |
129 |
|
|
+ } |
130 |
|
|
} |
131 |
|
|
|
132 |
|
|
sub hook_connect { |
133 |
|
|
my($self, $qp) = @_; |
134 |
|
|
|
135 |
|
|
my $p0f_socket = $self->{_args}->{p0f_socket}; |
136 |
|
|
- my $srcport = |
137 |
|
|
- my $destport = $self->qp->connection->local_port; |
138 |
|
|
+ my $local_ip = $self->{_args}{local_ip} || $self->qp->connection->local_ip; |
139 |
|
|
|
140 |
|
|
my $src = new Net::IP ($self->qp->connection->remote_ip) |
141 |
|
|
or $self->log(LOGERROR, "p0f: ".Net::IP::Error()), return (DECLINED); |
142 |
|
|
- my $dst = new Net::IP ($self->qp->connection->local_ip) |
143 |
|
|
+ my $dst = new Net::IP($local_ip) |
144 |
|
|
or $self->log(LOGERROR, "p0f: ".NET::IP::Error()), return (DECLINED); |
145 |
|
|
my $query = pack("L L L N N S S", |
146 |
|
|
$QUERY_MAGIC, |
147 |
|
|
-- |
148 |
|
|
1.7.2.2 |
149 |
|
|
|