Skip to content
DevOps AI ToolKit
Newsletter

Kali Linux Networking for DevOps · Part 6 of 15

TCP vs UDP for DevOps Engineers

Difficulty: Beginner ~17 min Part 6/15
Prerequisites: Networking fundamentalsIP addresses & CIDR
Series progress6 / 15
Series curriculum (15 lessons)

Every service you operate speaks one of two transport protocols underneath the application layer: TCP or UDP. When someone hands you a “connection refused,” a hung request, or a dig that times out, the fastest path to a diagnosis is knowing which protocol the service uses and how that protocol fails. TCP failures and UDP failures look completely different on the wire, and once you can recognize the difference you can often name the root cause before you have finished reading the output.

This lesson builds the mental model you will lean on for the rest of the series — especially in the tcpdump packet analysis lesson, where you will read these exact handshakes out of a real capture. You do not need prior networking knowledge beyond the networking fundamentals lesson and a sense of what an IP address and CIDR block are. Everything else we define as we go.

What You Will Learn

  • What “connection-oriented” (TCP) and “connectionless” (UDP) actually mean, and the trade-offs each makes.
  • How TCP guarantees delivery using sequence numbers, acknowledgements, and retransmissions — and what that costs.
  • The TCP 3-way handshake (SYN → SYN-ACK → ACK) drawn out step by step.
  • The three failure signatures every DevOps engineer should recognize on sight: SYN-ACK (success), RST (refused), and silence (dropped/timeout).
  • Which common services use TCP versus UDP, and how that changes the command you reach for to test them.

Connection-Oriented vs Connectionless

The single biggest difference between the two protocols is whether they establish a connection before sending data.

TCP (Transmission Control Protocol) is connection-oriented. Before any application data flows, the two ends perform a handshake to agree that they can both send and receive. Once established, TCP behaves like a reliable, ordered pipe: bytes arrive in the order you sent them, nothing is silently lost, and if a packet goes missing it is resent. You pay for that reliability with extra round trips and per-connection state on both hosts.

UDP (User Datagram Protocol) is connectionless. There is no handshake and no connection state — a host simply sends a datagram toward an address and port and hopes it arrives. There are no acknowledgements, no ordering, and no automatic retransmission. If a datagram is lost, UDP neither knows nor cares; recovering (or not) is left to the application. In exchange, UDP has far lower overhead and latency, which is exactly why it is used where speed matters more than guaranteed delivery.

A useful analogy: TCP is a phone call — you both say “hello,” confirm you can hear each other, and repeat anything the line garbles. UDP is a postcard — you drop it in the mailbox and it usually arrives, but nobody confirms receipt and you would never know if it got lost.

PropertyTCPUDP
ConnectionHandshake first (connection-oriented)None (connectionless)
DeliveryGuaranteed, retransmits lost dataBest-effort, no guarantee
OrderingIn-order, reassembledNo ordering
OverheadHigher (state + acks + handshake)Lower (fire-and-forget)
Fails asRST or timeout on connectSilence or ICMP port-unreachable
Typical useSSH, HTTP, databasesDNS, NTP, telemetry

How TCP Guarantees Delivery

TCP’s reliability is not magic — it is built from three cooperating mechanisms. Understanding them tells you why a TCP connection behaves the way it does when the network degrades.

  • Sequence numbers. Every byte TCP sends is numbered. The receiver uses these numbers to reassemble the stream in the correct order, even if packets arrive out of order, and to detect duplicates.
  • Acknowledgements (ACKs). The receiver tells the sender “I have everything up to byte N” by sending back an acknowledgement number. This is how the sender knows data actually arrived, not just that it left.
  • Retransmissions. If the sender does not receive an ACK within a timeout, it assumes the data was lost and sends it again. This is the mechanism that turns an unreliable network into a reliable stream — and also the mechanism behind the “everything is slow” symptom when a link is quietly dropping packets, because TCP keeps waiting and resending.

The practical takeaway: on a lossy network, TCP does not fail so much as slow down — latency climbs and throughput collapses as retransmissions pile up, but the data still gets through. UDP on the same network simply loses datagrams, and it is the application’s job to notice.

🏭 Why This Matters in Production — This is why a database query over TCP might crawl for 30 seconds instead of erroring outright on a flaky link, while a UDP-based metrics agent on the same host just silently drops data points with no error in the logs. Knowing the transport tells you whether to expect a slow, retrying failure or a silent, gap-in-the-data failure.

Common TCP and UDP Services

Most of the services you run every day are TCP, because they need reliable, ordered delivery. A few important ones are UDP, because low latency matters more than guaranteed delivery. Memorizing a handful of these port numbers pays off constantly.

