Improve support for listening to multiple ports and/or multiple IP addresses.

Document using plugins/tls to handle SMTPS (port 465).

git-svn-id: https://svn.perl.org/qpsmtpd/branches/0.3x@625 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
John Peacock 2006-03-01 16:44:20 +00:00
parent 2c683f22ef
commit 4a824a2e7d
2 changed files with 40 additions and 17 deletions

View File

@ -12,7 +12,15 @@ tls - plugin to support STARTTLS
=head1 DESCRIPTION =head1 DESCRIPTION
This plugin implements basic TLS support. This plugin implements basic TLS support. It can also be used to support
port 465 (SMTP over SSL), but only with qpsmtpd-forkserver. In this case,
be sure to load plugins/tls before any other connect plugins and start
qpsmtpd like this:
qpsmtpd-forkserver --port 25 --port 465
You can also specify multiple --listen-address options as well; see the help
for qpsmtpd-forkserver for more details.
If TLS is successfully negotiated then the C<tls_enabled> field in the If TLS is successfully negotiated then the C<tls_enabled> field in the
Connection notes is set. If you wish to make TLS mandatory you should check Connection notes is set. If you wish to make TLS mandatory you should check

View File

@ -19,7 +19,7 @@ $| = 1;
# Configuration # Configuration
my $MAXCONN = 15; # max simultaneous connections my $MAXCONN = 15; # max simultaneous connections
my $PORT = 2525; # port number my @PORT; # port number(s)
my @LOCALADDR; # ip address(es) to bind to my @LOCALADDR; # ip address(es) to bind to
my $USER = 'smtpd'; # user to suid to my $USER = 'smtpd'; # user to suid to
my $MAXCONNIP = 5; # max simultaneous connections from one IP my $MAXCONNIP = 5; # max simultaneous connections from one IP
@ -31,8 +31,9 @@ sub usage {
usage: qpsmtpd-forkserver [ options ] usage: qpsmtpd-forkserver [ options ]
-l, --listen-address addr : listen on specific address(es); can be specified -l, --listen-address addr : listen on specific address(es); can be specified
multiple times for multiple bindings. Default is multiple times for multiple bindings. Default is
0.0.0.0 (all interfaces). 0.0.0.0 (all interfaces).
-p, --port P : listen on a specific port; default 2525 -p, --port P : listen on a specific port; default 2525; can be
specified multiple times for multiple bindings.
-c, --limit-connections N : limit concurrent connections to N; default 15 -c, --limit-connections N : limit concurrent connections to N; default 15
-u, --user U : run as a particular user (default 'smtpd') -u, --user U : run as a particular user (default 'smtpd')
-m, --max-from-ip M : limit connections from a single IP; default 5 -m, --max-from-ip M : limit connections from a single IP; default 5
@ -46,22 +47,36 @@ GetOptions('h|help' => \&usage,
'l|listen-address=s' => \@LOCALADDR, 'l|listen-address=s' => \@LOCALADDR,
'c|limit-connections=i' => \$MAXCONN, 'c|limit-connections=i' => \$MAXCONN,
'm|max-from-ip=i' => \$MAXCONNIP, 'm|max-from-ip=i' => \$MAXCONNIP,
'p|port=i' => \$PORT, 'p|port=s' => \@PORT,
'u|user=s' => \$USER, 'u|user=s' => \$USER,
'pid-file=s' => \$PID_FILE, 'pid-file=s' => \$PID_FILE,
'd|detach' => \$DETACH, 'd|detach' => \$DETACH,
) || &usage; ) || &usage;
# detaint the commandline # detaint the commandline
if ($PORT =~ /^(\d+)$/) { $PORT = $1 } else { &usage }
@LOCALADDR = ( '0.0.0.0' ) if !@LOCALADDR; @LOCALADDR = ( '0.0.0.0' ) if !@LOCALADDR;
@PORT = ( 2525 ) if !@PORT;
my @LISTENADDR;
for (0..$#LOCALADDR) { for (0..$#LOCALADDR) {
if ($LOCALADDR[$_] =~ /^([\d\w\-.]+)(?::(\d+))?$/) { if ($LOCALADDR[$_] =~ /^([\d\w\-.]+)(?::(\d+))?$/) {
$LOCALADDR[$_] = { 'addr' => $1, 'port' => $2 || $PORT }; if ( defined $2 ) {
push @LISTENADDR, { 'addr' => $1, 'port' => $2 };
} else {
my $addr = $1;
for (0..$#PORT) {
if ( $PORT[$_] =~ /^(\d+)$/ ) {
push @LISTENADDR, { 'addr' => $addr, 'port' => $1 };
} else {
&usage;
}
}
}
} else { } else {
&usage; &usage;
} }
} }
if ($USER =~ /^([\w\-]+)$/) { $USER = $1 } else { &usage } if ($USER =~ /^([\w\-]+)$/) { $USER = $1 } else { &usage }
if ($MAXCONN =~ /^(\d+)$/) { $MAXCONN = $1 } else { &usage } if ($MAXCONN =~ /^(\d+)$/) { $MAXCONN = $1 } else { &usage }
@ -93,7 +108,7 @@ $SIG{TERM} = \&HUNTSMAN;
my $select = new IO::Select; my $select = new IO::Select;
# establish SERVER socket(s), bind and listen. # establish SERVER socket(s), bind and listen.
for my $listen_addr (@LOCALADDR) { for my $listen_addr (@LISTENADDR) {
my $server = IO::Socket::INET->new(LocalPort => $listen_addr->{'port'}, my $server = IO::Socket::INET->new(LocalPort => $listen_addr->{'port'},
LocalAddr => $listen_addr->{'addr'}, LocalAddr => $listen_addr->{'addr'},
Proto => 'tcp', Proto => 'tcp',
@ -137,7 +152,7 @@ my $groups = "$qgid $qgid";
while (my ($name,$passwd,$gid,$members) = getgrent()) { while (my ($name,$passwd,$gid,$members) = getgrent()) {
my @m = split(/ /, $members); my @m = split(/ /, $members);
if (grep {$_ eq $USER} @m) { if (grep {$_ eq $USER} @m) {
$groups .= " $gid"; $groups .= " $gid";
} }
} }
$) = $groups; $) = $groups;
@ -149,13 +164,13 @@ $> = $quid;
$qpsmtpd->load_plugins; $qpsmtpd->load_plugins;
foreach my $local_addr ( @LOCALADDR ) { foreach my $listen_addr ( @LISTENADDR ) {
::log(LOGINFO,"Listening on $local_addr->{'addr'}:$local_addr->{'port'}"); ::log(LOGINFO,"Listening on $listen_addr->{'addr'}:$listen_addr->{'port'}");
} }
::log(LOGINFO, 'Running as user '. ::log(LOGINFO, 'Running as user '.
(getpwuid($>) || $>) . (getpwuid($>) || $>) .
', group '. ', group '.
(getgrgid($)) || $))); (getgrgid($)) || $)));
if ($DETACH) { if ($DETACH) {
open STDIN, '/dev/null' or die "/dev/null: $!"; open STDIN, '/dev/null' or die "/dev/null: $!";
@ -225,8 +240,8 @@ while (1) {
my $pid = safe_fork(); my $pid = safe_fork();
if ($pid) { if ($pid) {
# parent # parent
$childstatus{$pid} = $iaddr; # add to table $childstatus{$pid} = $iaddr; # add to table
# $childstatus{$pid} = 1; # add to table # $childstatus{$pid} = 1; # add to table
$running++; $running++;
close($client); close($client);
next; next;