UNИX, осень 2008, 09 лекция (от 26 ноября)

Материал из eSyr's wiki.

Версия от 17:05, 26 ноября 2008; 158.250.19.27 (Обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

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

В прошлый раз была мутная деталь, которая более прозрачной не стала. О различии адресов транспортного и сетевого уровня. Одно производится из другого, но не всегда однозначное соответствие имеет место. Иногда IP и порт совпадают, но в общем случае адресация различна.

Что осталось необговорено на транспортном уровне? Во-первых, на траспортном уровне даются различные гарантии. Мы помним, что TCP гарантирует надежную доставку. Даются гарантии, связанные с тем, что данные не потеряются, не испортятся и пр. Было бы неплохо добавить еще один вектор надежности — защита данных от подсматривания и фальсификации. Помимо надежности есть вопрос о защите. Рассмотрим SSL. Кроме того, свойство траспортного уровня идентифицировать поток данных. Есть NAT. Можно добавить рассказ о шейпинге трафика, но там много всего. Есть такая вещь, как netcat. Еще есть tcpdump.

Начнем разговор с защиты потока данных на траспортном уровне. SSL. Есть такая вещь, как сетевое программирование, есть на втором курсе. Есть сокет — дырка, в которую можно с одной стороны кидать данные, с другой стороны получать. Мы забываем про маршрутизацию и работаем просто с сокетом. Нельзя сказать, что tcp и сокет — одно и то же. Сокеты бывают разные. Есть две дырки, а что между ними — непонятно.

Идея SSL состоит в том, чтобы прикрутить к этим дыркам шифрование. Если не вдаваться ни в какие подробности, то тут можно было бы и закончить. Нужно передать данные о алгоритме шифрования, должен быть сам алгоритм шифрования. Зашифрованные сообщения должны циркулировать между абонентом и адресатом. Никаких дополнительных ограничений на транспортный уровень не накладывается. Прикрутили с обоих сторон дырки шифровальные машинки, на лету шифрующие сообщения, которые затем проходят через Интернет.

По ряду причин, по причине того, что должен произойти первичный обмен данными для шифрования. Кто передает пароль для шифрования? Если он открыт, получается как у Ильфа и Петрова (строго спрашивал у всех пропуск, а у кого не было, пускал так). Можно где-то хранить, но тут есть проблемы. Факт того, что мы передали кому-то пароль фактически значит, что пароль раскрыт. Решение в использовании двух паролей — один для шифрования, другой для дешифрования. Зашифровать так, как мы, никто не может.

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

Проблема все равно осталась. Нужно вначале раздать ключ, но как проверить подлинность выдавшего ключ? Нужно вначале еще как-то проверить, что именно тот адресат присал этот ключ. При асимметричном шифровании ключ выдается один раз. Приходим к сертификатам. Подпись Васи Пупкина, за которого ручается более мощный Вася Пупкин, который очень богатый и которого нельзя подкупить.

Шифрование SSL используется довольно часто. Все знают про https — протокол http, натянутый поверх ssl. Эта вещь связана с пресловутым обменом сертификатами. Редко кто занимается ручной первоначальной передачей сертификатов. Вряд ли кто-то вручную скачивал публичный сертификат.

Либо мы заходим на сайт, сертификат которого уже подписан. В нашей машине уже установлен корневой сертификат. Либо мы попадаем на сайт с самоподписанным сертификатом. Формально тут возможна фальсификация, потому что мы не знаем, что это именно тот, кто подписался. Но довольно редко передается очень серьезная информация. Чаще нужно просто защитить логин/пароль. Тут может быть самоподписанный сертификат, если мы уверены, что из-за такой мелочи не будут взламывать сеть всерьез.

Сейчас есть практика, когда нужно нажать на кнопку, подтверждающую, что мы ничего не боимся. Реально единственная возможность защититься — когда все пространство под единым администрированием. Если мы обращаемся к сети с другим администратором, мы увидим, что мы хотим, а он увидит, что он хочет.

Надстройка над транспортным уровнем означаем, что когда мы пользуемся прикладным уровнем, при использовании SSL на сокетах мы не сможем принять решение. Все они должны быть защищены одним ключом. Есть два сайта, расположены на одной машине с одним IP-адресом. Возникла идея осуществить сервис, защищенный SSL. Мы встаем перед неразрешимой проблемой. Осуществляется соединение к первому сайту (Вася Пупкин) по 443 порту. Соединение осуществляется по IP. На уровне SSL невозможно различить что-то на прикладном уровне. С одной стороны, упираемся в грамотное разделение прикладного и транспортного уровня. Но те люди, которые выписывают сертификаты, выписывают их на адреса прикладного уровня. Из двух сертификатов будет выбран только один. Будет еще более страшное предупреждение о том, что сертификат выдан другим людям. Неоправдано смешаны уровни. IP-адрес не отличается, порт не отличается, а отличается только доменное имя, являющееся частью прикладного уровня. TLS требует модификации протокола.

Программа stunnel. Предназначена для превращения протокола, незащищенного по SSL в протокол, защищенный про SSL. Есть сервис поверх telnet. Можем подключиться, ввести логин/пароль и работать. Можем предоставить Telnet с SSL. Не SSH, а просто защищенное соединение. stunnel осуществляет подключение к порту на удаленной машине. На транспортном уровне осуществляет шифрование. В качестве результата выдает на локальной машине порт, по которому служба уже расшифрована. Подключение к такому порту возможно обычным способом, потом stunnel переложит его в зашифрованный сокет и там уже будет делать всю работу по шифрованию за нас. На сервере может быть аналогичная ситуация. Мы можем не шифровать логин/пароль, а переставлять систему каждую неделю. Можно использовать stunnel. Он подключится по локальному порту к службе, делает зашифрованный порт на нашей же машине, к которому можно подключиться снаружи. Stunnel перекладывает из одного сокета в другой.

Telnet — волшебная программа, которую по назначению никто не использует. Можно сесть за свою машину, подключится к другой машине и работать с ней по сети. Это было чудесно в 80-х гг, а потом в 90-х или даже раньше, стало очевидно, что данные передаются в нешифрованном виде. Логин/пароль интересуют многих. Существует целый список протоколов прикладного уровня, которые передают данные в нешифрованном или плохо шифрованном виде. Сегодня telnet выжила не как терминальный клиент, а как протокол, с помощью которого можно подключиться, потыкать клавиши, получить что-то. Лектор может использовать telnet для отправки письма. Можно смотреть сайты, если в голове есть парсер html.

Реально лучше использовать netcat, например, в скриптах. С его помощью можно скачивать куски сайта. Преобразует сетевой трафик в что-то понятное. Простая программа. Можно передавать файлы. Бывает единственный способ, например, для передачи ssh-ключа. Превращает соединение в поток байтов. Что это за инструменты, подглядывающие пароль? Неужели пароль транслируется по всему Интернету? В одном режиме карта фильтрует лишние пакеты, в другом режиме принимает даже ей не предназначенные. В таком режиме можно принять чужие логин/пароль. Есть даже специальные утилиты для этого.

Утилита tcpdump же — вещь полезная. Она переводит карту в беспорядочный режим. Мы увидим не только фреймы ethernet, но и дешифровку трафика транспортного уровня. В иллюстративном плане tcpdump весьма полезен. Имеет даже некоторые прикладные протоколы.

Когда мы говорили про сетевой уровень и диапазонные адреса, говорили, что предусмотрены диапазоны адресов, не обязанные быть уникальными в масштабе Интернета. Если мы не хотим регистрировать все машины в сети, даже раскрывать машины в сети, можем использовать их. На самом деле такие машины могут ходить в Интернет, это повседневная практика — делать внутренние адреса и делать преобразование сетевых адресов. Можно посылать пакеты и, что важно, получать их. Есть машина, производящая трансляцию сетевых адресов. Есть абонент, посылающий пакет на сервер NAT, тот преобразует его адрес отправителя в свой. Все выглядит кристально, если не начать думать. У нас много машин с внутренними IP-адресами. Возможны варианты. У нас столько же внешних адресов, сколько и внутренних машин. Вопрос — зачем это нужно? Чтобы скрыть внутренний IP и с ним помухлевать. А так — практически, марушритизация, разве что адрес поменяли.

Реально же обычно внешний адрес один. Допустим, отправили пакет, получили ответ. Как понять, какой из внутренних машин предназначен ответ? Если пакет был частью TCP-трафика, мы не можем ничего понять. Введем таблицу. В таблице можно запомнить адрес транспортного уровня — отправитель-порт, получатель-порт. У нас ушел пакет, он — часть TCP-трафика, где известно 4 числа. Когда по TCP вернется ответ, отправитель и получатель будут поменяны местами. Храним IP внутренней машины, порт отправителя, IP сервера, порт сервера. Тогда, когда придет ответ, его можно идентифицировать по IP сервера и порту, увидеть в таблице запись о канале и передать по адресу.

Нужно однозначно выдавать порт сервера. Это просто — мы не сможем выделить один порт для двух каналов. Мы не анализируем состояние TCP. Ждем либо FIN, либо большого таймаута. Есть одна загвоздка — если внутри много машин, на всех может не хватить портов. Проблема червей, нерезанного осла. Раз несколько тысяч соединений, два несколько тысяч и адресное пространство кончается (65 тысяч).

На уровне IP есть ICMP. Там каждый запрос сопровождается уникальным номером-идентификатором. Когда придет ответ, будет понятно, на чей эапрос это ответ. На высоком уровне все проще.

Можем даже залезать на прикладной уровень, если протокол несложен. Пример — DNS-запрос. Посылается UDP-датаграмма, даже на транспортном уровне не можем определить. Заглянув внутрь, мы увидим, что это данные, соответсвующие DNS, по этому протоколу есть номер (кто, кому, номер запроса). Когда приходит датаграмма, подменяем данные и возвращаем клиенту.

Свойства транспортного уровня позволяют вытворять с потоками данных различные малоприличные штуки. Опознавать трафик и переставлять пакеты в зависимости от типа трафика. Один пакет от Васи Пупкина, другой от начальника. Принятый от начальника, пусть недавно, отправляем сразу же. Пакеты перераспределяются по приоритетам. Другой вариант — равные приоритеты. Нагрузка от абонентов разная, но пересылаем по одному пакету от абонента. Еще можно дропнуть один пакет умным маршрутизатором, если идет много больших пакетов. Тогда клиент произведет откат. TCP — довольно удобный инструмент для организации трафика, ограничения трафика и т.д.

Программа netcat, занимающаящася чем? Говорим ей порт, она подсоединяется, мы посылаем с клавиатуры текст, что-то происходит. Можно сделать программу listener'ом, тогда к ней можно подключиться и она выведет то, что ей пошлют. Можно отправить ответ с клавиатуры. Идея программы. Есть сервер, принимающий запросы, отправляющий ответы. Сервер пишем на shell. Нам лень программировать, читаем со стандартного ввода. Лень обрабатывать подключения, выводим на стандартном вывод. Программа-фильтр, по терминологии UNIX-систем. Запускаем программу командой server > file. Осталось сделать так, чтобы это работало с сетью, а не с вводом-выводом. Можно использовать netcat, но лучше использовать метадемон inetd. Он регистрируется в качестве listener на список заданных портов. Можно написать RPC-сервер. Обрабатывает одно подключение по порту, либо сколько угодно подключений на один порт. Преобразует сетевой трафик в поток UNIX, передает нашей программе. Так могут работать популярные ftp-серверы и другие программы.

Происходит жесткое разделение на транспортный уровень, за который отвечает inetd, и прикладной уровень, за который отвечает программа. Единственный недостаток — это существенно медленнее работает, чем когда работает сама программа. Все работает через канал. Канал нельзя забивать, иначе начнется непролезание. Это нагружает систему, если задача — сложная. Сервер http обычно через inetd не пишут. Популярный сервер получает много подключений, которые будут тормозить систему.

Inetd — юниксовый демон, большой пакет. Тип подключение — tcp-udp, какую программу запускать, с какими ограничениями. Например, сколько соединений в секунду разрешать, или сколько соединений с одного IP. В большинстве используется xinetd. Он умеет обрабатывать RPC-запросы. У него не один конфиг-файл, а много. Для каждой службы можно добавить один файл, а для удаления — удалить один файл. Позволяет не редактировать чужие файлы.

В книге Курячий-Маслинский есть описание, как за полторы минуты сделать сервис, выдающий календарь на текущий месяц.

Почему это переход к прикладному уровню? Демон xinetd никакого разбора не делает. Осуществляет работу на транспортном уровне.

Почему разговор о прикладном уровне? Приложений много и много протоколов. Но есть очень важный протокол. Без протокола DNS «не работает Интернет».

Личные инструменты
Разделы