Шрифт:
О портах важно знать следующее: клиент выбирает такой порт со своей стороны, который в настоящее время не используется, но он практически всегда соединяется с каким-либо хорошо известным портом на стороне сервера. Вернитесь к выводу команды netstat из предыдущего раздела:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 10.23.2.4:47626 10.194.79.125:5222 ESTABLISHED
С небольшой подсказкой можно понять, что это соединение с удаленным сервером было, по-видимому, инициировано локальным клиентом, так как порт локальной стороны (47626) выглядит как динамически присвоенное число, в то время как удаленный порт (5222) является хорошо известной службой (службой сообщений Jabber или XMPP, если быть конкретнее).
примечание
Динамически назначаемый порт называется эфемерным портом.
Однако если локальный порт в этом выводе хорошо известен, то соединение, вероятно, было инициировано удаленным хостом. В приведенном ниже примере удаленный хост 172.24.54.234 подключился к порту 80 (веб-порт по умолчанию) локального хоста.
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 10.23.2.4:80 172.24.54.234:43035 ESTABLISHED
Удаленный хост, подключающийся к хорошо известному порту вашего компьютера, подразумевает, что сервер локального компьютера прослушивает данный порт. Чтобы убедиться в этом, выведите список всех TCP-портов, которые прослушивает ваш компьютер, с помощью команды netstat:
$ netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN
—snip—
Строка, которая содержит значение 0.0.0.0:80 как локальный адрес, говорит о том, что локальный компьютер прослушивает подключения к порту 80 от удаленных компьютеров. Сервер может ограничить доступ к некоторым интерфейсам, как показано в последней строке, где нечто прослушивает соединения только в интерфейсе локального хоста. Чтобы узнать еще больше подробностей, воспользуйтесь командой lsof для идентификации процесса, выполняющего прослушивание (как рассказано в подразделе 10.5.1).
9.14.3. Номера портов и файл /etc/services
Как узнать, является ли порт хорошо известным? Однозначно сказать нельзя, но начать стоит с просмотра файла /etc/services, который переводит значения хорошо известных портов в имена. Это простой текстовый файл. Вы можете увидеть в нем записи вроде:
ssh 22/tcp # SSH Remote Login Protocol
smtp 25/tcp
domain 53/udp
Первый столбец содержит имя, а во втором указаны номер порта и относящийся к нему протокол транспортного уровня (который может отличаться от TCP).
примечание
В дополнение к файлу /etc/services по адресусуществует онлайн-реестр портов, который регулируется документом RFC6335 о сетевых стандартах.
В Linux только те процессы, которые запущены с корневыми (superuser) правами, могут использовать порты с 1 по 1023. Все пользовательские процессы могут выполнять прослушивание и создавать соединения, применяя порты с 1024 и далее.
9.14.4. Характеристики протокола TCP
Протокол TCP популярен как протокол транспортного уровня, поскольку он требует сравнительно немного со стороны приложения. Процессу приложения надо знать лишь о том, как открывать (или прослушивать), считывать, записывать и закрывать соединение. Для приложения это напоминает входящие и исходящие потоки данных; процесс почти так же прост, как работа с файлом.
Однако за всем этим стоит большая работа. Для начала протоколу TCP необходимо знать о том, как разбивать исходящий от процесса поток данных на пакеты. Сложнее узнать, как преобразовать серию входящих пакетов во входной поток данных для процесса, в особенности тогда, когда входящие пакеты не обязательно приходят в правильном порядке. В дополнение к этому хост, использующий протокол TCP, должен выполнять проверку на ошибки: при пересылке через Интернет пакеты могут быть потеряны или повреждены, протокол TCP должен обнаружить и исправить подобные ситуации. На рис. 9.3 приведена упрощенная схема того, как хост может использовать протокол TCP для отправки сообщения.
К счастью, вам не нужно знать обо всем этом практически ничего, кроме того, что в Linux протокол TCP реализован главным образом в ядре, а утилиты, которые работают с транспортным уровнем, стремятся использовать структуры данных ядра. Одним из примеров является система фильтрации пакетов с помощью IP-таблиц, которая рассмотрена в разделе 9.21.
9.14.5. Протокол UDP
Протокол UDP является намного более простым транспортным уровнем по сравнению с протоколом TCP. Он определяет передачу только для отдельных сообщений, потока данных здесь нет. В то же время, в отличие от протокола TCP, протокол UDP не выполняет коррекцию утерянных или неправильно расположенных пакетов. На самом деле, хотя у протокола UDP и есть порты, он даже не обладает соединениями! Хост просто отправляет сообщение от одного из своих портов порту на сервере, а сервер отправляет что-либо обратно, если желает. Тем не менее в протоколе UDP все же присутствует выявление ошибок данных внутри пакета. Хост может установить, что пакет поврежден, но он ничего не должен делать в связи с этим.