Search code examples
perlsocketssmtpsocks

use NET::SMTP SSL/TLS with SOCKS


I have some realization of bind, connect to SOCKS and connect to SMTP server through SOCKS. How i can use this connect with SSL/TLS NET::SMTP? This question not help me, because SSL handshake can't start.

DEBUG: .../IO/Socket/SSL.pm:683: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:693: handshake failed because socket did not became ready

Here realization of connect to remote server via proxy:

sub connect {
    my ($ip, $port, $is_ssl, $pid, $server) = @_;
    if (defined $socket) {
        my ($packed_cmd, $buffer, @data, %response);
        $packed_cmd = pack("C4Nn", 0x05, 0x01, 0x00, 0x01, $ip, $port);
        $socket->send($packed_cmd);
        if (defined $socket->recv($buffer, 1024)) {
            @data = unpack("C4 L S", $buffer);
            $response{'version'} = $data[0];
            $response{'result'} = $data[1];
            $response{'reg'} = $data[2];
            $response{'type'} = $data[3];
            $response{'ip'} = $data[4];
            $response{'port'} = $data[5];
            $socket->blocking(0);
            if ($is_ssl) {
                &debug(3, $pid, "Try start SSL handshake with [$server]\n");
                IO::Socket::SSL->start_SSL($socket, SSL_version => 'SSLv23', SSL_ca_file => SSL_CA_FILE) or &debug(3, $pid, "Cannot start SSL handshake! $@\n") and return 0; 
                &debug(3, $pid, "SSL handshake done!\n");
            }
            # TODO: Make TLS support
            return 1;
        }
    }
    &debug(3, $pid, "Cannot connect to [$server:$port] through socks server [$socks_name:$socks_server]\n");
    return 0;
}

Bind SOCKS

sub bind_socks {
    my ($pid) = @_;
    my ($method, $packed_cmd, $buffer, @data, %response);
    $socket = IO::Socket::INET->new(
        PeerAddr => $socks_server,
        PeerPort => $socks_port,
        Proto => 'tcp',
        Timeout  => SOCKS5_CONNECT_TIMEOUT
    ) or &debug(3, $pid, "Cannot connect to the socks server [$socks_server] $@\n") and return 0;
    &debug(3, $pid, "Connected to the socks server [$socks_name:$socks_server]\n");
    $socket->blocking(1);
    if ($socks_username && $socks_password) {
        $method = 0x02;
    } else {
        $method = 0x00;
    }
    $packed_cmd = pack("C3", 0x05, 0x01, $method);
    $socket->send($packed_cmd);
    if (defined $socket->recv($buffer, 1024)) {
        @data = unpack("C2", $buffer);
        $response{'version'} = $data[0];
        $response{'method'} = $data[1];
        if ((defined $response{'version'}) && (defined $response{'method'}) && ($response{'version'} eq 5) && ($response{'method'} eq $method)) {
            if ($method == 2) {
                $packed_cmd = pack("CC", 0x01, length($socks_username)) . $socks_username . pack("C", length($socks_password)) . $socks_password;
                $socket->send($packed_cmd);
                if (defined $socket->recv($buffer, 1024)) {
                    @data = unpack("C2", $buffer);
                    $response{'version'} = $data[0];
                    $response{'status'} = $data[1];
                    return 1;
                }
            } else {
                return 1;
            }
        } else {
            &debug(3, $pid, "Cannot authenticate on socks server [$socks_name:$socks_server]\n");
            return 0;
        }
    }
    &debug(3, $pid, "Cannot authenticate on socks server [$socks_name:$socks_server]\n");
    return 0;
}

Solution

  • Here is my beta code to use SMTP via socks proxy. SSL is working correctly with all servers tested by me. With TLS still have sometimes problems, probably something not according to the RFC.