Site Mascot
 

Не удивляйтесь, сайт переехал: был http://smacker.fatal.ru, стал http://smacker.heliohost.org.

Dial-in Сервер, второй заход

30.06.2008 14:12

В этой заметке рассказывается, как организовать простой, но полноценный dial-in сервер на базе Linux для выхода в Интернет через модем.

 
Вводная
Я уже рассказывал о том, как научить Linux принимать звонки и устанавливать сетевое соединение PPP. Однако на тот момент у меня не было постоянного подключения к сети Интернет, поэтому вопросы о выходе в сеть я не рассматривал. Теперь я исправлю это упущение. Из данного текста вы узнаете, как стать самому себе провайдером.
Зачем вообще нужно поднимать dial-in сервер? Многие скажут, что модем является пережитком прошлого, что никто уже не пользуется dial-up'ом для выхода в Интернет и т.п. Однако, с моей точки зрения, всё еще есть масса случаев, когда модем может понадобиться. Например, я оплачиваю безлимитное подключение по PPPoE и хотел бы не платя лишних денег выходить в сеть, находясь на даче. Кто-то может захотеть «поделиться» интернетом с товарищем, у которого нет технической возможности использовать ADSL или домашнюю сеть.
Для того, чтобы сделать всё это возможным, нужно сделать несколько более того, что необходимо для простого соединения машин через телефонную линию. В частности, нужно позаботиться о маршрутизации и желательно поднять собственный DNS сервер. И, конечно, не забыть о том, чтобы сделать сам факт раздачи не очевидным для провайдера, если он открыто возражает против такого использования. Скажем, мой провайдер Э. ничего не имеет против того, чтобы я сам себе предоставлял доступ в интернет через dial-up. А вот провайдер Н., которого я когда-то рассматривал вариант, заявил, что посчитает это нарушением договора, даже несмотря на моё возражение, что это не будет «предоставлением услуги третьим лицам» (т.е. очевидное самодурство вопреки условиям договора). Так что на всякий случай нужно будет подумать о мерах предосторожности.
Всё описанное происходит с помощью дистрибутива ASP 11.2. Также предполагается, что доступ в интернет на будущем сервере уже настроен и успешно работает. В моём случае это соединение с помощью PPPoE. Из-за этого я не рассматриваю случаи, когда выход в сеть осуществляется через прокси-сервер провайдера. И кроме того, я не касаюсь вопроса об организации совместного доступа через собственный прокси. Все описанные действия требуют привелегий суперпользователя root.

 

Настройка ожидания дозвона
Для обработки входящего звонка я использую программу mgetty. Для её настройки нужно отредактировать всего несколько файлов, в частности:
/etc/mgetty+sendfax/mgetty.config
 #US ROBOTICS 2977 int hard fax/voice PCI
 port ttyS1
 speed 115200
 init-chat "" ATZ OK ATQ0\ M=0\ V1\ E1\ S7=40\ &C1\ &D2\ &D3\ +FCLASS=0 OK
 
Такая конфигурация обеспечивает бесшумный приём звонков. Надо отметить, что количество гудков до взятия трубки модемом указывается в другом месте. Узнать строку инициализации своего модема можно, например, с помощью wvdial, как это было описано ранее. Единственным отличием сейчас стало то, что пришлось заэкранировать пробелы.

 

Далее надо настроить подъем сетевого интерфейса PPP. В файле /etc/mgetty+sendfax/login.config можно указать до 9 параметров, передаваемых демону pppd. Обращу внимание на параметр ms-dns, который обозначает адрес DNS-сервера, который будет сообщен клиенту. В моём примере указан тот же адрес, что и адрес сервера, так как я использую собственный DNS (об этом — ниже). Если же этого не делать, то в качестве этого адреса нужно будет указать DNS-сервер вашего провайдера. Конечно, адреса серверов можно указывать на стороне клиента и вручную, но это совсем не удобно. Всё остальное осталось без изменений с прошлого раза: аппаратный контроль потока, авторизация только через pap, адрес, присваемый серверу — 192.168.93.10, клиенту — 192.168.93.20 (в файле это одна строка):
 /AutoPPP/ - - /usr/sbin/pppd \
 auth refuse-chap require-pap login modem crtscts ms-dns 192.168.93.10 192.168.93.10:192.168.93.20 

 

Настройка авторизации
Для простоты процесса предположим, что дозвон будет происходить под логином и паролем уже существующего пользователя. Впрочем, ничто не мешает задать фиктивный логин и пароль.
Для этого в файле /etc/ppp/pap-secrets (ибо refuse-chap) надо на каждого пользователя, кого мы хотим пускать на машину, завести по записи вида:
 someusername * "" * 
