LINUX.ORG.RU

Perl. Сокеты.


0

0

Задача: написать протопип FTP-прокси, который должен
1. Принимать подключения FTP-клиентов, в соответствии с именем пользователя выбирать из конфига параметры доступа к удалённому серверу, логиниться на нем и транлсировать команды FTP - протокола и ответы.
2. Вести логи.

Основная проблема - отделить "реальные" параметры доступа по FTP, от пользователей, которые их переодически проёживают, выдав им "игрушечные" параметры, в том числе и имя хоста этого прокси.

Средства отладки
1. Мой комп (127.0.0.1) и Perl-интерпретатор (типа прокси)
2. FTP-сервер в локальной сети (ftp://r-asian:111@150.150.150.254:21)
3. gftp как ftp-client, которым я и подключаюсь к 127.0.0.1:21

Исходный код:

#!/usr/bin/perl
use Socket;

$host = "127.0.0.1";
$port = 21;
$work = 1;
$buffer_size=65536;

$host = inet_aton($host);
$sock_name = sockaddr_in($port,$host)
	or die "Couldn't convert $host into an Internet address: $!\n";
socket(SERVER,PF_INET,SOCK_STREAM,getprotobyname('tcp'))
	or die "Couldn't create socket: $!\n";
setsockopt(SERVER,SOL_SOCKET,SO_REUSEADDR,1)
	or die "setsockopt() failed: $!\n";
bind(SERVER,$sock_name)
	or die "Couldn't bind to port $port: $!\n";
listen(SERVER,127);

while ($work){
	my $rem_addr = accept(CLIENT,SERVER);
	my $pid=fork();

    if ($pid==0)
    {
        # Алло, FTP-прокси слушает
   	    send(CLIENT,"220 FTP server ready.\r\n",0);
        while(1)
        {
            # Получаем от клиента очередную команду
            recv(CLIENT,$data,$buffer_size,0);
            print "client=>:  $data";
            # Получаем имя пользователя и по нему проводим авторизацию
            if ($data=~/^.*USER\s([\d\w\.\-\_]*).*$/)
            {
                socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));

                $iaddr = inet_aton(user2remote_ip($1));
                $paddr = sockaddr_in(user2remote_port($1), $iaddr);

                connect(SOCK, $paddr);
                $data=<SOCK>;

                send (SOCK, "USER ".user2remote_username($1)."\r\n", 0);
                $data=<SOCK>;
                print $data;

                send (SOCK, "PASS ".user2remote_password($1)."\r\n", 0);
                $data=<SOCK>;
                print $data;

           	    send(CLIENT,"$data.\r\n",0);
            }
            else
            {
                send(SOCK,$data,0);
                recv(SOCK,$data,$buffer_size,0);
                send(CLIENT,$data,0);
            }
            # Пропускаем пароль (нах..й он никому не нужен)
            if ($data=~/^.*PASS\s.*$/)
            {
            }
    	}
        close(SOCK);
    	close CLIENT;  
    }
  	close CLIENT;  
}

close SERVER;


sub user2remote_ip
{
    my ($username)=@_;
    $remote_ip="150.150.150.254";
    return $remote_ip;
}

sub user2remote_username
{
    my ($username)=@_;
    
    $remote_username="r-asian";
    return $remote_username;
}

sub user2remote_password
{
    my ($username)=@_;
    $remote_password="111";
    return $remote_password;
}


sub user2remote_port
{
    my ($username)=@_;
    $remote_port="21";
    return $remote_port;
}

--------------------------------------------
Как он работает:
--------------------------------------------
Поиск 127.0.0.1
Попытка 127.0.0.1:21
Подключение к 127.0.0.1:21
220 FTP server ready.
USER intelhouse.ru

230 User r-asian logged in.
SYST

.
215 UNIX Type: L8 Version: BSD-199506
TYPE I

200 Type set to I.
PWD

257 "/home/r-asian" is current directory.
Loading directory listing /home/r-asian from server (LC_TIME=ru_RU)
PASV

227 Entering Passive Mode (150,150,150,254,209,39)
LIST -aL

150 Opening BINARY mode data connection for '/bin/ls'.

И ТУТ ОН ПОВИСАЕТ :-((
---------------------------------------------------------

Дополнительно скажу, что:

Если выполнение perl-скрипта оборвать, то клиент показывает список файлов(что от него и требовалось)

Чо не так, а? :-(
★☆☆

Вопрос снят. Дело в FTP-протоколе.

r_asian ★☆☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.