Перейти к основному содержанию
Рецепты Linux

Main navigation

  • Основы
  • Система
  • Команды
  • Программы
  • Дистро
  • Интерфейсы
  • Устройства
  • Доки
User account menu
  • Войти

Строка навигации

  1. Главная
  2. Linux: Введение
  3. Сеть TCP/IP в Linux

Прикладной уровень

Как бы не был надёжен протокол TCP, он не имеет никакого понятия о том, что же, собственно, за данные с его помощью передаются. Да и не должен: принцип разделения уровней не позволяет заглядывать «внутрь» передаваемого пакета, и способов наверняка распознать используемый в нём прикладной протокол нет. Прикладной уровень, в отличие от транспортного, предусматривает сколько угодно протоколов передачи данных. Интерпретация данных, в конце концов, дело уже не ядра, а какой-нибудь программы («приложения», как правило, демона). Для того, чтобы можно было предположить, какой протокол используется при передаче данных и чтобы система могла передать эти данные соответствующей программе, ещё на транспортном уровне было введено понятие порт.

Клиент-серверная модель

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

Обратная ситуация, когда клиент хочет передать что-то серверу, сути дела не меняет: сервер предоставляет услугу клиенту, на этот раз — по приёму данных.

Отношения между программами, которые связываются по сети друг с другом, почти всегда ассимметричны: одной что-то надо, у другой это что-то есть. При установлении соединения и приложение (программа-клиент), и служба (программа-сервер) используют механизм сокетов, описанный в лекции Работа с внешними устройствами, однако ведут себя по-разному.

Служба, запускаясь на сервере, создаёт сетевой сокет и прикрепляет его к определённому порту сервера с помощью системного вызова bind(). Затем она регистрируется в качестве обработчика запросов (listener), приходящих на этот порт. Служба ждёт запросов, и когда они поступают, предпринимает какие-нибудь действия, например, считывает пришедшие данные и анализирует их в соответствии со своим протоколом, отсылает какие-то данные абоненту, пославшему запрос и т. п.

Приложение, запускаясь на клиенте, также создаёт сокет и присоединяется с его помощью к тому же порту на сервере, где запущена служба, используя системный вызов connect(). Затем оно, как и служба, посылает и получает данные. Разницы между обменом данными по сетевому сокету и по сокету в файловой системе нет. Очерёдность обмена данными определяется прикладным протоколом.

Как приложение узнаёт, к какому именно порту необходимо подключиться? За большинством прикладных протоколов закреплён постоянный номер порта. Постоянные номера портов и названия соответствущих протоколов хранятся в файле /etc/services:

[root@localhost root]# wc /etc/services                                                
  553  2794 19869 /etc/services
[root@localhost root]# egrep "^(ftp|http|smtp|ssh).*tcp" /etc/services 
 ftp             21/tcp                      # File Transfer [Control]
 ssh             22/tcp                      # SSH Remote Login Protocol
 smtp            25/tcp      mail            # Simple Mail Transfer Protocol
 http            80/tcp      www www-http    # World Wide Web HTTP

Пример 6.

Постоянные номера портов для некоторых протоколов Этот файл — не догма, а руководство к действию: каждый может организовать, допустим, сервис HTTP по 25-му порту. Только как об этом узнают другие клиенты, и что подумают почтовые программы, ожидая по этому порту встретить сервис SMTP (пересылка почты)? Вывести список установленных соединений, а также служб-обработчиков можно командой netstat:

[root@localhost root]# netstat -anA inet
 Active Internet connections (servers and established)
 Proto Recv-Q Send-Q Local Address        Foreign Address         State      
 tcp        0      0 0.0.0.0:111          0.0.0.0:*               LISTEN      
 tcp        0      0 0.0.0.0:22           0.0.0.0:*               LISTEN      
 tcp        0      0 192.168.102.125:22   192.168.102.1:33208     ESTABLISHED
 udp        0      0 0.0.0.0:111          0.0.0.0:*

Пример 7. Просмотр установленных соединений и служб

