GNUser
July 25, 2021

/GNUser/Linux для программиста/06-Network

Терминалы

Linux система, как и все её POSIX совместимые предшественницы является изначально многопользовательской. Не было такого периода времени в истории Linux, когда он работал бы только на персональной машине с монопольным управлением. Да, в корневом процессе init предусмотрены уровни 1 - монопольный и 2 - многопользовательский без подключения к сети. Но они являются именно нештатными, аварийными что ли, режимами, а 3-й уровень - нормальный - подразумевает как-раз, что система подключена к сети и готова по этой сети обслуживать подключения пользователей через терминалы.

Терминалы есть, опять же, локальные, которые про монитор и клавиатуру подключенные непосредственно к операционке, которые работают во всех режимах работы. А есть эмулируемые, которые предоставляются пользователям подключающимся к системе по сети. Таким образом любая POSIX совместимая ОС, каковой частично является и Linux, есть по сути терминальный сервер, машина предоставляющая виртуальные терминалы по сети.

Отсюда и историческое название таких терминалов - TTY (TeleTYpe). Конечно, с исходным устройством терминал операционной системы имеет мало общего, однако если кто-то помнит старые телефонные модемы, подключаемые к компьютеру через COM-порт, то это вот именно оно. Эти "прекрасные" программы типа HyperTerminal или техно-словечки вроде UART, Baud Rate, RS-232, "бит четности" все они про терминалы. Собственно, клавиатура и мышь до сих пор работают именно через последовательное UART соединение. Хоть и эмулируемое.

Для эмуляции же терминалов через сетевое подключение в POSIX системах используются так называемые псевдотерминалы - PTY. Операционная система создает внутри себя совершенно нормальное терминальное устройство, у которой ввод и вывод преобразуются не в UART сигналы, а в коммуникационные TCP/IP пакеты. А поскольку все устройства в таких системах являются элементами файловой системы, то и точно так же сетевые терминалы связаны с самыми обыкновенными файлами.

Порты и сокеты

Сетевые же устройства подключаются к псевдотермиалам посредством т.н. сокетов. Для протоколов TCP/UDP эти сокеты называются портами. С точки зрения прикладного программного обеспечения пары IP-адрес + порт являются ни чем иным как файлами в разделе '/proc'. Файл '/proc/<PID>/net/<PROTO>' процесса с номером PID является списком сокетов соединений в данный момент подключенных процессу по протоколу <PROTO>.

Как однако можно убедиться в прямом чтении такого файла толку мало. Во-первых, файл содержит 16-ричные адреса и индексы сокетов, во-вторых их еще нужно сопоставлять с конкретными дескрипторами файлов связанными с процессом $ ls /proc/<PID>/fd.

Что бы облегчить жизнь администратору или программисту, решившему взглянуть на кишки TCP/UDP сокетов к Bash приделали перевод нормальных адресов и портов в соответствующие дескрипторы. Например команда

$ echo Message > /dev/tcp/127.0.0.1/4444

отправит на порт 4444 машины по адресу 127.0.0.1 текст 'Message'. Ну а

$ exec 3<>/dev/tcp/127.0.0.1/4444

свяжет сокет с дескриптором '3' и будет перенаправлять все содержимое на него. Если, разумеется, кто-то в данный момент слушает этот порт, и что-то соответственно отвечает.

Слушать же порт можно, собственно, программой эмулирующей терминал, так это делает система, например при помощи демонов telnetd, sshd и прочих. Либо можно использовать утилиту nc (netcat). Она не входит в состав POSIX, но с большой вероятностью по умолчанию предусмотрена в вашем дистрибутиве Linux. По сути это тоже такая упрощалка для чтения и записи в коммуникационные сокеты произвольных данных. Команда

$ nc -k -l 4444

"посадит" на порт 4444 вашей машины утилиту, которая будет транслировать в консоль все что вы пошлете в соке 127.0.0.1:4444, ну, например браузером.

А введенное обратно в консоль, например 'Bad answer', соответственно, попадет ответом к браузеру. Пусть и в виде ошибки.

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

HTTP, сURL

Curl это более навороченная программа и одноименная библиотека для работы с сокетами и заточенная под протоколы более высокого - прикладного уровня, а в частности HTTP. С другой стороны она не может полностью заменить nc, поскольку предназначена чисто для клиентской стороны протокола и не может выступать в качестве сервера. Тем не менее, не смотря на развитие еще более навороченных средств отладки клиентской части инструмент остается эдаким эталонным, референсным изделием, который уж точно не привнесет никакой отсебятины. Не зря же его включили в состав Windows не когда-то там, а в 2018.

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

Наиболее часто утилита curl используется в качестве эдакого теста на вшивость серверного ПО. Просто посмотреть, что на самом деле отправляет API на тот или иной запрос. Ключ '-I' или '--head' позволяет выплюнуть в вывод полностью текст заголовка отправленного сервером. Который соответственно можно просто почитать, передать дальше в какой-нибудь парсер или клиентское приложение. И в отличии от nc запрос в curl можно сформировать более удобным и наглядным способом, чем если бы вы руками вводили все соответствующие заголовки.

Рассказывать обо всех возможных сценариях использования curl я тут не буду. Для этого понадобится отдельная книга, каковые в общем и существуют. Скажу лишь то, что с помощью него можно практически полностью симулировать работу браузера, включая использование SSL и cookie. Говорят, не менее ловко curl справляется с похожими задачами относительно почтовых, ftp, smb и всяких других клиентских приложений и протоколов.

Lynx, Wget

Редко, но метко, бывает нужно еще более наглядно посмотреть механику взаимодействия клиента HTTP со всемирной паутиной из консоли. Быстро и эффективно это можно сделать еще с одной из старейших утилит для работы в сети. Lynx (бывший links) - это по сути самый настоящий браузер. Он в полной мере понимает работу протокола HTTP и очень даже адекватно умеет рендерить HTML в консоль. То есть, да, это консольный браузер. Разнообразный JS интерактив конечно вы здесь не реализуете, но быстренько оценить разметку и запостить форму очень даже можно. Я так делал. И не раз.

Ну и куда же программисту без незаменимого web get. Эта утилита может быть не так часто используется напрямую, но если присмотреться ею буквально пронизано все, что касается операции чего-то откуда-то скачать. Менеджеры зависимостей, разнообразные установочные скрипты, менеджеры всяческих плагинов ко всему чему можно - все используют wget для доставки из сети требуемых файлов.

Можно, конечно, увидеть (особенно под Windows) редкие программы, которые самостоятельно что-то скачивают используя собственные механизмы, включая ту же библиотеку curl. Но большинство из них страдают низкой надежностью и отсутствием всеядности присущей wget. Wget понимает все... ВСЕ, мыслимые URL, кодировки, типы web-серверов, прокси, способы докачки, разбития, проверки контрольных сумм, и много всего о чем я даже не подозреваю. Опять же, wget работает полностью в консольном режиме.

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

:wq