#1 2008-05-22 07:39:02

milt
Ветеран
Зарегистрирован: 2008-04-22
Сообщений: 78
Профиль

Построение сетевого окружения "чужих" сетей

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

Всё намного сложнее в домашних сетях: здесь многое определяется застройкой и часто нет возможности разродится звездообразной конфигурацией. Вот и ходят пользователи к друг другу через всякие сканы, NetView-веры - а что делать. Также часто невозможно всё сделать правильно из-за разнородности материального положения сетей: одна сеть разжилась сервером с DHCP, WINS, обозревателем на самбе (мне больше нравится слово "оборзеватель" smile ), а в другой сети живут вообще без серверов, или, например, нет человека, хоть немного разбирающегося в сетевой "механике": помогать такой сети никто не собирается - чай не райсобес, но соединиться "по-правильному" хотелось бы. Что делать?

А ответ в данном случае достаточно прост: надо научиться строить добавлять пользователей чужих сетей в сетевое окружение (сетевой обозреватель) и в службу WINS. Классическое построение сети предполагает наличие в таких сетях реплицирующихся WINS-серверов (samba4wins или WINS на Windows) и главного обозревателя сети (PDC) на самбе с включенным режимом enhanced browsing и настроенным remote browse sync. Однако, по описанным выше причинам, классика здесь неприменима smile

Однако, сама самба имеет встроенный нереплицируемый WINS и умеет выполнять роль PDC - всё в одном флаконе, удобно. Т.е. дело за малым - научить самбу добавлять новых пользователей из чужих сетей в сетевое окружение и WINS (без WINS-а тупой пользователь будет тыкать мышкой в хост, а IP адреса-то его никто знать не будет smile ).

Вобщем всё получилось, результат патча на скриншоте.

За основу была взята самба 3.0.24-6etch4. Выяснить, имя и группу произвольного хоста в сети можно с помощью команды nmblookup -A <ip>, т.е. взяв за основу исходники nmblookup -A, можно построить нетбиос сканер.
Ф-ция на которой базируется nmblookup -A - node_status_query - находится в файле libsmb/namequery.c. В этой ф-ции надо подправить таймаут ожидания ответа с 2сек на 0.15сек, т.к. если реальный хост будет так "быстро" отвечать, то врядли он может кого-то заинтересовать smile

Код:

NODE_STATUS_STRUCT *node_status_query(int fd,struct nmb_name *name,
                      struct in_addr to_ip, int *num_names,
                      struct node_status_extra *extra)
{
    BOOL found=False;
    int retries = 2;
    int retry_time = 2000; // вот тут надо установить 150 млС
    struct timeval tval;
    struct packet_struct p;
    struct packet_struct *p2;
    struct nmb_packet *nmb = &p.packet.nmb;
    NODE_STATUS_STRUCT *ret;

Со сканером всё вроде понятно, теперь надо придумать, как полученные данные вписать сетевое окружение. Частенько можно встретить разные "замечательные" способы с исправлениями browse.dat, который формирует nmbd, а показывает smbd, но постараемя быть выше этого: стоит попробовать заставить nmbd сформировать правильный список сразу.
Списки пользователей nmbd формирует и хранит в памяти: nmbd только записывает файл browse.dat, но никогда не читает, т.е. надо найти точку внедрения в код. Внимание сразу же привлекает файл nmbd_incomingdgrams.c, а в нём ф-ция process_host_announce - это то, что доктор прописал. Из ф-ции видно, что хост добавляется след.образом:

1. вначале в памяти ищется рабочая группа, которой принадлежит хост

Код:

work = find_workgroup_on_subnet(subrec, work_name);

2. если такой группы ещё нет, то создаём её

Код:

// откат, если нулевой указатель
if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) goto done;

3. по аналогии с группой, ищем имя хоста и если его нет, создаём в списке обозревателя новую запись

Код:

if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
{
    create_server_on_workgroup(work, announce_name, 
        servertype|SV_TYPE_LOCAL_LIST_ONLY,ttl, comment);
}
else
{
    servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; // обновление типа хоста
    // обновляем время жизни записи, в своём коде впишем сюда "вечный" TTL
    update_server_ttl( servrec, ttl);
    fstrcpy(servrec->serv.comment,comment); // обновляем комментарий
}

Т.е. из этого кода видно, как можно добавить сервер в сетевое окружение: надо знать имя рабочей группы, имя хоста и коментарий, который можно сформировать и самим. Чуть ниже идёт код удаления хоста из списка.

Код:

if(!is_myname(announce_name) && (work != NULL) &&
    ((servrec = find_server_in_workgroup( work, announce_name))!=NULL))
{
    remove_server_from_workgroup( work, servrec);
}

Этого всего уже достаточно для того, чтобы самим формировать список обозревателя сети, теперь надо освоить работу со службой WINS: работа с WINS через файл wins.dat представляется несколько ущербной, т.к. этот файл читается только при запуске nmbd, а в процессе работы только записывается. На самом деле записи WINS хранятся в tdb-файлах мини-БД, встроенной в самбу. К тому же придётся написать свою ф-цию ip >-> name, обратную работе WINS для удаления старых записей имён в списке обозревателя. После недолгих "фтыканий" находим ф-цию

Код:

add_name_to_subnet(wins_server_subnet,announce_name,nb_type,(uint16)NB_ACTIVE,
    ttl,REGISTER_NAME,ip_nums, ip_list);

