Saturday, January 30, 2016

Э. Таненбаум, Д. Уэзеролл "Компьютерные сети", 5-ое издание

Я наконец-то дочитал эту действительно сложную для меня книгу. 930 страниц А4 следовало прочитать за месяц, причем прочитать вдумчиво, чтобы в голове что-то осталось. Кроме того, в конце каждой главы был список задач. Для лучшего усвоения материала я решал эти задачи. Сначала я пытался решить все, но потом понял, что это занимает много времени, а пользы от этого немного, поэтому я решал 10% задач после каждой главы (это обычно 4-5 задач). Минусы задач были в том, что ответов на них не было (в интернете тоже особо не найдешь), некоторые ответы были в главе, но до других надо было дойти самому, или посчитать самому, а свериться было не с чем. Я читал по 30 страниц в день (иногда получалось больше) в три подхода - 10 по дороге на работу, 10 на обеде, 10 по дороге домой. Книга шла довольно тяжело, некоторые абзацы (я бы сказал 90%) приходилось перечитывать по нескольку раз, так что я смело могу утверждать, что я прочитал ее, как минимум, три раза. Некоторые вещи я, конечно же упустил, но это не страшно, ведь я не собираюсь проектировать сети или работать с ними каждый день. Моя цель была закрыть пробелы в знаниях и размять мозг и эти цели, я думаю, были на 100% выполнены. Ниже находится мое краткое изложение книги, чтобы структурировать полученные знания и вспомнить, когда понадобится (скорее всего через год перечитаю этот пост). Для проходящего читателя тут, скорее всего, полезной информации не будет, но если вы бегло хотите понять стоит ли это книга того, чтобы читать, возможно мое изложение вам поможет. От себя хочу добавить, что без знаний математики и хотя бы азов программирования браться за нее не стоит. Книга написана с долей юмора и интересными историческими справками (порой, тоже с долей юмора). Книга не научит вас проектировать сети, здесь можно найти общие знания, так сказать, фундамент, который вам пригодится если вы будете работать с ними напрямую или косвенно. Если вам нужны более подробные темы, советую заглянуть на последние страницы, там приведена масса литературы с довольно интересными пояснениями для чего и кому это нужно читать. Лично я добавил несколько книжек в свою бесконечную очередь для прочтения. А теперь приступим к изложению.

Книга представляет из себя довольно объемный и подробный обзор структуры и принципов работы компьютерных сетей.  Конечно, очень много материалов осталось за рамками этой книги, просто потому что сама область довольно большая и по каждой мелкой детали, упомянутой у Таненбаума одним предложением, найдется отдельная книга на 900 страниц, но и этого достаточно, чтобы понять основны и понимать, что же происходит вокруг тебя каждую наносекунду в вечно бурлящем эфире и судорожно напряженных проводах.

Книга разделена на главы, каждая из которых (за исклюением двух) посвящена отедльному уровню сетевой модели. Краткий обзор существующих, наиболее популярных сетевых моделей (TCP/IP и OSI) дается во введении. Вкратце, сетевые модели делятся на уровни, для того чтобы разделить ответственность в сложной структуре, сделать сеть масштабируемой (то есть легко расширяемой на более сложные варианты) и гибкой (то есть, чтобы сеть не ломалась, если вдруг перевести ее с коаксиального кабеля на передачу с помощью радиоволн). Каждый уровень можно описать как протокол + интерфейс. Протокол предосталяет способ общаться одинаковым уровням получателя и отправителя, в нем определяется в каком виде будет происходить обмен данными и как будут выглядеть данные. Интерфейс предоставляется нижним уровнем верхнему в обе стороны, чтобы нижний уровень одного устройства, смог забрать данные у верхнего уровня того же устройства, обработать их и передать более нижнему уровню. В книге рассматривалась обобщенная, довольно обоснованная сетевая модель, учитывающая недостатки и TCP/IP и OSI. Модель поделена на 5 уровней (от нижнего к верхнему): физический, канальный, сетевой, транспортный, прикладной. Есть еще два, рассмотренных отдельно подуровня: подуровень управления доступом к среде (подуровень канального уровня) и не всегда существующий подуровень безопасности (SSL работает между прикладным и транспортным уровнем).