Common TCP services and their default ports:

SSH         22    (remote shell / admin)
HTTP        80    (web)
HTTPS       443   (web + TLS)
PostgreSQL  5432  (database)

Common UDP services and their default ports:

DNS         53    (name resolution)
NTP         123   (time sync)

A subtlety worth knowing: DNS is mostly UDP on port 53 for ordinary queries (small, fast, one datagram each way), but it falls back to TCP on the same port 53 for large responses. Most other everyday services are firmly one or the other.

🛠️ DevOps Perspective — Knowing a service is TCP versus UDP tells you exactly how to test it and how it fails. For a TCP service, nc -vz host port opens a real connection and prints success or “refused” — because there is a handshake to complete. For a UDP service there is no handshake to observe, so you must speak the protocol: use dig @server name for DNS rather than trying to “connect,” because a bare nc -u probe can look successful even when nothing is listening. We cover the exact commands in the testing connectivity lesson.

The TCP 3-Way Handshake

Before a single byte of application data crosses a TCP connection, the two ends exchange three packets to synchronize. This is the 3-way handshake, and it is the most important thing to recognize when you read a capture.

Client                         Server
SYN -------------------------->
    <--------------------- SYN-ACK
ACK -------------------------->
Connection Established

Reading it step by step:

  1. SYN — the client sends a packet with the SYN (“synchronize”) flag set, proposing a connection and its starting sequence number. This is the client saying “I want to talk, and I’ll start numbering my bytes here.”
  2. SYN-ACK — the server replies with both SYN and ACK flags set. It acknowledges the client’s SYN and sends its own SYN with its own starting sequence number. This is the server saying “I heard you, I agree, and here is my side.”
  3. ACK — the client acknowledges the server’s SYN. Now both ends have confirmed they can send and receive. The connection is established and application data (your HTTP request, your SQL query) can flow.

Those three packets — SYN, SYN-ACK, ACK — are the fingerprint of a healthy TCP connection. When you watch traffic and see all three, you know the transport layer is working end to end and any problem lies higher up (TLS, the application, or the data). When you don’t see all three, the way the handshake breaks tells you precisely what went wrong.

Failure Signatures: SYN-ACK vs RST vs Silence

Here is the payoff, and the single most useful pattern to recognize in a packet capture. A TCP connection attempt has exactly three possible outcomes, and each one points at a different root cause. You do not need to decode every field — you only need to see how the server (or the network) answers the client’s opening SYN.

1. SYN answered by SYN-ACK → success. The handshake completes as shown above. The port is open and a service is listening. Any remaining problem is above TCP.

2. Repeated SYN with no reply → timeout (dropped).

Client                         Server
SYN -------------------------->   (no answer)
SYN -------------------------->   (no answer)
SYN -------------------------->   (no answer)
... connection times out

The client keeps retransmitting its SYN (remember: TCP retransmits when it gets no acknowledgement) and nothing comes back. The connection eventually times out. Silence like this means a packet is being dropped somewhere in the path — most often a firewall / security group / network ACL / network policy configured to DROP rather than reject, or the destination host is down or unreachable. The defining clue is that the client is talking to a void: no answer of any kind.

3. SYN answered by RST → connection refused.

Client                         Server
SYN -------------------------->
    <--------------------------- RST
Connection refused

The server replies with the RST (“reset”) flag set. An RST is an active, immediate “no” — it means the SYN reached a live host, but nothing is listening on that port (or a firewall is configured to reject rather than drop). You get “connection refused” instantly, not after a timeout.

That contrast is the whole game:

SYN → SYN-ACK   = open, listening      (healthy)
SYN → RST       = reached host,
                  nothing listening     (refused)
SYN → (silence) = packet dropped
                  in the path           (timeout)

Why this distinction is the most useful thing in a capture

When a connection fails, the very first question is: did my packet reach a live host at all? The answer to that question splits the entire problem space in half, and the SYN response answers it for free:

  • An RST proves the packet reached a running host — the machine is up, it received your SYN, and it actively rejected it. The problem is on that host: the service isn’t running, it’s bound to the wrong address, or a local firewall rejects the port. You can stop looking at the network path.
  • Silence proves the packet was dropped before eliciting any response. The problem is in the path — a firewall dropping packets, a wrong route, a security group, or a host that is down. You can stop poking at the application; it may be perfectly healthy and simply unreachable.

One tells you to investigate the destination host; the other tells you to investigate the network between you and it. That is why “SYN-ACK vs RST vs silence” is worth more than any other single observation in a capture: three bytes of flag state route you to the correct half of the troubleshooting tree in seconds. Map it onto the failure vocabulary from the fundamentals lesson — RST is connection refused, silence is connection timeout — and you can name the class of fault before you have typed a second command.