Где первое поле — имя разрешенного пользователя, второе — имя сервера, на котором будет происходить авторизация, третье — «секрет», более известный как пароль — если его не указать (как у меня), то будет использоваться учётная запись существующего в системе пользователя с указанным логином. Последнее поле — ip адреса, которые можно будет использовать пользователю. Мы его уже задали.

 

Запус mgetty
Запустить mgetty можно только через inittab, добавив в файл /etc/inittab примерно такую строку:
 S1:2345:respawn:/sbin/mgetty -x 3 -n 10 /dev/ttyS1 
Для того, чтобы изменения вступили в силу, надо заставить систему заново считать inittab, сказав от root-a init q. Для того, чтобы отключить mgetty, надо закомментировать данную строку (#) и снова считать inittab.
Стоит особо отметить параметр -n, который указывает количество гудков, после которых произойдет соединение. Если вы не хотите, чтобы существование модема было легко обнаружить случайно позвонившему вам человеку или чтобы модем не мешал нормальным звонкам, установите число гудков побольше. Так, десять гудков — это примерно минута ожидания. Надо сказать, что при больших значениях этого параметра придётся «научить» звонящий модем ждать соответствующее количество времени, так как по умолчанию может быть установлено меньшее время — скажем, для модема Lucent/Agere на моём ноутбуке максимальное время, которое модем будет ждать соединения (строго говоря, завершения «рукопожатия», или «handshake») — 45 секунд (если мне не изменяет память). Поэтому для того, чтобы ждать дольше, в его строку инициализации пришлось добавить «S7=90», т.е. увеличить время ожидания «рукопожатия» до 90 секунд. О том, какой регистр отвечает за время ожидания соединения на вашем модеме, вам, наверное, придётся узнать самостоятельно, я не могу утверждать, что для всех модемов это будет S7.
Впрочем, это стоит хлопот — на модем, ждущий звонка минуту или две, сложно наткнуться случайному человеку (мало кто будет ждать ответа столько времени), а если вы находитесь дома — успеете снять трубку вовремя.

 

Маскарадинг
Итак, после проделанных операций, мы добились того, что между сервером и клиентом устанавливается соединение PPP. Однако наша цель — подключить клиента к сети. Так как у нас есть только одно подключение и один адрес IP, нам нужен маскарадинг (который нынче любят называть просто NAT-ом): сервер посылает пакеты от клиента, как если бы они исходили с самого сервера, а ответные пакеты отправляет обратно клиенту. В Linux это реализуется очень просто, с помощью iptables.

 

Сначала разрешим форвардинг пакетов в принципе:
 echo 1 > /proc/sys/net/ipv4/ip_forward 
Эту строчку имеет смысл добавить в /etc/rc.d/rc.local, чтобы команда выполнялась автоматически при загрузке. Но у меня она добавлена в скрипт /etc/init.d/pppoe из пакета rp-pppoe (Roaring Penguin PPPoE), который устанавливет PPPoE соединение.

 

После этого нужно установить правила для iptables. Прежде всего нужно запретить входящие соединения из сети и не принимать битые пакеты, которые часто могут использоваться для атак. Разрешить принимать только пакеты, приходящие в ответ на наши запросы. Подробнее об этом можно узнать из iptables tutorial:
 iptables -A INPUT -m state --state INVALID -j DROP
 iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j REJECT --reject-with tcp-reset
 iptables -A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP 
 iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
 

 

Нужно разрешить свободную передачу пакетов внутри нашей сети и применительно к loopback:
 iptables -A INPUT -d 127.0.0.1 -j ACCEPT 
 iptables -A INPUT -d 192.168.93.0/255.255.255.0 -j ACCEPT 
 iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT 
 iptables -A OUTPUT -s 192.168.93.0/255.255.255.0 -j ACCEPT 
 
Моя машина работает в качестве маршрутизатора и для локальной сети внутри квартиры, поэтому я указал диапазон адресов с помощью маски. Если же вам это не нужно, смело указывайте только конкретные адреса.

 

Наконец, главное — разрешить форвардинг (передачу) пакетов между внешним сетевым интерфейсом, смотрящим в интернет (у меня это ppp0) и интерфейсом, который установит mgetty (соответственно, им будет ppp1).
 iptables -A FORWARD -i ppp0 -o ppp1 -m state --state ESTABLISHED -j ACCEPT 
 iptables -A FORWARD -i ppp1 -o ppp0 -j ACCEPT 
 

 

В завершение озаботимся незаметностью нашего сервера извне. Поясню суть: у каждого пакета есть параметр TTL — time to live. Каждая машина, через которую проходит на пути к цели пакет, уменьшает это значение на единицу. Когда TTL становится равным 0, пакет «умирает», не передается дальше. Это делается для того, например, чтобы пакеты не могли циркулировать слишком долго или даже вечно из-за неправильной маршрутизации. Очевидно, что наша машина будет передавать в сеть пакеты с двумя разными значениями TTL — для пакетов клиента и для собственных (во-первых, у них могут быть разные настройки начального значения TTL. Во-вторых, TTL пакетов клиента будет уменьшаться на единицу). Это легко заметить и если провайдер не вполне адкеватен, то ему не составит труда отслеживать такие случаи автоматически. Избавиться от этого очень просто: надо сказать iptables, чтобы TTL для всех исходящих пакетов устанавливался один и тот же, например, 64:
 iptables -A POSTROUTING -o ppp0 -j TTL --ttl-set 64
 
Всё, теперь существование нашей схемы можно обнаружить только перлюстрацией передаваемых данных.

 

Для сохранения правил воспользуемся утилитой iptables-save, направив её вывод в файл /etc/sysconfig/iptables:
 iptables-save > /etc/sysconfig/iptables
 

 

DNS-сервер
Эту схему очень удобно расширить собственным кеширующим DNS-сервером. То есть запросы будут передаваться другим DNS-серверам, а полученные ответы храниться, и при повторном запросе браться из кеша. В результате, в частности, pppd может передавать один адрес DNS-сервера клиенту, а фактически работать будут 2 или даже больше серверов. А если указать несколько разных серверов в настройках BIND, то сбой сервера провайдера будет не страшен.
Приведу конфигурацию своего сервера. В секцию forwarders следует вписать как минимум DNS-сервера провайдера, при желании дополнив сторонними. В остальном всё довольно прямолинейно, но я настоятельно рекомендую предварительно изучить документацию к BIND (named).

 

 options {
 	listen-on port 53 { 
 		127.0.0.1;
 		192.168.93.1;
 		192.168.93.10;
 	};
 
 	directory 	"/var/named";
 	dump-file 	"/var/named/data/cache_dump.db";
         statistics-file "/var/named/data/named_stats.txt";
         memstatistics-file "/var/named/data/named_mem_stats.txt";
 	query-source    port 53;	
 
 	allow-query     { 
 		localhost;
 		192.168.93.0/24;
 	};
 
 	forwarders {
 		123.123.123.123;
 		231.231.231.231;
 	};
 
 };
 logging {
 
 	channel syslog {
 		file "data/named.syslog";
 		severity info;
 	};
 
         channel default_debug {
                 file "data/named.run";
                 severity dynamic;
         };
 	
 	channel default_syslog {
 		syslog daemon;
 		severity warning;
 	};
 
 	channel default_stderr {
 		syslog daemon;
 		severity warning;
 	};
 
 };
 
 view localhost_resolver {
 	match-clients 	   { localhost; };
 	match-destinations { localhost; };
 	recursion yes;
 	include "/etc/named.rfc1912.zones";
 };
 
 view local_network {
 	match-clients 	   { 192.168.93.0/24; };
 	match-destinations { 192.168.93.0/24; };
 	recursion yes;
 	include "/etc/named.rfc1912.zones";
 };
 
Как видно, запросы разрешены для сервера и для моей локальной сети (в которой будет находиться и dial-up клиент), уровень протоколирования сведён к минимуму, логи не забиваются сообщениями о разрешении каждого имени.

 

Заключение
Настройка полноценного dial-in сервера по определению охватывает несколько областей, по каждой из которой написаны отдельные большие маны и хавты, каждый из которых превышает мою статью в разы — настройка BIND, работа с модемами, маршрутизация. Я не претендую на такую же полноту изложения. Но полагаю, что мой текст вполне можно использовать в качестве руководства к действию. В остальном же рекомендую почитать дополнительные материалы.

 

Дополнение
С помощью трафик-компрессора ziproxy можно значительно увеличить пропускную способность полученного канала. Так, согласившись на потерю качества изображений в пользу меньшего их размера, я загрузил главную страницу «коммерсанта» не за 6 минут, а за 1 минуту 40 секунд. Кстати, если использовать JPEG2000 и поддерживающий этот стандарт браузер, то и потери в качестве будут значительно меньшими. Пока я не обратился к этой теме подробнее, рекомендую ознакомиться с обзором http://ylsoftware.com/?action=news&na=viewfull&news=289 и посетить официальный сайт http://ziproxy.sf.net
  1. Я буду рад, если вы оставите свой отзыв об этой заметке:

    Никнейм

    Email

    URL

    Заголовок комментария

    Проверка на человечность
    - Введите буквы:
    The CAPTCHA image