Физический уровень отвечает за то, как будут переданы данные в физической среде. Он оперирует битами данных, которым соответствуют некоторые уровни напряжения (например 3В это 1, 0В это 0). На физическом уровне решается что будет использоваться в качестве переносчика информации: коаксиальный кабель, оптоволокно, UTP (существует несколько версий этого кабеля),  или же беспроводные переносчики, такие как радиоволны на разных частотах. У каждого из этих способов есть свои проблемы, влияющие на стоимость реализации, способы передачи, количество ошибок. Например оптоволокно очень дорогое и хрупкое, а для UTP нужны повторители через каждые сколько-то метров (зависит от версии), поскольку сигнал в них затухает. Частот радиоволн ограниченное количество, их нужно распределять между разными сетями, кроме того, бытовые приборы, такие как микроволновая печь, могут вносить существенные помехи, а некоторые длины волн не проникают сквозь стены. Физическому уровню также требуется избавляться от шума в каналах. Для того чтобы устанавливать надежный двухсторонний канал связи, физический уровень использует различные методы уплотнения данных. Например, в структуре, где провайдер посылает данные на распределитель, а затем от распределителя данные приходят к каждому клиенту, нужен метод который будет соединять данные для всех клиентов в один поток. Для этого используется временное уплотнение, частотное уплотнение и амплитудно-фазовое уплотнение. Мне, в частности, было особо интересно как работает мобильная телефонная сеть, описанная в этой главе. 5-ое издание довольно старое, и об LTE там говорили как о приходящей технологии, тогда как сегодня на каждом шагу можно подключиться к сети четвертого поколения. 1-ое поколение мобильных сетей было аналоговым, все последующие поколения были цифровыми. Системы второго поколения уже использовали CDMA (метод уплотнения, в котором символы кодируются так, чтобы при ошибках в нескольких битах символ все-равно был бы распознаваем), но GSM, самая распространенная система, использовала TDM, предоставляя каждому каналу временной интервал для работы. Третье поколение уже полностью работала на CDMA. В мобильные сети большую роль играют телекоммуникационные вышки, которые делят зону покрытия на соты. Каждая вышка отвечает за всех абонентов в своей соте, когда абонент переходит из одной соты в другую происходит процедура передачи. В старых системах, предыдущая вышка переставала обслуживать абонента, а новая принимала его, в новых сетях порядок обратный.

В обязанности канального уровня входит обработка ошибок передачи данных и управление потоками данных, исключающее затопление медленного приемника более быстрым передатчиком. Канальный уровень оперирует кадрами. Кадр формируется когда канальный уровень получает данные от более высокого сетевого уровня. Данные сетевого уровня оборачиваются в заголовок, содеражащий информацию в зависимости от используемого стандарта (который в свою очередь зависит от используемого физического уровня) и концевик (мне не нравится это слово, но я не знаю как перевести лучше), который часто содержит контрольную сумму, для проверки или устранения ошибок на приемнике. Существует несколько способ разграничения кадров, самый надежный, это использование флагового байта, символизирующего окончание кадра, однако если такой же байт попадется в тексте сообщения, нужно поставить перед ним ESC-символ (перед каждым ESC-символом, случайно встретившимся в тексте, кстати, тоже). После того как данные были приняты все ESC-символы удаляются, остаются только чистые данные. Контроль ошибок обеспечивается с помощью контрольной суммы. Выбор способа расчета контрольной суммы зависит от надежности канала. Если канал надежный, дешевле будет переслать кадр в случае ошибки, чем добавлять к кадру лишние данные для исправление ошибок. Если канал ненадежный, то лучше переслать больше данных, чтобы исправить ошибку на получателе, чем забивать пропускную способность сети постоянными пересылками ошибочных кадров.

Подуровень управления доступом к среде занимается проблемой распределения доступа к физическому каналу между конкурирующими машинами. Существует много способов, зависящих от физической среды передачи данных, количества конкурирующих машин, топологии сети и т. д. Один из самых простых, например, когда все пытаются отправить данные, и если возникла коллизия (то есть данные от нескольких машин столкнулись и не дошли до получателя, о чем свидетельствует, чаще всего, ответ от получателя), машины ждут случайный промежуток времени и отправляют данные еще раз. Такой метод крайне не эффективен в плане использования сети, поэтому были разработаны методы с прослушиванием линии. Если машина определяет, что кто-то уже передает, она не начинает передачу. В беспроводных сетях это порождает новые проблемы: проблема засвеченной станции, когда станция передает, но не той машине, которой хочет передать текущая станция (тогда текущая думает что линия занята и передавать нельзя) и проблема скрытой станции (когда одна станция, не может слышать как передает другая из-за слишком большого расстояния и начинает передавать, из-за чего случается коллизия). В таких случаях применяется более сложный протокол, который пытается не определить коллизии, а избежать их. В этом случае передающая станция посылает запрос на передачу, а получающая посылает ответ, в итоге все всё слышат и понимают, что передавать не надо. В таких случаях тоже случаются коллизии, но гораздо реже. В этой же главе рассматривались протоколы ethernet (много его разновидностей), 802.11, 802.16, Bluetooth, RFID, но о них я уже писать не буду, в большинстве своем там слишком подробное описание кадров с помощью которых они общаются и название тех решений, из вышеописанных, которые применяются в данных сетях. Очень жаль, что я это не запомнил, возможно это и было самым важным в данной главе. Когда буду перечитывать этот пост, запланирую себе перечитать эту часть.

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

