Домен через SAMBA №2

Итак, мы построили собственный домен. Как ты понимаешь, построить его мало – домен необходимо обслуживать. Передо мной были поставлены ряд задач (со стороны начальства), которых я должен был придерживаться. Одна из них – распределение прав по пользователям, другая – удобное администрирование Samba через Web. Как я их решал ты можешь узнать во второй части статьи.

1. Интернет для избранных

Задача была следующей: необходимо было дать доступ в Интернет сотрудникам организации, но запретить всем остальным лицам. Сотрудники находились в группе work, им то и требовалось открыть Инет.

Итак, читаем маны на Самбу. Выясняем, что в конфиге могут содержаться директивы preexec и postexec, значения которых указывают на скрипт. Этот скрипт выполняется при подключении и отключении шары соответственно. У нас же имеется шара NetLogon, которая подключается при джойне юзера в домен. Нам необходимо сотворить следующее: добавить запись в фаервол, которая бы обеспечила маскарад на указанный ip-адрес. После логоффа юзера, правило должно быть удалено.

Все реализуемо. Единственное НО! Скрипт должен запускаться под рутом. Суид-бит устанавливать не очень охота, но на помощь приходит опять же man :). В Самбе существуют опции root preexec и root postexec, которые выполняют те же действия, но под суперпользователем.

Задача практически решена. Остается написать небольшой perl-скрипт:

#!/usr/bin/perl
use Getopt::Std;
getopt("aiu"); ## Забираем параметры из командной строки

$predir = '/etc/samba/scripts'; ## Устанавливаем директорию, где содержится файл с пользователями
if ($opt_a == 1) { ## Если опция a=1, значит юзер залогинился в систему
open(VIPS,"$predir/vips");
@users=<VIPS>;
close(VIPS);
foreach (@users) {
chomp;
if ($opt_u eq $_) {
$find = 1; ## Находим логин – значит следует врубить маскарад
}
}
if ($find == 1) {
system("/sbin/iptables -t nat -A POSTROUTING -s $opt_i -j MASQUERADE");
system("touch $predir/$opt_u\.lock"); ## Врубаем маскарад и создаем lock-файл
}
} else {
if (-f "$predir/$opt_u\.lock") { ## Иначе, при наличии lock-файла
unlink("$predir/$opt_u\.lock");
system("/sbin/iptables -t nat -D POSTROUTING -s $opt_i -j MASQUERADE"); ##
Убираем маскарад-правило
}
}

Вот простая реализация скрипта. Если ты внимательно смотрел код, то понял, что скрипту передаются три параметра - -a, -i и –u. Второй отвечает за IP-адрес машины, последний – имя пользователя, которое будет искаться в vips.

Остается добавить пару опций в smb.conf (в шару NetLogon):

root preexec = /etc/samba/scripts/masq.pl -u %U -a 1 -i %I
root postexec = /etc/samba/scripts/masq.pl -u %U -a 0 -i %I

Динамические переменные %U и %I отвечают за имя пользователя и IP-адрес соответственно.

Что мы получаем? После захода пользователя его логин ищется в файле vips. Если он найден – добавляется правило-маскарад, в противном случае ничего не происходит.

2. Админим с Web’а.

Второй проблемой является администрирование пользователей. В моей ситуации необходимо было сделать так, чтобы два работника могли добавить нового пользователя, либо сбросить пароль старому (если он забыл его). Вспомнив про такой замечательный проект Swat, который позволял админить Samba через Web-среду, я поспешно установил его (зачем изобретать велосипед), но затем понял, что он мне не подойдет. Дело в том, что Swat требует ввода рутового пароля для выполнения каких-либо операций. Я же рутовый пароль не скажу никому ни при какой ситуации (более того, шелла на сервер кроме меня никто не имел). Поэтому
былkо принято решение написать свой простенький проект администрирования :).

