
My first PC was a Windows XP machine; a lovingly red netbook.
One of the first informatics things I did with it was networking.
I wanted to game with friends, after all.
Therefore, I did a lot of tinkering with, well, networking on Windows.
Today I've been administrating and daily driving Linux machines for half my life.
And Linux networking always felt somewhat different to the Windows counterpart:
Windows does the entire networking.
Maybe you install a program doing something fancy like VPN but apart from that, the operating system Windows does all of it.
There typically isn't a choice on what vendor's tool to use for a networking job, you just use the Windows tool for it.
Now on Linux this is different because while Windows refers both to the operating system and its kernel, Linux technically does not;
Linux is only a kernel, not an entire operating system.
There are so many userspace programs doing a lot of the heavy lifting.
And here you have options, bundled together by the different distributions.
Even so, I'll be using Linux to reference an entire operating system.
Furthermore, I'll be referring to the Linux kernel simply as kernel from now on.
This naming situation leads to the following communication phenomenon:
When people say "On Linux X is done by Y," they sometimes refer to the Linux kernel doing X through Y.
Often times, however, they refer to a general paradigm many Linux distributions do, but not all.
For example, one might say "On Linux playing Windows games is done through Proton."
But, of course, the Linux kernel doesn't enforce this at all.
You can play some games through Wine or build an alternative to Proton on Linux.
That would still run on the same Linux kernel.
So: On Linux what does networking?
More precisely: I always wondered
- if the kernel implements network protocols itself? I.e., does the kernel implement UDP and TCP or does userspace do that?
- What tools tightly integrate with the kernel and represent Linux' natural way of doing networking? In other words: what behaviour doesn't differ from one distribution to the next.
- Do the userspace programs only configure the kernel or do they run in the background, actively parsing traffic.
- Does the kernel have it's own way of persisting configuration across reboots? Alternatively, do userspace programs configure the kernel again every time they start?
- May the user combine different tools; i.e., use
ipon a system running NetworkManager.

The Kernel Networking Stack: a Beast
To answer the first question:
The Kernel's networking stack is immense.
Once it is configured for the current network environment, almost all userspace applications (like Firefox or apt-get) can perform all their networking needs using the kernel.
The kernel implements Ethernet, WiFi, IP, UDP, TCP, packet filtering, NAT-ing and much, much more.
The Linux kernel is also very capable for use in dedicated networking equipment; it isn't limited to personal computers [1].
These applications only need userspace processes to reconfigure the kernel to handle changing network configurations [2].
May a userspace program skip the kernel and implement TCP and other protocols itself?
Yes, with the CAP_NET_RAW capability a process may use a SOCK_RAW AF_PACKET socket.
These permit sending raw Ethernet frames to the network interface controller [3].
Based on that one may implement their own network stack and even custom protocols.
socat and Python's scapy is a tool to play around with that, for example.
But, of course, the kernel's network implementation is what most applications use.
One thing the kernel doesn't do itself is resolving domains to IP addresses via DNS. Instead, there are userspace daemons like systemd-resolved [4] for this job. Even the kernel itself upcalls into userspace for its own domain resolution needs [5].
The Userspace Networking Stack: a Zoo
Below I've prepared figure 2 on Linux' userspace networking stack.
Don't worry, I'll go over the entire diagram in detail.
Do notice that the Linux userspace networking stack is quite well divisible into configuration and filtering.
Configuration concerns itself with, e.g., setting up links and routes.
Filtering, on the other hand, handles, e.g., firewalling and NAT-ing.

