Безопасность
Безопасность
Обратите внимание на то, что TFTP пакеты (рисунок 15.1) не содержат никаких данных об имени пользователя или пароле. Это брешь в секретности характерная для TFTP. Так как TFTP был разработан для использования в процессе загрузки, он не предоставляет возможности передать имя пользователя и пароль.
Эта характеристика TFTP была использована многими хакерами, чтобы получить копии файла паролей из Unix и затем расшифровать пароли. Чтобы предотвратить подобный доступ, большинство TFTP серверов в настоящее время регламентируют, какие файлы могут быть получены с использованием TFTP (как правило, файлы из директории /tftpboot в Unix системах). Эта директория содержит только загрузочные файлы, необходимые бездисковым системам.
Для дополнительной безопасности TFTP сервер, на Unix системе, обычно устанавливает свой пользовательский идентификатор (UID) и идентификатор группы (GID) в значения, которые не могут быть назначены реальному пользователю. Это позволяет доступ только к файлам, которые доступны для чтения и записи всем.
Формат пяти TFTP сообщений.
Рисунок 15.1 Формат пяти TFTP сообщений.
И клиент и сервер должны иметь возможность осуществить преобразование между этим форматом и каким-либо другим (другой разделитель строк), который используется на локальном хосте. Передача octet обозначает, что данные будут передаваться в виде 8-битных байтов без интерпретации.
Каждый пакет данных содержит номер блока (block number), который затем используется в пакете подтверждении. В качестве примера скажем, что когда необходимо осуществить чтение файла, клиент посылает запрос на чтение (RRQ), указывая имя файла и режим. Если файл может быть прочитан клиентом, сервер отвечает пакетом данных с номером блока равным 1. Клиент посылает подтверждение (ACK) на номер блока 1. Сервер отвечает следующим пакетом данных с номером блока равным 2. Клиент подтверждает номер блока 2. Это продолжается до тех пор, пока файл не будет передан. Каждый пакет данных содержит 512 байт данных, за исключением последнего пакета, который содержит от 0 до 511 байт данных. Когда клиент получает пакет данных, который содержит меньше чем 512 байт, он считает, что получил последний пакет.
В случае запроса на запись (WRQ) клиент посылает WRQ, указывая имя файла и режим. Если файл может быть записан клиентом, сервер отвечает подтверждением (ACK) с номером блока равным 0. Клиент посылает первые 512 байт файла с номером блока равным 1, сервер отвечает ACK с номером блока равным 1.
Этот тип передачи данных называется протоколом с остановкой и ожиданием подтверждения (stop-and-wait) . Он используется только в простых протоколах, таких как TFTP. Мы увидим в разделе "Изменение размера окна" главы 20, что TCP предоставляет другую форму подтверждений, которая позволяет добиться более высокой пропускной способности. TFTP разработан таким образом, чтобы реализация была как можно проще, а не для того чтобы повысить пропускную способность.
Последний тип TFTP сообщений это сообщения об ошибках, код операции (opcode) равен 5. Это как раз то, чем сервер отвечает в том случае, если запрос на чтение или запись не может быть обработан. Ошибки чтения или записи в течении передачи файла также приводят к тому, что отправляется сообщение об ошибке, при этом передача прекращается. Номер ошибки (error number) содержит цифровой код ошибки, за которым следует сообщение об ошибке в ASCII формате, которое может содержать дополнительную информацию предоставляемую операционной системой.
Так как TFTP использует ненадежный UDP, то именно от TFTP зависит, как будут обработаны потерянные и дублированные пакеты. В случае потери пакета, отправитель отрабатывает тайм-аут и осуществляет повторную передачу. (Возможно появление проблемы, называемой "синдромом новичка" (sorcerer's apprentice syndrome), которая может возникнуть, если с обеих сторон будет отработан тайм-аут и осуществлена повторная передача. Раздел 12.2 [Stevens 1990] показывает, в результате чего может возникнуть подобная проблема.) Как и в большинстве UDP приложений, контрольная сумма TFTP сообщения не расчитывается, а это означает, что любое повреждение данных может быть определено только с помощью контрольной суммы UDP (см. главу 11, раздел "Контрольная сумма UDP").
Краткие выводы
Краткие выводы
TFTP - это простой протокол, разработанный таким образом, чтобы помещаться в ПЗУ и быть использованным только в процессе загрузки бездисковых систем. Он использует небольшое количество форматов сообщений и протокол с остановкой и ожиданием подтверждения.
Чтобы позволить нескольким клиентам загружаться одновременно, TFTP сервер предоставляет несколько форм одновременной работы. Так как UDP не предоставляет уникального соединения между клиентом и сервером (как это делает TCP), TFTP сервер создает новый UDP порт для каждого клиента. Это позволяет разным клиентам выдавать датаграммы, которые будут демультиплексированы UDP модулем сервера, на основе номеров портов назначения, вместо того чтобы это делал сам сервер.
Протокол TFTP не предоставляет средства безопасности. Большинство реализаций позволяет доступ по протоколу TFTP только к файлам, которые необходимы при загрузке.
В главе 27 мы рассмотрим протокол передачи файлов (FTP - File Transfer Protocol), который разработан для общих целей, а также обеспечивает высокую пропускную способность при передаче файлов.
Обмен пакетами в случае TFTP.
Рисунок 15.2 Обмен пакетами в случае TFTP.
В строке 1 показан запрос на чтение от клиента к серверу. Порт назначения UDP для TFTP - заранее известный порт 69, tcpdump просматривает TFTP пакеты и печатает RRQ и имя файла. Длина UDP данных печатается как 19 байт и получается следующим образом: 2 байта - код операции, 7 байт - имя файла, 1 байт равный 0, 8 байт для netascii и еще 1 байт равный 0.
Следующий пакет приходит от сервера (строка 2) и содержит 516 байт: 2 байта - код операции, 2 байта - номер блока и 512 байт данных. Строка 3 - подтверждение на эти данные: 2 байта - код операции и 2 байта - номер блока.
И последний пакет данных (строка 4) содержит 450 байт данных. 512 байт данных в строке 2 и эти 450 байт составляют 962 байта данных, полученные клиентом.
Обратите внимание, что tcpdump не печатает дополнительную информацию о протоколе TFTP для строк 2 - 5, как он это сделал, интерпретировав TFTP сообщение в строке 1. Это происходит потому, что номер порта сервера сменился между строками 1 и 2. Протокол TFTP требует, чтобы клиент отправил первый пакет (RRQ или WRQ) на заранее известный порт UDP сервера (69). Сервер находит какой-либо неиспользуемый динамически назначаемый порт (1077 на рисунке 15.2), который затем используется сервером для дальнейшего обмена пакетами между клиентом и сервером. Номер порта клиента (1106 в данном примере) не меняется. tcpdump не имеет представления о том, что порт 1077 на хосте svr4 используется TFTP сервером.
Причина, по которой меняется номер порта сервера, заключается в том, что сервер не должен захватывать заранее известный порт на большой промежуток времени, требуемый на передачу файла (что может занять от нескольких секунд до нескольких минут). Вместо этого, заранее известный порт остается доступным для других TFTP клиентов, которые могут послать туда свой запрос. Тогда как в это время передача осуществляется через другой порт.
Обратимся к рисунку 10.6. RIP сервер, которому необходимо послать клиенту более чем 512 байт, отправляет обе UDP датаграммы с заранее известного порта сервера. В случае TFTP (из-за отличий в протоколе), долговременного взаимодействия между клиентом и сервером не осуществляется (которое, как мы сказали, может занимать от секунд до минут). Если один процесс сервера будет использовать заранее известный порт все время, пока осуществляется передача файла, возникнет необходимость отказать всем последующим запросам, которые придут от других клиентов, или один процесс сервера должен иметь возможность осуществлять множественную передачу файлов нескольким клиентам в одно и то же время с одного и того же порта (69). Простейшее решение заключается в том, что сервер переходит на другой порт, после того как получил RRQ или WRQ. Клиент определяет новый порт, когда он получает первый пакет данных (строка 2 на рисунке 15.2), а затем посылать все последующие подтверждения (строки 3 и 5) на новый порт.
В разделе "Пример" главы 16 мы увидим, как TFTP используется при загрузке X терминалов.
Пример
Пример
Давайте посмотрим, как работает протокол TFTP. Мы запустим TFTP клиента на хосте bsdi и получим текстовый файл с хоста svr4:
bsdi % tftp svr4 стартуем TFTP клиента
tftp> get test1.c получаем файл с сервера
Received 962 bytes in 0.3 seconds
tftp> quit разрываем соединение
bsdi % ls -l test1.c сколько байт в полученном файле?
-rw-r--r-- 1 rstevens staff 914 Mar 20 11:41 test1.c
bsdi % wc -l test1.c и сколько строк?
48 test1.c
Первый момент, который бросается в глаза, заключается в том, что файл в Unix содержит 914 байт, однако TFTP передает 962 байта. Воспользовавшись программой wc, мы увидим, что в файле 48 строк, таким образом, 48 символов новой строки в Unix были дополнены до 48 пар CR/LF, так как TFTP по умолчанию осуществляет передачу в режиме netascii.
На рисунке 15.2 показан обмен пакетами.
1 0.0 bsdi.1106 > svr4.tftp: 19 RRQ "test1.c"
2 0.287080 (0.2871) svr4.1077 > bsdi.1106: udp 516
3 0.291178 (0.0041) bsdi.1106 > svr4.1077: udp 4
4 0.299446 (0.0083) svr4.1077 > bsdi.1106: udp 454
5 0.312320 (0.0129) bsdi.1106 > svr4.1077: udp 4
Протокол
Протокол
Обмен между клиентом и сервером начинается с того, что клиент запрашивает сервер либо прочитать, либо записать файл для клиента. В стандартном варианте загрузки бездисковой системы первый запрос - это запрос на чтение (RRQ). На рисунке 15.1 показан формат пяти сообщений TFTP. (Коды операций 1 и 2 имеют одинаковый формат.)
Первые 2 байта TFTP сообщения это код операции (opcode). В запросе на чтение (RRQ) и в запросе на запись (WRQ) имя файла (filename) указывает файл на сервере, который клиент хочет либо считать, либо записать. Мы специально показали на рисунке 15.1, что это имя файла оканчивается нулевым байтом. Режим (mode) это ASCII строка: netascii или octet (любая комбинация больших или маленьких букв), которая также оканчивается байтом 0. netascii означает, что данные являются строками ASCII текста, причем каждая строка оканчивается 2-символьной последовательностью возврата каретки, за которой следует пропуск строки (обозначается - CR/LF).
Упражнения
Упражнения
Прочитайте требования к хостам Host Requirements RFC, чтобы посмотреть, что должен делать TFTP сервер, если он получит запрос, IP адрес назначения которого является широковещательным адресом. Как Вы думаете, что произойдет, когда номер блока TFTP изменится с 65535 на 0? Говорится ли что-нибудь по этому поводу в RFC 1350? Мы сказали, что TFTP отправитель осуществляет тайм-аут и повторную передачу, чтобы отработать потерю пакетов. Как это отразится на функционировании TFTP, когда он используется как часть процесса загрузки? Что является ограничивающим фактором по времени при передаче файла с использованием TFTP? Назад
Компания | Услуги | Для клиентов | Библиотека | Галерея | Cофт | Линки
На главную
Введение
Введение
TFTP - это простой протокол передачи файлов. Он, как правило, используется при загрузке бездисковых систем (рабочие станции или X терминалы). В отличие от протокола передачи файлов (FTP - File Transfer Protocol), который мы опишем в главе 27 и который использует TCP, TFTP использует UDP. Это сделано для того, чтобы протокол был как можно проще и меньше. Реализации TFTP (и необходимого UDP, IP и драйвера устройства) могут поместиться в постоянной памяти (ПЗУ).
В этой главе приводится только краткое описание TFTP, потому что в следующей главе мы рассмотрим протокол Bootstrap, который использует TFTP. Мы использовали протокол TFTP, когда загружали из сети хост sun (см. рисунок 5.1). Он выдавал TFTP запрос, после того как получил свой IP адрес с использованием RARP.
RFC 1350 [Sollins 1992] является официальной спецификацией TFTP версия 2. Глава 12 [Stevens 1990] предоставляет полные исходные коды реализации TFTP клиента и сервера и описывает некоторую технику программирования, использованную в TFTP.
BOOTP через маршрутизаторы
BOOTP через маршрутизаторы
В разделе "Реализация RARP сервера" главы 5 мы сказали, что одним из неприятных свойств RARP является то, что он использует широковещательные запросы канального уровня, которые обычно не перенаправляются маршрутизаторами. А это означает, что необходимо иметь RARP сервер в каждой физической сети. BOOTP может работать через маршрутизатор, если маршрутизатор поддерживает этот протокол. (Большинство производителей маршрутизаторов добавляют поддержку этой характеристики.)
Обычно это необходимо для бездисковых маршрутизаторов, потому что если в качестве маршрутизатора используется многопользовательская система с диском, она может сама запустить BOOTP сервер. Однако все BOOTP сервера на основе Unix (приложение F) поддерживают этот режим, но, повторим снова, если Вы можете запустить BOOTP сервер в одной физической сети, нет необходимости перенаправлять запросы от другого сервера из другой сети.
Что произойдет, если маршрутизатор (также называемый "BOOTP агент" (BOOTP relay agent)) слушает BOOTP запросы на заранее известном порту сервера (67). Когда запрос принят, агент помещает свой IP адрес в поле IP адреса шлюза (gateway IP address) в BOOTP запросе и отправляет запрос на реальный BOOTP сервер. (Адрес, помещенный агентом в поле шлюза, это IP адрес интерфейса, на который был принят запрос.) Агент также увеличивает на единицу значение в поле пересылок. (Это делается для того, чтобы предотвратить зацикливание, если запрос будет повторно перенаправлен. В RFC 951 говориться, что запрос должен быть отброшен, если счетчик пересылок достигнет значения 3.) Так как исходящий запрос это датаграмма с персональным адресом (исходный запрос от клиента был широковещательным), он может пройти по любому маршруту к любому BOOTP серверу, проходя через другие маршрутизаторы. Реальный сервер получает запрос, формирует BOOTP отклик и отправляет его назад агенту, а не клиенту. Реальный сервер знает что запрос был перенаправлен, так как значение в поле шлюза ненулевое. Агент получает отклик и отправляет его клиенту.
Формат BOOTP запроса и отклика.
Рисунок 16.2 Формат BOOTP запроса и отклика.
Код операции (opcode) равен 1 для запроса и 2 для отклика. Поле типа аппаратного адреса (hardware type) равно 1 для Ethernet 10 Мбит/сек, это же значение находится в поле с таким же именем в ARP запросе или отклике (см. рисунок 4.3). Длина аппаратного адреса (hardware address length) равна 6 байтам, как и для Ethernet.
Счетчик пересылок (hop count) устанавливается клиентом в 0, однако может быть использован уполномоченным сервером (описано в разделе "BOOTP через маршрутизаторы" этой главы).
Идентификатор транзакции (transaction ID) - 32-битное целое число, которое устанавливается клиентом и возвращается сервером. Оно позволяет клиенту сопоставить отклик с запросом. Клиент устанавливает в это поле случайное число для каждого запроса.
В поле количество секунд (number of seconds) клиент записывает время, когда он предпринял первую попытку загрузиться. На основании значения этого поля вторичный сервер делает вывод о том, что первичный сервер не доступен. (Вторичный сервер делает подобный вывод если величина в поле количества секунд достигла определенного значения.)
Если клиент уже знает свой IP адрес, он заполняет поле IP адрес клиента (client IP address). Есле нет - клиент устанавливает это значение в 0. В последнем случае сервер вставляет в поле ваш IP адрес (your IP address) IP адрес клиента. Поле IP адрес сервера (server IP address) заполняется сервером. Если используется уполномоченный сервер (раздел "BOOTP через маршрутизаторы" этой главы), он заполняет IP адрес шлюза (gateway IP address).
Клиент должен установить свой аппаратный адрес клиента (client hardware address). Это то же значение, которое находиться в заголовке Ethernet и в поле UDP датаграммы, благодаря чему оно становится доступным любому пользовательскому процессу (например, серверу BOOTP), который получил датаграмму. Обычно процессу, работающему с UDP датаграммами, сложно или практически невозможно определить значение, находящееся в поле заголовка Ethernet датаграммы, в которой передается UDP датаграмма.
Имя хоста сервера (server hostname) это строка, которая заполняется сервером (не обязательно). Сервер также может заполнить поле имени загрузочного файла (boot filename). В это поле заносится полный путь к файлу, который используется при загрузке.
Область производителя (vendor-specific) используется для различных расширений BOOTP. В разделе "Информация производителя" этой главы описываются некоторые из этих расширений.
Когда клиент стартует с использованием BOOTP (код операции равен 1), запрос обычно рассылается с помощью широковещательного сообщения канального уровня, при этом IP адрес назначения в IP заголовке обычно установлен в 255.255.255.255 (ограниченный широковещательный запрос, глава 12, раздел "Широковещательные запросы"). IP адрес источника - 0.0.0.0, так как клиент еще не знает своего IP адреса. Обратитесь к рисунку 3.9, где показано, что 0.0.0.0 это разрешенный IP адрес источника, используемый в момент загрузки источника.
Формат некоторых пунктов в области производителя.
Рисунок 16.4 Формат некоторых пунктов в области производителя.
Маска подсети и значение времени это пункты с фиксированной длиной, потому что их значение всегда занимает 4 байта. Смещение времени - это количество секунд после полуночи 1 января 1900 года, UTC.
Пункт шлюза это один из пунктов с переменной длиной. Длина всегда кратна 4, а значение - это 32-битные IP адреса одного или нескольких шлюзов (маршрутизаторов), которыми пользуется клиент. Первый из возвращенных адресов должен быть адресом предпочтительного шлюза.
В RFC 1533 определено еще 14 пунктов. Возможно, наиболее важный из них - это IP адрес DNS сервера со значением признака равным 6. В других пунктах содержатся IP адрес сервера печати, IP адрес сервера времени и так далее. Обратитесь к RFC, где приведены все подробности.
В примере, приведенном на рисунке 16.3, мы не видим ICMP запроса маски адреса (глава 6, раздел "ICMP запрос и отклик маски адреса"), который может быть разослан клиентом широковещательным сообщением для определения собственной маски подсети. Его также не было в выводе tcpdump, поэтому мы можем предположить, что маска подсети клиента была передана в области производителя в отклике BOOTP.
Требования к хостам Host Requirements RFC рекомендуют, чтобы система, использующая BOOTP, получала свою маску подсети с использованием BOOTP, а не ICMP.
Размер области производителя ограничен 64 байтами. Это требование выдвигается некоторыми приложениями. Новый протокол, протокол динамической конфигурации хостов (DHCP - Dynamic Host Configuration Protocol), заменяет собой BOOTP. В DHCP эта область увеличена до 312 байт, как определено в RFC 1541 [Droms 1993].
Формат пакета BOOTP
Формат пакета BOOTP
BOOTP запросы и отклики инкапсулируются в UDP датаграммы, как показано на рисунке 16.1.
Информация производителя
Информация производителя
На рисунке 16.2 мы показали 64-байтную область производителя. В RFC 1533 [Alexander and Droms 1993] определен формат этой области. Область производителя содержит необязательную информацию для сервера, которую он может вернуть клиенту.
Если информация присутствует, в первые 4 байта этой области устанавливается IP адрес 99.130.83.99. Это означает, что в области присутствует дополнительная информация.
Вся остальная область занята списком пунктов. Каждый пункт начинается с 1-байтового поля признака. Два из пунктов состоят только из поля признака: признак равный 0 это байт заполнения, а признак равный 255 обозначает конец пунктов. Все байты, расположенные после первого конечного байта, должны быть установлены в значение 255.
Все остальные пункты, кроме этих 1-байтовых пунктов, состоят из единичного байта, за которым следует информация. На рисунке 16.4 показан формат некоторых пунктов в области производителя.
Инкапсуляция запросов и откликов BOOTP в UDP датаграмму.
Рисунок 16.1 Инкапсуляция запросов и откликов BOOTP в UDP датаграмму.
На рисунке 16.2 приведен формат 300-байтного BOOTP запроса и отклика.
Краткие выводы
Краткие выводы
BOOTP использует UDP и разработан в качестве альтернативы RARP для загрузки бездисковых систем, которым необходимо определить свой IP адрес. BOOTP также может вернуть дополнительную информацию, такую как IP адрес маршрутизатора, маску подсети клиента и IP адрес DNS сервера.
Так как BOOTP используется в процессе загрузки, бездисковые системы должны иметь следующие протоколы в своей постоянной памяти: BOOTP, TFTP, UDP, IP и драйвер устройства для локальной сети.
Реализация BOOTP сервера значительно проще чем RARP сервера, так как BOOTP запросы и отклики используют UDP датаграммы, а не специальные фреймы канального уровня. Маршрутизаторы могут также выступать в роли уполномоченных агентов для реальных BOOTP серверов, перенаправляя запросы клиентов на реальные серверы в удаленные сети.
Номера портов
Номера портов
Для BOOTP выделено два заранее известных порта: 67 для сервера и 68 для клиента. Это означает, что клиент не выбирает неиспользуемый динамически назначаемый порт, а использует порт номер 68. Причина, по которой были выбраны два номера портов, вместо того чтобы использовать только один для сервера, заключается в том, что сервер может отправить отклик (хотя обычно он этого не делает) широковещательным образом.
Если отклик от сервера распространялся бы широковещательным образом, и если клиенту было бы необходимо выбрать динамически назначаемый номер порта, эти широковещательные пакеты также были бы получены другими приложениями на других хостах, которые используют тот же самый динамически назначаемый номер порта. Таким образом, можно сделать вывод, что отправлять широковещательный запрос на случайный (динамически назначаемый) номер порта не рационально.
Если клиент воспользуется заранее известным портом сервера (67), все сервера в сети будут вынуждены просматривать каждый широковещательный отклик. (Если все сервера были "разбужены", им придется проверить код операции, определить, что это отклик, а не запрос, и снова "уснуть".) Поэтому выбор был остановлен на том, как все сделано сейчас, то есть клиент имеет свой собственный единственный заранее известный порт, который отличается от заранее известного порта сервера.
Если несколько клиентов загружаются в одно и то же время, и если отклики от сервера распространяются широковещательными запросами, каждый клиент просматривает отклики, которые предназначены другим клиентам. Клиенты используют поле идентификатора транзакции в BOOTP заголовке, чтобы сопоставить отклик с запросом, или же просматривают возвращенный аппаратный адрес клиента.
Пример
Пример
Давайте рассмотрим, как работает BOOTP при загрузке X терминала. На рисунке 16.3 показан вывод команды tcpdump. (Имя клиента proteus, а имя сервера mercury. Вывод этой команды tcpdump был получен в другой сети, в отличие от всех других примеров, приведенных в тексте.)
1 0.0 0.0.0.0.68 > 255.255.255.255.bootp:
secs:100 ether 0:0:a7:0:62:7c
2 0.355446 (0.3554) mercury.bootp > proteus.68: secs:100 Y:proteus
S:mercury G:mercury ether 0:0:a7:0:62:7c
file "/local/var/bootfiles/Xncd19r"
3 0.355447 (0.0000) arp who-has proteus tell 0.0.0.0
4 0.851508 (0.4961) arp who-has proteus tell 0.0.0.0
5 1.371070 (0.5196) arp who-has proteus tell proteus
6 1.863226 (0.4922) proteus.68 > 255.255.255.255.bootp:
secs:100 ether 0:0:a7:0:62:7c
7 1.871038 (0.0078) mercury.bootp > proteus.68: secs:100 Y:proteus
S:mercury G:mercury ether 0:0:a7:0:62:7c
file "/local/var/bootfiles/Xncd19r"
8 3.871038 (2.0000) proteus.68 > 255.255.255.255.bootp:
secs:100 ether 0:0:a7:0:62:7c
9 3.878850 (0.0078) mercury.bootp > proteus.68: secs:100 Y:proteus
S:mercury G:mercury ether 0:0:a7:0:62:7c
file "/local/var/bootfiles/Xncd19r"
10 5.925786 (2.0469) arp who-has mercury tell proteus
11 5.929692 (0.0039) arp reply mercury is-at 8:0:2b:28:eb:1d
12 5.929694 (0.0000) proteus.tftp > mercury.tftp: 37 RRQ
"/local/var/bootfiles/Xncd19r"
13 5.996094 (0.0664) mercury.2352 > proteus.tftp: 516 DATA block 1
14 6.000000 (0.0039) proteus.tftp > mercury.2352: 4 ACK
в этом месте удалено много строк
15 14.980472 (8.9805) mercury.2352 > proteus.tftp: 516 DATA block 2463
16 14.984376 (0.0039) proteus.tftp > mercury.2352: 4 ACK
17 14.984377 (0.0000) mercury.2352 > proteus.tftp: 228 DATA block 2464
18 14.984378 (0.0000) proteus.tftp > mercury.2352: 4 ACK
Пример использования BOOTP при загрузке X терминала.
Рисунок 16.3 Пример использования BOOTP при загрузке X терминала.
В строке 1 мы видим, что запрос от клиента 0.0.0.0.68 направляется на 255.255.255.255.67. Единственные поля, которые заполнил клиент, это количество секунд и Ethernet адрес. Мы увидим, что клиент всегда устанавливает количество секунд в значение 100. Счетчик пересылок и идентификатор транзакции установлены в 0, поэтому они не присутствуют в выводе tcpdump. (Идентификатор транзакции, установленный в 0, означает, что клиент игнорирует это поле, иначе, если бы он хотел проверить это значение в отклике, он установил бы это поле в случайную величину.)
В строке 2 показан отклик от сервера. Поля, заполненные сервером, это IP адрес клиента (который tcpdump напечатал как имя proteus), IP адрес сервера (напечатан как имя mercury), IP адрес шлюза (напечатан как имя mercury) и имя загрузочного файла.
После получения BOOTP отклика клиент немедленно отправляет ARP запрос, чтобы посмотреть, не использует ли кто-либо в сети такой же IP адрес. Имя proteus, за которым следует who-has, соответствует IP адресу адресата (рисунок 4.3), а IP адрес отправителя устанавливается в 0.0.0.0. Он отправляет еще один идентичный ARP запрос через 0,5 секунды и еще один опять же через 0,5 секунды. В третьем ARP запросе (строка 5) клиент изменяет IP адрес отправителя, и устанавливает его в собственный IP адрес. Это так называемый "беспричинный" ARP запрос (глава 4, раздел "Беспричинный ARP").
В строке 6 показано, что клиент ожидает еще 0,5 секунды, после чего рассылает широковещательным запросом еще один BOOTP запрос. Единственное отличие между этим запросом и запросом, показанным в строке 1, заключается в том, что сейчас клиент помещает свой собственный IP адрес в IP заголовок. Он получает тот же самый отклик от того же самого сервера (строка 7). Клиент ждет еще 2 секунды и отправляет широковещательным образом еще один BOOTP запрос (строка 8) и снова получает тот же самый отклик от того же самого сервера.
Затем клиент ждет еще 2 секунды и отправляет ARP запрос на сервер mercury (строка 10). После того как получен ARP отклик, клиент незамедлительно отправляет TFTP запрос на чтение своего загрузочного файла (строка 12). Затем следуют 2464 пакета TFTP данных и подтверждений. Полный размер переданных данных составляет 512 х 2463 + 224 = 1261280 байт. Таким образом, в X терминал загружается операционная система. Мы удалили с рисунка 16.3 большинство строк, имеющих отношение к TFTP.
Необходимо обратить внимание на то, что этот пример TFTP обмена отличается от приведенного на рисунке 15.2 тем, что здесь клиент использует заранее известный порт TFTP (69) во время всей передачи. Так как один из трех партнеров использует порт 69, tcpdump знает, что пакеты это TFTP сообщения, поэтому он может интерпретировать каждый пакет с использованием TFTP протокола. Именно поэтому на рисунке 16.3 указано, какие из пакетов содержат данные, какие содержат подтверждения и каков номер блока для каждого пакета. Мы не могли получить эту дополнительную информацию на рисунке 15.2, потому что ни одна из сторон не использовала заранее известный порт TFTP для передачи данных. Обычно, TFTP клиент не может использовать заранее известный порт TFTP, так как этот порт используется сервером в многопользовательской системе. Однако здесь система только загружается, TFTP сервис не предоставляется, что позволяет клиенту использовать порт в течении всего времени передачи. Также из примера видно, что TFTP сервер на mercury не заботится о том, каков номер порта клиента - он отправляет на порт клиента данные вне зависимости от его номера.
На рисунке 16.3 мы видим, что 1261280 байт передано за 9 секунд. При этом скорость передачи составляет примерно 140000 байт в секунду. Несмотря на то, что это медленней, чем при передаче файлов с использованием FTP по Ethernet, это совсем неплохо для простого протокола с остановкой и ожиданием подтверждения, такого как TFTP.
После того как X терминал загрузился, осуществляется дополнительная передача файлов посредством TFTP, содержащих шрифты терминала, осуществляются некоторые запросы к DNS серверам и затем инициализация X протокола. Полное время загрузки на рисунке 16.3 составило почти 15 секунд, еще 6 секунд было истрачено на последующие шаги. Это означает, что бездисковый X терминал загрузился за 21 секунду.
Сервер BOOTP
Сервер BOOTP
BOOTP клиент обычно "живет" в постоянной памяти бездисковой системы. Однако нам интересно посмотреть, как обычно реализуется сервер.
Во-первых, сервер читает UDP датаграммы с заранее известного порта (67). Специальных средств не требуется. В этом заключается отличие от RARP сервера (см. главу 5, раздел "Реализация RARP сервера"), который, как мы говорили, читает Ethernet фреймы, у которых в поле типа установлено "RARP запрос" (RARP request). Протокол BOOTP также позволяет серверу легко получить аппаратный адрес клиента, поместив его в BOOTP пакет (см. рисунок 16.2).
Тут возникает интересная проблема: как сервер может послать отклик непосредственно клиенту? Отклик находится в UDP датаграмме, и сервер знает IP адрес клиента (который обычно считывается из конфигурационного файла на сервере). Однако, если клиент отправил UDP датаграмму на этот IP адрес (это обычный способ обработки вывода UDP), хост сервера, возможно, выдаст ARP запрос для этого IP адреса. Однако, клиент не может ответить на ARP запрос, так как он еще не знает своего IP адреса! (Проблема подробно описана в RFC 951.)
Существует два решения. Первое, которое обычно используется в Unix серверах, заключается в том, что сервер выдает ioctl (2) запрос в ядро, чтобы поместить определенный пункт в ARP кэш для этого клиента. (Это как раз то, что делает команда arp -s, глава 4, раздел "Команда arp".) Сервер может так поступить, так как он знает аппаратный адрес клиента и его IP адрес. Это означает, что когда сервер посылает UDP датаграмму (BOOTP отклик), ARP модуль сервера может найти IP адрес клиента в ARP кэше.
Альтернативное решение этой проблемы заключается в том, что сервер рассылает BOOTP отклик широковещательным запросом, вместо того чтобы посылать его непосредственно клиенту. Для того чтобы уменьшить количество широковещательных запросов в сети, это решение должно быть использовано только в том случае, когда сервер не может поместить пункт в свой ARP кэш. Обычно, для того чтобы ввести пункт в ARP кэш, необходимы права суперпользователя, а рассылка широковещательных откликов сервером не требует дополнительных привилегий.
Упражнения
Упражнения
Мы сказали, что одно из преимуществ BOOTP над RARP заключается в том, что BOOTP может работать через маршрутизаторы, тогда как RARP, который использует широковещательные запросы канального уровня, не может. В разделе "BOOTP через маршрутизаторы" этой главы, мы определили специальные способы, с помощью которых BOOTP может работать через маршрутизаторы. Что произойдет, если добавить маршрутизатору возможность перенаправлять RARP запросы? Мы сказали, что BOOTP клиент должен использовать идентификатор транзакции, чтобы сопоставить отклики с запросами, в том случае, если несколько клиентов загружаются в одно и то же время с одного и того же сервера, который использует широковещательные отклики. Однако на рисунке 16.3 идентификатор транзакции установлен в 0, что указывает на то, что этот клиент игнорирует идентификатор транзакции. Как Вы думаете, сопоставляет ли этот клиент отклики с запросами? Назад
Компания | Услуги | Для клиентов | Библиотека | Галерея | Cофт | Линки
На главную
Введение
Введение
В главе 5 мы описали, как в момент загрузки бездисковая система может определить свой IP адрес с использованием RARP. При использовании RARP возникает две проблемы: (1) единственное, что можно узнать, это IP адрес, и (2) так как RARP использует широковещательный запрос на канальном уровне, запросы RARP не перенаправляются маршрутизаторами (поэтому RARP сервер должен находиться в каждой физической сети). В этой главе мы опишем альтернативный метод загрузки бездисковых систем, который называется протоколом загрузки (BOOTP - Bootstrap Protocol).
BOOTP использует UDP и обычно используется совместно с TFTP (глава 15). Официальная спецификация BOOTP приведена в RFC 951 [Croft and Gilmore 1985], пояснения даются в RFC 1542 [Wimer 1993].
Инкапсуляция TCP данных в IP датаграмму.
Рисунок 17.1 Инкапсуляция TCP данных в IP датаграмму.
На рисунке 17.2 показан формат TCP заголовка. Обычно его размер составляет 20 байт, если не присутствуют опции.
Краткие выводы
Краткие выводы
TCP предоставляет надежный, ориентированный на соединения, и ориентированный на поток байтов сервис транспортного уровня. Мы коротко рассмотрели все поля TCP заголовка, подробное описание полей приведено в следующих главах.
TCP строит пакеты из пользовательских данных, упаковывая их в сегменты, устанавливает тайм-ауты в тот момент, когда он посылает данные, подтверждает принятые данные с удаленного конца, меняет порядок данных, которые пришли хаотически, отбрасывает продублированные данные, осуществляет контроль потока данных, рассчитывает и проверяет контрольную сумму в конечных точках передачи.
TCP используется множеством популярных приложений, таких Telnet, Rlogin, FTP и электронная почта (SMTP).
TCP сервисы
TCP сервисы
Несмотря на то, что TCP и UDP используют один и тот же сетевой уровень (IP), TCP предоставляет приложениям абсолютно другие сервисы, нежели UDP. TCP предоставляет основанный на соединении надежный сервис потока байтов.
Термин "основанный на соединении" (connection-oriented) означает, что два приложения, использующие TCP (как правило, это клиент и сервер), должны установить TCP соединение друг с другом, после чего у них появляется возможность обмениваться данными. Типичная аналогия - это набор телефонного номера, ожидание ответа от удаленного абонента, когда он говорит "алло", после чего необходимо сказать, кто звонит. В главе 18 мы рассмотрим, как устанавливается соединение и как это соединение разрывается через некоторое время, когда работа завершена.
Всегда существуют две конечные точки, которые общаются друг с другом с помощью TCP соединения. Концепции, о которых мы говорили в главе 12, широковещательная рассылка и групповая рассылка, не имеют отношения к TCP.
TCP обеспечивает свою надежность благодаря следующему: Данные от приложения разбиваются на блоки определенного размера, которые будут отправлены. Это полностью отличается от UDP, в котором каждая запись, которую осуществляет приложение, генерирует IP датаграмму этого размера. Блок информации, который передается от TCP в IP, называется сегментом (segment). (См. рисунок 1.7.) В разделе "Максимальный размер сегмента" главы 18 мы посмотрим, как TCP определяет нужный размер сегмента. Когда TCP посылает сегмент, он устанавливает таймер, ожидая, что с удаленного конца придет подтверждение на этот сегмент. Если подтверждение не получено по истечении времени, сегмент передается повторно. В главе 21 мы рассмотрим стратегию TCP, которую он реализует для тайм-аутов и повторных передач. Когда TCP принимает данные от удаленной стороны соединения, он отправляет подтверждение. Это подтверждение не отправляется немедленно, а обычно задерживается на доли секунды, что мы обсудим в разделе "Задержанные подтверждения" главы 19. TCP осуществляет расчет контрольной суммы для своего заголовка и данных. Это контрольная сумма, рассчитываемая на концах соединения, целью которой является выявить любое изменение данных в процессе передачи. Если сегмент прибывает с неверной контрольной суммой, TCP отбрасывает его и подтверждение не генерируется. (Ожидается, что отправитель отработает тайм-аут и осуществит повторную передачу.) Так как TCP сегменты передаются в виде IP датаграмм, а IP датаграммы могут прибывать беспорядочно, также беспорядочно могут прибывать и TCP сегменты. После получения данных TCP может по необходимости изменить их последовательность, в результате приложение получает данные в правильном порядке. Так как IP датаграмма может быть продублирована, принимающий TCP должен отбрасывать продублированные данные. TCP осуществляет контроль потока данных. Каждая сторона TCP соединения имеет определенное пространство буфера. TCP на принимающей стороне позволяет удаленной стороне посылать данные только в том случае, если получатель может поместить их в буфер. Это предотвращает от переполнения буферов медленных хостов быстрыми хостами.
Между двумя приложениями по TCP соединению осуществляется обмен потоком 8-битовых байтов. Автоматически TCP не вставляет записи маркеров. Это называется сервисом потока байтов (byte stream service). Если приложение на одном конце записало сначала 10 байт, затем 20 байт и затем еще 50 байт, приложение на другом конце соединения не может сказать какого размера была каждая запись. На другом конце эти 80 байт могут быть считаны, например, за 4 раза по 20 байт за каждый раз. Один конец соединения помещает поток байт в TCP, и точно так же идентичный поток байт появляется на другом конце.
TCP не интерпретирует содержимое байтов. TCP понятия не имеет о том, происходит ли обмен двоичными данными, ASCII символами, EBCDIC символами или чем-либо еще. Эта интерпретация потока байтов осуществляется приложениями на каждой стороне соединения.
Это представление потока байтов протоколом TCP напоминает представление файла в операционной системе Unix. Ядро Unix не интерпретирует байты, которые приложение читает или записывает - это полностью зависит от приложений. Ядро Unix не видит разницы между бинарными файлами и файлами, содержащими строки текста.
TCP заголовок.
Рисунок 17.2 TCP заголовок.
Каждый TCP сегмент содержит номер порта (port number) источника и назначения, с помощью которых идентифицируются отправляющее и принимающее приложения. Эти два значения вместе с IP адресом источника и назначения в IP заголовке уникально идентифицируют каждое соединение.
Комбинация IP адреса и номера порта иногда называется сокетом (socket) . Этот термин появился в исходной спецификации TCP (RFC 793), а позднее стал использоваться в качестве имени программного интерфейса Berkeley (глава 1, раздел "Интерфейсы прикладного программирования"). Эта пара сокетов (содержащая IP адрес клиента, номер порта клиента, IP адрес сервера и номер порта сервера) указывает две конечные точки, которые уникально идентифицируют каждое TCP соединение.
Номер последовательности (sequence number) идентифицирует байт в потоке данных от отправляющего TCP к принимающему TCP. Если мы представим поток байтов, текущий в одном направлении между двумя приложениями, TCP нумерует каждый байт номером последовательности. Номер последовательности представляет собой 32-битное беззнаковое число, которое переходит через 0, по достижению значения 232 - 1.
При установлении нового соединения, взводится флаг SYN. Поле номера последовательности (sequence number field) содержит исходный номер последовательности (ISN - initial sequence number), который выбирается хостом для данного соединения. Номер последовательности первого байта данных, который посылается этим хостом, будет равен ISN плюс один, потому что флаг SYN занимает собой номер последовательности. (Подробно мы опишем, как в действительности устанавливается соединение и как соединение разрывается, в следующей главе, где увидим, что флаг FIN также занимает собой номер последовательности.)
Так как каждый байт, который участвует в обмене, пронумерован, номер подтверждения (acknowledgment number) это следующий номер последовательности, который ожидает получить отправитель подтверждения. Это номер последовательности плюс 1 последнего успешно принятого байта данных. Это поле принимается в рассмотрение, только если флаг ACK (описан ниже) взведен.
Отправка ACK не стоит ничего (это означает, что на подтверждение не тратится сегмент), потому что 32-битное поле номера подтверждения всегда является частью заголовка, так же как и флаг ACK. Мы увидим, что когда соединение установлено, это поле всегда установлено и флаг ACK всегда взведен.
TCP предоставляет для прикладного уровня полнодуплексный сервис. Это означает, что данные могут передаваться в каждом направлении независимо от другого направления. Однако, на каждом конце соединения необходимо отслеживать номер последовательности данных, передаваемых в каждом направлении.
TCP может быть описан как протокол с изменяющимся окном без селективных или отрицательных подтверждений. (Изменение окна, используемое при передаче данных, описано в разделе "Изменение размера окна" главы 20.) Мы сказали, что в TCP нет селективных подтверждений, потому что номер подтверждения в TCP заголовке означает, что отправитель успешно принял, все байты за исключением этого байта. Таким образом, в настоящее время не существует возможности подтвердить отдельно выбранную часть потока данных. Например, если байты 1-1024 приняты нормально, а следующий сегмент содержит байты 2049-3072, принимающий не может подтвердить этот новый сегмент. Все что он может - это послать ACK с номером подтверждения 1025. Также нет никакого смысла посылать отрицательные подтверждения на сегмент. Например, если сегмент с байтами 1025-2048 прибыл, однако была определена ошибка в контрольной сумме, все что может послать принимающий TCP это ACK с номером подтверждения равным 1025. В разделе "Быстрая повторная передача и алгоритм быстрого восстановления" главы 21 мы увидим, как дублированные подтверждения могут помочь определить потерю пакетов.
Длина заголовка (header length) содержит длину заголовка в 32-битных словах. Это объясняется тем, что длина поля опций переменная. С 4-битным полем у TCP есть ограничение на длину заголовка в 60 байт. Без опций, однако, стандартный размер составляет 20 байт.
В TCP заголовке существуют 6 флаговых битов. Один или несколько из них могут быть установлены в единицу в одно и то же время. Здесь мы кратко опишем их использование, а позже опишем каждый флаг более подробно в соответствующих главах.
URG
Указатель срочности (urgent pointer) будет рассмотрен в разделе "Режим срочности (Urgent Mode)" главы 20.
ACK
Номер подтверждения необходимо принять в рассмотрение (acknowledgment).
PSH
Получатель должен передать эти данные приложению как можно скорее (глава 20, раздел "Флаг PUSH").
RST
Сбросить соединение (глава 18, раздел "Сегменты сброса (Reset)").
SYN
Синхронизирующий номер последовательности для установления соединения. Этот следующий флаги описаны в главе 18.
FIN
Отправитель заканчивает посылку данных.Контроль потока данных TCP осуществляется на каждом конце с использованием размера окна (window size) . Это количество байт, начинающееся с указанного в поле номера подтверждения, которое приложение собирается принять. Это 16-битовое поле ограничивает размер окна в 65535 байт. В разделе "Опция масштабирования окна" главы 24 мы увидим, что опция масштабирования окна позволяет изменять это значение, при этом могут быть использованы окна большего размера.
Контрольная сумма (checksum) охватывает собой весь TCP сегмент: TCP заголовок и TCP данные. Это обязательное поле, которое должно быть рассчитано и сохранено отправителем, а затем проверено получателем. Контрольная сумма TCP рассчитывается так же как контрольная сумма UDP, с использованием псевдозаголовка, как описано в разделе "Контрольная сумма UDP" главы 11.
Указатель срочности (urgent pointer) действителен только в том случае, если установлен флаг URG. Этот указатель является положительным смещением, которое должно быть прибавлено к полю номера последовательности сегмента, чтобы получить номер последовательности последнего байта срочных данных. Режим срочности TCP это способ, с помощью которого отправитель передает срочные данные на удаленный конец. Мы рассмотрим эту характеристику в разделе "Режим срочности (Urgent Mode)" главы 20.
Наиболее общее поле опций - это опция максимального размера сегмента (MSS - maximum segment size). На каждом конце соединения эта опция обычно указывается в первом сегменте, с которого начинается обмен (сегмент с установленным флагом SYN, который используется для установления соединения). Она указывает на максимальный размер сегмента, который может быть принят отправителем. Мы опишем опцию MSS более подробно в разделе "Максимальный размер сегмента" главы 18, а некоторые другие опции TCP в главе 24.
На рисунке 17.2 мы видели, что раздел данных в TCP сегменте необязателен. В главе 18 мы увидим, что когда устанавливается соединение или когда соединение разрывается, сегменты содержат только TCP заголовки с возможными опциями. Заголовок без данных также используется, чтобы подтвердить принятые данные, если в этом направлении не надо передавать данные. Также существует несколько случаев тайм-аутов, когда сегмент может быть отправлен без данных.
Упражнения
Упражнения
Мы рассмотрели следующие форматы пакетов, каждый из которых имеет контрольную сумму в своем заголовке: IP, ICMP, IGMP, UDP и TCP. Для каждого опишите, какая часть IP датаграммы покрывается контрольной суммой, и где контрольная сумма обязательна, а где нет. Почему все протоколы Internet, которые мы обсуждали (IP, ICMP, IGMP, UDP, TCP), молча отбрасывают пакеты, которые прибывают с ошибкой контрольной суммы? TCP предоставляет сервис потока байтов, где не происходит разграничения записей в процессе передачи между отправителем и получателем. Как могут приложения осуществить вставку своих собственных маркеров записей? Почему номера портов источника и назначения находятся в начале TCP заголовка? Почему TCP заголовок имеет поле длины заголовка, тогда как UDP заголовок (рисунок 11.2) не имеет? Назад
Компания | Услуги | Для клиентов | Библиотека | Галерея | Cофт | Линки
На главную
Введение
Введение
В этой главе описаны сервисы, которые TCP предоставляет приложениям. Здесь же рассмотриваются поля TCP заголовка. В следующих главах мы подробно рассмотрим эти поля и расскажем, как TCP функционирует.
Описанию TCP посвящена эта глава, и следующие семь глав. В главе 18 будет рассказано, как устанавливаются и разрываются TCP соединения, в главе 19 и главе 20 мы рассмотрим обычную передачу данных, как в диалоговом использовании (удаленный заход), так и передачу файлов. В главе 21 мы подробно рассмотрим, как TCP осуществляет тайм-ауты и повторные передачи. И в главе 22 и главе 23 мы рассмотрим некоторые таймеры TCP. И в заключение, в главе 24 мы рассмотрим новые характеристики и производительность TCP.
Основная спецификация TCP находится в RFC 793 [Postel 1981c], однако некоторые ошибки этого RFC исправлены в требованиях к хостам Host Requirements RFC.
Заголовок TCP
Заголовок TCP
Вспомним, что данные TCP инкапсулируются в IP датаграммы, как показано на рисунке 17.1.