Каждый маршрутизатор обладает очередью пакетов, как только очередь переполняется, маршрутизатор начинает отвергать пакеты. Отверженные пакеты являются основным сигналом о перегрузке. Для того чтобы определить перегрузку на ранних стадиях, маршрутизатор начинает отвергать случайные пакеты, когда его очередь забита не полностью, а до какого-то уровня (например на 2/3). Тогда есть возможность определить и устранить перегрузку до того как она стала слишком сильной. Бывает трафик настолько важный (как например голосовая связь), что нельзя отклонять пакеты от него. В таком случае используются специальные указатели качества обслуживания. Например на маршрутизаторе добавляется приоритетная очередь и она обслуживается первой при освободившейся пропускной способности. Провайдеры могу взымать за эту услугу дополнительную плату. 

Основным протоколом, работающими в интернете на сетевом уровне является IP. Сейчас большинство сетей используют IPv4, но его проблема в том, что адресного пространства для индивидуальных компьютеров слишком мало (используется 32 бита на адрес) и не хватает адресов для всех. Для этого были созданы разные методы, которые позволяют переиспользовать IP-адреса, такие как NAT, но это противоречит основной идеологии многоуровневой сетевой модели (хотя и обеспечивает надежный и работающий сервис). Для решения этих проблем был разработан новый стандарт IPv6, он уже включает 128-битный адрес, но полностью несовместим с протоколом IPv4, поэтому перейти на него довольно сложно.

Интернет состоит из очень многих связанных сетей, разных типов и размеров, для маршрутизации в нем используются свои протоколы, такие как OSPF и BGP, для маршрутизации пакета внутри подсети и вне соответственно. Для передачи пакета из одного типа сети в другую, часто используется туннелирование. В этом случае пакет одной сети заварачивается полностью в пакет другой сети (можно провести аналогию с поездом, который везет в вагоне автомобиль) и на выходе извлекается и передается как раньше.

В мобильных сетях (опять же более интересующий меня вопрос) способ маршрутизации несколько отличается. Каждый мобильный клиент обладает домашним хостом. Если мобильный клиент меняет местоположение, он сообщает своем хосту о том, где находится. Вызывающий клиент запрашивает вызов у домашнего хоста вызываемого, тот транслирует вызов на текущий хост мобильного клиента, а тот мобильному клиенту. Мобильный клиент, затем, устанавливает прямой канал связи с вызывающим клиентом.

Транспортный уровень обеспечивает пересылку данных от машине к машине так, как будто связь между ними установлена напрямую и никакой сети между ними нет. Транспортный уровень может также работать с установлением соединения (TCP) и без (UDP). Транспортный уровень общается с помощью сегментов (я так понимаю, потому что лучшего названия придумать не смогли). TCP обеспечивает надежную пересылку данных с контролем ошибок и контролем перегрузки сети, UDP кладет на это хуй (сомневаюсь, что кто-то дочитал до этого момента, поэтому могу себе позволить).  Транспортный уровень работает с помощью сокетов. По сути, сокет для пользователя ничем не отличается от файла: программа открывает его, получает файловый дескриптор, пишет туда данные и получает положительный ответ или уведомление об ошибки записи. Чтение из сокета происходит точно также. Отчличие только в том, что записанные данные отправляются по сети через маршрутизаторы к другому хосту, который может находиться на другом конце света. Поверх TCP и UDP еще используются протоколы для передачи медиа данных (например видео или видео в реальном времени). Адресация у TCP используется с помощью портов. Сущесвтует множество зарезервированных портов (так 80-ый порт используется для работы web-сайтов через HTTP), вроде их 1024, остальные (65536 - 1024 = 64512 ) можно использовать для своих приложений. Когда сетевой пакет приходит к конкретному хосту, из TCP сегмента изымается номер порта и программе, которая прослушивает данный порт передаются необходимые данные.