Здесь видно, что на компьютере зарегистрировано два TCP-обработчика (на портах 111 и 22), один UDP-обработчик по 11-му порту (понятие Listener, то есть обработчик соединения для UDP не имеет смысла), а также установлено одно соединение с компьютера 192.168.102.1, исходящий порт 33208, к 22-му порту (это порт службы Secure Shell, предоставляющей удалённый терминальный доступ... видимо, Гуревич работает?). В более сложных случаях, когда номер порта заранее неизвестен, а известно только название и версия сервиса, используется служба portmap, которая раздаёт незанятые порты службам и сообщает приложениям, к какому из них надо обратиться. Порт 111 соответстует именно этой службе.

Обслуживание прикладного уровня в Linux

Самый простой способ проверить, предоставляет ли некий сервер услуги по некоему TCP-порту — это подключиться к нему. Если под рукой нет приложения, работающего по требуемому протоколу, не беда: подойдёт утилита telnet. В качестве первого параметра следует указать адрес компьютера, к которому нужно подключиться, а в качестве второго (необязательного) — номер порта. Когда-то эта утилита использовалась в качестве клиента к терминальной службе, однако от неё пришлось отказаться: пароль пользователя передавался по сети нешифрованным. Но в качестве клиента других служб, многие из которых используют текстовые протоколы, telnet используется и поныне. Если даже протокол и не текстовый — не беда: можно выйти в командный режим telnet, нажав «^[», и подать команду close, которая закроет соединение:

[root@localhost root]# telnet 192.168.102.1 112
 Trying 192.168.102.1...
 telnet: connect to address 192.168.102.1: Connection refused
[root@localhost root]# telnet 192.168.102.1 111
 Trying 192.168.102.1...
 Connected to 192.168.102.1.
 Escape character is '^]'.
 ^]
 telnet> close
 Connection closed.

Пример 8. Использование telnet

В сценариях вместо интерактивной утилиты telnet стоит использовать netcat, которая работает как cat в указанный сокет или из него.

Как уже говорилось, интерпретацией прикладных протоколов занимаются разнообразные программы. Прикладной протокол можно представить как обмен сообщениями, часто текстовыми, между клиентом и сервером. Было бы естественно оформлять такие программы в виде фильтров, чтобы пользоваться простейшими функциями ввода-вывода. Однако механизм сокетов предусматривает асинхронную передачу данных, для чего используются другие функции. Программа, желающая обслуживать сетевые соединения по определённому порту, должна удовлетворять четырём требованиям:

  1. Быть демоном, то есть постоянно находиться в памяти;
  2. Создавать сокет, прикреплять его к порту;
  3. Регистрироваться как обработчик по этому сокету и принимать соединения (возможно, придётся обрабатывать несклько соединений одновременно);
  4. Анализировать прикладной протокол и действовать по результатам анализа.

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

Мефодий минут за пять написал службу, которая в ответ на подключение передаёт календарь на текущий месяц. В его системе используется модернизированная версия inetd — xinted, обученная чтению конфигурационных файлов по схеме «. d»: 

[root@localhost root]# grep quake /etc/services 
 quake           26000/tcp
 quake           26000/udp
[root@localhost root]# cat /etc/xinetd.d/calendar 
 service quake
 {
        socket_type     = stream
        protocol        = tcp
        wait            = no
        user            = nobody
        server          = /usr/bin/cal
        disable         = no
 }

Пример 9. Настройка cal в качестве сетевой службы

Вместо номера порта можно использовать название протокола из /etc/services. Мефодий воспользовался портом 26000 (чем мог создать некоторые трудности поклонникам одной компьютерной игры). Осталось только перезагрузить xinetd, чтобы он нашёл новый конфигурационный файл, и подключиться к 26000 порту:

[root@localhost root]# service xinetd restart
 Stopping xinetd service: [ DONE ]
 Starting xinetd service: [ DONE ]
