Контроль доступа с помощью tcpd

Начиная с открытия компьютера для сетевого доступа, в работу вовлекается много средств защиты. Некоторые из них, однако, могут быть непригодны (наиболее явно это показал RTM Internet worm) или могут не различать безопасные хосты, просьбы о частном обслуживании из которых будут приняты, и опасные хосты, чьи запросы должны быть отклонены. Мы уже кратко обсуждали сервисы finger и tftp. Увы, на уровне inetd нельзя ограничить доступ определенным хостам.

Полезное средство для этого tcpd так называемый "daemon wrapper". Для сервиса ТСP, который Вы хотите контролировать или защищать, вместо него вызывается tcpd. Он регистрирует запрос через syslog daemon, проверяет позволено ли этому хосту использовать затребованный сервис и только, если это так, запускает программу соответствующего сервера. Заметьте, что такой подход не работает с udp-сервисами.

Например, чтобы ограничить доступ к finger, Вы должны изменить строку в inetd.conf:

# unwrapped finger daemon
finger    stream tcp nowait bin    /usr/sbin/fingerd in.fingerd
на:
# wrap finger daemon
finger  stream  tcp     nowait  root    /usr/sbin/tcpd   in.fingerd

Без добавления какого-либо контроля доступа ничего для клиента не изменится за исключением того, что любые запросы будут регистрироваться в syslog auth.

А вот теперь добавим контроль доступа. Он выполнен посредством двух файлов: /etc/hosts.allow и /etc/hosts.deny. Они содержат разрешения и запреты доступа к некоторым сервисам и хостам. Когда tcpd обрабатывает просьбу о доступе к finger от клиентского хоста biff.foobar.com, он просматривает hosts.allow и hosts.deny (именно в этом порядке!) в поисках соответствующей записи для сервиса и клиентского хоста. Если запись была найдена в hosts.allow, доступ будет предоставлен независимо от записей в hosts.deny. Если соответствие найдено в hosts.deny, то запрос будет отклонен. Если никакого соответствия не найдено вообще, запрос будет принят.

Записи в файлах доступа выглядят так:

servicelist: hostlist [:shellcmd]

servicelist задает список имен сервисов из /etc/services или ключевое слово ALL. Чтобы соответствовать всем сервисам, за исключением finger и tftp, используйте ALL EXCEPT finger, tftp.

hostlist задает список имен хостов, адресов IP или ключевых слов ALL, LOCAL, UNKNOWN или PARANOID. ALL соответствует любому хосту, LOCAL имени хоста, не содержащему точек. UNKNOWN соответствует любым множествам, чьи названия или адреса ошибочны. Наконец, PARANOID соответствует любому хосту, чье имя не преобразуется в IP-адрес. Имя, начинающееся с точки, соответствует всем хостам, чьи домены являются равными этому имени. Например, .foobar.com подойдет для biff.foobar.com. Имеются также условия для сетевых адресов IP и подсетей. Имя, заканчивающиееся на точку, соответствует всем адресам, которые начинаются на заданный шаблон. Так, 172.16. подойдет для 172.16.32.0, но не для 172.15.9.1. Шаблон вида n.n.n.n/m.m.m.m задает адрес и сетевую маску подсети, например, 172.16.0.0/255.255.0.0. Необязательно здесь указывать все адреса и имена. Их можно разместить в файле, а в этом месте вписать имя файла, начинающееся с "/", допустим, /var/access/trustedhosts.

Для того, чтобы отказать в доступе к finger и tftp всем, кроме локальных хостов, сделайте пустым /etc/hosts.allow и поместите в /etc/hosts.deny:

in.tftpd, in.fingerd: ALL EXCEPT LOCAL, .your.domain

Произвольная запись shellcmd может содержать команду для вызова оболочки, когда запись совпадает. Полезно установить ловушку, которая может разоблачить потенциальных нападающих:

in.ftpd: ALL EXCEPT LOCAL, .vbrew.com : \
      echo "request from %d@%h: >> /var/log/finger.log; \
      if [ %h != "vlager.vbrew.com:" ]; then \
          finger -l @%h >> /var/log/finger.log \
      fi

Аргументы %h и %d tcpd превратит в имя хоста клиента и имя сервиса. Подробности есть на man-странице hosts_access(5).