Configuration Tools
Beginning with figure 2's left half, there is a zoo of network configuration tools.
The modern iproute2 tools are one of the major players here.
They contain the ip, bridge, arp, tc and ss terminal programs, among other (all shown in figure 2).
Say you want to connect two PCs with a single Ethernet cable and, for example, use SSH on this link.
In such a setup you typically don't have a DHCP server automatically configuring this network.
(Even though, your PCs probably come with a DHCP client in the form of a userspace daemon, which I'll get to in a moment.)
A dedicated off-the-shelf router typically comes with a DHCP server, which is why connecting two PCs to a consumer router just works.
In the direct Ethernet cable connection, there is no DHCP server.
To fill this gap you could host a DHCP server yourself or use the iproute2 tools.
The iproute2 tools allow you to assign static IPs to both PCs' network links and configure IP routes; doing parts manually that DHCP would have done automatically.
Notice the word static;
The iproute2 tools don't have a daemon able to react to network changes.
All these tools do is configure the kernel's networking stack for the current network situation.
Furthermore, these tools don't have any internal state, they only configure the kernel.
Therefore, any configuration you enter using the iproute2 tools doesn't persist across reboots.
If you want to persist your configuration, you could simply write a shell script running your commands.
Then, for example, a systemd unit could run your script at boot, setting up your network to your liking [6].
Baturin's user guide [7] is a highly useful reference for iproute2.
And I do recommend playing around with these tools.
Once I ran ip route show (see figure 3) and I solved a long standing mystery:
why does docker sometimes require --net host for containers to reach the internet on my machine.
It turns out that one of the corporate WiFi networks I often work in, has a conflicting subnet with Docker's default.

But what about dynamic network changes?
What if you unplug an Ethernet cable and connect to some other network?
Then you'd have to manually run the iproute2 tools again.
Boot scripts cannot help here.
The solution for such dynamic networking environments are network managers like NetworkManager or systemd-networkd.
A network manager runs a userspace daemon, in the background dynamically changing the kernel's network configuration to the changing network environment.
Additionally, network managers provide higher-level features like network profiles [6].

While you configure systemd-networkd through configuration files [8], NetworkManager also exposes a D-Bus API, which libnm connects to [9]. libnm, in turn, is the library desktop managers like GNOME use to show and adjust the current network state. When you expand the GNOME quick settings (see figure 4) [10], for example, you're interacting with libnm [11].
These desktop managers are very closely intertwined with NetworkManager.
If you want to use some other network manager, like systemd-networkd, you need to mimic NetworkManager's D-Bus API[12].
Meanwhile on the terminal there is nmcli, which also uses libnm [13].
So taking my example from before, connecting a linux PC to an off-the-shelf router typically automatically establishes a link.
NetworkManager does that using its integrated DHCP client.
The NetworkManager daemon depends on udev to receive a notification on network device discovery [14].
Then it dynamically changes the kernel's network configuration according to the new device.
For wireless networks it might also use wpa_supplicant for authentication [6].
udev is another userspace daemon listening for device events from the kernel [15].
udev also performs systemd's predictable network interface naming (e.g., enp2s0, wlp1s0, ...).
This naming is predictable in contrast to the kernel's own naming scheme, (e.g, eth0, eth1, ...), which may change from one boot to the next [16].
Importantly, iproute2 through libnetlink, systemd-networkd through sd-netlink and NetworkManager directly interact with the kernel via Netlink [17] [18] [19]. Netlink is how most network tools communicate with the Kernel [20]. The tools typically don't store the current network configuration themselves but let the kernel store that state. That makes them interoperable. The iproute2 tools may even be used in parallel with NetworkManager. NetworkManager detects what iproute2 did and takes care as to not conflict [21].
As an aside, there is another layer on top of network managers:
netplan parses yaml files and creates NetworkManager or systemd-networkd configuration files [22].
There are other userspace daemons on Linux that do network-related work, also.
avahi-daemon, for example, implements mDNS and Apple Zeroconf to advertise and find hostnames and services being provided on the network, i.e., printers [6].
Furthermore, arpd, for example is a userspace daemon with a more complicated ARP implementation than the kernel's.
But arpd only populates the kernels ARP database with IP-MAC pairs, leaving the kernel to use them for sending out frames [23].
As a last example, there is software like FRRouting for dedicated routers running Linux.
FRRouting implements large-scale routing protocols like OSPF or RIP.
One of the problems it solves is that the kernel itself forgets routes when links go down.
FRRouting's daemons populate the kernel's routing tables dynamically.
FRRouting also uses Netlink directly [24].
Lastly, before iproute2 there was net-tools, which, among others, provided the now deprecated brctl, ifconfig and netstat terminal applications [7].
Filtering Tools
The network configuration tools all individually, directly communicate with the kernel via Netlink.
On the filtering side (figure 2's right side), however, there's a more monolithic userspace system: nftables by the netfiler.org project.
The nftables software mainly consists of a kernel component, three libraries (libmnl, libnftnl and libnftables) and the nft terminal program.
The kernel component implements a virtual machine, which executes bytecode to perform the per-packet filtering activity [25].
(Be aware that this is a different virtual machine than what eBPF runs on.)
A large part of nftables complexity resides in the libnftnl userspace library.
libnftnl compiles firewall rules into bytecode and passes that bytecode using libmnl through Netlink to the kernel, where it runs.
This explains why there is no alternative to the monolithic nftables userspace system:
The nftables' kernel component is tightly integrated with libnftnl.
Therefore, all methods of interacting with the modern Linux firewall, nftables, better use libnftnl.
There is no comparable library on the network configuration side.
The user may use nftables' terminal application nft to configure a static firewall.
This already includes NAT-ing but isn't capable of persisting rules across reboots or reacting to dynamic network changes [26].
Interestingly, nft is only a thin wrapper around libnftables, permitting programmatic management of the firewall.
For example, firewalld uses libnftables to implement higher-level filtering concepts, like network zones [27].
firewalld is a daemon, running in the background to react to network changes.
It uses NetworkManager to be notified about network device renamings [28] and then applies changes via libnftables.
UFW is another firewall manager.
Different to firewalld, UFW doesn't have a daemon but runs after every boot and when the user decides to.
This makes it unsuitable for changing network environments.
Furthermore, UFW uses the now deprecated iptables, which nftables replaced [29].
For UFW to still work on modern Linux' nftables, there is iptables-nft, which uses libnftnl to implement the old iptables (and ip6tables, arptables, ...) terminal interface [30].
Lastly, while one may combine different configuration tools, one shouldn't use, e.g., both nftables together with firewalld [31].
Conclusion
After all this, a pattern emerges:
The kernel implements the live handling of packets, implements the physical, link, network and transport protocols for a static network.
The network configuration and firewall administration is done through userspace processes.
Dynamic changes are handled by userspace daemons.
Here users have choices on how and with what tools to administrate their network.
That's where different distributions take different approaches, too.
Coming back to our leading question: On Linux, what does networking?
This depends on what networking means in ones context.
In this very article I've used networking as a malleable term.
If one refers to a static setup, where the applications only use UDP/TCP without DNS, the kernel does all the networking.
In all other cases there are userspace components implementing relevant networking parts.
References
- ^ OpenWrt. Accessed: 2026-06-25
- ^ Embedded Linux networking training. bootlin. Accessed: 2026-06-25
- ^ packet(7). Linux page. Accessed: 2026-06-25
- ^ systemd-resolved. Arch Wiki. Accessed: 2026-06-25
- ^ DNS Resolver Module. kernel.org. Accessed: 2026-06-25
- ^ 0 1 2 3 Network Configuration. Arch Wiki. Accessed: 2026-06-24
- ^ 0 1 Task-centered iproute2 user guide. Daniil Baturin. Accessed: 2026-06-25
- ^ systemd-networkd. Arch Wiki. Accessed: 2026-06-25
- ^ Introduction to libnm. NetworkManager. Accessed: 2026-06-25
- ^ Quick Settings. GNOME. Accessed: 2026-06-25
- ^ gnome-shell. Arch Packages. Accessed: 2026-06-25
- ^ nmlinkd. subz69. Accessed: 2026-06-25
- ^ Using libnm. NetworkManager. Accessed: 2026-06-25
- ^ NetworkManager. NetworkManager. Accessed: 2026-06-25
- ^ udev(7). Linux page. Accessed: 2026-06-25
- ^ Predictable Network Interface Names. systemd. Accessed: 2026-06-25
- ^ libnetlink.c. Git. Accessed: 2026-06-25
- ^ nm-netlink-monitor.c. NetworkManager Git. Accessed: 2026-06-25
- ^ sd-netlink.h. Git. Accessed: 2026-06-25
- ^ Netlink. Linux Kernel Internals. Accessed: 2026-06-25
- ^ Configuring IP Networking with ip Commands. Red Hat. Accessed: 2026-06-25
- ^ YAML configuration. Netplan documentation. Accessed: 2026-06-25
- ^ arpd - ARP daemon. Linux Wiki. Accessed: 2026-06-25
- ^ Kernel Interface. FRRouting. Accessed: 2026-06-25
- ^ nftables. netfilter.org. Accessed: 2026-06-25
- ^ DeveloperDocs/nftables internals. Wiki. Accessed: 2026-06-25
- ^ firewalld. Accessed: 2026-06-25
- ^ Architecture. firewalld. Accessed: 2026-06-25
- ^ netfilter.org. Accessed: 2026-06-25
- ^ UFW. Arch Wiki. Accessed: 2026-06-25
- ^ Getting started with nftables. Red Hat. Accessed: 2026-06-24
Similar Articles

Real-Time Application Development on Linux with PREEMPT RT
29th September, 2025 34min
While Linux is optimized for throughput and efficiency, real-time applications require bounded worst case latencies. However, with the merging of PREEMPT RT, mainline Linux converts to a real-time operating system (RTOS). Through presenting the application developer’s perspective and the changes PREEMPT RT introduces to the kernel, we review Linux’ real-time capabilities. Additionally, we investigate dynamic worst case execution time (WCET) analysis using a StarFive VisionFive 2 as a case study. Finally, we compare Linux to other RTOSes and argue that the lack of static WCET analysis is Linux’ main drawback for real-time applications.

Why I love Open-Source
11th October, 2025 23min
We all live in a world of immensely complex technology. The concept of Open-Source might seem radical at first but it's indispensable in our world. Regardless if you are a user, developer or simply interested in a healthy society, you benefit from Open-Source and we should fight for every bit of it. Open-Source is a quality mark, a form of democracy and ownership, capitalism at its best and thus the response to this world, a world in which software exists. This article gets to that conclusion without requiring any prior technical knowledge.

Real-Time Linux on RISC-V
27th June, 2025 8min
Setting up Linux v6.12 on a StarFive VisionFive 2 with PREEMPT_RT. Also: How to setup your Linux laptop as a simple NAT router.

LunarVim in Distrobox
25th October, 2022 3min
You're missing that one program that isn't available in your Linux distro? With Distrobox, the 'Linux Subsystem for Linux,' you can install it anyways. This article explains how to do that with the example of installing LunarVim on Red Hat.
