From eaebf766bca9e07d1aee8d9db18ad867de4f9643 Mon Sep 17 00:00:00 2001 From: luzluna park Date: Fri, 30 May 2014 15:21:08 +0900 Subject: [PATCH] stunnel proxy protocol remote ip,port setting feature added for smtps. reference : http://www.stunnel.org/static/stunnel.html protocol spec : http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt --- lib/Qpsmtpd/PollServer.pm | 1 + lib/Qpsmtpd/SMTP.pm | 48 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/Qpsmtpd/PollServer.pm b/lib/Qpsmtpd/PollServer.pm index a9e6ba0..39313af 100644 --- a/lib/Qpsmtpd/PollServer.pm +++ b/lib/Qpsmtpd/PollServer.pm @@ -85,6 +85,7 @@ sub reset_for_next_message { $self->SUPER::reset_for_next_message(@_); $self->{_commands} = { + proxy => 1, ehlo => 1, helo => 1, rset => 1, diff --git a/lib/Qpsmtpd/SMTP.pm b/lib/Qpsmtpd/SMTP.pm index fe8e63e..2eeb156 100644 --- a/lib/Qpsmtpd/SMTP.pm +++ b/lib/Qpsmtpd/SMTP.pm @@ -34,7 +34,7 @@ sub new { my $self = bless({args => \%args}, $class); - my (@commands) = qw(ehlo helo rset mail rcpt data help vrfy noop quit); + my (@commands) = qw(proxy ehlo helo rset mail rcpt data help vrfy noop quit); my (%commands); @commands{@commands} = ('') x @commands; @@ -150,6 +150,52 @@ sub connection { || ($self->{_connection} = Qpsmtpd::Connection->new()); } +# proxy command process for stunnel (protocol = proxy) config to support smtps +sub proxy { + my ($self, $line) = @_; + # if not stunnel bypass + return if ( $self->connection->remote_ip() ne '127.0.0.1' ); + # input format : PROXY TCP4 192.168.41.227 10.27.11.106 50060 465 + if ( $line =~ m/^(.*?) (.*?) (.*?) (.*?) (.*?)$/ ) { + my $protocol = $1; + my $remote_ip = $2; + my $local_ip = $3; + my $remote_port = $4; + my $local_port = $5; + $self->connection->remote_ip( $remote_ip ); + $self->connection->remote_port( $remote_port ); + $self->connection->remote_info( "[$remote_ip]"); + + if ( $self->isa('Qpsmtpd::PollServer') ) { + use ParaDNS; + ParaDNS->new( + finished => sub { $self->continue_read() }, + callback => sub { $self->connection->remote_host($_[0]) }, + host => $remote_ip, + ); + } + else { + my $res = Net::DNS::Resolver->new( dnsrch => 0 ); + $res->tcp_timeout(3); + $res->udp_timeout(3); + my $query = $res->query( $remote_ip, 'PTR' ); + if ($query) { + foreach my $rr ($query->answer) { + next if $rr->type ne 'PTR'; + $self->connection->remote_host( $rr->ptrdname ); + } + } + } + + $self->connection->notes('proxy', 'YES'); + $self->connection->notes('protocol', $protocol); + $self->connection->notes('remote_ip', $remote_ip); + $self->connection->notes('remote_port', $remote_port); + $self->connection->notes('local_ip', $local_ip); + $self->connection->notes('local_port', $local_port); + } +} + sub helo { my ($self, $line) = @_; my ($rc, @msg) = $self->run_hooks('helo_parse');