🔎 Troubleshooting Tip — When curl hangs then times out, expect silence on the wire (dropped — look at firewalls, security groups, routes, or a downed host). When curl fails instantly with “connection refused,” expect a RST (the host is up but nothing is listening on that port — check that the service is running and bound to the right address with ss -tulpn). The speed of the failure is itself a clue: instant = RST, slow = drop.

🔐 Security Note — Reading handshakes means capturing traffic, and later lessons use tools like tcpdump, Wireshark, and Nmap. Only scan, inspect, or test systems you own or have explicit permission to assess. Use a controlled lab or reader-owned infrastructure. This is authorized infrastructure validation and defensive troubleshooting, not hacking — frame it that way and keep your captures to networks you are responsible for.

Try It Yourself

You can watch all three outcomes on your own machine, no external targets required.

# Start a real TCP listener on port 8080 (leave this running)
python3 -m http.server 8080

In a second terminal, test three ports and compare how each fails:

# 1. Open port — SYN-ACK, handshake completes
nc -vz 127.0.0.1 8080

# 2. Closed port — instant RST, "connection refused"
nc -vz 127.0.0.1 9999

# 3. Dropped — a non-routable address times out (Ctrl-C to stop)
nc -vz -w 5 10.255.255.1 80

Read the results as signatures: port 8080 succeeds because a listener completed the handshake; port 9999 is refused instantly because the host is up but nothing is bound there (a RST); and 10.255.255.1 hangs until the timeout because the SYNs are going into a void (silence/drop). You have now produced the exact three outcomes you will learn to spot in a capture.

🧪 Try It — Now do the same for UDP and feel the difference. Run dig @1.1.1.1 example.com and you get an answer because you spoke the DNS protocol over UDP/53. Then try nc -vzu 127.0.0.1 9999 against a closed UDP port — notice how ambiguous the result is compared to TCP’s crisp “refused.” That ambiguity is the lesson: UDP has no handshake to observe, so you test UDP services by exercising the application (dig, ntpdate -q), not by “connecting.”

Common Problems

  • “Connection refused” the instant you connect. The host is up and answered with a RST — nothing is listening on that port, or the service is bound to 127.0.0.1 only. Confirm with ss -tulpn on the destination; this is covered in ports and listening services.
  • The connection hangs, then times out. The SYN is being dropped in the path — a firewall/security group set to DROP, a wrong route, or a host that is down. Nothing on the destination host will explain it because your packet never got a reply.
  • A UDP “test” looks successful but the service is broken. Because UDP has no handshake, a naive nc -u probe can report success against a port with nothing listening. Always test UDP services by speaking their protocol (dig for DNS, an NTP query for time) rather than trusting a bare port probe.
  • TCP “works” but everything is painfully slow. Not a refused or dropped connection — this is retransmission from packet loss. The handshake completes, but data-carrying packets are being lost and resent. Look for a lossy link or an MTU mismatch, not a firewall.

What You Learned

  • TCP is connection-oriented and reliable — it performs a handshake, numbers every byte with sequence numbers, confirms delivery with acknowledgements, and retransmits anything that goes unacknowledged. That reliability costs round trips and per-connection state.
  • UDP is connectionless and best-effort — no handshake, no acknowledgements, no ordering, no retransmission. Lower overhead and latency, but the application must handle any loss itself.
  • The TCP 3-way handshake is SYN → SYN-ACK → ACK, and seeing all three is the fingerprint of a healthy connection where any remaining fault lies above the transport layer.
  • The three failure signatures are the highest-value pattern in a capture: SYN-ACK = open/listening, RST = reached the host but nothing listening (connection refused, instant), and silence/repeated SYN = packet dropped in the path (connection timeout, slow). RST sends you to investigate the host; silence sends you to investigate the network path.
  • Transport dictates how you test and how things fail — use nc -vz for TCP (there is a handshake to complete) and protocol-aware tools like dig for UDP, and expect TCP to slow down under loss while UDP silently drops data.

Next up: Part 7 — Ports and Listening Services, where you will use ss -tulpn to prove exactly which services are listening and on which addresses — turning “SYN got a RST” into “PostgreSQL is bound to loopback only,” a specific, fixable finding.

Affiliate Disclosure: Some links on this page are affiliate links. If you purchase through one of these links, DevOps AI Toolkit may earn a commission at no additional cost to you. See our affiliate disclosure.

← Back to Kali Linux Networking for DevOps Back to Kali Linux

Related on DevOps AI Toolkit