[root@localhost root]# telnet localhost quake
 Trying 127.0.0.1...
 Connected to localhost.
 Escape character is '^]'.
    December 2004
 Su Mo Tu We Th Fr Sa 
           1  2  3  4
  5  6  7  8  9 10 11
 12 13 14 15 16 17 18
 19 20 21 22 23 24 25
 26 27 28 29 30 31

Пример 10. Подключение к самодельной службе «календарь»

Служба доменных имён

В предыдущих примерах Мефодий использовал ключ «-n» многих сетевых утилит, чтобы избежать путаницы между IP-адресами и доменными именами компьютеров. С другой стороны, доменные имена — несколько слов (часто осмысленных) – запоминать гораздо удобнее, чем адреса (четыре каких-то числа).

Когда-то имена всех компьютеров в сети, соответствующие IP-адресам, хранились в файле /etc/hosts. Пока абоненты Internet были наперечёт, поддерживать правильность его содержимого не составляло труда. Как только сеть начала расширяться, неувязок стало больше. Трудность была не только в том, что содержимое hosts быстро менялось, но и в том, что за соответствие имён адресам в различных сетях отвечали разные люди и разные организации. появилась необходимость структурировать глобальную сеть не только топологически (с помощью IP и сетевых масок), но и административно, с указанием, за какие группы адресов кто отвечает.

Проще всего было структурировать сами имена компьютеров. Вся сеть была поделена на домены — зоны ответственности отдельных государств («us», «uk», «ru», «it» и т. п.) или независимые зоны ответственности («com», «org», «net», «edu» и т. п.). Для каждого из таких доменов первого уровня должно присутствовать подразделение, выдающее всем желающим абонентам имена, заканчивающиеся на «.домен». Подразделение обязано огранизовать и поддерживать службу, заменяющую файл hosts: любой желающий имеет право узнать, какой IP-адрес соответствует имени компьютера в этом домене или какому доменному имени соответствует определённый IP-адрес.

Такая служба называется DNS (Domain Name Service, служба доменных имён). Она имеет иерархическую структуру. Если за какую-то группу абонентов домена отвечают не хозяева домена, а кто-то другой, ему выделяется поддомен (или домен второго уровня), и он сам распоряжается именами вида «имя_компьютера.поддомен.домен». Например, за компьютеры в домене «. ru», принадлещие корпорации «Dry Bugs» отвечают сотрудники соответствующего подразделения этой корпорации. Корпорация владеет поддоменом dbugs.ru. В домене ru не обязаны знать, какие именно адреса есть в поддомене, но обязаны предоставить информацию о том, как обратиться к серверу имён поддомена dbugs.ru. Сами сотрудники «Dry Bugs» тоже отвечают только за несколько собственных компьютеров, а всю ответственность за компьютеры в подразделениях перекладывают на сетевых администраторов этих подразделений, выделив им поддомены третьего уровня pr.dbugs.ru, cook.dbugs.ru и warehouse.dbugs.ru. Таким образом получается нечто вроде распределённой сетевой базы данных, хранящей короткие записи о соответствии доменных имён IP-адресам.

доменное имя
Имя абонента Internet, имеющее текстовый формат и используемое вместо IP-адреса. Состоит из собственного имени абонента в домене и имени домена, определяющего административную принадлежность абонента. В отличие от IP-адреса, доменное имя не задаётся самим абонентом сети, а устанавливается службой доменных имён.

Все программы, работающие с доменными именами, оказываются клиентами какого-нибудь сервера доменных имён (DNS-сервера). Для этого они обращаются к функциям из библиотеки libresolv (или им подобным), а те уже определяют, как превратить доменное имя в адрес. Функции используют файл /etc/host.conf, описывающий, какими способами они должны выполнять преобразование доменных имён в адреса и обратно, а также формат выдачи данных в различных случаях. Обычно сначала проверяется файл /etc/hosts, а если там соответствий не найдено — /etc/resosv.conf. В resolv.conf указан домен по умолчанию (он приписывается в конец имени, если другим способом имя никак не удаётся преобразовать в адрес) и один-два адреса DNS-серверов, к которым и обращаются функции. Такими клиентами выступили утилиты ping и traceroute в предыдущих примерах, преобразуя имя www.ru в адрес 194.87.0.50. Если утилите traceroute не указывать ключ «-n», она подаст несколько DNS-запросов, по одному на каждый маршрутизатор, на обратное преобразование — из IP-адреса в доменное имя.