Здесь announce_name - имя, регистрируемое в WINS, nb_type - тип нетбиос имени, далее идёт статус записи, время жизни, описание имени (доменное, винс и т.п.), ip_nums - кол-во адресов в массиве ip_list, которые относятся к имени. Удалять имя из WINS - вредно, поэтому на это заморачиваться не будем, ведём только накопительную деятельность smile  Регистрировать будем 2 типа записей: nb_type=0x00 и nb_type=0x20. Осталось разобраться с мини-БД самбы для реализации ip >-> name, и можно приступать к написанию патча на самбу.

Каталог TDB достаточно документирован для того, чтобы сообразить с первого подхода, как написать поиск имени по IP, поэтому код поиска по связанному списку приводится без предисловия: он прост.

Код:

BOOL find_name_by_ip(uint32 ip,fstring ntb_name)
{
    TDB_DATA            key, data, newkey;
    struct  name_record *namerec=NULL;

    for(key=tdb_firstkey(wins_tdb); // находим первый элемент в списке
         key.dptr; // проверяем, а не хвост ли это? он вообще указвает на что-либо?
         newkey=tdb_nextkey(wins_tdb,key),safe_free(key.dptr),key=newkey)
    // а текущий элемент указывает на следующий элемент
    {
        data=tdb_fetch(wins_tdb,key);
        if (data.dsize==0) continue;
        namerec=wins_record_to_name_record(key,data); // перевод записи в удобоваримый формат
        SAFE_FREE(data.dptr);
        if (!namerec) continue;
        if (namerec->data.num_ips)
        {
            DEBUG(9,("find_name_by_ip: %s ip=%s\n",namerec->name.name,inet_ntoa(*(namerec->data.ip)) ));
            if  (*((uint32*)namerec->data.ip)==ip)
            {
                pull_ascii_nstring(ntb_name,sizeof(fstring),namerec->name.name);
                SAFE_FREE(namerec->data.ip);
                SAFE_FREE(namerec);
                return True;
            }
        }
        SAFE_FREE(namerec->data.ip);
        SAFE_FREE(namerec);
    }
    return False;
}

Всё, все составляющие для дополнения самбы готовы, процесс сканирования будет жить в отдельном треде и передавать данные в бесконечный рабочий цикл nmbd, т.к. ф-ции, которыми будем пользоваться - нереентерантны. В дополнение к скану снабдим самбу полезным свойством "нерегистрации" левых групп типа FRILAN вместо FREELAN, или S2LANE вместо S2LAN, которые создают тупые пользователи. Для этого немного изменим ф-цию create_workgroup в файле nmbd_workgroupdb.c дополнив её проверкой check_workgroup, которая говорит о полезности или вредности группы в списке.

Код:

DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n",
    name, subrec->subnet_name));
if (!check_workgroup((char*)name)) return NULL;
if ((work = create_workgroup(name, ttl)))
{
    add_workgroup(subrec, work);

Также сделаем свой коментарий (адрес хоста) для найденного или анонсировавшего себя хоста.

Код:

void create_comment(char* name, uint32 ip, fstring cm_text)
{
    if (name[0]>0x20)
    {
    snprintf(cm_text,MAX_SERVER_STRING_LENGTH,"%s",
        inet_ntoa(*((struct in_addr*)&ip)) );
    }
}

Из текста патча, приведённого ниже, будет видно, что в секции [global] появляются два новых параметра scan net и allow groups. В параметр scan net вписываются все сети, которые надо сканировать  в формате сеть/маска, сети записываются через пробел или запятую, например:

scan net = 192.168.15.0/24 192.168.12.0/255.255.255.0 192.168.14.0/24

Если параметр scan net пуст, то фича сканирования не будет активизирована и самба будет работать, как "нормальная" самба без патча.

Разрешённые группы записываются в параметре allow groups через пробел или запятую, например

allow groups = OPENLAN FREELAN S2LAN LIFESTREAM

Если список пуст или параметр не задан, то доступны все сканированные или анонсировавшие себя группы.

И хотя фича сканирование задумывалась для дополнения "своего" списка самбы хостами из других подсетей, оказалось, что очень удобно сканировать и свою сеть: решаются проблемы "могильных камней" и становятся однотипными коментарии. Крайне не рекомендуется включать scan net  с выключенным своим WINS, надеюсь, что не надо объяснять почему smile

Собственно и всё. Скачать патчи для samba-3.0.24 можно здесь, а для samba-3.0.28a - здесь.

Вот пример конфигурационного файла /etc/samba/smb.conf

Код:

[global]
        workgroup = S2LAN
        dos charset = CP1251
        server string = S2LAN-14 Router

        obey pam restrictions = Yes
        domain logons = No
        lm announce = Yes
        dns proxy = No
        ldap ssl = no

        os level = 124
        domain master = Yes
        local master = Yes
        preferred master = Yes

        wins support = yes

        scan net = 192.168.15.0/24 192.168.12.0/24 192.168.14.0/24
        allow groups = S2LAN VGU


        share modes = Yes
        security = share
        encrypt passwords = yes

        load printers = No
        show add printer wizard = No

Вложения

Отредактировано milt (2008-10-20 13:43:24)

Неактивен

 

Board footer

Powered by PunBB

[ Generated in 0.017 seconds, 9 queries executed ]