Networking Basics: OSI & TCP/IP
Almost every attack and every defence travels over a network. A port scan, a phishing email, a stolen session cookie and a firewall rule all make sense only when you know how data moves from one computer to another.
In this lesson you will learn the two models people use to describe networks (OSI and TCP/IP), how data is wrapped in headers as it travels, how TCP opens a connection, and where common attacks fit at each layer. You will also decode a real IPv4 header with Python.
The OSI model
The OSI model splits networking into seven layers. Each layer does one job and talks only to the layers directly above and below it. Real networks do not follow OSI exactly, but security people use its layer numbers all the time ("a layer 7 attack", "a layer 2 switch").
| Layer | Name | Job | Examples | Security example |
|---|---|---|---|---|
| 7 | Application | Services that programs use | HTTP, DNS, SMTP, SSH | SQL injection, phishing |
| 6 | Presentation | Data format, encoding, encryption | TLS (often placed here), character sets | Weak encryption settings |
| 5 | Session | Keeping conversations open | Session handling, RPC | Session hijacking |
| 4 | Transport | Delivery between programs, using ports | TCP, UDP | SYN flood, port scanning |
| 3 | Network | Addressing and routing between networks | IP, ICMP | IP spoofing |
| 2 | Data link | Delivery on the local network | Ethernet, Wi-Fi, MAC addresses, ARP | ARP spoofing, MAC flooding |
| 1 | Physical | Signals on cables and radio | Copper, fibre, radio | Cable tapping, jamming |
A memory trick from layer 1 upwards: "Please Do Not Throw Samosa Packets Away".
The TCP/IP model
The internet actually runs on the TCP/IP model, which has four layers. It merges OSI layers 5 to 7 into one application layer and layers 1 and 2 into one link layer.
| TCP/IP layer | Matches OSI layers | Unit of data |
|---|---|---|
| Application | 5, 6, 7 | Data or message |
| Transport | 4 | Segment (TCP) or datagram (UDP) |
| Internet | 3 | Packet |
| Link | 1, 2 | Frame |
Encapsulation: headers inside headers
When Ananya's browser sends a request, each layer adds its own header (control information) in front of the data. This is called encapsulation. The receiving computer removes the headers in reverse order. This program shows the idea with text labels:
data = "GET / HTTP/1.1"
segment = "[TCP 51544->3000]" + data
packet = "[IP 192.168.56.102->192.168.56.101]" + segment
frame = "[ETH aa:aa->bb:bb]" + packet + "[FCS]"
for name, unit in [("Application", data), ("Transport", segment), ("Internet", packet), ("Link", frame)]:
print(f"{name:<12} {unit}")Application GET / HTTP/1.1 Transport [TCP 51544->3000]GET / HTTP/1.1 Internet [IP 192.168.56.102->192.168.56.101][TCP 51544->3000]GET / HTTP/1.1 Link [ETH aa:aa->bb:bb][IP 192.168.56.102->192.168.56.101][TCP 51544->3000]GET / HTTP/1.1[FCS]
The TCP header carries the ports (which program), the IP header carries the IP addresses (which computer), and the Ethernet header carries the MAC addresses (which network card on this local network). FCS is a checksum at the end of the frame that detects damaged frames.
Reading a real IPv4 header
Real headers are bytes, not text. Security tools such as Wireshark and intrusion detection systems decode them field by field. Python's struct module can do the same with a 20-byte IPv4 header captured in a lab:
import ipaddress
import struct
header = bytes.fromhex("4500003c1c4640004006b1e6c0a83866c0a83865")
ver_ihl, tos, length, ident, frag, ttl, proto, checksum, src, dst = struct.unpack("!BBHHHBBH4s4s", header)
protocols = {1: "ICMP", 6: "TCP", 17: "UDP"}
print("Version: ", ver_ihl >> 4)
print("Header bytes:", (ver_ihl & 0x0F) * 4)
print("Total length:", length)
print("TTL: ", ttl)
print("Protocol: ", protocols.get(proto, proto))
print("Source: ", ipaddress.ip_address(src))
print("Destination: ", ipaddress.ip_address(dst))Version: 4 Header bytes: 20 Total length: 60 TTL: 64 Protocol: TCP Source: 192.168.56.102 Destination: 192.168.56.101
! in the format string means network byte order (big-endian), B is one byte, H is two bytes and 4s is four raw bytes. The TTL (time to live) drops by one at each router, which stops packets looping forever. Different operating systems start with different TTL values, which is one small clue tools use to guess the operating system.
TCP: the three-way handshake
TCP (Transmission Control Protocol) is reliable: it numbers every byte, resends lost data and delivers it in order. Before sending data, the two sides open a connection with a three-way handshake:
steps = [
("client", "server", "SYN", "I want to connect. My sequence number starts at 100."),
("server", "client", "SYN-ACK", "Agreed. I got 100. Mine starts at 300."),
("client", "server", "ACK", "I got 300. The connection is open."),
]
for sender, receiver, flags, meaning in steps:
print(f"{sender:>6} -> {receiver:<6} {flags:<8} {meaning}")client -> server SYN I want to connect. My sequence number starts at 100. server -> client SYN-ACK Agreed. I got 100. Mine starts at 300. client -> server ACK I got 300. The connection is open.
What the server sends back to a SYN tells a scanner a lot, which you will use in Network Scanning with Nmap:
- SYN-ACK means a program is listening: the port is open.
- RST (reset) means nothing is listening: the port is closed.
- No reply at all usually means a firewall dropped the packet: the port is filtered.
A SYN flood is a denial-of-service attack that sends huge numbers of SYNs and never completes the handshake, filling the server's table of half-open connections. Defences include SYN cookies and upstream filtering.
UDP, MAC addresses and ARP
UDP (User Datagram Protocol) has no handshake and no guarantee of delivery. It is fast and simple, which suits DNS lookups, video calls and online games. Because there is no handshake, UDP scanning is slower and less certain than TCP scanning.
On a local network, computers deliver frames using MAC addresses, 48-bit hardware addresses such as 08:00:27:8e:1c:2d. ARP (Address Resolution Protocol) answers the question "which MAC address has IP 192.168.56.1?". ARP has no authentication, so a machine on the same network can send false answers and place itself between two victims. This is ARP spoofing, a classic man-in-the-middle attack. Defences include switches with dynamic ARP inspection, encrypted protocols such as HTTPS and SSH (so intercepted traffic is unreadable), and keeping untrusted devices off sensitive networks.
To watch these protocols for yourself, capture traffic on your lab network only. On Kali:
sudo tcpdump -i eth1 -n host 192.168.56.101Wireshark, also on Kali, shows the same capture with every header decoded. Capturing other people's traffic on a shared network without permission is illegal interception.
Common mistakes
- Mixing up layers. IP addresses are layer 3, ports are layer 4, MAC addresses are layer 2. Getting this right makes firewall rules and scan results much easier to understand.
- Thinking "filtered" means "closed". Filtered means you could not tell; a service may still be running behind the firewall.
- Assuming the local network is safe. ARP and many older protocols trust everyone on the same network, which is why encryption matters even inside an office.
Key points
- The OSI model has seven layers; the TCP/IP model used on the internet has four.
- Encapsulation wraps data in a transport header (ports), an IP header (addresses) and a link header (MAC addresses).
- TCP opens connections with SYN, SYN-ACK, ACK; replies to a SYN reveal open, closed or filtered ports.
- UDP has no handshake, so it is fast but harder to scan reliably.
- ARP has no authentication, which makes ARP spoofing possible on local networks.
- Only capture traffic on networks you own or are authorised to monitor.
Exercise
Change the header in the IPv4 example so the protocol is UDP (17) and the TTL is 128, then run it. Hint: in the hex string, TTL is the 9th byte (40) and protocol is the 10th byte (06). Write a function layer_of(term) that returns the OSI layer number for "IP address", "port", "MAC address" and "HTTP".
Show solution
header = bytes.fromhex("4500003c1c4640008011b1e6c0a83866c0a83865")
print(header[8], header[9]) # TTL and protocol bytes
def layer_of(term):
layers = {"IP address": 3, "port": 4, "MAC address": 2, "HTTP": 7}
return layers.get(term, "unknown")
for t in ["IP address", "port", "MAC address", "HTTP"]:
print(t, "-> layer", layer_of(t))80 in hex is 128 and 11 in hex is 17, so the decoder now reports TTL 128 and protocol UDP. The checksum is now wrong, but the decoder does not verify it.
Quick Quiz
1. Which OSI layer uses port numbers?
Ports identify programs, which is the transport layer's job (TCP and UDP).
2. A port scanner sends a SYN and receives an RST. What does this mean?
RST means the host is reachable but no program is listening on that port.
3. Why is ARP spoofing possible?
Any device on the local network can send an ARP reply, and hosts accept it without checking.
4. Which protocol has no handshake?
UDP sends datagrams without setting up a connection first.
Learn Cyber Security with a mentor
Free lessons get you started. Our Ethical Hacking & Cyber Security training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