[root@localhost root]# cat /etc/host.conf 
 order hosts,bind
 multi on
[root@localhost root]# cat /etc/resolv.conf
 domain nipponman.ru
 nameserver 192.168.102.1
[root@localhost root]# traceroute -q1 www.ru
 traceroute to www.ru (194.87.0.50), 30 hops max, 38 byte packets
  1  fuji.nipponman.ru (192.168.102.1)  1.378 ms
  2  ppp83-237-29-1.pppoe.mtu-net.ru (83.237.29.1)  41.155 ms
  3  195.34.53.53 (195.34.53.53)  48.503 ms
  4  195.34.53.53 (195.34.53.53)  24.033 ms
  5  M9-cr01-A197-cr01.core.mtu.ru (195.34.53.10)  33.414 ms
  6  M9-gw2-M9-cr01.core.mtu.ru (195.34.53.81)  26.259 ms
  7  s-b3-pos0-0.telia.net (213.248.67.93)  59.791 ms
  8  s-bb1-pos5-0-0.telia.net (213.248.66.1)  67.011 ms
  9  mow-b1-pos1-0.telia.net (213.248.101.10)  76.138 ms
 10  demos-101566-mow-okt-i1.c.telia.net (213.248.78.170)  78.591 ms
 11  m9-3-GE4-0-0-vl10.Demos.net (194.87.0.66)  69.813 ms
 12  www.ru (194.87.0.50)  70.583 ms

Пример 11. Работа DNS-клиента, встроенного в traceroute

Как видно из примера, обратное преобразование в современной сети работает не всегда. Отсутствие обратной зоны не поощряется сообществом, но и не считается преступлением. Мефодий заметил, что компьютер, не имеющий обратного преобразования адреса, вообще какой-то странный: один раз он передал пакет сам себе (здесь Мефодий не совсем прав: на самом деле этот маршрутизатор отчего-то уменьшает TTL пакета на 2, поэтому-то и на третьем, и на четвёртом шаге именно он возвращает ICMP-сообщение). Кстати сказать, именно по причине того, что DNS-запрос невелик, зато даже один абонент сети может выдать их множество, основным транспортным протоколом для DNS выбран UDP, а не TCP (это не касается протоколов обмена целыми зонами между DNS-серверами, там, коначно, господствует TCP). Если вся задача пользователя — это послать DNS-запрос, то лучше воспользоваться утилитой host, специально для этого предназначенной:

methody@localhost:~ $ host www.ru      
 www.ru has address 194.87.0.50
methody@localhost:~ $ host 194.87.0.51
 51.0.87.194.in-addr.arpa domain name pointer www.demos-internet.ru.
methody@localhost:~ $ host -t ns www.ru
 www.ru name server ns.demos.su.
 www.ru name server ns1.demos.net.
methody@localhost:~ $ host -t mx www.ru
 www.ru mail is handled by 5 hq.demos.ru.

Пример 12. Утилита host

Довольно необычен формат, в котором хранятся таблицы обратного преобразования адресов. Оказывается, IP-адрес представлен в такой таблице как имя в домене in-addr.arpa, причём это имя совпадает с адресом, записанным задом наперёд. Такой формат идёт от иерархической структуры DNS. Если некоторая организация получает во владение сеть, допустим, 194.0.0.0/8, она должна обслуживать DNS-запросы к домену 194.in-addr.arpa. Если при этом сеть 194.87.0.0/16 передана другой организации, ей же передаётся обязанность обслуживать DNS-запросы к поддомену этого домена — 87.194.in-addr.arpa, и так вплоть до собственно IP-адресов. Вместо host можно использовать утилиту dig, которая выводит больше информации о том, как проходил сам запрос.