Для того, чтобы выполнить привилегированные операции с правами nobody, я написал пару Suid-скриптов: null.c и add.c. Почему C? Просто не хотел мучиться с suidperl, а просто выставить suid-бит на бинарники. Привожу здесь листинг всего одного скрипта, ибо не совсем хорошо знаю C (если тебе понадобится листинг add.c – мыль мне). Повторюсь, скрипт обнуляет пароль заданному пользователю:

int main (int argc, char *argv[])
{
char cmd[100],username[20];
setuid(0);
setgid(0); // Выставляем права root
strcpy(username,argv[1]); // Определяем username как argv[1]
sprintf(cmd,"/usr/bin/smbpasswd -n %s >/dev/null 2>&1",username); // Формируем системную переменную
system(cmd); // И выполняем ее.
}

В общем все просто: компилим, получаем рабочий бинарник. Устанавливаем на него владельца root и suid-бит. На этом первая часть нашего кодинга закончена. Переходим к perl :).

Я написал маленький Perl-скрипт, который выполняет заданные операции, а также ведет лог всех запросов. Вот что у меня получилось:

#!/usr/bin/perl

use CGI qw(:standard); ## Юзаем CGI (как же без него?)
$mypath="/usr/web/cgi-bin";
$log="/usr/www/admin.log"; ## Путь к текущей директории и логу
$user=param("user");
$group=param("group");
$logic=param("logic"); ## Основные параметры – группа, юзер и логика (0 – обнулить пароль, 1 – создать юзера).

print "Content-type: text/html\n\n"; ## Хидер

unless ($logic) {
error() unless ($user);
system("$mypath/null $user"); ## Обнуляем пароль, в то же время следим, чтобы поле User было заполнено
} else {
error() unless ($user || $group);
system("$mypath/add $user $group"); ## Иначе при наличии двух заполненных полей – создаем юзера.
}

open(LOG,">$log");
print LOG "$ENV{REMOTE_ADDR}: $logic $user $group\n";
close(LOG);
print "All ok\n"; ## Пишем в лог и на экран.
exit 1; ## И выходим.

sub error {
print "Заполните все поля!\n";
exit 0;
} ## Ругаемся и выходим при недостатке данных.

И третьим шагом будет написание простенькой html-страницы с формой. Приводить листинг ее тоже не буду – напишешь сам :).

Остается лишь поставить права 644 на лог и выставить владельца nobody. А также авторизовать доступ к /usr/web/cgi-bin. Это делается просто. Если не знаешь как – напоминаю - создается файл .htaccess со следующим содержанием:

AuthType Basic
AuthName "Admin Zone"
AuthUserFile /usr/web/cgi-bin/.htpasswd
require valid-user

А затем выполняется команда для создания первого юзера:

htpasswd -cm .htpasswd root

У тебя спросят пароль на пользователя, затем будет создан .htpasswd (опция –c) и пароль закодится в MD5 (опция –m). Теперь для доступа к скриптам от тебя потребуется ввод пароля, совсем не обязательно совпадающего с системным рутовым.

3. Осторожно! Вирус!

И, наконец, пришло время рассказать об еще одной проблеме: вирусы. В наше время вполне реально интегрировать Samba и модуль-перехватчик. Для этого устанавливается демон drwebd и модуль smb_spider (все скачиваем с сайта
www.drweb.ru). После нехитрой установки запишем в нужную шару строку:

vfs object = /path/to/smb_spider.so

И выполним service smb reload.

Теперь попытка передать вирус будет блокирована. В моем случае это выглядело следующим образом:

# smbclient //127.0.0.1/shared -U root
Password:
Domain=[Domain] OS=[Unix] Server=[Samba ALT/2.2.7]
smb: \> put viruzz.exe
putting file viruzz.exe as \editor.dll NT_STATUS_UNSUCCESSFUL closing remote file \viruzz.exe
smb: \>

Таким образом, мы добились решения целых трех проблем :). Хотя лично я со временем отказался от инета по маскарадингу, а реализовал доступ через Squid, ибо при таком раскладе можно определить кто сколько нагнал трафику. Но это уже совсем другая история...