Прикладной уровень это то, с чем имеют дело обычные люди чаще всего. Он включает в себя протоколы для работы с электронной почтой (например SMTP), протокол передачи гипертекста (HTTP) и доменную службу имен (DNS). Поподробнее расскажу про DNS, потому что про остальное мне и так известно, так как имею дело с этим каждый день. DNS существует для того, чтобы люди могли вбивать в адресную строку браузера не непонятные цифры IP-адреса, которые невозможно запомнить и кроме того постоянно меняются, а знакомые всем буквы. DNS хранит у себя таблицу записей о том какому IP-адресу какое имя соответствует и еще кучу разной информации. Все домены поделены на уровни. Верхние уровни, это доменные зоны стран, такие как .ru .uk .sg и прочие, а также всем известные .com .org .net .edu. Домены второго уровня это любое незанятое слово, которое вы хотите использовать для вашего сайта. Каждый домен управляет доменами уровнем ниже. Процесс поиска адреса по имени происходит следующим образом: хост, пытаясь найти имя получателя, опрашивает свой региональный доменный сервер, знает ли тот, какому IP-адресу принадлежит данное имя. Если в кэше этого сервера нет данного имени он опрашивает верхние домены и так пока цепочка не дойдет до корневого сервера. В следующей главе была описана атака на DNS кэш, когда злоумышленник в ответе на запрос его домена, отвечает, в дополнительной информации, что этот же IP-адрес используется и для любого другого доменного имени (например vk.com).  DNS сервер жертвы кеширует это у себя и, как только жертва захочет посетить vk.com, она посетит страницу злоумышленника.

Последняя глава рассказывала о безопасности в сети. Для обеспечения безопасноти используются различные методы шифрования. Все методы шифрования можно разделить на два типа: замена и перестановка. Шифрование с заменой заключается в том, что каждый символ исходного текста заменяется каким-нибудь другим символом. Шифрование с перестановкой заключается в перестановке исходных символов местами. Все алгоритмы шифрования так или иначе используют один или комбинацию этих способов. Одним из самых эффективных методов шифрования считается одноразовый блокнот. Суть заключается в том, что ключ это битовая строка, равная по длине битовой строке текста. Шифрование получается в результате операции XOR между двумя этими строками. Проблема в использовании этого шифра заключается в способе передачи ключа от отправитея к получателю. В качестве одного из способов передачи можно использовать квантовую криптографию (довольно сложно реализуемую для простых смертных). Суть заключается в том, что отправителем выбираются значения поляризации света, соответствующие битовому ключу, например за 1 будет отвечать диагонально направленый фотон слева направо и вертикальный, а за 0 диагональный справа налево и горизонтальный. Получатель выбирает случайную комбинацию поляризаторов перепендикулярных друг другу (вертикальный-горизонтальный и такой же, но повернутый на 45 градусов), а отправитель отправляет фотоны. Затем получатель отправляет отправителю комбинацию поляризаторов, что он использовал, а отправитель отвечает какие были правильными. Угаданный получателем ключ используют для шифрования. В данный момент существуют алгоритмы шифрования симметричные и асимметричные. Симметричные алгоритмы шифрования и шифруются и расшифровываются одним и тем же ключом, асимметричные используют для каждого метода разные ключи. Из симметричных довольно популярны были DES и AES (блочные шифры, то есть разбивали текст на блоки, а потом шифровали). Для обеспечения большей безопасности,  (так как символы зашифрованного блока соответствовали символам текст и переставив их можно было переставить текст) используют режим сцепления блоков, когда между следующим блоком перед шифровкой и предыдущим зашифрованным выполняют операцию XOR. Теперь если переставить строчки при расшифровке исходного текста не получится. 

Асимметричные алгоритмы используют два ключа такие, что невозможно из открытого ключа вывести закрытый. В основном ключами являются простые числа, достаточно большие, чтобы можно было их угадать, но есть алгоритмы завязанные на вычисления логарифмов. Самый распространенный алгоритм с открытым ключом это RSA. При передаче сообщения отправитель шифрует сообщение открытым ключом получателя, а получатель расшифровывает своим закрытым ключом. RSA работает медленно и его используют чаще всего для того чтобы передать общий ключ шифрования для отправителя и получателя, либо для электронной подписи. Электронная подпись нужна для документов, чтобы никто не мог ее подделать и легко было понять, что человек поставил ее сам. Электронную подпись ставят не на документ, а на хэш-функцию от содержания документа, чтобы в случае чего, можно было проверить что текст не менялся. Для этого считают хэш-функцию для документа еще раз, расшифровывают присланую хэш функцию открытым ключом того, кто ставил подпись, и сравнивают хэш функции. Если они не совпадают, значит текст кто-то поменял и ему доверять нельзя. Для лицензирования открытых ключей используют сертификаты. Сертификаты выдаются доверительным органом, который ставит на сертификат хэш и подписывает его своим закрытым RSA ключом. Даже если кто-то расшифрует его с помощью открытого ключа лицензирующего органа, подменить хэш будет нельзя, так как закрытый ключ шифрования не известен никому.