Relation Between The Kernel and Networking
Linux networking is not implemented by one command or one component. When an application sends data, the request passes through several layers of the operating system before packets reach a physical or virtual network interface. Incoming packets travel through the kernel in the opposite direction until they eventually reach the application that is waiting for them.
You have already used commands that expose different parts of this system: ip shows interfaces, addresses, and routes; ss shows sockets; nc can establish TCP connections; and curl can exercise an application protocol. This lesson connects those pieces to the Linux kernel.
Where Does Networking Actually Happen?
A simplified Linux networking path looks like this:
Application
│
│ socket API
▼
+-----------------------------+
| Linux Kernel |
| |
| Socket layer |
| ↓ |
| TCP / UDP |
| ↓ |
| IP routing |
| ↓ |
| Network interface |
+-----------------------------+
│
▼
Network device
│
▼
Physical networkThe application normally does not manipulate Ethernet frames or IP packets directly.
Instead, it asks the kernel to communicate through a socket.
For example:
curl
↓
socket
↓
TCP
↓
IP
↓
network interfaceThe kernel handles the lower-level work required to turn the application’s data into network traffic.
Applications Talk To Sockets
Consider:
curl https://example.comcurl is an application running in user space.
It needs to communicate with a remote HTTP server, but it does not normally implement Ethernet, IP routing, or TCP packet transmission itself.
Instead, it uses the operating system’s socket interface.
Conceptually:
curl
│
│ "I want a TCP connection to example.com:443"
▼
Linux socket API
│
▼
TCP
│
▼
IP
│
▼
Network interfaceThe socket API is therefore the boundary through which ordinary applications use the kernel’s networking facilities.
This is why commands such as:
sscan show connections created by completely different applications.
The applications own sockets, but the kernel maintains the networking state associated with those sockets.
What Is A Socket?
A socket is an endpoint for network communication.
For a TCP connection, you can think about the connection using a combination such as:
local IP
local port
remote IP
remote port
protocolFor example:
192.168.1.20:49152
│
│ TCP
▼
93.184.216.34:443The application doesn’t need to manually construct every TCP packet.
It asks the kernel to create and use a socket, and the kernel manages the TCP connection.
This is what you have been observing with:
ss -tnor:
ss -tnpThe latter can also associate sockets with processes.
User Space And Kernel Space
A useful distinction is:
User space
────────────────────────────
curl
Python program
web server
ssh
other applications
socket API
Kernel space
────────────────────────────
socket layer
TCP / UDP
IP
routing
network interfaces
packet processingApplications run in user space.
The kernel provides the networking machinery they use.
This separation is important because an application does not normally get unrestricted access to the network hardware.
Instead, it uses controlled kernel interfaces.
The Socket API
A simplified TCP client looks conceptually like this:
socket()
↓
connect()
↓
send()
↓
receive()
↓
close()A server has a different lifecycle:
socket()
↓
bind()
↓
listen()
↓
accept()
↓
send()/receive()
↓
close()You don’t need to implement these system calls to understand Linux networking, but they explain a lot of what you see from tools such as ss.
For example:
bind()
↓
local address/port
listen()
↓
waiting for TCP connections
accept()
↓
new connectionThis maps naturally to:
ss -lntwhich shows listening TCP sockets.
What Happens When A TCP Server Starts?
Suppose a Python server listens on:
0.0.0.0:8080Conceptually, the application performs:
socket()
↓
bind(:8080)
↓
listen()The kernel now knows that a TCP socket is listening on port 8080.
You can observe that with:
ss -lntYou might see:
LISTEN 0 128 0.0.0.0:8080 0.0.0.0:*The application is waiting.
The kernel is responsible for receiving incoming packets and determining that TCP traffic destined for this listening socket belongs to that server.
What Happens When A Client Connects?
Suppose another machine connects to:
192.168.1.20:8080The rough path is:
Client
│
│ TCP packets
▼
Network interface
│
▼
Linux kernel
│
▼
IP layer
│
▼
TCP layer
│
▼
Listening socket
│
▼
Server processThe kernel processes the incoming packets.
Once the TCP connection is established, the server application can accept it and read data from its socket.
The important point is that the network interface does not directly “call” the Python process.
The kernel sits between the hardware and the application.
Incoming Packets
Let’s look more closely at the receive path.
A simplified version is:
Network
│
▼
Network interface
│
▼
Device driver
│
▼
Linux networking stack
│
├── Ethernet processing
│
├── IP processing
│
└── TCP/UDP processing
│
▼
Socket
│
▼
ApplicationThe exact implementation is considerably more sophisticated, but this model is useful for understanding the architecture.
A packet arriving at an Ethernet interface doesn’t immediately become application data.
The kernel progressively processes the packet through the relevant networking layers.
Outgoing Packets
The direction reverses when an application sends data:
Application
│
▼
Socket
│
▼
TCP / UDP
│
▼
IP
│
▼
Routing decision
│
▼
Network interface
│
▼
NetworkThe kernel determines how the data should be transmitted.
For IP traffic, routing is particularly important.
The kernel needs to answer:
Which interface and next hop should be used for this destination?
That is the information you inspected with:
ip routeRouting Is A Kernel Decision
Suppose:
ip routeshows:
default via 192.168.1.1 dev eth0
192.168.1.0/24 dev eth0 src 192.168.1.20When an application connects to:
8.8.8.8the application generally doesn’t choose:
eth0itself.
The kernel performs the routing lookup.
Conceptually:
Application
│
│ destination = 8.8.8.8
▼
IP layer
│
▼
Routing table
│
▼
eth0 + gateway 192.168.1.1This is why changing the routing table can change the behavior of applications without changing the applications themselves.
ip route get Exposes This Decision
You can ask the kernel directly:
ip route get 8.8.8.8This is a particularly useful command because it connects the abstract idea of routing with an actual packet destination.
The result can tell you things such as:
destination
source address
interface
next hopSo when debugging:
curl https://example.comyou can investigate the underlying route with:
ip route get <resolved-ip>The application doesn’t have to know the route. The kernel handles it.
Where DNS Fits
DNS is slightly different from routing and TCP.
When you run:
curl https://example.comthe name:
example.commust first become an IP address.
Conceptually:
curl
│
│ "What is example.com?"
▼
System name-resolution mechanism
│
▼
DNS server
│
▼
IP addressThen the networking path can proceed:
IP address
↓
socket
↓
TCP
↓
routing
↓
interfaceDNS is therefore not itself a layer underneath IP in the same sense as TCP.
It is a service used to obtain information needed by applications before they establish their network connection.
What Does ss Actually Show?
You have used:
ss -tnto inspect TCP connections.
The information comes from kernel networking state.
A simplified relationship is:
Application
│
│ owns/uses
▼
Socket
│
│ maintained by
▼
Linux kernel
│
│ exposed through
▼
ssThis is why ss can show:
LISTEN
ESTAB
TIME-WAITand local/remote addresses and ports.
It is observing the kernel’s socket state rather than inspecting the application source code.
Process And Socket Are Not The Same Thing
It is tempting to think:
process = connectionbut that isn’t correct.
A process can have:
many socketsand a socket represents a communication endpoint.
For example:
web-server process
│
├── listening socket :443
├── client socket → database
├── client socket → cache
└── client socket → external APIYou can inspect the process/socket relationship with:
sudo ss -lntpor:
sudo ss -tnpThis is one reason socket inspection is so useful during troubleshooting.
Network Interfaces Are Kernel Objects Too
When you run:
ip linkyou are looking at network interfaces known to the kernel.
They may represent:
Physical NIC
↓
eth0
Wireless adapter
↓
wlan0
Loopback
↓
lo
Virtual interface
↓
...The interface does not have to represent a physical Ethernet port.
Linux can have many virtual network interfaces, and the kernel treats them as part of its networking infrastructure.
The Loopback Interface
You have already encountered:
lowith:
ip addrThe loopback interface is a special interface used for communication within the local machine.
For example:
curl http://127.0.0.1:8080does not send traffic through a physical Ethernet interface.
The traffic stays within the kernel’s networking stack through the loopback interface.
Conceptually:
Application A
│
▼
socket
│
▼
Linux kernel
│
▼
loopback
│
▼
Linux kernel
│
▼
socket
│
▼
Application BThis is why services bound to:
127.0.0.1can communicate locally while remaining inaccessible through the machine’s external interfaces.
Why 127.0.0.1 And 0.0.0.0 Matter
Suppose a server listens on:
127.0.0.1:8080The socket is associated with the loopback address.
A remote machine connecting to:
192.168.1.20:8080will not normally reach that listener.
If the server instead listens on:
0.0.0.0:8080it is listening on all local IPv4 interfaces.
The kernel can then accept connections arriving through the machine’s other IPv4 addresses, subject to routing and filtering.
This is an excellent example of the relationship between:
application configuration
↓
socket
↓
kernel networking
↓
network interfacePackets Are Not The Same As Connections
Another useful distinction is between packets and connections.
A TCP application thinks in terms of:
connectionwhile the network carries:
packetsA simplified TCP exchange might look like:
Client Server
SYN ------------------------>
<------------------- SYN-ACK
ACK ------------------------>
TCP connection establishedAfter that, application data is carried in packets belonging to the connection.
The application does not normally see each Ethernet frame.
It sees a byte stream through its socket.
The kernel handles the TCP details required to turn that stream into network traffic and reconstruct it on the receiving side.
TCP Gives The Application A Byte Stream
Suppose an application sends:
HELLO WORLDIt does not normally need to care whether the data is transmitted as:
one packetor:
several packetsTCP provides a reliable ordered byte stream to the application.
Conceptually:
Application
│
│ "send these bytes"
▼
TCP
│
├── segment
├── retransmit if needed
├── reorder
└── acknowledge
│
▼
IP packetsThe network can lose or reorder packets, but TCP hides those details from the application when the connection is functioning normally.
UDP Is Different
UDP does not provide the same connection-oriented, reliable byte-stream behavior as TCP.
An application sends datagrams through a UDP socket.
Conceptually:
Application
│
▼
UDP socket
│
▼
IP
│
▼
NetworkThere is no TCP connection establishment and no TCP retransmission mechanism.
This is why applications that use UDP often need to handle reliability, ordering, or loss themselves if they require those properties.
Where The Network Interface Fits
Eventually outgoing traffic has to leave the machine.
The kernel passes the packet toward a network interface.
For a physical Ethernet interface, this eventually reaches a device driver and network hardware.
Conceptually:
Application
↓
Socket
↓
TCP/UDP
↓
IP
↓
Routing
↓
Interface
↓
Driver
↓
NIC
↓
Ethernet
↓
NetworkThe exact path inside modern Linux includes additional mechanisms such as queues, interrupt handling, and packet-processing infrastructure, but this model is enough to understand the architectural relationship.
What Happens On The Way In?
The reverse path is approximately:
Network
↓
NIC
↓
Driver
↓
Kernel networking stack
↓
IP
↓
TCP/UDP
↓
Socket
↓
ApplicationThis explains an important debugging principle.
If packets never reach the interface, the application cannot possibly receive them.
If packets reach the interface but there is no listening socket, the application still cannot receive a connection.
If the socket exists but the application isn’t reading from it, the kernel may buffer received data, but the application still isn’t processing it.
Different failures occur at different points in the path.
Connecting The Commands To The Kernel
The commands you’ve used throughout networking are really different windows into this architecture.
ip link
↓
network interfaces
ip addr
↓
IP addresses
ip route
↓
routing state
ss
↓
socket state
nc
↓
creates/tests TCP connections
curl
↓
uses sockets to perform application protocols
nmcli
↓
manages networking through NetworkManagerThis is a useful mental model because these commands are not unrelated utilities.
They observe or interact with different parts of the same system.
A Complete Example
Suppose you run:
curl https://example.comA simplified sequence is:
1. curl needs an IP address
↓
2. Name resolution obtains the address
↓
3. curl creates a socket
↓
4. curl asks the kernel to connect to port 443
↓
5. TCP establishes the connection
↓
6. Kernel performs the routing lookup
↓
7. Traffic leaves through a network interface
↓
8. Remote server responds
↓
9. Incoming packets enter the kernel
↓
10. TCP processes the packets
↓
11. Data becomes available through the socket
↓
12. curl reads the responseYou can inspect different parts of this process with:
getent hosts example.com
ip route get <resolved-ip>
ss -tnp
curl -v https://example.comEach command gives you a different view.
Why This Matters For Debugging
Suppose:
curl https://example.comfails.
You now have a mental model for where to look.
If the hostname cannot resolve:
DNS / name resolutionIf the route is wrong:
IP routingIf TCP cannot connect:
socket / TCP / path / filteringIf the connection works but HTTP returns:
500the lower-level network path worked and the problem is now in the application.
The kernel is the common piece underneath most of these operations.
The Big Picture
The most useful mental model is:
flowchart TD
A["Application<br/>curl / Python / web server"] --> B["Socket API"]
B --> C["TCP / UDP"]
C --> D["IP Layer"]
D --> E["Routing"]
E --> F["Network Interface"]
F --> G["Driver / NIC"]
G --> H["Network"]
For incoming traffic, follow the same path in reverse:
Network
↓
NIC / driver
↓
Interface
↓
IP
↓
TCP / UDP
↓
Socket
↓
ApplicationThe Linux kernel is the central piece connecting applications to the network.
What You Should Remember
You don’t need to memorize the kernel’s internal implementation to understand Linux networking.
Keep these relationships clear:
Application
↓
Socket
↓
TCP / UDP
↓
IP
↓
Routing
↓
Interface
↓
NetworkAnd remember what the tools expose:
ip → interfaces, addresses, routes
ss → sockets and connections
nc → TCP/UDP connection testing
curl → application-level HTTP interaction
nmcli → NetworkManager configurationWhen traffic comes in, the kernel moves it upward from the network interface toward the appropriate socket.
When traffic goes out, the kernel moves it downward from the socket through transport and IP processing, makes a routing decision, and sends it through the appropriate interface.
That is the relationship between the Linux kernel and networking: applications use the kernel’s networking interfaces, while the kernel handles the machinery that turns those requests into actual network communication.