Русские Блоги
Понимание сетевого стека Linux (1): краткое описание стека сетевых протоколов Linux
В этой серии статей описывается сетевой стек Linux, в том числе:
(4) Технология разгрузки сегментации в среде QEMU / KVM + VxLAN (принимающая сторона)
1. Сетевой путь Linux
1.1 отправитель
1.1.1 Уровень приложения
(1) Socket
Различные сетевые приложения на прикладном уровне в основном взаимодействуют со стеком сетевых протоколов пространства ядра через программный интерфейс Linux Socket. Linux Socket разработан на основе BSD Socket, является одной из важных частей операционной системы Linux и основой сетевых приложений. На иерархическом уровне он расположен на уровне приложений и представляет собой API, предоставляемый операционной системой для программистов приложений, через который приложения могут получить доступ к протоколу транспортного уровня.
- Сокет расположен над протоколом транспортного уровня, что позволяет скрыть различия между разными сетевыми протоколами.
- Socket — это вход в сетевое программирование. Он обеспечивает большое количество системных вызовов и составляет основную часть сетевых программ.
- В системе Linux сокеты являются частью файловой системы, а сетевое взаимодействие можно рассматривать как чтение файлов, что делает управление сетью таким же удобным, как управление файлами.
Процесс обработки сокета UDP (источник) Процесс обработки сокета TCP (источник)
(2) Поток обработки на уровне приложений
- Веб-приложение вызывает Socket APIsocket (int family, int type, int protocol) Чтобы создать сокет, вызов в конечном итоге вызовет системный вызов Linux socket () и, наконец, метод sock_create () ядра Linux. Этот метод возвращает файловый дескриптор созданного сокета. Для каждого сокета, созданного сетевым приложением пользовательского пространства, в ядре есть соответствующая структура сокета и структура сокета. Среди них struct sock имеет три очереди (очереди), а именно rx, tx и err. Когда структура sock инициализируется, эти буферные очереди также инициализируются; в процессе приема и отправки квитанций каждая очередь сохраняется для отправки или получения Экземпляр skb структуры данных сетевого стека Linux sk_buffer, соответствующий каждому пакету.
- Для сокета TCP приложение вызывает API connect (), чтобы клиент и сервер установили виртуальное соединение через сокет. В этом процессе стек протокола TCP устанавливает TCP-соединение посредством трехстороннего рукопожатия. По умолчанию API будет ждать, пока квитирование TCP завершит установление соединения, прежде чем вернуться. Важным шагом в процессе установления соединения является определение максимального размера сегмента (MSS), используемого обеими сторонами. Поскольку UDP — протокол без установления соединения, этот шаг не требуется.
- Приложение вызывает API отправки или записи Linux Socket для отправки сообщения принимающей стороне.
- вызывается sock_sendmsg, он использует дескриптор сокета для получения структуры sock и создает заголовок сообщения и сообщение управления сокетом
- Вызывается _sock_sendmsg, и в соответствии с типом протокола сокета вызывается функция отправки соответствующего протокола.
- Для TCP вызовите функцию tcp_sendmsg.
- Для UDP приложение пользовательского пространства может вызвать любой из трех системных вызовов send () / sendto () / sendmsg () для отправки сообщений UDP, и в конечном итоге они вызовут функцию udp_sendmsg () в ядре.
1.1.2 Транспортный уровень
Конечная цель транспортного уровня — предоставить своим пользователям эффективные, надежные и экономичные услуги передачи данных.Основные функции включают (1) построение сегмента TCP (2) вычисление контрольной суммы (3) отправку пакета ответа (ACK) (4) Операция, гарантирующая надежность, например, скользящий отвод. Общий процесс обработки стека протоколов TCP показан на следующем рисунке:
Краткий процесс работы стека TCP:
- Функция tcp_sendmsg сначала проверяет статус установленного TCP-соединения, затем получает MSS соединения и запускает процесс отправки сегмента.
- Создайте загрузку сегмента TCP: он создает экземпляр skb структуры данных sk_buffer пакета в пространстве ядра и копирует данные пакета из буфера пространства пользователя в буфер skb.
- Создайте заголовок TCP.
- Вычислить контрольную сумму TCP (контрольную сумму) и порядковый номер (порядковый номер).
- Контрольная сумма TCP — это сквозная контрольная сумма, вычисляемая отправителем и затем проверяемая получателем. Его цель — обнаруживать любые изменения в заголовке TCP и данных от отправителя к получателю. Если получатель обнаруживает ошибку в контрольной сумме, сегмент TCP будет напрямую отброшен. Контрольная сумма TCP покрывает заголовок TCP и данные TCP.
- Требуется контрольная сумма TCP
Краткий процесс работы стека UDP:
- UDP инкапсулирует сообщение в дейтаграмму UDP
- Вызовите метод ip_append_data (), чтобы отправить пакет на уровень IP для обработки.
1.1.3 IP-сетевой уровень — добавление заголовка и контрольной суммы, обработка маршрутизации, IP-фрагментация
Задача сетевого уровня — выбрать подходящие узлы маршрутизации и коммутации между сетями для обеспечения своевременной передачи данных. Сетевой уровень составляет пакеты данных из кадров, предоставленных канальным уровнем.Заголовок сетевого уровня инкапсулируется в пакет, который содержит информацию о логическом адресе — сетевые адреса исходного сайта и адреса конечного сайта. В его основные задачи входит (1) обработка маршрутизации, то есть выбор следующего перехода (2) добавление IP-заголовка (3) вычисление контрольной суммы IP-заголовка, которая используется для определения того, содержит ли заголовок IP-пакета ошибку во время процесса распространения (4), если возможно, продолжить После обработки IP-фрагментации (5) получите MAC-адрес следующего перехода, установите заголовок канального уровня и затем передайте на канальный уровень для обработки.
Базовый процесс обработки IP-стека показан на следующем рисунке:
- Сначала ip_queue_xmit (skb) проверит информацию о маршрутизации skb-> dst. Если нет, например, первый пакет сокета, используйте ip_route_output () для выбора маршрута.
- Затем заполните различные поля IP-пакета, такие как версия, длина заголовка, TOS и т. Д.
- Некоторые средние фрагменты можно найти в соответствующих документах. Основная идея состоит в том, что когда длина сообщения больше, чем mtu, а длина gso не равна 0, для фрагментации будет вызываться ip_fragment, иначе для отправки данных будет вызван ip_finish_output2. В функции ip_fragment будет проверяться бит флага IP_DF, Если пакет IP-данных, подлежащий фрагментированию, не может быть фрагментирован, вызовите icmp_send () отправляет отправителю причину необходимости Фрагментация и цель установки флага отсутствия фрагментации недоступны Пакеты ICMP и отбросить пакеты, то есть установить статус IP В случае сбоя фрагментации отпустите skb, и возвращаемое сообщение будет слишком длинным код ошибки. Чтобы
- Затем используйте ip_finish_ouput2, чтобы установить заголовок канального уровня. Если буфер заголовка канального уровня есть (то есть hh не пуст), скопируйте его в skb. Если нет, то вызовите neigh_resolve_output и используйте ARP для его получения.
1.1.4 Уровень канала передачи данных
Функционально, на основе услуги потока битов, предоставляемой физическим уровнем, устанавливается канал данных между соседними узлами, обеспечивается безошибочная передача кадров данных (Frame) по каналу посредством контроля ошибок, и выполняются действия в каждой цепи. серии. Уровень канала передачи данных обеспечивает надежную передачу на ненадежных физических носителях. Роль этого уровня включает: адресацию физических адресов, формирование кадров данных, управление потоком, обнаружение ошибок данных, повторную передачу и т. Д. На этом уровне единица данных называется кадром. Представители протоколов уровня звена данных включают: SDLC, HDLC, PPP, STP, Frame Relay и т. Д.
С точки зрения реализации, Linux предоставляет уровень абстракции сетевого устройства, фактически это теперь linux / net / core / dev.c. Конкретные физические сетевые устройства должны реализовывать виртуальные функции в драйвере устройства (driver.c). Уровень абстракции сетевого устройства вызывает функции определенных сетевых устройств.
、
1.1.5 Инкапсуляция и передача физического уровня на физическом уровне
- После получения запроса на отправку физический уровень копирует данные из основной памяти во внутреннюю RAM (буфер) через DMA. В копию данных одновременно добавляются соответствующий заголовок, IFG, преамбула и CRC, соответствующие протоколу Ethernet. Для сетей Ethernet CSMA / CD используется для передачи на физическом уровне, то есть конфликты каналов отслеживаются во время передачи.
- После того, как сетевая карта завершит передачу сообщения, будет сгенерировано прерывание для уведомления ЦП, а затем обработчик прерывания на уровне драйвера может удалить сохраненный skb.
1.1.6 Краткое резюме
(источник)
1.2 Ресивер
1.2.1 Физический уровень и уровень канала данных
- Когда пакет поступает на физический сетевой адаптер машины, когда он получает фрейм данных, он инициирует прерывание и передает его rx_ring в памяти ядра Linux через DMA.
- Сетевая карта выдает прерывание, чтобы уведомить ЦП о наличии пакета, который необходимо обработать. Обработчик прерывания в основном выполняет следующие операции, включая выделение структуры данных skb_buff и копирование полученного кадра данных из порта ввода-вывода сетевого адаптера в буфер skb_buff; извлечение некоторой информации из кадра данных и установка соответствующего skb_buff Параметры, эти параметры будут использоваться сетевым протоколом верхнего уровня, например skb-> protocol;
- После простой обработки программа терминальной обработки отправляет мягкое прерывание (NET_RX_SOFTIRQ), чтобы уведомить ядро о получении нового кадра данных.
- В ядре 2.5 представлен набор новых API-интерфейсов для обработки полученного фрейма данных, а именно NAPI. Следовательно, у драйвера есть два способа уведомить ядро: (1) через предыдущую функцию netif_rx; (2) через механизм NAPI. Обработчик прерывания вызывает функцию netif_rx_schedule сетевого устройства, входит в поток обработки мягкого прерывания, а затем вызывает функцию net_rx_action.
- Эта функция закрывает прерывание, получает все пакеты в rx_ring каждого сетевого устройства, и, наконец, pacakage удаляется из rx_ring и входит в поток обработки netif _receive_skb.
- netif_receive_skb — это последняя станция, на которой канальный уровень принимает дейтаграммы. В соответствии с типами дейтаграмм сетевого уровня, зарегистрированными в глобальных массивах ptype_all и ptype_base, он доставляет датаграммы приемным функциям различных протоколов сетевого уровня (в основном ip_rcv и arp_rcv в домене INET). Эта функция в основном предназначена для вызова функции приема протокола третьего уровня для обработки пакета skb и перехода на третий сетевой уровень для обработки.
1.2.2 Сетевой уровень
- Функция входа уровня IP находится в функции ip_rcv. Эта функция сначала выполняет различные проверки, включая контрольную сумму пакета, и, если необходимо, дефрагментирует IP (объединяет несколько фрагментов), затем пакет вызывает зарегистрированный обработчик netfilter предварительной маршрутизации и, наконец, после завершения достигает функции ip_rcv_finish.
- Функция ip_rcv_finish вызовет функцию ip_router_input для входа в процесс маршрутизации. Сначала он вызовет ip_route_input для обновления маршрута, а затем Найдите маршрут и решите, будет ли пакет отправлен на локальную машину, перенаправлен или отклонен:
- Если он отправляется на локальный компьютер, вызовите функцию ip_local_deliver, которая может де-фрагментировать (объединить несколько IP-пакетов), а затем вызовите функцию ip_local_deliver. Эта функция вызывает интерфейс следующего уровня в соответствии с номером протокола следующего уровня обработки пакета, включая tcp_v4_rcv (TCP), udp_rcv (UDP), icmp_rcv (ICMP), igmp_rcv (IGMP). Для TCP вызывается функция tcp_v4_rcv, так что поток обработки входит в стек TCP.
- Если требуется пересылка, войдите в процесс пересылки. Этот процесс должен обработать TTL, а затем вызвать функцию dst_input. Эта функция (1) обработает Netfilter Hook (2) выполнит IP-фрагментацию (3) вызовет dev_queue_xmit и войдет в поток обработки канального уровня.
1.2.3 Транспортный уровень (TCP / UDP)
- Запись обработки TCP транспортного уровня находится в функции tcp_v4_rcv (находится в файле linux / net / ipv4 / tcp ipv4.c), которая выполняет проверку заголовка TCP и другую обработку.
- Вызовите _tcp_v4_lookup, чтобы найти открытый сокет пакета. Если его не найти, пакет будет удален. Затем проверьте состояние сокета и подключения.
- Если для сокета и соединения все в порядке, вызовите tcp_prequeue, чтобы пакет вошел в пользовательское пространство из ядра и поместил его в очередь приема сокета. Затем сокет будет разбужен, вызовет системный вызов и, наконец, вызовет функцию tcp_recvmsg, чтобы получить сегмент из очереди приема сокета.
1.2.4 Уровень приемника-приложения
- Каждый раз, когда пользовательское приложение вызывает read или recvfrom, этот вызов будет сопоставлен с системным вызовом sys_recv в /net/socket.c и преобразован в вызов sys_recvfrom, а затем будет вызвана функция sock_recgmsg.
- Для сокетов INET будет вызван метод inet_recvmsg в / net / ipv4 / af inet.c, который вызовет метод получения данных соответствующего протокола.
- Для TCP вызовите tcp_recvmsg. Эта функция копирует данные из буфера сокета в пользовательский буфер.
- Для UDP любой из трех системных вызовов recv () / recvfrom () / recvmsg () может быть вызван из пользовательского пространства для получения пакета UDP, и эти системные вызовы в конечном итоге вызовут метод udp_recvmsg в ядре.
1.2.5 Краткое описание процесса получения сообщения
2. Linux структура данных sk_buff struct и очередь (очередь)
2.1 sk_buff
2.1.1 Что такое sk_buff
Когда сетевой пакет обрабатывается ядром, данные нижележащего протокола передаются на более высокий уровень, и при передаче данных процесс меняется на противоположный. Данные (включая заголовок и нагрузку), генерируемые различными протоколами, непрерывно передаются на нижний уровень, пока они не будут окончательно отправлены. Поскольку скорость этих операций критична для производительности сетевого уровня, ядро использует специальную структуру, называемую sk_buff, файл определения которой находится вskbuffer.h. Буферы сокетов используются для обмена данными на уровне реализации сети без копирования или депакетирования пакетов данных — это значительный выигрыш в скорости. Чтобы
- sk_buff — это основная структура данных сети Linux, и ее файл определения находится вskbuffer.h。
- Буфер ядра сокета (skb) — это буфер, используемый сетевым стеком ядра Linux (от L2 до L4) для обработки сетевых пакетов (пакетов), его тип — sk_buffer. Проще говоря, один skb представляет пакет в сетевом стеке Linux; несколько skb, созданных сегментацией TCP, и IP-пакет хранятся в виде списка skb.
- struct sock имеет три очереди skb (очередь sk_buffer): rx, tx и err.
Его основные конструктивные элементы:
2.1.2 Основная операция skb
(1) Размещение skb = alloc_skb (len, GFP_KERNEL)
(2) Добавить полезную нагрузку (skb_put (skb, user_data_len))
(3) Используйте skb-> push, чтобы добавить заголовок протокола, или skb-> pull, чтобы удалить заголовок.
2.2 Очередь драйверов, используемая сетевым стеком Linux (очередь драйверов)
(Выдержки из этой главыQueueing in the Linux Network Stack by Dan Siemon)
2.2.1 Очередь
Между стеком IP и драйвером сетевого адаптера существует очередь драйверов. Обычно он реализуется как кольцевой буфер FIFO, который можно рассматривать просто как фиксированный размер. Эта очередь не содержит пакетных данных. Напротив, она сохраняет только указатель буфера ядра сокета (skb), а использование skb описано в предыдущем разделе на протяжении всей обработки сетевого стека ядра.
Пакеты, обрабатываемые стеком IP при вводе очереди. Эти пакеты либо генерируются приложением на локальном компьютере, либо поступают на локальный компьютер и маршрутизируются. Пакеты, добавленные в очередь IP-стеком, будут извлечены драйвером сетевого устройства (драйвером оборудования) и отправлены на аппаратное устройство NIC через шину данных и переданы.
Если TSO / GSO не используется, длина пакетов, отправленных из IP-стека в эту очередь, должна быть меньше MTU.
2.2.2 размер skb — максимальный размер по умолчанию — NIC MTU
Большинство сетевых карт имеют атрибут фиксированной максимальной единицы передачи (MTU), который представляет собой размер самого большого кадра, который может передать сетевое устройство. Для Ethernet значение по умолчанию составляет 1500 байт, но некоторые сети Ethernet могут поддерживать кадры jumbo размером до 9000 байт. В стеке IP-сети MTU указывает размер самого большого пакета, который может быть отправлен на NIC. Например, если приложение записывает 2000 байтов данных в сокет TCP, стеку IP необходимо создать два IP-пакета, чтобы размер каждого пакета был равен или меньше 1500 байтов. Можно видеть, что для передачи больших объемов данных относительно небольшой MTU приведет к передаче большого количества небольших пакетов в очередь драйвера. Это называется фрагментацией IP.
На следующем рисунке показана фрагментация IP-пакета с полезной нагрузкой 1500 байтов при MTU 1000 и 600:
Networking¶
The development of the Internet has led to an exponential increase in network applications and, as a consequence, to increasing the speed and productivity requirements of an operating system’s networking subsystem. The networking subsystem is not an essential component of an operating system kernel (the Linux kernel can be compiled without networking support). It is, however, quite unlikely for a computing system (or even an embedded device) to have a non-networked operating system due to the need for connectivity. Modern operating systems use the TCP/IP stack. Their kernel implements protocols up to the transport layer, while application layer protocols are typically implemented in user space (HTTP, FTP, SSH, etc.).
Networking in user space¶
In user space the abstraction of network communication is the socket. The socket abstracts a communication channel and is the kernel-based TCP/IP stack interaction interface. An IP socket is associated with an IP address, the transport layer protocol used (TCP, UDP etc) and a port. Common function calls that use sockets are: creation ( socket ), initialization ( bind ), connecting ( connect ), waiting for a connection ( listen , accept ), closing a socket ( close ).
Network communication is accomplished via read / write or recv / send calls for TCP sockets and recvfrom / sendto for UDP sockets. Transmission and reception operations are transparent to the application, leaving encapsulation and transmission over network at the kernel’s discretion. However, it is possible to implement the TCP/IP stack in user space using raw sockets (the PF_PACKET option when creating a socket), or implementing an application layer protocol in kernel (TUX web server).
For more details about user space programming using sockets, see Beej’s Guide to Network Programming Using Internet Sockets.
Linux networking¶
The Linux kernel provides three basic structures for working with network packets: struct socket , struct sock and struct sk_buff .
The first two are abstractions of a socket:
- struct socket is an abstraction very close to user space, ie BSD sockets used to program network applications;
- struct sock or INET socket in Linux terminology is the network representation of a socket.
The two structures are related: the struct socket contains an INET socket field, and the struct sock has a BSD socket that holds it.
The struct sk_buff structure is the representation of a network packet and its status. The structure is created when a kernel packet is received, either from the user space or from the network interface.
The struct socket structure¶
The struct socket structure is the kernel representation of a BSD socket, the operations that can be executed on it are similar to those offered by the kernel (through system calls). Common operations with sockets (creation, initialization/bind, closing, etc.) result in specific system calls; they work with the struct socket structure.
The struct socket operations are described in net/socket.c and are independent of the protocol type. The struct socket structure is thus a generic interface over particular network operations implementations. Typically, the names of these operations begin with the sock_ prefix.
Operations on the socket structure¶
Socket operations are:
Creation¶
Creation is similar to calling the socket() function in user space, but the struct socket created will be stored in the res parameter:
- int sock_create(int family, int type, int protocol, struct socket **res) creates a socket after the socket() system call;
- int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res) creates a kernel socket;
- int sock_create_lite(int family, int type, int protocol, struct socket **res) creates a kernel socket without parameter sanity checks.
The parameters of these calls are as follows:
- net , where it is present, used as reference to the network namespace used; we will usually initialize it with init_net ;
- family represents the family of protocols used in the transfer of information; they usually begin with the PF_ (Protocol Family) string; the constants representing the family of protocols used are found in linux/socket.h , of which the most commonly used is PF_INET , for TCP/IP protocols;
- type is the type of socket; the constants used for this parameter are found in linux/net.h , of which the most used are SOCK_STREAM for a connection based source-to-destination communication and SOCK_DGRAM for connectionless communication;
- protocol represents the protocol used and is closely related to the type parameter; the constants used for this parameter are found in linux/in.h , of which the most used are IPPROTO_TCP for TCP and IPPROTO_UDP for UDP.
To create a TCP socket in kernel space, you must call:
and for creating UDP sockets:
A usage sample is part of the sys_socket() system call handler:
Closing¶
Close connection (for sockets using connection) and release associated resources:
- void sock_release(struct socket *sock) calls the release function in the ops field of the socket structure:
Sending/receiving messages¶
The messages are sent/received using the following functions:
- int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags);
- int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t size, int flags);
- int sock_sendmsg(struct socket *sock, struct msghdr *msg);
- int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t size);
The message sending/receiving functions will then call the sendmsg / recvmsg function in the ops field of the socket. Functions containing kernel_ as a prefix are used when the socket is used in the kernel.
The parameters are:
- msg , a struct msghdr structure, containing the message to be sent/received. Among the important components of this structure are msg_name and msg_namelen , which, for UDP sockets, must be filled in with the address to which the message is sent ( struct sockaddr_in );
- vec , a struct kvec structure, containing a pointer to the buffer containing its data and size; as can be seen, it has a similar structure to the struct iovec structure (the struct iovec structure corresponds to the user space data, and the struct kvec structure corresponds to kernel space data).
A usage example can be seen in the sys_sendto() system call handler:
The struct socket fields¶
The noteworthy fields are:
- ops — the structure that stores pointers to protocol-specific functions;
- sk — The INET socket associated with it.
The struct proto_ops structure¶
The struct proto_ops structure contains the implementations of the specific operations implemented (TCP, UDP, etc.); these functions will be called from generic functions through struct socket ( sock_release() , sock_sendmsg() , etc.)
The struct proto_ops structure therefore contains a number of function pointers for specific protocol implementations:
The initialization of the ops field from struct socket is done in the __sock_create() function, by calling the create() function, specific to each protocol; an equivalent call is the implementation of the __sock_create() function:
This will instantiate the function pointers with calls specific to the protocol type associated with the socket. The sock_register() and sock_unregister() calls are used to fill the net_families vector.
For the rest of the socket operations (other than creating, closing, and sending/receiving a message as described above in the Operations on the socket structure section), the functions sent via pointers in this structure will be called. For example, for bind , which associates a socket with a socket on the local machine, we will have the following code sequence:
As you can see, for transmitting the address and port information that will be associated with the socket, a struct sockaddr_in is filled.
The struct sock structure¶
The struct sock describes an INET socket. Such a structure is associated with a user space socket and implicitly with a struct socket structure. The structure is used to store information about the status of a connection. The structure’s fields and associated operations usually begin with the sk_ string. Some fields are listed below:
- sk_protocol is the type of protocol used by the socket;
- sk_type is the socket type ( SOCK_STREAM , SOCK_DGRAM , etc.);
- sk_socket is the BSD socket that holds it;
- sk_send_head is the list of struct sk_buff structures for transmission;
- the function pointers at the end are callbacks for different situations.
Initializing the struct sock and attaching it to a BSD socket is done using the callback created from net_families (called __sock_create() ). Here’s how to initialize the struct sock structure for the IP protocol, in the inet_create() function:
The struct sk_buff structure¶
The struct sk_buff (socket buffer) describes a network packet. The structure fields contain information about both the header and packet contents, the protocols used, the network device used, and pointers to the other struct sk_buff . A summary description of the content of the structure is presented below:
- next and prev are pointers to the next, and previous element in the buffer list;
- dev is the device which sends or receives the buffer;
- sk is the socket associated with the buffer;
- destructor is the callback that deallocates the buffer;
- transport_header , network_header , and mac_header are offsets between the beginning of the packet and the beginning of the various headers in the packets. They are internally maintained by the various processing layers through which the packet passes. To get pointers to the headers, use one of the following functions: tcp_hdr() , udp_hdr() , ip_hdr() , etc. In principle, each protocol provides a function to get a reference to the header of that protocol within a received packet. Keep in mind that the network_header field is not set until the packet reaches the network layer and the transport_header field is not set until the packet reaches the transport layer.
The structure of an IP header ( struct iphdr ) has the following fields:
- protocol is the transport layer protocol used;
- saddr is the source IP address;
- daddr is the destination IP address.
The structure of a TCP header ( struct tcphdr ) has the following fields:
- source is the source port;
- dest is the destination port;
- syn , ack , fin are the TCP flags used; for a more detailed view, see this diagram.
The structure of a UDP header ( struct udphdr ) has the following fields:
- source is the source port;
- dest is the destination port.
An example of accessing the information present in the headers of a network packet is as follows:
Conversions¶
In different systems, there are several ways of ordering bytes in a word (Endianness), including: Big Endian (the most significant byte first) and Little Endian (the least significant byte first). Since a network interconnects systems with different platforms, the Internet has imposed a standard sequence for the storage of numerical data, called network byte-order. In contrast, the byte sequence for the representation of numerical data on the host computer is called host byte-order. Data received/sent from/to the network is in the network byte-order format and should be converted between this format and the host byte-order.
For converting we use the following macros:
- u16 htons(u16 x) converts a 16 bit integer from host byte-order to network byte-order (host to network short);
- u32 htonl(u32 x) converts a 32 bit integer from host byte-order to network byte-order (host to network long);
- u16 ntohs(u16 x) converts a 16 bit integer from network byte-order to host byte-order (network to host short);
- u32 ntohl(u32 x) converts a 32 bit integer from network byte-order to host byte-order (network to host long).
netfilter¶
Netfilter is the name of the kernel interface for capturing network packets for modifying/analyzing them (for filtering, NAT, etc.). The netfilter interface is used in user space by iptables.
In the Linux kernel, packet capture using netfilter is done by attaching hooks. Hooks can be specified in different locations in the path followed by a kernel network packet, as needed. An organization chart with the route followed by a package and the possible areas for a hook can be found here.
Linux Network Stack
By
Priya Pedamkar
Introduction to Linux Network Stack
In the Linux operating system, the network stack is useful to communicate the application with the physical network devices. The network stack is divided into multiple layers. There are different network layers. The same different roles are playing their individual role. Generally, all the operating system supports the network stack role. With the help of the network, we are able to use or connect the different network devices like routers, modems, cable modems, ISDN Mode, Wi-Fi devices, Ethernet cards, Broadband connector, Token Ring cards, etc. While communicating with different devices, the physical layer comes in the picture. It is representing the data in terms of bit format and communicates the different devices physical layer in bit format only.
Syntax of the Linux Network Stack
Web development, programming languages, Software testing & others
- Network Command/Utility : As per the requirement and use, we can use the “Network Command or Utility” keyword in the syntax or command. It will take different arguments like options, input file, IP address, different compatible options. As per the provided arguments, it will provide the network-related information on the screen.
- OPTIONS : We can provide the different flags as the option that is compatible with the “Network Command or Utility”.
- FILE / IP / INPUT FILE: As per the condition or requirement, we can provide the different options or arguments to the “Network Command/Utility”.
How Linux Network Stack Works?
Linux is a multi-user support operating system and supports all the network stack functionality. While communicating with the network, it will follow the two ways of communication. First, the end-user or the client will request access or the file request. Second, as per the necessary access or request type, the request will full fill and set the acknowledgment to the end-user or the client. In this network process number of different network-layer comes into the picture.
Below is the list of layers that come into the picture.
- Application Layer
- System call Interface
- Protocol Agnostic Interface
- Network Protocol
- Device Agnostic Interface
- Device Drivers
- Physical Hardware
- Application Layer: It comes to the TCP as well as the UDP protocols. On the application layer, applications like different browser or other application which accesses the Internet works in this layer. Any application or jobs that are accessing the internet then it will consider in the application layer. When we are opening or closing any file on the network level with the help of any tool or application, it will relay on the same application.
- System call Interface: The SCI stands for System Call Interface. The call will happen when the application layer to the kernel level. Let’s continue with the sample example of editing any image. We need to request for the file from a network or remote location. In the same case, we are sending the read request to the kernel for the editing of the image.
- Protocol Agnostic Interface: In the Protocol Agnostic Interface, it will create the socket. The same created socket is responsible for the two types of communication i.e., talking or listening. Each socket has its own ID. The same id will further be used specifically for an application.
- Network Protocol: The Network Protocol is responsible for sending and receiving data. In other words, we can say that how the data is sent or received. The network layers controls the send and receive information across the network. Specifically, in-network layer work on the router level or router table. This layer is also providing the network routing information.
- Device Agnostic Interface: The Device Agnostic Interface is used to communicate or connect the data from or to the Kernel level and the network drivers or device drivers.
- Device Drivers: The Device Drivers Layer, in this layer the real device driver of the network device will use. This layer is allowed preparing the data for the transmission. Once the data is ready for the transmission. It will transmit the data over the network device.
- Physical Hardware: The Physical Hardware layer is also known as the hardware layer or the network hardware. On the same layer, the data packets will transmit or received from the network medium. The network medium will be cable or wireless.
Examples to Implement Linux Network Stack
Lets us discuss the examples of Linux network stack.
Linux Network Stack: arpwatch
In the Linux network stack, the arpwatch is a utility to observe the Ethernet traffic activity. It will also observe the changing IP and MAC Address.
Command :
Explanation :
As per the above command, we are using the network utility i.e. arpwatch. It is monitoring the activity on the “enp0s3” network interphase and if the arpwatch utility finds any changes in the interphase level. It will mark it in “/var/log/messages” file.
Output :
Linux Network Stack – ifstat
With the help of ifstat utility, we are able to get detail information of the network interfaces.
Command :
Explanation :
In the ifstat command, we are getting the detail information of the network interphase i.e. “enp0s3”.
Output :
Linux Network Stack – nload
With the help of nload utility, we are able to get detail information about the network traffic.
Command :
Explanation :
As per the above command, we are able to get the network load or traffic information on the system.
Output :
Linux Network Stack – hping
In Linux, we are having the functionality to analyse the TCP and the IP things.
Command :
Explanation :
As per the above command, we are analysing the TCP port 80 on the IP address 192.168.56.60.
Output :
Conclusion
We have seen the uncut concept of “Linux Network Stack” with the proper example, explanation, and command with different outputs. It is very important to understand how the network flow is and which different layers comes in the picture while data is flowing in between the different application levels or job level.
Recommended Articles
We hope that this EDUCBA information on “Linux Network Stack” was beneficial to you. You can view EDUCBA’s recommended articles for more information.
Network stack
You can file an issue about it and ask that it be added.
Table of Contents
- Network stack
An illicit ICMP redirect message could result in a man-in-the-middle attack.
On all interfaces
IPv6 router advertisements
An illicit router advertisement message could result in a man-in-the-middle attack.
On all interfaces
IPv6 support automatic loading
Any unnecessary network stacks — including IPv6 — should be disabled, to reduce the vulnerability to exploitation.
On all interfaces
Source-routed packets allow the source of the packet to suggest routers forward the packet along a different path than configured on the router, which can be used to bypass network security measures.
On all interfaces
Ignore bogus ICMP error responses
Ignoring bogus ICMP error responses reduces log size, although some activity would not be logged.
On all interfaces
Accepting ICMP redirects
ICMP redirect messages are used by routers to inform hosts that a more direct route exists for a particular destination. These messages modify the host’s route table and are unauthenticated.
On all interfaces
Use reverse path filtering
Enabling reverse path filtering drops packets with source addresses that should not have been able to be received on the interface they were received on.
On all interfaces
Accepting secure redirects
Accepting «secure» ICMP redirects (from those gateways listed as default gateways) has few legitimate uses. It should be disabled unless it is absolutely required.
On all interfaces
A TCP SYN flood attack can cause a denial of service by filling a system’s TCP connection table with connections in the SYN_RCVD state.
This feature is activated when a flood condition is detected, and enables the system to continue servicing valid connection requests.
On all interfaces
Log Martian packets
The presence of «martian» packets (which have impossible addresses) as well as spoofed packets, source-routed packets, and redirects could be a sign of nefarious network activity. Logging these packets enables this activity to be detected.
On all interfaces
ICMP broadcast echo requests
Responding to broadcast (ICMP) echoes facilitates network mapping and provides a vector for amplification attacks.
Ignoring ICMP echo requests (pings) sent to broadcast or multicast addresses makes the system slightly more difficult to enumerate on the network.
On all interfaces
Routing protocol daemons are typically used on routers to exchange network topology information with other routers. If this capability is used when not required, system network information may be unnecessarily transmitted across the network.
On all interfaces
Sending ICMP redirects
ICMP redirect messages are used by routers to inform hosts that a more direct route exists for a particular destination. These messages contain information from the system’s route table possibly revealing portions of the network topology.
On all interfaces
Keep sockets in FIN-WAIT-2 state
Not available from C2S/CIS standard.
The connection is being kept around so that any delayed packets can be matched to the connection and handled appropriately.
Decreasing this value can avoid some DDoS attacks or other problems (e.g. memory consuming) that arose from getting huge amounts of connections.
On all interfaces
If you set too large value to tcp_fin_timeout , the system may become out of port, file-descripter and memory. If you set too small value, the system may leak delayed packets.
Keepalive packets to keep an connection alive
Not available from C2S/CIS standard.
TCP keepalive keeps the connection open in case an error has happened. This kernel feature ensures that a TCP connection will be kept active by simulating traffic on it so it is not marked by the communication layer as inactive.
On all interfaces
Remember that keepalive support, even if configured in the kernel, is not the default behavior in Linux. Programs must request keepalive control for their sockets using the setsockopt interface.
High values can be especially harmful for expensive connections such as database connections.
The Practical Linux Hardening Guide provides a high-level overview of the hardening GNU/Linux systems. It is not an official standard or handbook but it touches and use industry standards.