Глава 7. Сетевая среда
Содержание
В этой главе мы намерены изучить как подсистема Windows для Linux настраивает сетевую среду внутри самой подсистемы и как изменения и обновления в построении сетевой среды распространяются со стороны Windows в WSL. Кроме того, мы рассмотрим что представляют собой сокеты Linux и как WSL реализует их для предоставления хорошей практики Linux поверх операционной системы Windows в то же время сопровождая возможность взаимодействия.
В наши дни все компьютеры подключены к сетевым средам и устройствам и нам необходим постоянный доступ к Интернету и прочим системам через сетевой стек для обмена данными, перемещения файлов и тому подобного, что добавляет дополнительно важность сетевых сред как одного из критически важных компонентов стоящих позади успеха любого программного приложения.
Давайте начнём с небольшого обзора того как устанавливается сетевая среда в Linux и в его реализации в WSL, а также позвольте нам немного порассуждать о выборах архитектуры выполняемых для создания бесшовного уровня наведения моста в промежутке между построением сетей в Windows и Linux.
Linux применяет общие системные вызовы, которые можно использовать для управления (считыванием и записью) любого устройства, например, сетевых интерфейсов, и такие вызовы также носят название IOCTL (Input/Output Control, управления вводом/ выводом). IOCTL делают возможным просмотр перечня всех подключённых к Linux сетевых устройств через осуществление таких системных вызовов для считывания имеющихся сетевых интерфейсов и сохранения этих сведений в ядре. Однако WSL1 не обладает такой возможностью, ибо нет доступного ядра и мы фактически эмулируем Linux поверх Windows, применяя трансляцию системных вызовов на уровне совместимости.
Чтобы заполнить этот пробел, как только экземпляр WSL запускается в Windows, служба диспетчера LXSS запрашивает перечень имеющихся в операционной системе Windows сетевых устройств и передаёт этот список в драйвер WSL (lxcore.sys), и когда из дистрибутива Linux выполняется некий системный вызов (IOCTL), тогда вышеупомянутая кэшировнная информация предоставляет имеющийся список сетевых устройств в WSL.
Тот же самый перечень получает автоматическое заполнение в файле /etc/resolv.conf
,
который выступает файлом разрешения конфигурации в Linux и который содержит свой перечень системных серверов
доменных имён, настроенных в Windows. Существует множество параметров настройки, которые можно применять в этом
файле, однако по умолчанию он создаётся в общей конфигурации:
nameserver <namer server IP address>
Значением IP адреса может быть либо некий IPv4 адрес в нотации с точками, либо адрес IPv6 в нотации точек/ двоеточий, как это показано на Рисунке 7-1.
Некоторые из запрошенных таких сетевых сведений также заполняют файл
/etc/hosts
, который также носит название файла хостов и содержит
статическую таблицу нахождения имён хостов и соответствующих им IP адресов, как это показано на
Рисунке 7-2.
Сочетание /etc/resolv.conf
и
/etc/hosts
делает возможным поддержку необходимых DNS в
подсистеме Windows для Linux.
Однако построение сетевой среды очень динамичная вещь и ситуации могут меняться стремительно, например,
пользователь может очень быстро переключаться с кабельного Ethernet на беспроводную сеть. В WSL должен существовать
некий механизм поддержки обновлений таких изменений из Windows в WSL с тем, чтобы служба диспетчера LXSS снова
вписывалась в общую картину регистрируя саму себя для всех изменений, связанных с обновлениями в сетевых интерфейсах
на стороне Windows. Это означает, что служба диспетчера LXSS ожидает любых уведомлений об изменениях и, когда
происходят изменения в сетевой среде, он снова автоматически заполняются в WSL с применением вышеупомянутых
подходов, как это демонстрируется на
Рисунке 7-3.
Это удерживает файлы /etc/resolv.conf
и
/etc/hosts
в актуальном состоянии и синхронизирует их с настройками Windows.
Рисунок 7-3 демонстрирует, что на шаге 3, когда сетевой интерфейс отключён на стороне Windows, соответствующий Eternet немедленно исчезает из подсистемы Windows для Linux (что проверяется отсутствием MAC адреса на шаге 4), а запросы ICMP начинают отказывать на шаге 6.
Сокет является неким абстрактным представлением конечной точки пути сетевого взаимодействия. Сокеты также способны служить некоторыми конечными точками для локальных, не подключаемых к сетевой среде межпроцессных взаимодействий. В наших последующих подразделах мы выполним краткий обзор сокетов Беркли в Linux и аналогичную реализацию в операционной системе Windows с названием Winsock Kernel (WSK), которая делает возможной для WSL трансляцию API вызовов сокета Беркли в API вызовы Winsock Kernel и наоборот для того, чтобы сделать возможным сетевой обмен между Windows и Linux.
Сокеты Беркли
В Linux сокеты Беркли (также именуемые сокетами BSD) это некий интерфей API, который делает возможным межпроцессное взаимодействие (IPC, inter-process communication). Для установления соединения любые две терминальные точки открывают некий сокет на каждом из своих концов, которые далее привязываются к заданному адресу с тем, чтобы между ними можно было бы отправлять и получать данные.
Вот некоторые из распространённых функций API сокета Беркли.
socket( )
Применяется для создания некого нового сокета определённого типа и для открытия сокета существуют три требования, причём они далее могут применяться для категоризации получаемых сокетов:
-
Семейство адреса (AF, Address family) или домен - Сокет может быть одним из следующих доменов или семейств адреса:
-
AF_INET
это реализация Linux IPv4. -
AF_UNIX
, также именуемыйAF_LOCAL
, применяется для межпроцессного взаимодействия внутри общей системы. -
Сокеты
AF_NETLINK
используются для взаимодействия между режимом пользователя и ядром, поскольку они составляются из стандартного интерфейса на основе сокета для процессов пространства пользователя и некого внутреннего API ядра для модулей ядра.
-
-
Тип сокета - определяет является ли его протокол ориентированным на соединение или нет.
-
SOCK_DGRAM
для UDP -
SOCK_STREAM
для TCP -
SOCK_RAW
для ICMP
-
-
Протокол сокета - Значение аргумента протокола может быть установлено в ноль “0” для запроса устанавливаемого по умолчанию реализации типа сокета для данного протокола.
Синтаксис:
socket(AddressFamily, Type, Protocol);
Пример:
socket(AF_INET, SOCK_STREAM, 0);
bind( )
Эта функция связывает некий сокет с адресом сокета, то есть, комбинацией IP адреса и номера порта.
listen( )
Данная функция помечает определяемый сокет в качестве пассивного, который лишь принимает входящие подключения.
connect( )
Эта функция применяется для установления соединения между указанным сокетом и передаваемым IP адресом.
send( ), recv( ), sendto( ) и recvfrom( )
Как и предполагают их наименования, эти функции используются для отправки и получения данных через сокеты.
close( )
Данная функция применяется для высвобождения системных ресурсов прекращением некого установленного через сокеты соединения.
Winsock и WSK (Winsock Kernel)
Операционная система Windows обладает реализацией режима пользователя вышеупомянутых сокетов BSD, носящих
название “Winsock”, причём их реализация очень похожа, но не идентична, и она не может применяться в подсистеме
Windows для Linux, потому что реализация сокета WSL выполняется в режиме ядра, то есть внутри библиотеки драйвера
подсистемы Linux (WslSocket.lib
).
Для решения этой проблемы в WSL был применён другой API Windows нижнего уровня, носящий название Winsock Kernel (WSK). WSK это интерфейс сетевого программирования режима ядра и, применяя его, любое программное обеспечение ядра способно осуществлять сетевые операции ввода/ вывода в точности как в режиме пользователя “Winsock”. В основном, драйверы подсистемы Windows для Linux транслируют вызовы из API сокета BSD в API WSK и реализуют нечто ещё, что пропущено для поддержки почти такой же сетевой практики, которая имеется в естественном дистрибутиве Linux.
Как демонстрируется на
Рисунке 7-4,
когда некое приложение создаёт сокет BSD, запущенный в дистрибутиве Linux поверх WSL, тогда системные вызовы
сокета BSD выполняются в соответствующий драйвер режима ядра lxcore.sys
WSL, который обрабатывает необходимую трансляцию. lxcore.sys
транслирует
такие системные вызовы сокета BSD в вызовы, которые понятны для WSK (Winsock Kernel), что является API нижнего
уровня в соответствующем ядре NT для обработки всех относящихся к сокету запросов в операционной системе
Windows и соединяет соответствующий сокет с лежащим в основе стеком TCP/IP.
То как реализовано построение сетевой среды в подсистемах Windows для Linux версий 1 и 2, совершенно различно, и на самом деле важно понимать эту разницу; в противном случае вы столкнётесь с сетевыми проблемами и неожиданным поведением.
Одно из основных отличий состоит в том, что в WSL1 подсистема пользуется тем же самым физическим сетевым интерфейсом, который применяет лежащая в его основе операционная система Windows, потому что это всё ещё некая эмуляция или, иными словами, некий уровень совместимости, собранный для поддержки дистрибутива Linux в Windows. Это означает, что вы пользуетесь теми же самыми картами сетевого интерфейса (NIC), IP адресами и DNS серверами.
Однако это изменилось в WSL2, потому как в версии 2 подсистема Windows для Linux теперь запускается в облегчённой вспомогательной виртуальной машине собранной с применением Hyper-V и в точности как и любая виртуальная машина, WSL2 обладает своим собственным, выделенным виртуальным сетевым интерфейсом, что показано на Рисунке 7-5, причём он обладает иными IP адресами и DNS серверами.
Помимо этого, WSL1 и WSL, обе всё ещё заполняют файлы /etc/resolv.conf
и /etc/hosts
чтобы заставить работать DNS, пока эти файлы не перекрываются
в явном виде.
В этой главе мы изучили основные понятия построения сетевой среды, стоящие за подсистемой Windows для Linux, которые делают доступной бесшовную практику и возможность взаимодействия между операционной системой Windows и подсистемой Linux. Мы рассмотрели сетевые интерфейсы и то как в WSL устанавливается и настраивается разрешение имён, а затем мы взглянули на сокеты Беркли и аналогичную, но не идентичную реализацию в Windows с названием Winsock Kernel, которая делает возможным построение сетевой среды в подсистеме Windows для Linux посредством трансляции вызовов API. Наконец, мы рассмотрели основные ключевые отличия в построении сетевой среды для WSL1, которая эмулирует некую среду Windows в Windows и WSL2, которая является облегчённой служебной виртуальной машиной, запускаемой в операционной системе Windows с неким выделенным сетевым интерфейсом.