Skip to content

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 network

The 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 interface

The kernel handles the lower-level work required to turn the application’s data into network traffic.

Applications Talk To Sockets

Consider:

curl https://example.com

curl 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 interface

The socket API is therefore the boundary through which ordinary applications use the kernel’s networking facilities.

This is why commands such as:

ss

can 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
protocol

For example:

192.168.1.20:49152
        │
        │ TCP
        ▼
93.184.216.34:443

The 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 -tn

or:

ss -tnp

The 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 processing

Applications 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 connection

This maps naturally to:

ss -lnt

which shows listening TCP sockets.

What Happens When A TCP Server Starts?

Suppose a Python server listens on:

0.0.0.0:8080

Conceptually, 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 -lnt

You 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:8080

The rough path is:

Client
  │
  │ TCP packets
  ▼
Network interface
  │
  ▼
Linux kernel
  │
  ▼
IP layer
  │
  ▼
TCP layer
  │
  ▼
Listening socket
  │
  ▼
Server process

The 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
   │
   ▼
Application

The 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
   │
   ▼
Network

The 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 route

Routing Is A Kernel Decision

Suppose:

ip route

shows:

default via 192.168.1.1 dev eth0
192.168.1.0/24 dev eth0 src 192.168.1.20

When an application connects to:

8.8.8.8

the application generally doesn’t choose:

eth0

itself.

The kernel performs the routing lookup.

Conceptually:

Application
    │
    │ destination = 8.8.8.8
    ▼
IP layer
    │
    ▼
Routing table
    │
    ▼
eth0 + gateway 192.168.1.1

This 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.8

This 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 hop

So when debugging:

curl https://example.com

you 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.com

the name:

example.com

must first become an IP address.

Conceptually:

curl
  │
  │ "What is example.com?"
  ▼
System name-resolution mechanism
  │
  ▼
DNS server
  │
  ▼
IP address

Then the networking path can proceed:

IP address
   ↓
socket
   ↓
TCP
   ↓
routing
   ↓
interface

DNS 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 -tn

to inspect TCP connections.

The information comes from kernel networking state.

A simplified relationship is:

Application
   │
   │ owns/uses
   ▼
Socket
   │
   │ maintained by
   ▼
Linux kernel
   │
   │ exposed through
   ▼
ss

This is why ss can show:

LISTEN
ESTAB
TIME-WAIT

and 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 = connection

but that isn’t correct.

A process can have:

many sockets

and a socket represents a communication endpoint.

For example:

web-server process
   │
   ├── listening socket :443
   ├── client socket → database
   ├── client socket → cache
   └── client socket → external API

You can inspect the process/socket relationship with:

sudo ss -lntp

or:

sudo ss -tnp

This is one reason socket inspection is so useful during troubleshooting.

Network Interfaces Are Kernel Objects Too

When you run:

ip link

you 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:

lo

with:

ip addr

The loopback interface is a special interface used for communication within the local machine.

For example:

curl http://127.0.0.1:8080

does 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 B

This is why services bound to:

127.0.0.1

can 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:8080

The socket is associated with the loopback address.

A remote machine connecting to:

192.168.1.20:8080

will not normally reach that listener.

If the server instead listens on:

0.0.0.0:8080

it 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 interface

Packets Are Not The Same As Connections

Another useful distinction is between packets and connections.

A TCP application thinks in terms of:

connection

while the network carries:

packets

A simplified TCP exchange might look like:

Client                         Server

   SYN ------------------------>
       <------------------- SYN-ACK
   ACK ------------------------>

       TCP connection established

After 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 WORLD

It does not normally need to care whether the data is transmitted as:

one packet

or:

several packets

TCP provides a reliable ordered byte stream to the application.

Conceptually:

Application
    │
    │ "send these bytes"
    ▼
TCP
    │
    ├── segment
    ├── retransmit if needed
    ├── reorder
    └── acknowledge
    │
    ▼
IP packets

The 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
    │
    ▼
Network

There 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
   ↓
Network

The 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
   ↓
Application

This 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 NetworkManager

This 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.com

A 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 response

You can inspect different parts of this process with:

getent hosts example.com
ip route get <resolved-ip>
ss -tnp
curl -v https://example.com

Each command gives you a different view.

Why This Matters For Debugging

Suppose:

curl https://example.com

fails.

You now have a mental model for where to look.

If the hostname cannot resolve:

DNS / name resolution

If the route is wrong:

IP routing

If TCP cannot connect:

socket / TCP / path / filtering

If the connection works but HTTP returns:

500

the 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
   ↓
Application

The 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
    ↓
Network

And 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 configuration

When 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.

Last updated on