Помимо записей типа «адрес» (A, прямое преобразование) и «указатель ни имя» (PTR, обратное преобразование) в системе DNS может храниться и другая информация. Таблица (зона) некоторого дамена должна содержать адреса доменных серверов всех его поддоменов (записи типа NS). Кроме того в домене должно быть определено имя почтового пересыльщика (запись типа MX). Если почтовый пересыльщик домена не указан, электронная почта направляется почтовому пересыльщику родительского домена.

В зоне DNS есть даже запись типа «просто текст», TXT: при желании можно самому определить интерпретацию полей этой записи и организовать поверх DNS предназначенную для каких угодно целей базу данных по IP-адресам или доменным именам.

Так поступают, например, при создании «чёрных списков» абонентов сети, от которых почтовый сервер не принимает писем.

В отличие от dig, которой для запроса к обратной зоне требуется ключ «-x», утилита host различает запросы к прямой и обратной зонам по тому, задан ли в качестве параметра адрес или доменное имя. Для указания конкретного типа искомой записи обеим утилитам требуется этот тип передать явно. Тип any означает поиск всех записей с указанным именем: 

methody@localhost:~ $ dig www.us any

 ; <<>> DiG 9.2.4rc5 <<>> www.us any
 ;; global options:  printcmd
 ;; Got answer:
 ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6451
 ;; flags: qr rd ra; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 4

 ;; QUESTION SECTION:
 ;www.us.                                IN      ANY

 ;; ANSWER SECTION:
 www.us.                 1766    IN      A       209.173.57.26
 www.us.                 1766    IN      A       209.173.53.26
 www.us.                 1767    IN      NS      pine.neustar.com.
 www.us.                 1767    IN      NS      willow.neustar.com.
 www.us.                 1767    IN      NS      cypress.neustar.com.
 www.us.                 1767    IN      NS      oak.neustar.com.
 www.us.                 1771    IN      MX      20 pine.neustar.com.
 www.us.                 1771    IN      MX      5 oak.neustar.com.
 www.us.                 1771    IN      MX      5 willow.neustar.com.
 www.us.                 1771    IN      MX      10 cypress.neustar.com.

 ;; ADDITIONAL SECTION:
 pine.neustar.com.       135024  IN      A       209.173.57.70
 willow.neustar.com.     135024  IN      A       209.173.53.84
 cypress.neustar.com.    135024  IN      A       209.173.57.84
 oak.neustar.com.        135024  IN      A       209.173.53.70

 ;; Query time: 932 msec
 ;; SERVER: 192.168.102.1#53(192.168.102.1)
 ;; WHEN: Wed Dec 22 22:01:24 2004
 ;; MSG SIZE  rcvd: 281

Пример 13. Утилита dig

Перекрёстные ссылки книги для Прикладной уровень

  • Транспортный уровень
  • Вверх
  • Сетевые и серверные возможности

Book navigation

  • Предисловие
  • Сеанс работы в Linux
  • Терминал и командная строка
  • Структура файловой системы
  • Работа с файловой системой
  • Доступ процессов к файлам и каталогам
  • Права доступа
  • Работа с текстовыми данными
  • Возможности командной оболочки
  • Текстовые редакторы
  • Этапы загрузки системы
  • Работа с внешними устройствами
  • Конфигурационные файлы
  • Управление пакетами
  • Сеть TCP/IP в Linux
    • Сетевые протоколы. Семейство протоколов TCP/IP
    • Аппаратный и интерфейсный уровни
    • Сетевой уровень
    • Транспортный уровень
    • Прикладной уровень
  • Сетевые и серверные возможности
  • Графический интерфейс (X11)
  • Прикладные программы
  • Политика свободного лицензирования

Последние материалы

  • Файл sudoers
    14 hours 12 minutes ago
  • Утилита visudo
    1 day 22 hours ago
  • Файловый менеджер Thunar
    1 week 4 days ago
  • Эмулятор терминала Terminator
    2 weeks 2 days ago
  • Приложение scanimage
    3 weeks 1 day ago
RSS feed

Secondary menu

  • О проекте

© 2008–2025 Олег Меньшенин mensh@yandex.ru