The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Распределенная авторизация или не только авторизация, !*! ziben, 29-Июл-03, 20:40  [смотреть все]
Есть задачка: на одном сервере хранится текстовом файле база данных (сервер А), на втором (сервер В) нужно организовать вычисления по данным той базы. Каким макаром можно сделать так, что бы сервер В сказал серверу А: "вот тебе входные данные" и в ответ получил "вот результат"?
В литературе нашел примеры организации tcp и udp серверов и клиентов, но там все заканчивается на самом интересном: вот мы и установили сокет! А как его теперь применить написано очень размыто :(

Заранее благодарен хотя бы за то, что обратили внимание на мое сообщение :)

  • Распределенная авторизация или не только авторизация, !*! XMan, 01:30 , 30-Июл-03 (1)
    Отправка данных по TCP:

    send(сокет, ссылка_на_данные, размер_данных_в_байтах, флаги);

    Прием данных по TCP:

    recv(сокет, ссылка_на_память_для_данных, размер_принимаемых_данных_в_байтах, флаги);

    Вместо флагов обычно используется "0". Рекомендуется обратить внимание еще и на функции poll и select. А так же почитать умную книжку "Программирование TCP/IP". Автор, кажись, некто Стивенсон. Точно не скажу - под рукой сейчас нет :)

    Короче, man :
    socket, fcntl, bind, listen, accept, connect, send, recv, sendto, recvfrom, poll, select, shutdown, close

  • Распределенная авторизация или не только авторизация, !*! asso, 12:03 , 30-Июл-03 (2)
    Посылать и получать - send и recv или sendto и recvfrom.  В манах они хорошо описаны, в книгах не хуже.  Внимательно смотри на все что касается сигналов, это пригодится в будущем.

    Теперь определимся с терминами.  Авторизация - это проверка полномочий (прав доступа).  Судя по вопросу, до проблем авторизации тебе еще далеко, тебе надо реализовать протокол обмена данными.

    Рассматривай сетевое соединение как трубу, через которую передаются данные.  В один конец трубы запихали байт, из другой трубы он вылез.  Конечно, пихать данные по одному байту крайне не эффективно, лучше посылать данные блоками.  Тут подстерегает коварная ошибка: при использовании TCP если ты отправил блок, скажем, из 100 байт, это не значит что на другой стороне recv() получит сразу 100 байт.  Он может получить, например, сначала 10, а потом остальные 90, а может сразу 200 (если захватит кусок от предыдущей или последующей порции данных).

    Тебе надо изобрести протокол, по которому будут общаться клиент и сервер. Например, сервер B может послать строку "DATA BEGIN" с переводом строки на конце, затем послать данные в текстовом виде, так же разделенные символом перевода строки, потом "DATA END" как знак того, что данные окончились.  Сервер A после приема всех данных может ответить, например, строчкой "RESULT: 47", передав таким способом результат.  Протокол полностью зависит от твоих целей и задач.

    Есть ошибка, которую любят совершать новички: НЕЛЬЗЯ передавать по сети структуры.  Структуры могут по-разному выравниваться разными компиляторами, на разных компьютерах могут быть разные размеры слов и разный порядок слов в байте.  Передавать любые бинарные данные по сети надо с большой остороностью.

    Если все это кажется сложным, используй более высокоуровневые библиотеки, которые возьмут все заботы на себя.  Например, какой-нибудь RPC или CORBA. Последняя не так сложна, как это может сначала показаться. Простые вещи в CORBA реализуются достаточно просто, но нет предела усложнению.

    • Распределенная авторизация или не только авторизация, !*! ziben, 12:41 , 30-Июл-03 (3)
      Спасибо за ответ.
      > Судя по вопросу, до проблем авторизации тебе еще далеко, тебе
      >надо реализовать протокол обмена данными.
      Именно так. Я уже сделал авторизацию, но потом оказалось что база пользователей лежит на другом сервере. Теперь вот думаю как это реализовать.
      >Тебе надо изобрести протокол, по которому будут общаться клиент и сервер. Например,
      >сервер B может послать строку "DATA BEGIN" с переводом строки на
      >конце, затем послать данные в текстовом виде, так же разделенные символом
      >перевода строки, потом "DATA END" как знак того, что данные окончились.
      > Сервер A после приема всех данных может ответить, например, строчкой
      >"RESULT: 47", передав таким способом результат.  Протокол полностью зависит от
      >твоих целей и задач.
      Мне то в принципе нужно что бы так: в одну сторону $login + $passwd, обратно "да-нет"+$users_alias+$email... и все, но похоже в реализации это выглядит гораздо сложнее :)

      >Если все это кажется сложным, используй более высокоуровневые библиотеки, которые возьмут все
      >заботы на себя.  Например, какой-нибудь RPC или CORBA. Последняя не
      >так сложна, как это может сначала показаться. Простые вещи в CORBA
      >реализуются достаточно просто, но нет предела усложнению.
      Хм... нужно поглядеть что за Корба такая... может действительно с ее помощью что-то придумается


      • Распределенная авторизация или не только авторизация, !*! ziben, 13:26 , 30-Июл-03 (4)
        >>Если все это кажется сложным, используй более высокоуровневые библиотеки, которые возьмут все
        >>заботы на себя.  Например, какой-нибудь RPC или CORBA. Последняя не
        >>так сложна, как это может сначала показаться. Простые вещи в CORBA
        >>реализуются достаточно просто, но нет предела усложнению.
        >Хм... нужно поглядеть что за Корба такая... может действительно с ее помощью
        >что-то придумается
        Поглядел... похоже это типа из Агромной пушки по мелкому воробью :)


      • Распределенная авторизация или не только авторизация, !*! asso, 14:12 , 30-Июл-03 (5)
        >Именно так. Я уже сделал авторизацию, но потом оказалось что база пользователей
        >лежит на другом сервере. Теперь вот думаю как это реализовать.

        Если нужно сделать правильно, то надо что-то вроде Kerberos.  Популярно о принципах лежащих в его основе рассказывается здесь:

        http://web.mit.edu/kerberos/www/dialogue.html


        >Мне то в принципе нужно что бы так: в одну сторону $login
        >+ $passwd, обратно "да-нет"+$users_alias+$email... и все, но похоже в реализации это
        >выглядит гораздо сложнее :)

        Лущше $password не посылать.  Логинящийся посылает $login, ему в ответ $random_string.  Логинящийся посылает MD5($random_string . $password). Сервер проделывает то же самое, и если результат совпал то продолжает диалог иначе разрывает соединение.

        • Распределенная авторизация или не только авторизация, !*! ziben, 14:28 , 30-Июл-03 (6)
          >Лущше $password не посылать.  Логинящийся посылает $login, ему в ответ $random_string.
          > Логинящийся посылает MD5($random_string . $password). Сервер проделывает то же самое,
          >и если результат совпал то продолжает диалог иначе разрывает соединение.
          вот именно в этом и есть загвоздка - пока я не пойму КАК организовать вот это "передал строку - получил строку".
          А насчет передавать пароль или его крипт - это уже детали. причем не шибко важные, ибо все это вертится во внутренней сети, и хаккеров пока не предвидится, юзеры MS Word с трудом осилили, им не до взлома :)


          • Распределенная авторизация или не только авторизация, !*! konst, 19:09 , 30-Июл-03 (7)
            >>Лущше $password не посылать.  Логинящийся посылает $login, ему в ответ $random_string.
            >> Логинящийся посылает MD5($random_string . $password). Сервер проделывает то же самое,
            >>и если результат совпал то продолжает диалог иначе разрывает соединение.
            >вот именно в этом и есть загвоздка - пока я не пойму
            >КАК организовать вот это "передал строку - получил строку".
            >А насчет передавать пароль или его крипт - это уже детали. причем
            >не шибко важные, ибо все это вертится во внутренней сети, и
            >хаккеров пока не предвидится, юзеры MS Word с трудом осилили, им
            >не до взлома :)
            Не проще ли вместо текстовой БД пользовать нормальную (e.g. Postgres,MySQL). С ней не будет проблем соединится по IP-host,login,password


            • Распределенная авторизация или не только авторизация, !*! ziben, 20:06 , 30-Июл-03 (8)
              >Не проще ли вместо текстовой БД пользовать нормальную (e.g. Postgres,MySQL). С ней
              >не будет проблем соединится по IP-host,login,password
              Нет, не проще: база уже давно работает, переписывать базу - это жуткое дело, ибо она используется еще рядом других задач.
              Эх, если б можно было MySQL базу заюзать, разве весь этот сыр-бор я поднимал? :(
              • Распределенная авторизация или не только авторизация, !*! XMan, 21:42 , 30-Июл-03 (9)
                Короче. Делается всё элементарно - ищется модуль для системной библиотеки с названием, типа nss-mysql (для постгреса такой есть), ставится в систему, строится на предмет сервера и таблиц и вообще забывается про то, как кто где авторизуется.

                Серьезный минус только один - нужно заставить PAM при создании пользователя шифровать пароль и засылать его на SQL-сервер. Ручной метод "втупую" - "adduser xxx; passwd xxx", заглядываем в /etc/shadow, берем оттуда пароль, сами запросом втыкаем его в нужную таблицу, "userdel xxx; rm -rf /home/xxx".

                Плюсы:

                a) в /etc/passwd, /etc/group и /etc/shadow никаких ссылок на пользователей нет - всё лежит в базе;

                б) пароли от запрашивающей программы никуда не передаются - от сервера поступает пароль в зашифрованном виде в соответствии с системой, в которой его шифровали (в линухе в последнее время обычно MD5). То есть открытые пароли по сети вообще не бегают;

                в) данные по соответствию uid/gid символьным именам пользователей и групп доступны любой программе. Если не использовать nss, то половина серверных программ вообще работать не будет. Например, почтовые сервисы;

                г) имеется масса потенциальных возможностей, которых нет в стандартных средствах *nix.

                Я пол-года назад почти дописал сетевую авторизации со своим протоколом (дабы отвязать клиента от конкретной SQL-базы вообще - к ней привязана только серверная часть) с использованием механизма NSS и базы PostgreSQL. Отлично работал. За основу клинетской части был взят тот самый nss-pgsql и капитально переписан.
                Сейчас потихоньку переделываю всё это хозяйство - сервер перевел на потоки с порционным созданием в зависимости от нагрузки (аля NetWare), наворотил конфигурацию (в принципе, можно создавать группы в группах, чего нельзя делать стандартными средствами *nix), имеется возможность раздавать свои данные разным сервисам (например, зачем команде "ls -l" посылать пароль, если ей нужно только имя пользователя и группы узнать) на разных машинах, имеется возможность кеширования на стороне клиента и на стороне сервера (на случай частых запросов одного и того же; например, "ls -l ~/"). Есть некоторые мысли по поводу защиты от DoS-атак. Еще некоторые улучшения будут. Планирую в ближашие пару месяцев таки добить это дело и пустить в работу на офисе, если времени будет достаточно. А то совсем загрузили фигней всякой :)

                • Распределенная авторизация или не только авторизация, !*! ziben, 11:12 , 31-Июл-03 (11)
                  >Серьезный минус только один - нужно заставить PAM при создании пользователя шифровать
                  >пароль и засылать его на SQL-сервер. Ручной метод "втупую" - "adduser
                  >xxx; passwd xxx", заглядываем в /etc/shadow, берем оттуда пароль, сами
                  Еще раз уточняю: _без_ SQL нужно, база хранится на втором сервере в текстовом формате! Вот я хотел написать на перле некую двойку: одна часть на веб-сервере из формы получает имя-пароль, обращается ко второй части (на другой сервер) и каким-то макаром (вопрос безопасности пока не рассматриваю) вторая часть сравнивает с текстовой базой. Собственно сам процесс авторизации - это отлажено для случая, если база юзеров лежит на одной машине с веб-сервером. Теперь нужно изобрести как это разнести на разные машины. Причем, средства ограничены - на веб-сервере провайдер никаких наворотов ставить не согласится (поэтому все прийдется делать обычным перловым скриптом), да и на втором сервере тоже ничего в принципе воротить нельзя, тоже максимум перловый скрипт, или может сишная программа небольшая.
                  Буду очень признателен если у кого-то найдется пример типа: две простенькие программки: (1) слушает непрерывно и в случает получения строки отвечает отправкой другой строки, (2) отправила строку и получила ответную. И все. Да, желательно все это на Perl. Или крайний случай: программа (1) - Си, (2) - перл
                  Заранее признателен, Константин
                  • а что тебе мешает посмотреть на исходники того же апача?, !*! йцукенг, 04:46 , 05-Авг-03 (12)
                    или thttpd?
                    да и на перле много демонов написано, webmin, например

                    • а что тебе мешает посмотреть на исходники того же апача?, !*! ziben, 11:46 , 05-Авг-03 (13)
                      >да и на перле много демонов написано, webmin, например
                      хм, webmin нужно поглядеть, ща займусь.
                      Хотя уже частично решил проблему, теперь другие грабли:
                      отправляю строку, сервер ее получает (могу ее в переменную загнать и обрабатывать), сервер отвечает что-то, клиентский скрипт получает, могу вывести на print, а вот в переменную - не могу, не вижу ее снаружи:

                      #!/usr/bin/perl
                          
                      use Socket;

                      $port = 4000;
                      $them = '192.168.1.100';

                      $SIG{'Int'} = 'dokill';

                      sub dokill {
                          kill 9, $child if $child;
                      }

                      #Нужно отправить функции строку, в ответ получить другую.

                      $zapros = "test\n";
                      $otvet=autoriz($zapros);
                      print "Otvet = $otvet\n\n";


                      sub autoriz {

                      chop($hostname = `hostname`);

                      ($name, $aliases, $proto) = getprotobyname('tcp');

                      ($name, $aliases, $port) = getservbyname($port,'tcp')
                          unless $port =~ /^\d+$/;

                      print "Using port $port to connect to server on host $them...\n\n\n";

                      ($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);

                      ($name, $aliases,$type,$len,$thataddr) = gethostbyname($them);

                      if (socket(S,AF_INET, SOCK_STREAM, $proto)) {
                      #    print "Socket creation succeeded.\n";
                      }
                      else {
                          die $!;
                      }

                      $sockaddr = 'S n a4 x8';
                      $this = pack($sockaddr, AF_INET, 0, $thisaddr);
                      $that = pack($sockaddr, AF_INET, $port, $thataddr);

                      if (bind(S, $this)) {
                      #    print "Bind succeeded.\n";
                      }
                      else  {
                          die $!;
                      }

                      # This is similar to the 'accept' in the server, except the server is
                      # waiting for a call and we're actively initiating the conversation.
                      # 'connect' connects our socket to the server's socket on the other end.

                      if (connect(S, $that)) {
                      #    print "Connect succeeded.\n";
                      }
                      else {
                          die $!;
                      }

                      # Force our socket to flush output immediately after a print

                      select(S);
                      $| = 1;

                      select(STDOUT);

                      if ($child = fork) {
                      #Отправляю серверу строку - он ее получает
                      send (S, $_[0], 0);
                          # Sleep for 3 seconds then...
                          sleep 3;
                          
                      } else {
                          # Вот тут планирую ответ сервера в переменную запихнуть
                          while (<S>) {
                              #сервер получил строку "test" и ответил "OK"
                          print "Server: $_";
                              # на экране вижу Server: OK
                          $tempper="$_\n\n";
                          }
                      }

                      return "Repl: $tempper\n";
                      #А получаю в ответ из функции только "Repl:", т.е. $tempper = ""
                      }

                      и где ж тут грабли то?

                      • ошибка тута, !*! йцукенг, 11:01 , 08-Авг-03 (20)
                        ошибка здесь:
                        $tempper="$_\n\n";
                        делай, например, так:
                        $tempper=$tempper."$_\n\n";
                        а то у тебя в цикле результат не накапливается
                        • ошибка тута, !*! ziben, 11:11 , 08-Авг-03 (21)
                          >ошибка здесь:
                          >$tempper="$_\n\n";
                          >делай, например, так:
                          >$tempper=$tempper."$_\n\n";
                          >а то у тебя в цикле результат не накапливается
                          беда не в том, что не накапливался, а в том, что он принципиально не возвращался из процедуры :)
                          но уже найден простой вариант

                          #!/usr/bin/perl -w
                          # gethttp.pl

                          use Socket;
                          use strict;

                          @main::otvet=autoriz();
                          print @main::otvet;

                          sub autoriz {
                          my $serveraddr="127.0.0.1";

                          my $sock_name = GetSockName($serveraddr,4000)
                                or die "Couldn't convert $serveraddr into an Internet address: $!\n";

                          socket(CONN,PF_INET,SOCK_STREAM,getprotobyname('tcp'));
                          connect(CONN,$sock_name)
                                or die "Couldn't' connect to $serveraddr: $!\n";

                          select(CONN); $|=1; select(STDOUT);

                          print CONN "1\n\n";
                          my @body = <CONN>;
                          close(CONN);

                          return @body;
                          }

                          sub GetSockName{
                                my ($nm,$pt) = @_;
                                return undef unless defined($nm);
                                return undef unless defined($pt);
                                return undef unless $nm = gethostbyname($nm);
                                return sockaddr_in($pt,$nm);
                          }

                  • Распределенная авторизация или не только авторизация, !*! Bah, 03:53 , 08-Авг-03 (18)
                    > перловый скрипт, или может сишная программа небольшая.
                    >Буду очень признателен если у кого-то найдется пример типа: две простенькие программки:
                    >(1) слушает непрерывно и в случает получения строки отвечает отправкой другой строки,
                    >(2) отправила строку и получила ответную. И все.

                    Попробую вырезать из своего демона...
                    use IO::Socket;
                    use strict;

                    my $client = "";
                    my $bindaddr   = "127.0.0.1";
                    my $serverport = 12345;

                    while (1) {
                      get_input();
                    }
                    sub startsrv {
                      my $server=IO::Socket::INET->new(LocalAddr=>$bindaddr,
                                                       LocalPort=>$serverport,
                                                       Type=>SOCK_STREAM,
                                                       Reuse=>1,
                                                       Listen=>10) or die "Couldn't be a TCP server on port $serverport";
                      return $server;
                    }

                    sub getinput {
                      while ($client = $server->accept()) {
                        die "Can't fork!: $@" if (!defined (my $child=fork()));
                        if ($child == 0) {
                          # find client ip address
                          my $haddr = getpeername($client);
                          my ($port,$iaddr) = unpack_sockaddr_in($haddr);
                          my $in_ip =  inet_ntoa($iaddr);
                          # Send "wellcome banner" to CLIENT
                          $client->print("Wellcome to example TCP server (Your ip: <$in_ip>)\n");
                          my $cmd = $client->getline; # Recive incoming string from CLIENT
                          # Do something with recieved string
                          .....
                          # Send some datas to CLIENT
                          $client->print("....\n");
                          close $client;
                          exit 0;
                        } else {
                          close $client;
                        }
                      }
                    }

                    читай perldoc IO:Socket;
                    для клиента все с точностью до наоборот. Ну и форкаться не надо, сомо собой... :-)

          • Распределенная авторизация или не только авторизация, !*! Gelin, 07:16 , 08-Авг-03 (19)
            Насчет шифрования паролей:
            RFC 2138 - Radius


  • Распределенная авторизация или не только авторизация, !*! chepil, 07:13 , 31-Июл-03 (10)
    Смотри сюда
    https://www.opennet.ru/openforum/vsluhforumID9/1913.html
    Тут то что тебе нужно
    слева оракл, справа pam (это тебе не надо)
    а посередине сокет сервер и сокет клиент которые пароль шифрованный гоняют туда сюда. Реализация с ошибками, есть у меня без ошибок, уже исправил.
    Попробуй эту, если понравится, скину новую версию




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру