GitHub avatar

Fox's Blog

How Machines Talk to Each Other: An Overview from TCP to mTLS

Why TCP, UDP, TLS, mTLS, HTTP, and WebSocket are not competing alternatives but stacked layers; a hierarchical overview of machine-to-machine communication, from raw transport to mutual authentication.

The problem: too many acronyms, not enough hierarchy

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; most resources that cover them present them as a flat list of interchangeable options, "to choose based on the use case." In reality they are not on the same level: some are transport protocols, others are security layers that wrap around transport, and still others are application protocols built on top of the first two. Understanding the hierarchy means understanding why you never "choose" between TCP and TLS: you choose TCP, then you decide whether to put TLS on top.

This article rebuilds this hierarchy layer by layer, from raw transport to mutual authentication, with for each level: what it guarantees, what it does not guarantee, and when to settle for it.

Level 1: transport (TCP vs UDP)

Everything starts here. TCP and UDP are the two main protocols of the Transport (Layer 4) layer of the OSI model. Their role is identical: to transport a data stream between two applications running on different machines. Yet their approach is radically different.

It is important to understand that IP (Internet Protocol), located at the network layer (Layer 3), only routes packets from one host to another. It does not guarantee their delivery, their order, or even their uniqueness. Routers simply make independent routing decisions for each packet.

It is precisely this lack of guarantees that TCP compensates for, while UDP deliberately chooses to add nothing in order to remain extremely lightweight.

TCP: reliability above all

TCP (Transmission Control Protocol) is a connection-oriented protocol. Before exchanging a single byte of data, the two machines must establish a logical connection.

This connection is created through the famous Three-Way Handshake:


Client                           Server
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Connection established

Each step has a precise purpose:

  • SYN: the client announces it wishes to open a connection and provides an Initial Sequence Number (ISN).

  • SYN-ACK: the server accepts the connection, acknowledges the SYN, and in turn provides its own sequence number.

  • ACK: the client confirms receipt of the server's information.

From this point on, both machines know the state of the connection and can begin exchanging data.

Sequence numbers

TCP does not view data as a succession of packets, but as a continuous byte stream.

Each byte sent has a sequence number.

Example:

Message:

Bonjour

B = byte 0
o = byte 1
n = byte 2
...

If a segment containing bytes 1000 through 1499 is lost during transport, the receiver can detect exactly what is missing.

The sender retransmits only that portion.

This granularity is one of the reasons for TCP's robustness.

Acknowledgments (ACK)

After receiving data, the recipient sends an ACK (Acknowledgment).

Contrary to what is often imagined, an ACK does not mean:

"I received this packet"

Rather it means:

"I have received all bytes up to number X."

For example:

Client sends:

0 → 999

Server responds:

ACK = 1000

This means:

"Everything before byte 1000 has arrived safely."

This mechanism allows acknowledging multiple segments at once (cumulative acknowledgments), reducing the number of control packets.

Retransmissions

If an ACK never arrives, TCP assumes the segment is lost.

It automatically retransmits it.

The Retransmission Timeout (RTO) is not fixed.

TCP continuously measures the round-trip time (RTT) using received ACKs and dynamically calculates the RTO to avoid unnecessary retransmissions.

Modern implementations also use mechanisms like Fast Retransmit: when a sender receives several duplicate ACKs (typically three), it infers that an intermediate segment was lost and resends it immediately, without waiting for the timer to expire.

Packet reordering

The Internet absolutely does not guarantee that two packets follow the same path.

Example:

Packet 1
Paris
 ↓
London
 ↓
New York

Packet 2
Paris
 ↓
Frankfurt
 ↓
Chicago
 ↓
New York

The second packet may arrive before the first.

TCP then temporarily stores out-of-order segments in a reassembly buffer, then reassembles them before delivering them to the application.

To the application, everything appears to arrive perfectly in order.

Flow control

A connection does not depend solely on the network.

The receiver also has limited memory capacity.

If it receives data faster than it can process, its buffers will eventually saturate.

TCP solves this problem using a Sliding Window.

The receiver indicates in each ACK:

Window = 32768 bytes

This means:

"You can send me up to 32 KB more."

If this window drops to zero:

Window = 0

The sender temporarily suspends transmissions until the receiver announces a new available window.

This mechanism is Flow Control and prevents a fast host from overwhelming a slower one.

Congestion control

Even if the receiver can absorb the data, the network itself can become saturated.

Routers have limited queues.

When they overflow, packets are dropped.

TCP interprets losses as a sign of congestion and automatically adjusts its rate using a Congestion Window (cwnd).

Modern algorithms (such as Reno, CUBIC, or BBR, depending on operating systems) adjust this window to strike a balance between maximum throughput and network stability.

Early TCP versions mainly used two mechanisms:

  • Slow Start: exponential increase in throughput until congestion is detected.

  • Congestion Avoidance: thereafter more cautious growth, typically linear.

This ongoing adaptation is one of the reasons TCP remains performant despite variations in network quality.

Connection termination

Unlike UDP, a TCP connection also has a proper teardown.

Each end independently closes its stream using the FIN flag.

A full close typically requires four exchanges:

FIN
ACK
FIN
ACK

This procedure ensures that all in-transit data has been delivered before the connection is destroyed.

UDP: maximum simplicity

UDP (User Datagram Protocol) takes the opposite philosophy.

It is connectionless.

There is:

  • no handshake;

  • no sequence numbers;

  • no acknowledgments;

  • no retransmissions;

  • no flow control;

  • no congestion control.

Each message is simply encapsulated in an independent datagram, transmitted to the network, then forgotten by the sender.

Application → UDP Datagram → IP → Internet

The protocol maintains no state between two sends.

Each datagram is completely independent of the previous ones.

Data integrity

Although UDP does not guarantee delivery or order, it does protect data integrity with a checksum.

Upon reception, the checksum is recalculated.

  • If the values match, the datagram is accepted.

  • Otherwise, it is immediately discarded.

UDP therefore detects corrupted data, but never attempts to recover it.

Why is UDP so fast?

The UDP header is only 8 bytes, compared to a minimum of 20 bytes for TCP (excluding options like timestamps, SACK, or Window Scaling).

Since no connection is maintained, the operating system does not have to track the state of each exchange, which also reduces memory consumption and processing cost.

The application receives data almost as soon as it arrives, without waiting for potential retransmissions.

When losing data is preferable

The fundamental idea is simple:

Old information can be worth less than lost information.

Take a VoIP conversation.

Each packet carries about 20 ms of voice.

If a packet is lost, retransmitting it would often take longer than those 20 ms.

By the time it finally arrived, the conversation would have already moved on.

Most applications therefore prefer to mask the loss (interpolation, silence, error correction) rather than wait for retransmission.

The same reasoning applies to:

  • real-time multiplayer games;

  • video streaming;

  • telemetry streams;

  • IoT sensors;

  • GPS position data.

A recent value is almost always more useful than an old, perfectly reliable one.

Level 2: encryption, TLS

TLS (Transport Layer Security, successor to SSL) does not replace TCP, it is added on top. Concretely, TLS establishes a normal TCP connection, then negotiates an encrypted session inside it: certificate exchange, agreement on a cipher algorithm, derivation of session keys. Everything that travels afterwards is encrypted and authenticated.

Three distinct guarantees, often confused:

  • Confidentiality: no one other than the two parties can read the content.

  • Integrity: any alteration of data in transit is detected.

  • Authentication: but in classic TLS, one-way only: the client verifies that the server is who it claims to be (via its certificate, signed by a trusted authority), but the server does not verify anything about the client's identity. This is exactly the model of HTTPS when you visit a website: the browser authenticates the site, the site does not authenticate you (user authentication goes through a separate mechanism, session cookie, token).

TLS 1.3 (the current recommended version) reduced the handshake to a single round-trip in the common case, compared to two for TLS 1.2, which significantly reduces connection latency.

Level 2bis: mTLS -- authentication becomes mutual

mTLS (mutual TLS) is TLS with an additional constraint: the server also requires a certificate from the client, and verifies it. Both parties prove their identity via a certificate signed by a common trusted authority.

This is the natural mechanism for service-to-service communication in a distributed architecture: where classic HTTPS suffices for a browser to talk to a public server, mTLS answers a different question: how does an internal service know it is really talking to another authorized internal service, and not to an attacker who landed on the network?

Client                                          Server
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + server certificate ──────────│
  │──── verifies server certificate ──────────────│
  │──── sends ITS OWN client certificate ────────▶│
  │◀─── verifies client certificate ──────────────│
  │──── session keys derived, encrypted channel ──▶│

The counterpart of mTLS is operational: you need an internal certificate authority (CA), a mechanism for distributing certificates to each service, and a rotation/revocation strategy. In a single-machine environment with few services, this is sometimes more complexity than benefit -- mTLS becomes necessary when inter-service traffic crosses a network you do not fully control (multiple hosts, multi-tenant cloud), or as soon as you want a zero-trust policy, where no service is implicitly trustworthy simply because it is "inside" the network.

Level 3: application protocols on top of TCP+TLS

Once transport and encryption are in place, the remaining question is how to structure the exchanges. This is the role of application protocols.

HTTP / HTTPS

HTTP is a request-response protocol: the client opens a connection (or reuses one, with keep-alive), sends a request, waits for a response, then the connection can be closed or reused. HTTPS is simply HTTP over TLS -- the S does not change the semantics of the protocol, only the fact that the transport is encrypted.

The request-response model has a structural limitation: the server can never speak first. It can only respond to what the client asks. For frequent polling (checking "is there anything new?" every second), it works but wastes resources -- each request recreates protocol overhead for, most of the time, nothing new to announce.

WebSocket (WS / WSS)

WebSocket addresses precisely this limitation. The connection starts as a regular HTTP request (with an Upgrade: websocket header), but once the handshake is accepted, the underlying TCP connection is no longer an HTTP request-response channel -- it becomes a bidirectional full-duplex channel where client and server can send messages at any time, without having to re-issue a request-response cycle for each exchange.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS is simply WebSocket over TLS, exactly as HTTPS is HTTP over TLS. It is the protocol of choice for anything that requires real-time server push -- chat, notifications, trading feeds, game events -- without wanting to manage a binary protocol over raw TCP yourself.

gRPC

Less known outside the microservices world but central in service-to-service communication: gRPC builds on HTTP/2 (thus TCP + optional TLS), serializes messages in Protocol Buffers (binary, typed, compact -- unlike the text JSON of most REST APIs), and natively supports bidirectional streaming thanks to HTTP/2 multiplexing (multiple logical streams over a single TCP connection, without the head-of-line blocking that multiple sequential HTTP/1.1 requests would have).

QUIC / HTTP3

QUIC changes the game by starting from UDP rather than TCP at the transport level, while reimplementing on top the reliability guarantees that TCP natively offered -- but per-stream rather than globally, which eliminates head-of-line blocking at the transport level (a lost packet on one stream no longer blocks other streams on the same connection). TLS 1.3 is integrated directly into QUIC rather than added on top, further reducing handshake latency. HTTP/3 is HTTP over QUIC.

Overview: where each protocol sits

Layer Protocols Role Transport TCP, UDP Move bytes around, reliable or not Transport (new generation) QUIC UDP + per-stream reliability + built-in TLS Security TLS, mTLS Encryption, integrity, authentication (one-way or mutual) Application HTTP/HTTPS, WS/WSS, gRPC Structure exchanges (request-response, bidirectional, typed RPC)

A concrete example to set the ideas: a microservices architecture with a web dashboard and internal services could reasonably combine HTTPS (dashboard ↔ public API, one-way authentication sufficient on the browser side), mTLS (service ↔ service internally, mutual authentication required), and WSS (real-time notifications pushed to the dashboard) -- three different application protocols, all built on the same TCP + TLS foundation.

How to choose, in practice

Three questions are usually enough to decide:

  1. Do I need reliability and ordering, or does data freshness take precedence over guaranteed delivery? → TCP if yes, UDP if no (or QUIC to have both via a different trade-off).

  2. Does the server need to initiate messages, or does the client always make the first request? → WebSocket/gRPC streaming if the server needs to push, regular HTTP otherwise.

  3. Do both parties need to prove their identity mutually, or does only one need to be verified? → mTLS for service-to-service in a zero-trust environment, plain TLS for regular public clients.

Operational complexity increases with each added layer: bare TCP has no infrastructure to manage, TLS requires certificates, mTLS requires a CA and a rotation strategy, gRPC requires a shared Protobuf schema definition. The right reflex is to only increase complexity when the layer below shows a concrete limitation, not preemptively.

Comment les machines se parlent : un tour d'horizon de TCP à mTLS

Pourquoi TCP, UDP, TLS, mTLS, HTTP et WebSocket ne sont pas des alternatives concurrentes mais des couches empilées; un tour d'horizon hiérarchique de la communication machine à machine, du transport brut à l'authentification mutuelle.

Le problème : trop de sigles, pas assez de hiérarchie

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; la plupart des ressources qui en parlent les présentent comme une liste plate d'options interchangeables, "à choisir selon le cas d'usage". En réalité ils ne sont pas sur le même plan : certains sont des protocoles de transport, d'autres des couches de sécurité qui s'enroulent autour du transport, d'autres encore des protocoles applicatifs qui s'appuient sur les deux premiers. Comprendre la hiérarchie, c'est comprendre pourquoi on ne "choisit" jamais entre TCP et TLS: on choisit TCP, puis on décide si on met TLS par-dessus.

Cet article reconstruit cette hiérarchie couche par couche, du transport brut jusqu'à l'authentification mutuelle, avec pour chaque niveau : ce qu'il garantit, ce qu'il ne garantit pas, et quand s'en contenter.

Niveau 1 : le transport (TCP contre UDP)

Tout commence ici. TCP et UDP sont les deux principaux protocoles de la couche Transport (Layer 4) du modèle OSI. Leur rôle est identique : transporter un flux de données entre deux applications exécutées sur des machines différentes. Pourtant, leur manière d'y parvenir est radicalement différente.

Il est important de comprendre qu'IP (Internet Protocol), situé à la couche réseau (Layer 3), ne fait qu'acheminer des paquets d'un hôte à un autre. Il ne garantit ni leur arrivée, ni leur ordre, ni même leur unicité. Les routeurs prennent simplement des décisions de routage indépendantes pour chaque paquet.

C'est précisément cette absence de garanties que TCP vient compenser, tandis qu'UDP choisit délibérément de ne rien ajouter afin de rester extrêmement léger.

TCP : la fiabilité avant tout

TCP (Transmission Control Protocol) est un protocole orienté connexion (connection-oriented). Avant d'échanger le moindre octet de données, les deux machines doivent établir une connexion logique.

Cette connexion est créée grâce au célèbre Three-Way Handshake :


Client                           Serveur
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Connexion établie

Chaque étape possède un objectif précis :

  • SYN : le client annonce qu'il souhaite ouvrir une connexion et fournit un premier numéro de séquence (Initial Sequence Number - ISN).

  • SYN-ACK : le serveur accepte la connexion, accuse réception du SYN et fournit à son tour son propre numéro de séquence.

  • ACK : le client confirme la réception des informations du serveur.

À partir de ce moment, les deux machines connaissent l'état de la connexion et peuvent commencer à échanger des données.

Les numéros de séquence

TCP ne voit pas les données comme une succession de paquets, mais comme un flux continu d'octets (byte stream).

Chaque octet envoyé possède un numéro de séquence.

Exemple :

Message :

Bonjour

B = octet 0
o = octet 1
n = octet 2
...

Si un segment contenant les octets 1000 à 1499 est perdu pendant le transport, le récepteur peut détecter exactement ce qui manque.

L'émetteur retransmet uniquement cette portion.

Cette granularité est l'une des raisons de la robustesse de TCP.

Les accusés de réception (ACK)

Après réception des données, le destinataire envoie un ACK (Acknowledgment).

Contrairement à ce que l'on imagine souvent, un ACK ne signifie pas :

"J'ai reçu ce paquet"

Il signifie plutôt :

"J'ai reçu tous les octets jusqu'au numéro X."

Par exemple :

Client envoie :

0 → 999

Serveur répond :

ACK = 1000

Cela signifie :

"Tout ce qui précède l'octet 1000 est bien arrivé."

Ce mécanisme permet d'accuser réception de plusieurs segments à la fois (cumulative acknowledgments), réduisant ainsi le nombre de paquets de contrôle.

Les retransmissions

Si un ACK n'arrive jamais, TCP suppose que le segment est perdu.

Il le retransmet automatiquement.

Le délai de retransmission (Retransmission Timeout – RTO) n'est pas fixe.

TCP mesure en permanence le temps aller-retour (RTT) grâce aux ACK reçus et calcule dynamiquement le RTO afin d'éviter des retransmissions inutiles.

Les implémentations modernes utilisent également des mécanismes comme Fast Retransmit : lorsqu'un émetteur reçoit plusieurs ACK dupliqués (généralement trois), il déduit qu'un segment intermédiaire a été perdu et le renvoie immédiatement, sans attendre l'expiration du temporisateur.

Réorganisation des paquets

Internet ne garantit absolument pas que deux paquets suivent le même chemin.

Exemple :

Paquet 1
Paris
 ↓
Londres
 ↓
New York

Paquet 2
Paris
 ↓
Francfort
 ↓
Chicago
 ↓
New York

Le deuxième paquet peut arriver avant le premier.

TCP stocke alors temporairement les segments reçus hors ordre dans un tampon (reassembly buffer), puis les réassemble avant de les livrer à l'application.

Pour l'application, tout semble arriver parfaitement dans l'ordre.

Contrôle de flux

Une connexion ne dépend pas uniquement du réseau.

Le récepteur possède également une capacité mémoire limitée.

S'il reçoit plus vite qu'il ne peut traiter les données, ses buffers finissent par saturer.

TCP résout ce problème grâce à une fenêtre glissante (Sliding Window).

Le récepteur indique dans chaque ACK :

Window = 32768 octets

Cela signifie :

"Tu peux m'envoyer jusqu'à 32 Ko supplémentaires."

Si cette fenêtre tombe à zéro :

Window = 0

L'émetteur suspend temporairement les transmissions jusqu'à ce que le récepteur annonce une nouvelle fenêtre disponible.

Ce mécanisme constitue le contrôle de flux (Flow Control) et empêche qu'un hôte rapide n'inonde un hôte plus lent.

Contrôle de congestion

Même si le récepteur est capable d'absorber les données, le réseau lui-même peut devenir saturé.

Les routeurs disposent de files d'attente (queues) limitées.

Lorsqu'elles débordent, les paquets sont supprimés.

TCP interprète les pertes comme un signe de congestion et adapte automatiquement son débit grâce à une fenêtre de congestion (Congestion Window – cwnd).

Les algorithmes modernes (comme Reno, CUBIC ou BBR, selon les systèmes d'exploitation) ajustent cette fenêtre afin de trouver un équilibre entre débit maximal et stabilité du réseau.

Les premières versions de TCP utilisaient principalement deux mécanismes :

  • Slow Start : augmentation exponentielle du débit jusqu'à détecter une congestion.

  • Congestion Avoidance : croissance ensuite plus prudente, généralement linéaire.

Cette adaptation permanente est l'une des raisons pour lesquelles TCP reste performant malgré les variations de qualité du réseau.

Fermeture de connexion

Contrairement à UDP, une connexion TCP possède également une fermeture propre.

Chaque extrémité ferme indépendamment son flux grâce au drapeau FIN.

Une fermeture complète nécessite généralement quatre échanges :

FIN
ACK
FIN
ACK

Cette procédure garantit que toutes les données en transit ont bien été livrées avant la destruction de la connexion.

UDP : la simplicité maximale

UDP (User Datagram Protocol) adopte la philosophie inverse.

Il est sans connexion (connectionless).

Il n'existe :

  • aucun handshake ;

  • aucun numéro de séquence ;

  • aucun accusé de réception ;

  • aucune retransmission ;

  • aucun contrôle de flux ;

  • aucun contrôle de congestion.

Chaque message est simplement encapsulé dans un datagramme indépendant, transmis au réseau, puis oublié par l'émetteur.

Application → Datagramme UDP → IP → Internet

Le protocole ne conserve aucun état entre deux envois.

Chaque datagramme est totalement indépendant des précédents.

L'intégrité des données

Bien qu'UDP ne garantisse ni la livraison ni l'ordre, il protège tout de même l'intégrité des données grâce à un checksum.

À la réception, le checksum est recalculé.

  • Si les valeurs correspondent, le datagramme est accepté.

  • Sinon, il est immédiatement rejeté.

UDP détecte donc les données corrompues, mais ne tente jamais de les récupérer.

Pourquoi UDP est-il si rapide ?

L'en-tête UDP ne contient que 8 octets, contre un minimum de 20 octets pour TCP (sans compter les options comme les timestamps, SACK ou Window Scaling).

Aucune connexion n'étant maintenue, le système d'exploitation n'a pas à suivre l'état de chaque échange, ce qui réduit également la consommation mémoire et le coût de traitement.

L'application reçoit les données quasiment dès leur arrivée, sans attendre d'éventuelles retransmissions.

Quand perdre une donnée est préférable

L'idée fondamentale est simple :

Une information ancienne peut avoir moins de valeur qu'une information perdue.

Prenons une conversation VoIP.

Chaque paquet transporte environ 20 ms de voix.

Si un paquet est perdu, le retransmettre prendrait souvent plus de temps que ces 20 ms.

Lorsqu'il arriverait enfin, la conversation aurait déjà avancé.

La plupart des applications préfèrent alors masquer la perte (interpolation, silence, correction d'erreur) plutôt que d'attendre la retransmission.

Le même raisonnement s'applique :

  • aux jeux multijoueurs temps réel ;

  • au streaming vidéo ;

  • aux flux de télémétrie ;

  • aux capteurs IoT ;

  • aux données de position GPS.

Une valeur récente est presque toujours plus utile qu'une valeur ancienne parfaitement fiable.

Niveau 2 : le chiffrement, TLS

TLS (Transport Layer Security, successeur de SSL) ne remplace pas TCP, il s'ajoute par-dessus. Concrètement, TLS établit une connexion TCP normale, puis négocie une session chiffrée à l'intérieur : échange de certificats, accord sur un algorithme de chiffrement, dérivation de clés de session. Tout ce qui transite ensuite est chiffré et authentifié.

Trois garanties distinctes, souvent confondues :

  • Confidentialité : personne d'autre que les deux parties ne peut lire le contenu.

  • Intégrité : toute altération des données en transit est détectée.

  • Authentification : mais dans le TLS classique, à sens unique : le client vérifie que le serveur est bien celui qu'il prétend être (via son certificat, signé par une autorité de confiance), mais le serveur ne vérifie rien sur l'identité du client. C'est exactement le modèle de HTTPS quand vous visitez un site : le navigateur authentifie le site, le site ne vous authentifie pas (l'authentification utilisateur passe par un mécanisme séparé, cookie de session, token).

TLS 1.3 (la version actuelle recommandée) a réduit le handshake à un seul aller-retour dans le cas courant, contre deux pour TLS 1.2, ce qui réduit sensiblement la latence de connexion.

Niveau 2bis : mTLS -- l'authentification devient mutuelle

mTLS (mutual TLS) est TLS avec une contrainte supplémentaire : le serveur exige aussi un certificat du client, et le vérifie. Les deux parties prouvent leur identité via un certificat signé par une autorité de confiance commune.

C'est le mécanisme naturel pour la communication service-à-service dans une architecture distribuée : là où HTTPS classique suffit pour qu'un navigateur parle à un serveur public, mTLS répond à une question différente; comment un service interne sait-il qu'il parle bien à un autre service interne autorisé, et pas à un attaquant qui aurait atterri sur le réseau ?

Client                                          Serveur
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificat serveur ──────────│
  │──── vérifie le certificat serveur ─────────────│
  │──── envoie SON PROPRE certificat client ──────▶│
  │◀─── vérifie le certificat client ───────────────│
  │──── clés de session dérivées, canal chiffré ──▶│

La contrepartie de mTLS est opérationnelle : il faut une autorité de certification (CA) interne, un mécanisme de distribution des certificats à chaque service, et une stratégie de rotation/révocation. Dans un environnement mono-machine avec peu de services, c'est parfois plus de complexité que de bénéfice -- mTLS devient nécessaire à partir du moment où le trafic inter-services traverse un réseau qu'on ne contrôle pas entièrement (plusieurs hôtes, cloud multi-tenant), ou dès qu'on veut une politique de type zero trust, où aucun service n'est implicitement digne de confiance simplement parce qu'il est "à l'intérieur" du réseau.

Niveau 3 : les protocoles applicatifs au-dessus de TCP+TLS

Une fois le transport et le chiffrement en place, reste à définir comment structurer les échanges. C'est le rôle des protocoles applicatifs.

HTTP / HTTPS

HTTP est un protocole requête-réponse : le client ouvre une connexion (ou en réutilise une, avec le keep-alive), envoie une requête, attend une réponse, la connexion peut ensuite se refermer ou être réutilisée. HTTPS, c'est simplement HTTP sur TLS -- le S ne change rien à la sémantique du protocole, uniquement au fait que le transport est chiffré.

Le modèle requête-réponse a une limite structurelle : le serveur ne peut jamais parler en premier. Il ne peut que répondre à ce que le client demande. Pour du polling fréquent (vérifier "y a-t-il du nouveau ?" toutes les secondes), ça marche mais gaspille des ressources -- chaque requête recrée du overhead protocolaire pour, la plupart du temps, ne rien avoir de nouveau à annoncer.

WebSocket (WS / WSS)

WebSocket répond exactement à cette limite. La connexion démarre comme une requête HTTP classique (avec un header Upgrade: websocket), mais une fois la poignée de main acceptée, la connexion TCP sous-jacente n'est plus un canal requête-réponse HTTP -- elle devient un canal bidirectionnel full-duplex où client et serveur peuvent envoyer des messages à tout moment, sans avoir à réémettre un cycle requête-réponse à chaque échange.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS est simplement WebSocket sur TLS, exactement comme HTTPS est HTTP sur TLS. C'est le protocole de choix pour tout ce qui nécessite du push serveur en temps réel -- chat, notifications, flux de trading, événements de jeu -- sans vouloir gérer soi-même un protocole binaire par-dessus TCP nu.

gRPC

Moins connu hors du monde microservices mais central en communication service-à-service : gRPC s'appuie sur HTTP/2 (donc TCP + TLS optionnel), sérialise les messages en Protocol Buffers (binaire, typé, compact - contrairement au JSON texte de la plupart des API REST), et permet nativement le streaming bidirectionnel grâce au multiplexage de HTTP/2 (plusieurs flux logiques sur une seule connexion TCP, sans le head-of-line blocking qu'aurait plusieurs requêtes HTTP/1.1 séquentielles).

QUIC / HTTP3

QUIC change la donne en repartant d'UDP plutôt que de TCP au niveau transport, tout en réimplémentant par-dessus les garanties de fiabilité que TCP offrait nativement - mais flux par flux plutôt que globalement, ce qui élimine le head-of-line blocking au niveau transport (un paquet perdu sur un flux ne bloque plus les autres flux de la même connexion). TLS 1.3 est intégré directement dans QUIC plutôt qu'ajouté par-dessus, ce qui réduit encore la latence de handshake. HTTP/3 est HTTP par-dessus QUIC.

Vue d'ensemble : où se situe chaque protocole

Couche Protocoles Rôle Transport TCP, UDP Faire voyager des octets, fiable ou non Transport (nouvelle génération) QUIC UDP + fiabilité par flux + TLS intégré Sécurité TLS, mTLS Chiffrement, intégrité, authentification (uni ou mutuelle) Application HTTP/HTTPS, WS/WSS, gRPC Structurer les échanges (requête-réponse, bidirectionnel, RPC typé)

Un exemple concret pour fixer les idées : une architecture microservices avec un dashboard web et des services internes pourrait raisonnablement combiner HTTPS (dashboard ↔ API publique, authentification uni-directionnelle suffisante côté navigateur), mTLS (service ↔ service en interne, authentification mutuelle nécessaire), et WSS (notifications temps réel poussées vers le dashboard) -- trois protocoles applicatifs différents, tous construits sur le même socle TCP + TLS.

Comment choisir, en pratique

Trois questions suffisent généralement à trancher :

  1. Ai-je besoin de fiabilité et d'ordre, ou la fraîcheur de la donnée prime-t-elle sur sa livraison garantie ? → TCP si oui, UDP si non (ou QUIC pour avoir les deux à la fois via un compromis différent).

  2. Le serveur doit-il pouvoir initier des messages, ou le client fait-il toujours la première demande ? → WebSocket/gRPC streaming si le serveur doit pousser, HTTP classique sinon.

  3. Les deux parties doivent-elles se prouver mutuellement leur identité, ou seule une des deux a besoin d'être vérifiée ? → mTLS pour du service-à-service en environnement zero-trust, TLS simple pour du client public classique.

La complexité opérationnelle augmente à chaque couche ajoutée, TCP nu n'a aucune infrastructure à gérer, TLS demande des certificats, mTLS demande une CA et une stratégie de rotation, gRPC demande une définition de schéma Protobuf partagée. Le bon réflexe est de ne monter en complexité que quand la couche du dessous montre une limite concrète, pas par anticipation.

机器如何相互通信:从 TCP 到 mTLS 的协议全景

为什么 TCP、UDP、TLS、mTLS、HTTP 和 WebSocket 不是互斥的替代方案,而是层层叠加的协议栈;一篇从裸传输到双向认证的机器间通信层次化概述。

问题:太多缩写,不够的层次感

TCP、UDP、TLS、mTLS、WebSocket、HTTP、HTTPS、gRPC、QUIC;大多数相关的资料把它们当作一个扁平的、可互换的选项列表,"根据使用场景选择"。但实际上它们并不在同一个层面上:有些是传输协议,有些是包裹在传输之上的安全层,还有一些是建立在前面两者之上的应用层协议。理解了层次结构,就能理解为什么你永远不会在 TCP 和 TLS 之间"二选一":你先选择 TCP,_然后_决定是否在其上叠加 TLS。

本文将从裸传输到双向认证,逐层重构这个协议层次结构,每层都会说明:它保证了什么、不保证什么,以及何时可以满足于此。

第1层:传输(TCP 对比 UDP)

一切从这里开始。TCP 和 UDP 是 OSI 模型中**传输层(Layer 4)**的两个主要协议。它们的作用相同:在不同机器上运行的两个应用之间传输数据流。然而,它们实现这一目标的方式截然不同。

需要理解的是,位于网络层(Layer 3)的 IP(Internet Protocol)仅负责将数据包从一台主机路由到另一台主机。它既不保证数据包的到达,也不保证其顺序,甚至不保证其唯一性。路由器只是独立地为每个数据包做出路由决策。

正是这种缺乏保证的情况,TCP 来弥补,而 UDP 则故意不添加任何东西以保持极致的轻量。

TCP:可靠性至上

TCP(Transmission Control Protocol)是一种面向连接的协议。在交换任何一个数据字节之前,两台机器必须先建立一条逻辑连接。

这条连接通过著名的三次握手建立:


Client                           Serveur
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Connexion établie

每一步都有其特定的目的:

  • SYN:客户端宣告它希望打开一条连接,并提供一个初始序列号(Initial Sequence Number - ISN)。

  • SYN-ACK:服务器接受连接,确认收到 SYN,并提供它自己的序列号。

  • ACK:客户端确认收到服务器的信息。

从此刻起,两台机器都知道连接的状态,并可以开始交换数据。

序列号

TCP 不将数据视为数据包的简单序列,而是将其视为一个连续的字节流。

每个发送的字节都有一个序列号。

示例:

Message :

Bonjour

B = octet 0
o = octet 1
n = octet 2
...

如果在传输过程中丢失了一个包含第 1000 到第 1499 字节的段,接收方可以精确检测到丢失了什么。

发送方仅重传这一部分。

这种粒度是 TCP 健壮性的原因之一。

确认应答(ACK)

收到数据后,接收方发送一个 ACK(Acknowledgment)。

与我们通常想象的相反,ACK 并不意味着:

"我收到了这个数据包"

它的意思是:

"我已经收到了直到编号 X 的所有字节。"

例如:

Client envoie :

0 → 999

Serveur répond :

ACK = 1000

这意味着:

"第 1000 字节之前的所有内容都已成功到达。"

这种机制允许一次确认多个段(累积确认),从而减少控制包的数量。

重传

如果 ACK 从未到达,TCP 就假定该段已丢失。

它会自动重传。

重传超时(Retransmission Timeout – RTO)不是固定的。

TCP 通过收到的 ACK 持续测量往返时间(RTT),并动态计算 RTO,以避免不必要的重传。

现代实现还使用诸如快速重传之类的机制:当发送方收到多个重复的 ACK(通常是三个)时,它推断中间的一个段已丢失,并立即重新发送,无需等待计时器到期。

数据包重组

互联网完全不保证两个数据包走同一条路径。

示例:

Paquet 1
Paris
 ↓
Londres
 ↓
New York

Paquet 2
Paris
 ↓
Francfort
 ↓
Chicago
 ↓
New York

第二个数据包可能比第一个先到达。

TCP 会将收到的乱序段暂时存放在一个缓冲区(重组缓冲区)中,然后在交付给应用程序之前将它们重新组装。

对于应用程序来说,一切看起来都是完美有序地到达。

流量控制

一个连接不仅仅依赖于网络。

接收方也有有限的内存容量。

如果它接收数据的速度快于处理速度,它的缓冲区最终会饱和。

TCP 通过一个滑动窗口来解决这个问题。

接收方在每个 ACK 中指示:

Window = 32768 octets

这意味着:

"你可以再给我发送最多 32 KB。"

如果这个窗口降到零:

Window = 0

发送方将暂时暂停传输,直到接收方通告一个新的可用窗口。

这种机制构成了流量控制,并防止快主机淹没慢主机。

拥塞控制

即使接收方能够吸收数据,网络本身也可能变得饱和。

路由器有有限的队列。

当队列溢出时,数据包就会被丢弃。

TCP 将丢包解释为拥塞的信号,并通过一个拥塞窗口自动调整其传输速率。

现代算法(如 Reno、CUBIC 或 BBR,取决于操作系统)会调整这个窗口,以在最大吞吐量和网络稳定性之间找到平衡。

早期的 TCP 版本主要使用两种机制:

  • 慢启动:指数级增加传输速率,直到检测到拥塞。

  • 拥塞避免:之后更谨慎的增长,通常是线性的。

这种持续的适应是 TCP 尽管网络质量变化多端却仍能保持高性能的原因之一。

连接关闭

与 UDP 不同,TCP 连接也有一个干净的关闭过程。

每个端点通过 FIN 标志独立关闭其数据流。

一个完整的关闭通常需要四次交换:

FIN
ACK
FIN
ACK

这个过程保证了所有在途的数据在连接销毁前都已被成功交付。

UDP:极致的简单

UDP(User Datagram Protocol)采用了相反的哲学。

它是无连接的。

它没有:

  • 任何握手;

  • 任何序列号;

  • 任何确认应答;

  • 任何重传;

  • 任何流量控制;

  • 任何拥塞控制。

每个消息只是简单地封装在一个独立的数据报中,发送到网络,然后被发送方遗忘。

Application → Datagramme UDP → IP → Internet

该协议在两次发送之间不保留任何状态。

每个数据报完全独立于前一个。

数据完整性

虽然 UDP 既不保证交付也不保证顺序,但它仍然通过校验和来保护数据完整性。

收到数据时,校验和被重新计算。

  • 如果值匹配,数据报被接受。

  • 否则,它被立即丢弃。

因此,UDP 能检测到损坏的数据,但从不尝试恢复它。

为什么 UDP 如此之快?

UDP 头部只有 8 个字节,而 TCP 最少 20 个字节(不包括时间戳、SACK 或 Window Scaling 等选项)。

由于不维护任何连接,操作系统不需要跟踪每次交换的状态,这也降低了内存消耗和处理成本。

应用程序几乎在数据到达时就能收到,无需等待潜在的重传。

何时丢失数据比等待更好

基本思想很简单:

过时的信息可能比丢失的信息价值更低。

以 VoIP 通话为例。

每个数据包携带大约 20 毫秒的语音。

如果一个数据包丢失了,重传它所花费的时间通常超过这 20 毫秒。

当它最终到达时,对话已经继续了。

大多数应用程序更倾向于掩盖丢失(插值、静音、纠错)而不是等待重传。

同样的逻辑也适用于:

  • 实时多人游戏;

  • 视频流;

  • 遥测数据流;

  • IoT 传感器;

  • GPS 位置数据。

一个最新的值几乎总是比一个完美可靠的旧值更有用。

第2层:加密,TLS

TLS(Transport Layer Security,SSL 的后继者)不取代 TCP,而是叠加在 TCP 之上。具体来说,TLS 先建立一条普通的 TCP 连接,然后在其中协商一个加密会话:交换证书、协商加密算法、派生会话密钥。之后传输的所有内容都被加密和认证。

三个常被混淆的独立保证:

  • 机密性:除了通信双方之外,没有人能读取内容。

  • 完整性:传输过程中数据的任何篡改都会被检测到。

  • 认证:但在经典 TLS 中,是单向的:客户端验证服务器确实是它所声称的身份(通过由受信任机构签名的证书),但服务器不验证客户端身份。这正是你访问网站时 HTTPS 的模型:浏览器认证网站,网站不认证你(用户认证通过单独的机制进行,如会话 cookie、token)。

TLS 1.3(当前推荐版本)在常见情况下将握手减少到单次往返,而 TLS 1.2 需要两次,这显著降低了连接延迟。

第2层补充:mTLS -- 认证变成双向的

mTLS(mutual TLS)是 TLS 加上一个额外的约束:服务器_也_要求客户端的证书并进行验证。双方通过由共同信任的证书颁发机构签名的证书来证明身份。

这是在分布式架构中服务间通信的自然机制:经典 HTTPS 足以让浏览器与公共服务器通信,而 mTLS 回答了一个不同的问题:一个内部服务如何确定它正在与另一个授权的内部服务通信,而不是一个潜入网络的攻击者?

Client                                          Serveur
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificat serveur ──────────│
  │──── vérifie le certificat serveur ─────────────│
  │──── envoie SON PROPRE certificat client ──────▶│
  │◀─── vérifie le certificat client ───────────────│
  │──── clés de session dérivées, canal chiffré ──▶│

mTLS 的代价是运维方面的:需要一个内部的证书颁发机构(CA)、一个向每个服务分发证书的机制,以及一个轮换/撤销策略。在单机环境中服务很少的情况下,这有时带来的复杂性问题大于收益----mTLS 只有在服务间流量穿越无法完全控制的网络(多主机、多云租户环境)时,或者当你希望采用_零信任_策略(没有任何服务仅仅因为"在内部"网络中就隐式可信)时,才变得必要。

第3层:基于 TCP+TLS 的应用层协议

一旦传输和加密就位,还需要定义_如何结构化通信_。这就是应用层协议的角色。

HTTP / HTTPS

HTTP 是一个请求-响应协议:客户端打开一个连接(或通过 keep-alive 重用连接),发送一个请求,等待一个响应,连接随后可以关闭或重用。HTTPS 就是 HTTP 在 TLS 之上----这个 S 没有改变协议的语义,只是传输被加密了。

请求-响应模型有一个结构性限制:服务器永远不能先发起消息。它只能响应客户端的请求。对于频繁的轮询(每秒检查"有新的吗?"),这是可行的,但会浪费资源----每次请求都会重新产生协议开销,而在大多数情况下并没有什么新东西需要宣告。

WebSocket(WS / WSS)

WebSocket 正好解决了这个限制。连接开始时就像一次普通的 HTTP 请求(包含 Upgrade: websocket 头),但一旦握手被接受,底层的 TCP 连接就不再是一个 HTTP 请求-响应通道----它变成一个全双工的双向通道,客户端和服务器可以随时发送消息,无需每次交换都重新发起请求-响应周期。

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS 就是 WebSocket 在 TLS 之上,就像 HTTPS 是 HTTP 在 TLS 之上一样。它是所有需要实时服务器推送的场景的首选协议----聊天、通知、交易流、游戏事件----而不希望自己在裸 TCP 之上实现二进制协议。

gRPC

在微服务世界之外鲜为人知,但在服务间通信中至关重要:gRPC 基于 HTTP/2(因此基于 TCP + 可选的 TLS),使用 Protocol Buffers 序列化消息(二进制、类型化、紧凑----与大多数 REST API 的文本 JSON 相反),并通过 HTTP/2 的多路复用原生支持双向流(多个逻辑流共享一个 TCP 连接,没有多个顺序 HTTP/1.1 请求会出现的队头阻塞)。

QUIC / HTTP3

QUIC 改变了游戏规则,它在传输层重新使用 UDP 而不是 TCP,同时在其之上重新实现了 TCP 原生提供的可靠性保证----不过是按流而不是全局实现的,这消除了传输层的队头阻塞(一个流上丢失的数据包不再阻塞同一连接中的其他流)。TLS 1.3 被直接集成到 QUIC 中而不是叠加在其上,这进一步减少了握手延迟。HTTP/3 就是基于 QUIC 的 HTTP。

总览:每个协议所处的层次

层 协议 角色 传输 TCP, UDP 传输字节,可靠或不可靠 传输(新一代) QUIC UDP + 按流的可靠性 + 内置 TLS 安全 TLS, mTLS 加密、完整性、认证(单向或双向) 应用 HTTP/HTTPS, WS/WSS, gRPC 结构化通信(请求-响应、双向、类型化 RPC)

一个具体示例来帮助理解:一个带有 Web 仪表盘和内部服务的微服务架构可以合理地将 HTTPS(仪表盘 ↔ 公共 API,浏览器端单向认证足够)、mTLS(内部服务 ↔ 服务,需要双向认证)和 WSS(实时通知推送到仪表盘)结合起来----三种不同的应用层协议,都构建在同一个 TCP + TLS 基础之上。

实践中如何选择

三个问题通常足以做出决定:

  1. 我需要可靠性和顺序,还是数据的新鲜度比其保证交付更重要? → 如果是,选 TCP;如果否,选 UDP(或 QUIC,通过不同的折衷方案同时拥有两者)。

  2. 服务器是否需要能够主动发起消息,还是客户端总是先发起请求? → 如果需要服务器推送,选 WebSocket/gRPC 流;否则选经典 HTTP。

  3. 双方是否需要相互证明身份,还是只需要验证其中一方? → 零信任环境中的服务间通信选 mTLS,经典公共客户端选简单 TLS。

每增加一层,运维复杂性也随之增加:裸 TCP 无需管理任何基础设施,TLS 需要证书,mTLS 需要一个 CA 和轮换策略,gRPC 需要共享的 Protobuf 模式定义。正确的做法是只在底层显示出具体限制时才增加复杂性,而不是预先加码。

マシン同士の会話:TCPからmTLSまでの概観

TCP、UDP、TLS、mTLS、HTTP、WebSocketは競合する選択肢ではなく、積み重ねられた層である。トランスポートから相互認証に至る、マシン間通信の階層的概観。

問題:多すぎる略語、足りない階層構造

TCP、UDP、TLS、mTLS、WebSocket、HTTP、HTTPS、gRPC、QUIC。これらについて語るほとんどの資料は、それらを「ユースケースに応じて選択する」フラットな選択肢リストとして提示する。しかし実際には、これらは同じ平面にはない。あるものはトランスポートプロトコルであり、別のものはトランスポートを包み込むセキュリティ層であり、さらに別のものは最初の二つの上に構築されるアプリケーションプロトコルである。この階層構造を理解することは、なぜTCPとTLSの間で「選択」することが決してないのかを理解することに他ならない。すなわち、TCPを選び、それから TLSをその上に載せるかどうかを決めるのである。

本稿では、トランスポートから相互認証に至るまで、この階層構造を層ごとに再構築する。各層について、何を保証し、何を保証せず、どのような場合にそれで十分かを解説する。

レベル1:トランスポート(TCP対UDP)

すべてはここから始まる。TCPとUDPは、OSIモデルの**トランスポート層(レイヤ4)**における二つの主要プロトコルである。それらの役割は同じである。すなわち、異なるマシン上で動作する二つのアプリケーション間でデータストリームを転送すること。しかし、その実現方法は根本的に異なる。

IP(Internet Protocol)はネットワーク層(レイヤ3)に位置し、パケットをホスト間で転送するだけであることを理解することが重要である。IPはパケットの到着、順序、一意性さえも保証しない。ルーターは各パケットに対して独立したルーティング判断を下すだけである。

TCPが補償するのはまさにこの保証の欠如であり、一方UDPは極めて軽量であることを優先して、あえて何も追加しないことを選択する。

TCP:何よりも信頼性

TCP(Transmission Control Protocol)はコネクション型(connection-oriented)プロトコルである。データの1バイトでも交換する前に、両方のマシンが論理的なコネクションを確立しなければならない。

このコネクションは、有名なThree-Way Handshakeによって作成される。

Client                           Serveur
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Connexion établie

各ステップには明確な目的がある。

  • SYN:クライアントがコネクションの開始を希望することを通知し、最初のシーケンス番号(Initial Sequence Number - ISN)を提供する。
  • SYN-ACK:サーバーがコネクションを受け入れ、SYNの受信を確認し、自身のシーケンス番号を提供する。
  • ACK:クライアントがサーバーからの情報の受信を確認する。

この時点から、両方のマシンはコネクションの状態を把握し、データの交換を開始できる。

シーケンス番号

TCPはデータをパケットの連続としてではなく、連続したバイトストリーム(byte stream)として見る。

送信される各バイトにはシーケンス番号が割り当てられる。

例:

Message :

Bonjour

B = octet 0
o = octet 1
n = octet 2
...

1000から1499までのバイトを含むセグメントが転送中に失われた場合、受信側は何が欠けているかを正確に検出できる。

送信側はその部分のみを再送信する。

この粒度がTCPの堅牢性の理由の一つである。

ACK(Acknowledgement、確認応答)

データを受信した後、受信側は**ACK(Acknowledgement)**を送信する。

よく想像されるのとは異なり、ACKが意味するのは以下のようなものではない。

「このパケットを受信しました」

むしろ、以下のような意味である。

「番号Xまでのすべてのバイトを受信しました。」

例えば:

Client envoie :

0 → 999

Serveur répond :

ACK = 1000

これは以下を意味する。

「バイト1000より前のすべてが正しく到着しました。」

この仕組みにより、複数のセグメントを同時に確認応答することができ(累積確認応答、cumulative acknowledgments)、制御パケットの数を削減できる。

再送信

ACKが決して到着しない場合、TCPはセグメントが失われたと推定する。

TCPは自動的にセグメントを再送信する。

再送信タイムアウト(Retransmission Timeout – RTO)は固定ではない。

TCPは受信したACKによって往復時間(RTT)を常に測定し、不必要な再送信を避けるためにRTOを動的に計算する。

最新の実装では、Fast Retransmitのようなメカニズムも使用される。送信側が複数の重複ACK(通常は3つ)を受信すると、中間のセグメントが失われたと推定し、タイマーの期限を待たずに直ちにそのセグメントを再送信する。

パケットの並べ替え

インターネットは、二つのパケットが同じ経路をたどることを全く保証しない。

例:

Paquet 1
Paris
 ↓
Londres
 ↓
New York

Paquet 2
Paris
 ↓
Francfort
 ↓
Chicago
 ↓
New York

2番目のパケットが1番目のパケットより先に到着する可能性がある。

TCPは、順序不同で受信したセグメントを一時的にバッファ(reassembly buffer)に格納し、アプリケーションに渡す前に再構成する。

アプリケーションにとっては、すべてが完全に順序通りに到着しているように見える。

フロー制御

コネクションはネットワークだけに依存するわけではない。

受信側にも限られたメモリ容量がある。

受信側がデータを処理できる速度よりも速くデータを受信すると、バッファが溢れてしまう。

TCPは**スライディングウィンドウ(Sliding Window)**によってこの問題を解決する。

受信側は各ACKの中で以下を通知する。

Window = 32768 octets

これは以下を意味する。

「さらに最大32KBまで送信できます。」

このウィンドウがゼロになると:

Window = 0

送信側は、受信側が新たに利用可能なウィンドウを通知するまで、一時的に送信を中断する。

このメカニズムが**フロー制御(Flow Control)**を構成し、高速なホストが低速なホストを圧倒するのを防ぐ。

輻輳制御

受信側がデータを吸収できる場合でも、ネットワーク自体が飽和状態になる可能性がある。

ルーターには限られたキュー(queue)がある。

キューが溢れると、パケットは破棄される。

TCPは損失を輻輳の兆候として解釈し、**輻輳ウィンドウ(Congestion Window – cwnd)**によってスループットを自動的に調整する。

最新のアルゴリズム(OSに応じてReno、CUBIC、BBRなど)はこのウィンドウを調整し、最大スループットとネットワーク安定性のバランスを見つける。

初期のTCPバージョンは主に二つのメカニズムを使用していた。

  • Slow Start:輻輳を検出するまでスループットを指数関数的に増加させる。
  • Congestion Avoidance:その後はより慎重に、通常は線形的に増加させる。

この継続的な適応こそが、ネットワーク品質の変動にもかかわらずTCPが高性能を維持する理由の一つである。

コネクションの終了

UDPとは異なり、TCPコネクションには適切な終了手順もある。

各端点はFINフラグによって独立してストリームを閉じる。

完全な終了には通常4つの交換が必要である。

FIN
ACK
FIN
ACK

この手順は、コネクションが破棄される前に、転送中のすべてのデータが確実に配信されることを保証する。

UDP:究極のシンプルさ

UDP(User Datagram Protocol)は逆の哲学を採用する。

UDPは**コネクションレス(connectionless)**である。

以下のものは存在しない。

  • ハンドシェイク
  • シーケンス番号
  • 確認応答
  • 再送信
  • フロー制御
  • 輻輳制御

各メッセージは単に独立したデータグラムにカプセル化され、ネットワークに送信され、その後送信側によって忘れられる。

Application → Datagramme UDP → IP → Internet

プロトコルは二つの送信間で状態を保持しない。

各データグラムは以前のものから完全に独立している。

データの整合性

UDPは配信も順序も保証しないが、チェックサムによってデータの整合性は保護する。

受信時にチェックサムが再計算される。

  • 値が一致すれば、データグラムは受け入れられる。
  • そうでなければ、直ちに拒否される。

したがって、UDPは破損したデータを検出するが、それを回復しようとは決してしない。

なぜUDPはそんなに速いのか?

UDPヘッダーはわずか8バイトであり、TCPの最小20バイト(タイムスタンプ、SACK、Window Scalingなどのオプションを除く)と比較される。

コネクションが維持されないため、オペレーティングシステムは各交換の状態を追跡する必要がなく、メモリ消費と処理コストも削減される。

アプリケーションは、データが到着するとほぼ即座に受信し、再送信の可能性を待つ必要がない。

データを失う方が望ましい場合

基本的な考え方はシンプルである。

古い情報は、失われた情報よりも価値が低い場合がある。

VoIP通話を例にとろう。

各パケットは約20ミリ秒の音声を運ぶ。

パケットが失われた場合、それを再送信するのにかかる時間は、しばしばこの20ミリ秒よりも長い。

ようやく到着したときには、会話はすでに先に進んでいる。

ほとんどのアプリケーションは、再送信を待つよりも、損失をマスクする(補完、無音、誤り訂正)ことを好む。

同じ理屈は以下にも当てはまる。

  • リアルタイムマルチプレイヤーゲーム
  • ビデオストリーミング
  • テレメトリーフィード
  • IoTセンサー
  • GPS位置データ

最近の値は、完全に信頼性のある古い値よりもほとんどの場合において有用である。

レベル2:暗号化、TLS

TLS(Transport Layer Security、SSLの後継)はTCPを置き換えるのではなく、その上に追加される。具体的には、TLSは通常のTCPコネクションを確立し、その内部で暗号化セッションをネゴシエートする。証明書の交換、暗号アルゴリズムの合意、セッション鍵の導出などである。その後、やり取りされるすべてのデータは暗号化され、認証される。

しばしば混同される三つの異なる保証:

  • 機密性:二者以外の誰も内容を読むことができない。
  • 完全性:転送中のデータへの改ざんはすべて検出される。
  • 認証:ただし、標準的なTLSでは一方向のみ。クライアントはサーバーが名乗る通りの存在であることを検証する(信頼できる認証局によって署名された証明書による)が、サーバーはクライアントの身元については何も検証しない。これは、Webサイトを訪問する際のHTTPSのモデルそのものである。ブラウザはサイトを認証するが、サイトはユーザーを認証しない(ユーザー認証は別のメカニズム、セッションクッキーやトークンを介して行われる)。

TLS 1.3(現在推奨されているバージョン)は、通常の場合、ハンドシェイクを1回の往復に削減した(TLS 1.2では2回)。これにより、接続レイテンシが大幅に低減される。

レベル2bis:mTLS -- 認証が相互になる

mTLS(mutual TLS)は、追加の制約があるTLSである。サーバーもクライアントからの証明書を要求し、検証する。両者は、共通の信頼できる認証局によって署名された証明書を介して身元を証明する。

これは分散アーキテクチャにおけるサービス間通信の自然なメカニズムである。標準的なHTTPSがブラウザと公開サーバーの通信に十分であるのに対し、mTLSは別の問いに答える。すなわち、内部サービスは、自分が許可された別の内部サービスと通信しているのであって、ネットワークに侵入した攻撃者と通信しているのではないことを、どうやって知るのか?

Client                                          Serveur
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificat serveur ──────────│
  │──── vérifie le certificat serveur ─────────────│
  │──── envoie SON PROPRE certificat client ──────▶│
  │◀─── vérifie le certificat client ───────────────│
  │──── clés de session dérivées, canal chiffré ──▶│

mTLSの代償は運用面にある。内部認証局(CA)、各サービスへの証明書配布メカニズム、ローテーション/失効戦略が必要となる。少数のサービスしかないシングルマシン環境では、これはベネフィットを上回る複雑さをもたらすことがある。mTLSが必要になるのは、サービス間トラフィックが完全には制御できないネットワーク(複数ホスト、マルチテナントクラウド)を通過する場合、あるいは暗黙的に信頼できるサービスは「ネットワーク内部にある」という理由だけでは存在しないという、ゼロトラスト タイプのポリシーを適用したい場合である。

レベル3:TCP+TLS上のアプリケーションプロトコル

トランスポートと暗号化が整ったら、次に_交換をどのように構造化するか_を定義する。これがアプリケーションプロトコルの役割である。

HTTP / HTTPS

HTTPは要求-応答プロトコルである。クライアントはコネクションを開き(またはkeep-aliveで再利用し)、要求を送信し、応答を待ち、その後コネクションは閉じられるか再利用される。HTTPSは、単にTLS上のHTTPである。Sはプロトコルのセマンティクスを何も変えず、トランスポートが暗号化されているという事実のみを変更する。

要求-応答モデルには構造上の限界がある。サーバーは決して先に話すことができない。サーバーはクライアントが要求したものに応答することしかできない。頻繁なポーリング(毎秒「新しい情報はあるか?」を確認する)の場合、これは機能するがリソースを浪費する。各要求はプロトコルオーバーヘッドを再度発生させ、ほとんどの場合、通知すべき新しい情報は何もない。

WebSocket(WS / WSS)

WebSocketはまさにこの限界に対応する。コネクションは標準的なHTTP要求として開始されるが(Upgrade: websocketヘッダー付き)、ハンドシェイクが受け入れられると、基礎となるTCPコネクションはもはやHTTPの要求-応答チャネルではなくなる。クライアントとサーバーがいつでもメッセージを送信できる、全二重の双方向チャネルとなり、交換のたびに要求-応答サイクルを再発行する必要がない。

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSSは、HTTPSがTLS上のHTTPであるのとまったく同じく、TLS上のWebSocketである。リアルタイムのサーバープッシュを必要とするすべてのもの(チャット、通知、トレーディングフィード、ゲームイベント)にとって、裸のTCP上で独自のバイナリプロトコルを管理したくない場合の選択肢となるプロトコルである。

gRPC

マイクロサービス界隈以外ではあまり知られていないが、サービス間通信において中心的な役割を果たす。gRPCはHTTP/2(つまりTCP + オプションのTLS)に基づき、メッセージをProtocol Buffers(ほとんどのREST APIのテキストベースJSONとは対照的に、バイナリ、型付け、コンパクト)でシリアライズし、HTTP/2の多重化(単一のTCPコネクション上の複数の論理ストリーム、逐次的なHTTP/1.1要求が持つヘッドオブラインブロッキングがない)により、ネイティブで双方向ストリーミングを可能にする。

QUIC / HTTP3

QUICは、トランスポートレベルでTCPではなくUDPをベースにすることで状況を一変させる。その上に、TCPがネイティブに提供していた信頼性保証を再実装するが、グローバルではなくストリームごとに行う。これにより、トランスポートレベルのヘッドオブラインブロッキングが排除される(あるストリームでパケットが失われても、同じコネクションの他のストリームをブロックしない)。TLS 1.3はQUICに後付けではなく直接統合されており、ハンドシェイクのレイテンシをさらに削減する。HTTP/3はQUIC上のHTTPである。

全体像:各プロトコルの位置づけ

Couche Protocoles Rôle Transport TCP, UDP Faire voyager des octets, fiable ou non Transport (nouvelle génération) QUIC UDP + fiabilité par flux + TLS intégré Sécurité TLS, mTLS Chiffrement, intégrité, authentification (uni ou mutuelle) Application HTTP/HTTPS, WS/WSS, gRPC Structurer les échanges (requête-réponse, bidirectionnel, RPC typé)

具体的な例として、Webダッシュボードと内部サービスを持つマイクロサービスアーキテクチャを考えよう。HTTPS(ダッシュボード ↔ 公開API、ブラウザ側では一方向認証で十分)、mTLS(内部のサービス ↔ サービス、相互認証が必要)、WSS(ダッシュボードへのリアルタイム通知プッシュ)の三つを合理的に組み合わせることができる。三つの異なるアプリケーションプロトコルだが、すべて同じTCP + TLSの基盤の上に構築されている。

実践的な選択方法

通常は三つの質問で十分に判断できる。

  1. 信頼性と順序が必要か、それともデータの鮮度が保証された配信よりも優先されるか? → はいの場合はTCP、いいえの場合はUDP(または異なるトレードオフで両方を実現するQUIC)。
  2. サーバーがメッセージを開始できる必要があるか、それとも常にクライアントが最初に要求するか? → サーバーがプッシュする必要がある場合はWebSocket/gRPCストリーミング、そうでない場合は標準的なHTTP。
  3. 両者が互いに身元を証明する必要があるか、それとも一方のみの検証で十分か? → ゼロトラスト環境でのサービス間通信にはmTLS、標準的な公開クライアントには単純なTLS。

運用の複雑さは層が追加されるごとに増大する。裸のTCPは管理すべきインフラが何もない。TLSは証明書を必要とする。mTLSはCAとローテーション戦略を必要とする。gRPCは共有のProtobufスキーマ定義を必要とする。適切な姿勢は、下の層が具体的な限界を示した場合にのみ複雑性を上げることであり、先回りして上げることではない。

기계들이 서로 대화하는 방법: TCP에서 mTLS까지 개요

TCP, UDP, TLS, mTLS, HTTP, WebSocket이 경쟁 관계가 아니라 계층적으로 쌓여 있는 이유; 원시 전송부터 상호 인증까지 기계 간 통신의 계층별 개요.

문제: 약어는 너무 많은데, 계층 구조는 부족하다

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; 이들을 다루는 대부분의 자료는 "사용 사례에 따라 선택하라"며 평평한 목록으로 제시한다. 실제로 이들은 같은 차원 위에 있지 않다: 어떤 것은 전송 프로토콜이고, 다른 것은 전송 주위를 감싸는 보안 계층이며, 또 다른 것은 앞선 둘 위에서 동작하는 애플리케이션 프로토콜이다. 계층 구조를 이해하는 것은 TCP와 TLS 사이에서 "선택"하지 않는 이유를 이해하는 것이다: TCP를 선택하고, 그 다음에 TLS를 그 위에 얹을지 결정한다.

이 글은 원시 전송부터 상호 인증까지 각 계층이 보장하는 것, 보장하지 않는 것, 그리고 언제 그것으로 충분한지를 계층별로 재구성한다.

1계층: 전송 (TCP 대 UDP)

모든 것은 여기서 시작된다. TCP와 UDP는 OSI 모델의 전송 계층 (Layer 4) 의 두 주요 프로토콜이다. 그들의 역할은 동일하다: 서로 다른 기계에서 실행되는 두 애플리케이션 간에 데이터 흐름을 운반하는 것. 그러나 이를 달성하는 방식은 근본적으로 다르다.

IP(Internet Protocol)는 네트워크 계층(Layer 3)에 위치하며 단지 한 호스트에서 다른 호스트로 패킷을 전달할 뿐이라는 점을 이해하는 것이 중요하다. IP는 패킷의 도착, 순서, 심지어 유일성도 보장하지 않는다. 라우터는 각 패킷에 대해 독립적인 라우팅 결정을 내릴 뿐이다.

바로 이러한 보장의 부재를 TCP가 보완하는 반면, UDP는 극도의 경량성을 유지하기 위해 일부러 아무것도 추가하지 않기로 선택한다.

TCP: 신뢰성이 최우선

TCP(Transmission Control Protocol)는 연결 지향(connection-oriented) 프로토콜이다. 데이터 바이트 하나를 교환하기 전에 두 기계는 논리적 연결을 설정해야 한다.

이 연결은 유명한 Three-Way Handshake를 통해 생성된다:


Client                           Serveur
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Connexion établie

각 단계는 명확한 목적을 가진다:

  • SYN: 클라이언트가 연결을 열겠다고 알리고 첫 번째 시퀀스 번호(ISN)를 제공한다.

  • SYN-ACK: 서버가 연결을 수락하고 SYN을 확인 응답한 후 자신의 시퀀스 번호를 제공한다.

  • ACK: 클라이언트가 서버의 정보 수신을 확인한다.

이 시점부터 두 기계는 연결 상태를 알게 되고 데이터를 교환하기 시작할 수 있다.

시퀀스 번호

TCP는 데이터를 일련의 패킷이 아닌 연속적인 바이트 스트림(byte stream) 으로 본다.

전송되는 각 바이트는 시퀀스 번호를 가진다.

예시:

Message :

Bonjour

B = octet 0
o = octet 1
n = octet 2
...

1000~1499 바이트를 포함하는 세그먼트가 전송 중 손실되면, 수신자는 정확히 무엇이 누락되었는지 감지할 수 있다.

송신자는 해당 부분만 재전송한다.

이러한 세분성은 TCP의 견고성 이유 중 하나다.

확인 응답 (ACK)

데이터 수신 후, 수신자는 ACK(Acknowledgment) 를 보낸다.

흔히 생각하는 것과 달리, ACK는 다음을 의미하지 않는다:

"이 패킷을 받았습니다."

대신 다음을 의미한다:

"X번까지의 모든 바이트를 받았습니다."

예를 들어:

Client envoie :

0 → 999

Serveur répond :

ACK = 1000

이는 다음을 의미한다:

"바이트 1000 이전의 모든 것이 잘 도착했습니다."

이 메커니즘은 여러 세그먼트를 한 번에 확인 응답(cumulative acknowledgments)할 수 있게 하여 제어 패킷 수를 줄인다.

재전송

ACK가 도착하지 않으면 TCP는 세그먼트가 손실되었다고 가정한다.

자동으로 재전송한다.

재전송 시간 초과(Retransmission Timeout – RTO)는 고정되어 있지 않다.

TCP는 수신된 ACK를 통해 왕복 시간(RTT)을 지속적으로 측정하고 불필요한 재전송을 피하기 위해 RTO를 동적으로 계산한다.

최신 구현은 Fast Retransmit과 같은 메커니즘도 사용한다: 송신자가 여러 개의 중복 ACK(보통 3개)를 수신하면 중간 세그먼트가 손실되었다고 추론하고 타이머 만료를 기다리지 않고 즉시 재전송한다.

패킷 재정렬

인터넷은 두 패킷이 동일한 경로를 따를 것이라고 전혀 보장하지 않는다.

예시:

Paquet 1
Paris
 ↓
Londres
 ↓
New York

Paquet 2
Paris
 ↓
Francfort
 ↓
Chicago
 ↓
New York

두 번째 패킷이 첫 번째 패킷보다 먼저 도착할 수 있다.

TCP는 순서가 잘못된 수신 세그먼트를 재조립 버퍼(reassembly buffer)에 임시로 저장한 후 애플리케이션에 전달하기 전에 재조립한다.

애플리케이션에게는 모든 것이 완벽하게 순서대로 도착하는 것처럼 보인다.

흐름 제어

연결은 네트워크에만 의존하지 않는다.

수신자 또한 제한된 메모리 용량을 가진다.

데이터를 처리할 수 있는 속도보다 빠르게 수신하면 버퍼가 결국 포화된다.

TCP는 슬라이딩 윈도우(Sliding Window) 를 통해 이 문제를 해결한다.

수신자는 각 ACK에 다음을 표시한다:

Window = 32768 octets

이는 다음을 의미한다:

"최대 32KB까지 추가로 보낼 수 있습니다."

이 윈도우가 0이 되면:

Window = 0

송신자는 수신자가 새 윈도우를 사용할 수 있다고 알릴 때까지 전송을 일시 중단한다.

이 메커니즘은 흐름 제어(Flow Control) 를 구성하며 빠른 호스트가 느린 호스트를 압도하는 것을 방지한다.

혼잡 제어

수신자가 데이터를 흡수할 수 있더라도 네트워크 자체가 포화될 수 있다.

라우터는 제한된 큐(queue)를 가진다.

큐가 넘치면 패킷이 폐기된다.

TCP는 손실을 혼잡의 신호로 해석하고 혼잡 윈도우(Congestion Window – cwnd) 를 통해 자동으로 전송 속도를 조절한다.

최신 알고리즘(운영체제에 따라 Reno, CUBIC 또는 BBR)은 최대 처리량과 네트워크 안정성 사이의 균형을 찾기 위해 이 윈도우를 조정한다.

초기 TCP 버전은 주로 두 가지 메커니즘을 사용했다:

  • Slow Start: 혼잡이 감지될 때까지 지수적으로 처리량 증가.

  • Congestion Avoidance: 이후 보다 신중한 성장, 일반적으로 선형적.

이러한 지속적인 적응은 TCP가 네트워크 품질 변화에도 불구하고 성능을 유지하는 이유 중 하나다.

연결 종료

UDP와 달리, TCP 연결은 명확한 종료 과정도 가진다.

각 끝점은 FIN 플래그를 통해 독립적으로 자신의 흐름을 닫는다.

완전한 종료는 일반적으로 네 번의 교환이 필요하다:

FIN
ACK
FIN
ACK

이 절차는 전송 중인 모든 데이터가 연결 파괴 전에 안전하게 전달되도록 보장한다.

UDP: 극도의 단순함

UDP(User Datagram Protocol)는 반대 철학을 채택한다.

비연결형(connectionless) 이다.

다음이 존재하지 않는다:

  • 핸드셰이크 없음;

  • 시퀀스 번호 없음;

  • 확인 응답 없음;

  • 재전송 없음;

  • 흐름 제어 없음;

  • 혼잡 제어 없음.

각 메시지는 독립적인 데이터그램(datagram) 으로 캡슐화되어 네트워크로 전송된 후 송신자에 의해 잊혀진다.

Application → Datagramme UDP → IP → Internet

프로토콜은 두 전송 사이에 어떤 상태도 유지하지 않는다.

각 데이터그램은 이전 것과 완전히 독립적이다.

데이터 무결성

UDP는 전달이나 순서를 보장하지 않지만, 체크섬(checksum) 을 통해 데이터 무결성을 보호한다.

수신 시 체크섬이 다시 계산된다.

  • 값이 일치하면 데이터그램이 수락된다.

  • 그렇지 않으면 즉시 거부된다.

따라서 UDP는 손상된 데이터를 감지하지만 복구를 시도하지는 않는다.

UDP는 왜 이렇게 빠른가?

UDP 헤더는 8바이트만 포함하는 반면, TCP는 최소 20바이트다 (타임스탬프, SACK, Window Scaling 같은 옵션 제외).

연결이 유지되지 않으므로 운영체제가 각 교환의 상태를 추적할 필요가 없어 메모리 소비와 처리 비용도 줄어든다.

애플리케이션은 가능한 재전송을 기다리지 않고 데이터가 도착하는 즉시 거의 받아본다.

데이터 손실이 더 나은 경우

근본적인 아이디어는 간단하다:

오래된 정보는 손실된 정보보다 가치가 낮을 수 있다.

VoIP 대화를 생각해보자.

각 패킷은 약 20ms의 음성을 운반한다.

패킷이 손실되면 재전송하는 데 이 20ms보다 더 오래 걸리는 경우가 많다.

마침내 도착했을 때는 대화가 이미 진행되었을 것이다.

대부분의 애플리케이션은 재전송을 기다리는 대신 손실을 은폐(보간, 무음, 오류 정정)하는 것을 선호한다.

동일한 논리가 적용된다:

  • 실시간 멀티플레이어 게임;

  • 비디오 스트리밍;

  • 텔레메트리 스트림;

  • IoT 센서;

  • GPS 위치 데이터.

최신 값은 완벽하게 신뢰할 수 있는 오래된 값보다 거의 항상 더 유용하다.

2계층: 암호화, TLS

TLS(Transport Layer Security, SSL의 후속)는 TCP를 대체하지 않고 그 위에 추가된다. 구체적으로, TLS는 정상적인 TCP 연결을 설정한 후 내부에서 암호화된 세션을 협상한다: 인증서 교환, 암호화 알고리즘 합의, 세션 키 파생. 이후 전송되는 모든 것은 암호화되고 인증된다.

종종 혼동되는 세 가지 별개의 보장:

  • 기밀성(Confidentialité) : 양 당사자 외에는 누구도 내용을 읽을 수 없다.

  • 무결성(Intégrité) : 전송 중 데이터 변경이 감지된다.

  • 인증(Authentification) : 그러나 기존 TLS에서는 단방향이다. 클라이언트는 서버가 주장하는 바로 그 서버인지 확인하지만(신뢰할 수 있는 인증 기관이 서명한 인증서를 통해), 서버는 클라이언트의 신원에 대해 아무것도 확인하지 않는다. 이는 사이트를 방문할 때 HTTPS의 정확한 모델이다: 브라우저는 사이트를 인증하지만, 사이트는 사용자를 인증하지 않는다(사용자 인증은 세션 쿠키, 토큰 등 별도 메커니즘을 통해 이루어진다).

TLS 1.3(현재 권장 버전)은 일반적인 경우 핸드셰이크를 한 번의 왕복으로 줄였으며, TLS 1.2는 두 번이 필요했으므로 연결 지연 시간이 현저히 감소했다.

2bis계층: mTLS -- 인증이 상호 방식이 되다

mTLS(mutual TLS)는 추가 제약이 있는 TLS다: 서버가 클라이언트의 인증서도 _요구_하고 확인한다. 양측 모두 공통 신뢰 인증 기관이 서명한 인증서를 통해 자신의 신원을 증명한다.

이는 분산 아키텍처에서 서비스 간 통신을 위한 자연스러운 메커니즘이다: 일반 HTTPS가 브라우저가 공용 서버와 통신하는 데 충분한 반면, mTLS는 다른 질문에 답한다: 내부 서비스가 네트워크에 침투한 공격자가 아닌 권한 있는 다른 내부 서비스와 통신하고 있음을 어떻게 알 수 있을까?

Client                                          Serveur
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificat serveur ──────────│
  │──── vérifie le certificat serveur ─────────────│
  │──── envoie SON PROPRE certificat client ──────▶│
  │◀─── vérifie le certificat client ───────────────│
  │──── clés de session dérivées, canal chiffré ──▶│

mTLS의 대가는 운영적이다: 내부 인증 기관(CA), 각 서비스에 인증서를 배포하는 메커니즘, 그리고 갱신/폐기 전략이 필요하다. 서비스가 적은 단일 머신 환경에서는 때로는 이점보다 복잡성이 더 클 수 있다 -- mTLS는 서비스 간 트래픽이 완전히 제어할 수 없는 네트워크(여러 호스트, 멀티테넌트 클라우드)를 통과할 때, 또는 단순히 네트워크 "내부"에 있다는 이유만으로 어떤 서비스도 암시적으로 신뢰하지 않는 제로 트러스트 정책을 원할 때 필요해진다.

3계층: TCP+TLS 위의 애플리케이션 프로토콜

전송과 암호화가 준비되면, 이제 _교환을 어떻게 구조화할지_를 정의해야 한다. 이것이 애플리케이션 프로토콜의 역할이다.

HTTP / HTTPS

HTTP는 요청-응답 프로토콜이다: 클라이언트가 연결을 열고(keep-alive로 재사용하거나), 요청을 보내고, 응답을 기다리며, 연결은 닫히거나 재사용될 수 있다. HTTPS는 단순히 TLS 위의 HTTP다 -- S는 프로토콜의 의미론을 변경하지 않으며, 단지 전송이 암호화된다는 사실만 다르다.

요청-응답 모델에는 구조적 한계가 있다: 서버가 먼저 말할 수 없다. 서버는 클라이언트가 요청한 것에만 응답할 수 있다. 빈번한 폴링(매초 "새로운 것이 있나?" 확인)의 경우 작동하지만 리소스를 낭비한다 -- 매 요청이 프로토콜 오버헤드를 다시 생성하며, 대부분의 경우 발표할 새로운 것이 없다.

WebSocket (WS / WSS)

WebSocket은 정확히 이 한계를 해결한다. 연결은 일반 HTTP 요청으로 시작되지만(Upgrade: websocket 헤더와 함께), 핸드셰이크가 수락되면 기본 TCP 연결은 더 이상 HTTP 요청-응답 채널이 아니라 클라이언트와 서버가 언제든지 메시지를 보낼 수 있는 전이중 양방향 채널이 되며, 매 교환마다 요청-응답 주기를 다시 발생시킬 필요가 없다.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS는 HTTPS가 TLS 위의 HTTP인 것처럼, TLS 위의 WebSocket이다. 이는 실시간 서버 푸시가 필요한 모든 것(채팅, 알림, 거래 스트림, 게임 이벤트)에 선택되는 프로토콜이며, 베어 TCP 위에 직접 바이너리 프로토콜을 관리하고 싶지 않을 때 사용한다.

gRPC

마이크로서비스 세계 밖에서는 덜 알려졌지만 서비스 간 통신에서 핵심적인 gRPC는 HTTP/2를 기반으로 하므로(따라서 TCP + 선택적 TLS), 메시지를 Protocol Buffers(바이너리, 타입화, 컴팩트 -- 대부분 REST API의 텍스트 JSON과 대조됨)로 직렬화하며, HTTP/2의 다중화 덕분에 양방향 스트리밍을 기본 지원한다(단일 TCP 연결 위의 여러 논리적 스트림, 순차적 HTTP/1.1 요청이 가졌던 head-of-line 차단 없음).

QUIC / HTTP3

QUIC은 전송 계층에서 TCP 대신 UDP로 시작하면서 판을 바꾸는 동시에, TCP가 기본적으로 제공했던 신뢰성 보장을 전체 연결이 아닌 스트림별로 재구현하여 전송 계층의 head-of-line 차단을 제거한다(한 스트림의 패킷 손실이 동일 연결의 다른 스트림을 차단하지 않음). TLS 1.3은 위에 추가되는 대신 QUIC에 직접 통합되어 핸드셰이크 지연 시간을 더욱 줄인다. HTTP/3는 QUIC 위의 HTTP다.

개요: 각 프로토콜의 위치

Couche Protocoles Rôle Transport TCP, UDP Faire voyager des octets, fiable ou non Transport (nouvelle génération) QUIC UDP + fiabilité par flux + TLS intégré Sécurité TLS, mTLS Chiffrement, intégrité, authentification (uni ou mutuelle) Application HTTP/HTTPS, WS/WSS, gRPC Structurer les échanges (requête-réponse, bidirectionnel, RPC typé)

구체적인 예시: 웹 대시보드와 내부 서비스를 가진 마이크로서비스 아키텍처는 합리적으로 HTTPS(대시보드 ↔ 공개 API, 브라우저 측 단방향 인증으로 충분), mTLS(내부 서비스 ↔ 서비스, 상호 인증 필요), WSS(대시보드로 푸시되는 실시간 알림)를 결합할 수 있다 -- 세 가지 다른 애플리케이션 프로토콜이 모두 동일한 TCP + TLS 기반 위에 구축된다.

실전에서 어떻게 선택할까

보통 세 가지 질문으로 결정할 수 있다:

  1. 신뢰성과 순서가 필요한가, 아니면 데이터의 신선도가 보장된 전달보다 우선하는가? → 그렇다면 TCP, 아니라면 UDP(또는 다른 절충안을 통해 둘 다 원한다면 QUIC).

  2. 서버가 메시지를 먼저 시작할 수 있어야 하는가, 아니면 클라이언트가 항상 먼저 요청하는가? → 서버가 푸시해야 한다면 WebSocket/gRPC 스트리밍, 아니라면 일반 HTTP.

  3. 양측 모두 상호 신원을 증명해야 하는가, 아니면 한쪽만 확인이 필요한가? → 제로 트러스트 환경에서 서비스 간 통신은 mTLS, 일반 공용 클라이언트는 단순 TLS.

운영 복잡성은 계층이 추가될 때마다 증가한다. 베어 TCP는 관리할 인프라가 전혀 없고, TLS는 인증서가 필요하며, mTLS는 CA와 갱신 전략이 필요하고, gRPC는 공유 Protobuf 스키마 정의가 필요하다. 올바른 방법은 아래 계층이 구체적인 한계를 보일 때만 복잡성을 높이는 것이지, 미리 대비해서 높이는 것이 아니다.

Makineler Birbirleriyle Nasıl Konuşur: TCP'den mTLS'ye Bir Bakış

TCP, UDP, TLS, mTLS, HTTP ve WebSocket neden rakip alternatifler değil de üst üste bindirilmiş katmanlardır; ham taşımadan karşılıklı kimlik doğrulamaya kadar makineden makineye iletişimin hiyerarşik bir turu.

Sorun: Çok fazla kısaltma, yeterince hiyerarşi yok

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; bunlardan bahseden çoğu kaynak, onları "kullanım durumuna göre seçilecek" düz bir alternatifler listesi olarak sunar. Gerçekte ise aynı düzlemde değillerdir: bazıları taşıma protokolleridir, bazıları taşımanın etrafına sarılan güvenlik katmanlarıdır, bazıları ise ilk ikisinin üzerine inşa edilen uygulama katmanı protokolleridir. Hiyerarşiyi anlamak, TCP ile TLS arasında neden asla "seçim yapılmadığını" anlamaktır: önce TCP seçilir, sonra üzerine TLS eklenip eklenmeyeceğine karar verilir.

Bu makale, bu hiyerarşiyi katman katman, ham taşımadan karşılıklı kimlik doğrulamaya kadar yeniden inşa eder; her seviyede: neyi garanti ettiği, neyi garanti etmediği ve ne zaman bununla yetinileceği.

Seviye 1: Taşıma (TCP ve UDP)

Her şey burada başlar. TCP ve UDP, OSI modelinin Taşıma Katmanı (Layer 4)'nın iki ana protokolüdür. Rolleri aynıdır: farklı makinelerde çalışan iki uygulama arasında veri akışı taşımak. Ancak bunu başarma biçimleri kökten farklıdır.

Ağ katmanında (Layer 3) bulunan IP'nin (Internet Protokolü) yalnızca paketleri bir ana bilgisayardan diğerine yönlendirdiğini anlamak önemlidir. Ne varmayı, ne sıralamayı, ne de tekilliği garanti eder. Yönlendiriciler her paket için bağımsız yönlendirme kararları alır.

İşte tam da bu garanti eksikliğini TCP telafi ederken, UDP son derece hafif kalmak için bilinçli olarak hiçbir şey eklememeyi tercih eder.

TCP: Önce güvenilirlik

TCP (İletim Kontrol Protokolü) bağlantı odaklı (connection-oriented) bir protokoldür. Herhangi bir veri baytı değiş tokuş edilmeden önce, iki makine mantıksal bir bağlantı kurmalıdır.

Bu bağlantı, ünlü Üç Yollü El Sıkışma (Three-Way Handshake) ile oluşturulur:


İstemci                          Sunucu
SYN ---------------------------->
         <--------------------- SYN + ACK
ACK ---------------------------->
Bağlantı kuruldu

Her adımın belirli bir amacı vardır:

  • SYN: istemci bir bağlantı açmak istediğini bildirir ve bir ilk sıra numarası (ISN) sağlar.

  • SYN-ACK: sunucu bağlantıyı kabul eder, SYN'in alındığını onaylar ve kendi sıra numarasını sağlar.

  • ACK: istemci, sunucunun bilgilerini aldığını onaylar.

Bu noktadan itibaren, iki makine bağlantının durumunu bilir ve veri alışverişine başlayabilir.

Sıra numaraları

TCP verileri bir dizi paket olarak değil, sürekli bir bayt akışı (byte stream) olarak görür.

Gönderilen her baytın bir sıra numarası vardır.

Örnek:

Mesaj:

Merhaba

M = bayt 0
e = bayt 1
r = bayt 2
...

1000'den 1499'a kadar olan baytları içeren bir segment taşıma sırasında kaybolursa, alıcı tam olarak neyin eksik olduğunu tespit edebilir.

Gönderici yalnızca bu kısmı yeniden iletir.

Bu ayrıntı düzeyi, TCP'nin sağlamlığının nedenlerinden biridir.

Alındı bildirimleri (ACK)

Veriler alındıktan sonra, alıcı bir ACK (Alındı Bildirimi - Acknowledgment) gönderir.

Çoğu zaman sanılanın aksine, bir ACK şu anlama gelmez:

"Bu paketi aldım"

Bunun yerine şu anlama gelir:

"X numarasına kadar tüm baytları aldım."

Örneğin:

İstemci gönderir:

0 → 999

Sunucu yanıtlar:

ACK = 1000

Bu şu anlama gelir:

"Bayt 1000'den önceki her şey sorunsuz geldi."

Bu mekanizma, aynı anda birden fazla segmentin alındığını bildirmeye olanak tanır (kümülatif alındı bildirimleri - cumulative acknowledgments), böylece kontrol paketlerinin sayısını azaltır.

Yeniden iletimler

Bir ACK asla gelmezse, TCP segmentin kaybolduğunu varsayar.

Onu otomatik olarak yeniden iletir.

Yeniden iletim zaman aşımı (RTO - Retransmission Timeout) sabit değildir.

TCP, alınan ACK'ler sayesinde gidiş-dönüş süresini (RTT) sürekli ölçer ve gereksiz yeniden iletimleri önlemek için RTO'yu dinamik olarak hesaplar.

Modern uygulamalar ayrıca Hızlı Yeniden İletim (Fast Retransmit) gibi mekanizmalar kullanır: bir gönderici birden fazla yinelenen ACK aldığında (genellikle üç), aradaki bir segmentin kaybolduğu sonucunu çıkarır ve zamanlayıcının dolmasını beklemeden onu hemen yeniden gönderir.

Paketlerin yeniden sıralanması

İnternet, iki paketin aynı yolu izleyeceğini kesinlikle garanti etmez.

Örnek:

Paket 1
Paris
 ↓
Londra
 ↓
New York

Paket 2
Paris
 ↓
Frankfurt
 ↓
Şikago
 ↓
New York

İkinci paket, birinciden önce gelebilir.

TCP daha sonra sıra dışı alınan segmentleri geçici olarak bir tamponda (yeniden birleştirme tamponu - reassembly buffer) saklar ve uygulamaya teslim etmeden önce bunları yeniden birleştirir.

Uygulama için her şey mükemmel bir sırayla geliyormuş gibi görünür.

Akış kontrolü

Bir bağlantı yalnızca ağa bağlı değildir.

Alıcının ayrıca sınırlı bir bellek kapasitesi vardır.

Verileri işleyebileceğinden daha hızlı alırsa, tamponları sonunda dolar.

TCP bu sorunu bir kayan pencere (Sliding Window) mekanizmasıyla çözer.

Alıcı her ACK'de şunu belirtir:

Window = 32768 bayt

Bu şu anlama gelir:

"Bana 32 KB'ye kadar daha gönderebilirsin."

Bu pencere sıfıra düşerse:

Window = 0

Gönderici, alıcı yeni bir kullanılabilir pencere bildirene kadar iletimleri geçici olarak durdurur.

Bu mekanizma Akış Kontrolü (Flow Control) olarak adlandırılır ve hızlı bir ana bilgisayarın daha yavaş bir ana bilgisayarı boğmasını engeller.

Tıkanıklık kontrolü

Alıcı verileri absorbe edebilse bile, ağın kendisi doygun hale gelebilir.

Yönlendiricilerin sınırlı kuyrukları (queues) vardır.

Bunlar taştığında, paketler silinir.

TCP kayıpları bir tıkanıklık işareti olarak yorumlar ve bir tıkanıklık penceresi (Congestion Window – cwnd) aracılığıyla hızını otomatik olarak ayarlar.

Modern algoritmalar (işletim sistemine bağlı olarak Reno, CUBIC veya BBR gibi) maksimum hız ve ağ kararlılığı arasında bir denge bulmak için bu pencereyi ayarlar.

TCP'nin ilk sürümleri esas olarak iki mekanizma kullanıyordu:

  • Slow Start (Yavaş Başlangıç): tıkanıklık tespit edilene kadar üstel hız artışı.

  • Congestion Avoidance (Tıkanıklıktan Kaçınma): ardından daha ihtiyatlı, genellikle doğrusal büyüme.

Bu sürekli uyum, TCP'nin ağ kalitesi değişimlerine rağmen performanslı kalmasının nedenlerinden biridir.

Bağlantı kapatma

UDP'nin aksine, bir TCP bağlantısının ayrıca düzgün bir kapanışı vardır.

Her uç nokta, FIN bayrağı sayesinde kendi akışını bağımsız olarak kapatır.

Tam bir kapanış genellikle dört alışveriş gerektirir:

FIN
ACK
FIN
ACK

Bu prosedür, bağlantı sonlandırılmadan önce iletilmekte olan tüm verilerin teslim edilmesini garanti eder.

UDP: Maksimum basitlik

UDP (Kullanıcı Veri Birimi Protokolü) ters felsefeyi benimser.

Bağlantısızdır (connectionless).

Aşağıdakilerin hiçbiri yoktur:

  • el sıkışma yok;

  • sıra numarası yok;

  • alındı bildirimi yok;

  • yeniden iletim yok;

  • akış kontrolü yok;

  • tıkanıklık kontrolü yok.

Her mesaj, bağımsız bir veri birimi (datagram) içinde kapsüllenir, ağa iletilir ve ardından gönderici tarafından unutulur.

Uygulama → UDP Veri Birimi → IP → İnternet

Protokol, iki gönderim arasında herhangi bir durum tutmaz.

Her veri birimi öncekilerden tamamen bağımsızdır.

Veri bütünlüğü

UDP teslimatı veya sıralamayı garanti etmese de, bir sağlama toplamı (checksum) sayesinde veri bütünlüğünü yine de korur.

Alımda, sağlama toplamı yeniden hesaplanır.

  • Değerler eşleşirse, veri birimi kabul edilir.

  • Aksi takdirde, hemen reddedilir.

UDP bu nedenle bozuk verileri tespit eder, ancak asla kurtarmaya çalışmaz.

UDP neden bu kadar hızlıdır?

UDP başlığı yalnızca 8 bayt içerirken, TCP için minimum 20 bayt (zaman damgaları, SACK veya Window Scaling gibi seçenekler hariç).

Herhangi bir bağlantı sürdürülmediğinden, işletim sisteminin her alışverişin durumunu takip etmesi gerekmez, bu da bellek tüketimini ve işlem maliyetini azaltır.

Uygulama, olası yeniden iletimleri beklemeden verileri geldikleri anda alır.

Bir veriyi kaybetmenin tercih edilebilir olduğu durumlar

Temel fikir basittir:

Eski bir bilgi, kaybolmuş bir bilgiden daha az değerli olabilir.

Bir VoIP konuşmasını ele alalım.

Her paket yaklaşık 20 ms ses taşır.

Bir paket kaybolursa, onu yeniden iletmek genellikle bu 20 ms'den daha uzun sürer.

Sonunda ulaştığında, konuşma zaten ilerlemiş olur.

Çoğu uygulama, yeniden iletimi beklemek yerine kaybı maskelemeyi (interpolasyon, sessizlik, hata düzeltme) tercih eder.

Aynı mantık şunlar için de geçerlidir:

  • gerçek zamanlı çok oyunculu oyunlar;

  • video akışı;

  • telemetri akışları;

  • IoT sensörleri;

  • GPS konum verileri.

Güncel bir değer, mükemmel şekilde güvenilir eski bir değerden neredeyse her zaman daha kullanışlıdır.

Seviye 2: Şifreleme, TLS

TLS (Taşıma Katmanı Güvenliği, SSL'in halefi) TCP'nin yerini almaz, onun üzerine eklenir. Somut olarak, TLS normal bir TCP bağlantısı kurar, ardından içinde şifreli bir oturum müzakere eder: sertifika değişimi, bir şifreleme algoritması üzerinde anlaşma, oturum anahtarlarının türetilmesi. Daha sonra iletilen her şey şifrelenir ve doğrulanır.

Genellikle karıştırılan üç ayrı garanti:

  • Gizlilik: iki taraftan başka hiç kimse içeriği okuyamaz.

  • Bütünlük: iletilen verilerdeki herhangi bir değişiklik tespit edilir.

  • Kimlik Doğrulama: ancak klasik TLS'de, tek yönlüdür: istemci, sunucunun gerçekten iddia ettiği kişi olduğunu doğrular (güvenilir bir otorite tarafından imzalanmış sertifikası aracılığıyla), ancak sunucu istemcinin kimliği hakkında hiçbir şey doğrulamaz. Bu, bir siteyi ziyaret ettiğinizde HTTPS'nin tam olarak modelidir: tarayıcı siteyi doğrular, site sizi doğrulamaz (kullanıcı kimlik doğrulaması ayrı bir mekanizma olan oturum çerezi, token aracılığıyla yapılır).

TLS 1.3 (önerilen güncel sürüm), el sıkışmayı normal durumda tek bir gidiş-dönüşe indirgemiştir (TLS 1.2'de iki iken), bu da bağlantı gecikmesini önemli ölçüde azaltır.

Seviye 2b: mTLS -- kimlik doğrulama karşılıklı hale gelir

mTLS (karşılıklı TLS), ek bir kısıtlama ile TLS'dir: sunucu ayrıca istemciden de bir sertifika talep eder ve bunu doğrular. Her iki taraf da ortak bir güvenilir otorite tarafından imzalanmış bir sertifika aracılığıyla kimliklerini kanıtlar.

Bu, dağıtık bir mimaride hizmetten hizmete iletişim için doğal mekanizmadır: klasik HTTPS'nin bir tarayıcının genel bir sunucuyla konuşması için yeterli olduğu yerde, mTLS farklı bir soruyu yanıtlar; bir iç hizmet, yetkili başka bir iç hizmetle mi yoksa ağa sızmış bir saldırganla mı konuştuğunu nasıl bilir?

İstemci                                          Sunucu
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + sunucu sertifikası ──────────│
  │──── sunucu sertifikasını doğrula ──────────────│
  │──── KENDİ istemci sertifikasını gönder ───────▶│
  │◀─── istemci sertifikasını doğrula ─────────────│
  │──── oturum anahtarları türetilir, şifreli kanal▶│

mTLS'nin karşılığı operasyoneldir: dahili bir sertifika otoritesi (CA), her hizmete sertifika dağıtmak için bir mekanizma ve bir döndürme/iptal stratejisi gerekir. Az sayıda hizmete sahip tek makinelik bir ortamda, bu bazen faydadan çok karmaşıklık getirir -- mTLS, hizmetler arası trafik tam olarak kontrol edilmeyen bir ağdan (birden çok ana bilgisayar, çok kiracılı bulut) geçtiğinde veya hiçbir hizmetin yalnızca ağın "içinde" olduğu için örtük olarak güvenilir olmadığı zero trust tipi bir politika istendiğinde gerekli hale gelir.

Seviye 3: TCP+TLS üzerinde uygulama katmanı protokolleri

Taşıma ve şifreleme yerine oturduktan sonra, geriye alışverişlerin nasıl yapılandırılacağını tanımlamak kalır. Bu, uygulama katmanı protokollerinin rolüdür.

HTTP / HTTPS

HTTP, istek-yanıt protokolüdür: istemci bir bağlantı açar (veya keep-alive ile mevcut birini yeniden kullanır), bir istek gönderir, bir yanıt bekler, bağlantı daha sonra kapanabilir veya yeniden kullanılabilir. HTTPS, HTTP'nin TLS üzerinde olmasıdır -- S, protokolün anlambilimini değiştirmez, yalnızca taşımanın şifrelenmiş olmasını sağlar.

İstek-yanıt modelinin yapısal bir sınırlaması vardır: sunucu asla ilk konuşamaz. Yalnızca istemcinin talep ettiği şeylere yanıt verebilir. Sık yoklama (polling) için (her saniye "yeni bir şey var mı?" diye kontrol etmek), çalışır ancak kaynak israfına neden olur -- her istek, çoğu zaman bildirilecek yeni bir şey olmamasına rağmen, protokol yükünü yeniden oluşturur.

WebSocket (WS / WSS)

WebSocket tam olarak bu sınırlamayı yanıtlar. Bağlantı klasik bir HTTP isteği olarak başlar (Upgrade: websocket başlığı ile), ancak el sıkışma kabul edildikten sonra, alttaki TCP bağlantısı artık bir HTTP istek-yanıt kanalı değildir -- istemci ve sunucunun her an mesaj gönderebildiği, her alışverişte istek-yanıt döngüsünü yeniden başlatmaya gerek olmayan çift yönlü tam çift yönlü (full-duplex) bir kanal haline gelir.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS, HTTPS'nin HTTP üzerinde TLS olması gibi, WebSocket'in TLS üzerinde olmasıdır. Gerçek zamanlı sunucu itme (push) gerektiren her şey için tercih edilen protokoldür -- sohbet, bildirimler, ticaret akışları, oyun etkinlikleri -- çıplak TCP üzerinde kendi ikili protokolünü yönetmek istemediğinizde.

gRPC

Mikroservis dünyası dışında daha az bilinir ancak hizmetten hizmete iletişimde merkezidir: gRPC, HTTP/2'ye dayanır (dolayısıyla TCP + isteğe bağlı TLS), mesajları Protocol Buffers ile serileştirir (çoğu REST API'nin metin JSON'unun aksine ikili, tür belirtilmiş, kompakt) ve HTTP/2'nin çoğullaması sayesinde yerel olarak çift yönlü akışa izin verir (tek bir TCP bağlantısı üzerinde birden fazla mantıksal akış, sıralı HTTP/1.1 isteklerinin sahip olacağı head-of-line blocking olmadan).

QUIC / HTTP3

QUIC, taşıma seviyesinde TCP yerine UDP'den başlayarak işleri değiştirir, aynı zamanda TCP'nin yerel olarak sunduğu güvenilirlik garantilerini üzerine yeniden uygular -- ancak genel olarak değil, akış bazında, bu da taşıma seviyesinde head-of-line blocking'i ortadan kaldırır (bir akışta kaybolan paket, aynı bağlantının diğer akışlarını engellemez). TLS 1.3, üzerine eklenmek yerine doğrudan QUIC'in içine entegre edilmiştir, bu da el sıkışma gecikmesini daha da azaltır. HTTP/3, QUIC üzerinde HTTP'dir.

Genel bakış: her protokolün yeri

Katman Protokoller Rol Taşıma TCP, UDP Bayt taşımak, güvenilir veya değil Taşıma (yeni nesil) QUIC UDP + akış bazında güvenilirlik + gömülü TLS Güvenlik TLS, mTLS Şifreleme, bütünlük, kimlik doğrulama (tek veya karşılıklı) Uygulama HTTP/HTTPS, WS/WSS, gRPC Alışverişleri yapılandırma (istek-yanıt, çift yönlü, tür belirtilmiş RPC)

Somut bir örnek: bir web panosu ve iç hizmetleri olan bir mikroservis mimarisi, makul bir şekilde HTTPS (pano ↔ genel API, tarayıcı tarafında tek yönlü kimlik doğrulama yeterli), mTLS (içte hizmet ↔ hizmet, karşılıklı kimlik doğrulama gerekli) ve WSS (panoya gerçek zamanlı bildirimler) birleştirebilir -- tümü aynı TCP + TLS temeli üzerine inşa edilmiş üç farklı uygulama katmanı protokolü.

Pratikte nasıl seçim yapılır

Üç soru genellikle karar vermek için yeterlidir:

  1. Güvenilirlik ve sıralamaya mı ihtiyacım var, yoksa verinin tazeliği garantili teslimattan daha mı önemli? → Evetse TCP, hayırsa UDP (veya her ikisini de farklı bir uzlaşmayla birleştiren QUIC).

  2. Sunucu mesaj başlatabilmeli mi, yoksa istemci her zaman ilk talebi mi yapar? → Sunucu itmeli (push) ise WebSocket/gRPC akışı, değilse klasik HTTP.

  3. Her iki taraf da birbirine kimliğini kanıtlamalı mı, yoksa yalnızca birinin doğrulanması mı gerekiyor? → Zero-trust ortamında hizmetten hizmete için mTLS, klasik genel istemci için basit TLS.

Operasyonel karmaşıklık eklenen her katmanla artar: çıplak TCP'nin yönetilecek altyapısı yoktur, TLS sertifikalar gerektirir, mTLS bir CA ve döndürme stratejisi gerektirir, gRPC paylaşılan bir Protobuf şema tanımı gerektirir. Doğru refleks, karmaşıklığı yalnızca alttaki katman somut bir sınır gösterdiğinde artırmaktır, önceden değil.

Come le macchine comunicano tra loro: una panoramica da TCP a mTLS

Perché TCP, UDP, TLS, mTLS, HTTP e WebSocket non sono alternative concorrenti ma livelli sovrapposti; una panoramica gerarchica della comunicazione macchina a macchina, dal trasporto grezzo all'autenticazione reciproca.

Il problema: troppi acronimi, poca gerarchia

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; la maggior parte delle risorse che ne parlano li presentano come una lista piatta di opzioni intercambiabili, "da scegliere in base al caso d'uso". In realtà non sono sullo stesso piano: alcuni sono protocolli di trasporto, altri sono livelli di sicurezza che si avvolgono attorno al trasporto, altri ancora sono protocolli applicativi che si basano sui primi due. Comprendere la gerarchia significa capire perché non si "sceglie" mai tra TCP e TLS: si sceglie TCP, poi si decide se mettere TLS sopra.

Questo articolo ricostruisce questa gerarchia strato per strato, dal trasporto grezzo all'autenticazione reciproca, con per ogni livello: cosa garantisce, cosa non garantisce, e quando accontentarsene.

Livello 1: il trasporto (TCP contro UDP)

Tutto inizia qui. TCP e UDP sono i due principali protocolli del livello Trasporto (Layer 4) del modello OSI. Il loro ruolo è identico: trasportare un flusso di dati tra due applicazioni eseguite su macchine diverse. Tuttavia, il loro modo di raggiungerlo è radicalmente diverso.

È importante capire che IP (Internet Protocol), situato al livello di rete (Layer 3), si limita a instradare pacchetti da un host all'altro. Non garantisce né la loro consegna, né il loro ordine, né la loro unicità. I router prendono semplicemente decisioni di instradamento indipendenti per ogni pacchetto.

È proprio questa assenza di garanzie che TCP viene a compensare, mentre UDP sceglie deliberatamente di non aggiungere nulla per rimanere estremamente leggero.

TCP: l'affidabilità prima di tutto

TCP (Transmission Control Protocol) è un protocollo orientato alla connessione (connection-oriented). Prima di scambiare il minimo byte di dati, le due macchine devono stabilire una connessione logica.

Questa connessione viene creata grazie al famoso Three-Way Handshake:


Client                           Server
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Connessione stabilita

Ogni passo ha un obiettivo preciso:

  • SYN: il client annuncia di voler aprire una connessione e fornisce un primo numero di sequenza (Initial Sequence Number - ISN).

  • SYN-ACK: il server accetta la connessione, accusa ricevuta del SYN e fornisce a sua volta il proprio numero di sequenza.

  • ACK: il client conferma la ricezione delle informazioni del server.

Da questo momento, le due macchine conoscono lo stato della connessione e possono iniziare a scambiare dati.

I numeri di sequenza

TCP non vede i dati come una successione di pacchetti, ma come un flusso continuo di byte (byte stream).

Ogni byte inviato possiede un numero di sequenza.

Esempio:

Messaggio:

Bonjour

B = byte 0
o = byte 1
n = byte 2
...

Se un segmento contenente i byte da 1000 a 1499 viene perso durante il trasporto, il ricevente può rilevare esattamente cosa manca.

Il mittente ritrasmette solo quella porzione.

Questa granularità è una delle ragioni della robustezza di TCP.

Gli acknowledgement (ACK)

Dopo la ricezione dei dati, il destinatario invia un ACK (Acknowledgment).

Contrariamente a quanto si immagina spesso, un ACK non significa:

"Ho ricevuto questo pacchetto"

Significa piuttosto:

"Ho ricevuto tutti i byte fino al numero X."

Per esempio:

Client invia:

0 → 999

Server risponde:

ACK = 1000

Ciò significa:

"Tutto ciò che precede il byte 1000 è arrivato correttamente."

Questo meccanismo permette di accusare ricevuta di più segmenti contemporaneamente (cumulative acknowledgments), riducendo così il numero di pacchetti di controllo.

Le ritrasmissioni

Se un ACK non arriva mai, TCP presume che il segmento sia perso.

Lo ritrasmette automaticamente.

Il tempo di ritrasmissione (Retransmission Timeout – RTO) non è fisso.

TCP misura continuamente il tempo di andata e ritorno (RTT) grazie agli ACK ricevuti e calcola dinamicamente l'RTO per evitare ritrasmissioni inutili.

Le implementazioni moderne utilizzano anche meccanismi come Fast Retransmit: quando un mittente riceve più ACK duplicati (di solito tre), deduce che un segmento intermedio è stato perso e lo rinvia immediatamente, senza attendere la scadenza del timer.

Riordino dei pacchetti

Internet non garantisce assolutamente che due pacchetti seguano lo stesso percorso.

Esempio:

Pacchetto 1
Parigi
 ↓
Londra
 ↓
New York

Pacchetto 2
Parigi
 ↓
Francoforte
 ↓
Chicago
 ↓
New York

Il secondo pacchetto può arrivare prima del primo.

TCP memorizza temporaneamente i segmenti ricevuti fuori ordine in un buffer (reassembly buffer), poi li riassembla prima di consegnarli all'applicazione.

Per l'applicazione, tutto sembra arrivare perfettamente in ordine.

Controllo di flusso

Una connessione non dipende solo dalla rete.

Anche il ricevente possiede una capacità di memoria limitata.

Se riceve più velocemente di quanto possa elaborare i dati, i suoi buffer finiscono per saturarsi.

TCP risolve questo problema grazie a una finestra scorrevole (Sliding Window).

Il ricevente indica in ogni ACK:

Window = 32768 byte

Ciò significa:

"Puoi inviarmi fino a 32 KB aggiuntivi."

Se questa finestra scende a zero:

Window = 0

Il mittente sospende temporaneamente le trasmissioni finché il ricevente non annuncia una nuova finestra disponibile.

Questo meccanismo costituisce il controllo di flusso (Flow Control) e impedisce che un host veloce inondi un host più lento.

Controllo della congestione

Anche se il ricevente è in grado di assorbire i dati, la rete stessa può diventare satura.

I router dispongono di code (queues) limitate.

Quando traboccano, i pacchetti vengono eliminati.

TCP interpreta le perdite come un segno di congestione e adatta automaticamente la sua velocità grazie a una finestra di congestione (Congestion Window – cwnd).

Gli algoritmi moderni (come Reno, CUBIC o BBR, a seconda dei sistemi operativi) regolano questa finestra per trovare un equilibrio tra velocità massima e stabilità della rete.

Le prime versioni di TCP utilizzavano principalmente due meccanismi:

  • Slow Start: aumento esponenziale della velocità fino al rilevamento di una congestione.

  • Congestion Avoidance: crescita successivamente più prudente, generalmente lineare.

Questo adattamento permanente è una delle ragioni per cui TCP rimane performante nonostante le variazioni di qualità della rete.

Chiusura della connessione

A differenza di UDP, una connessione TCP ha anche una chiusura pulita.

Ogni estremità chiude indipendentemente il proprio flusso grazie al flag FIN.

Una chiusura completa richiede generalmente quattro scambi:

FIN
ACK
FIN
ACK

Questa procedura garantisce che tutti i dati in transito siano stati correttamente consegnati prima della distruzione della connessione.

UDP: la massima semplicità

UDP (User Datagram Protocol) adotta la filosofia opposta.

È senza connessione (connectionless).

Non esiste:

  • alcun handshake;

  • alcun numero di sequenza;

  • alcun acknowledgement;

  • alcuna ritrasmissione;

  • alcun controllo di flusso;

  • alcun controllo della congestione.

Ogni messaggio è semplicemente incapsulato in un datagramma indipendente, trasmesso alla rete, e poi dimenticato dal mittente.

Applicazione → Datagramma UDP → IP → Internet

Il protocollo non mantiene alcuno stato tra due invii.

Ogni datagramma è totalmente indipendente dai precedenti.

L'integrità dei dati

Sebbene UDP non garantisca né la consegna né l'ordine, protegge comunque l'integrità dei dati grazie a un checksum.

Alla ricezione, il checksum viene ricalcolato.

  • Se i valori corrispondono, il datagramma viene accettato.

  • Altrimenti, viene immediatamente respinto.

UDP rileva quindi i dati corrotti, ma non tenta mai di recuperarli.

Perché UDP è così veloce?

L'intestazione UDP contiene solo 8 byte, contro un minimo di 20 byte per TCP (senza contare le opzioni come timestamp, SACK o Window Scaling).

Non essendo mantenuta alcuna connessione, il sistema operativo non deve tenere traccia dello stato di ogni scambio, riducendo così anche il consumo di memoria e il costo di elaborazione.

L'applicazione riceve i dati quasi immediatamente dopo il loro arrivo, senza attendere eventuali ritrasmissioni.

Quando perdere un dato è preferibile

L'idea di fondo è semplice:

Un'informazione vecchia può avere meno valore di un'informazione persa.

Prendiamo una conversazione VoIP.

Ogni pacchetto trasporta circa 20 ms di voce.

Se un pacchetto viene perso, ritrasmetterlo richiederebbe spesso più tempo di questi 20 ms.

Quando finalmente arriverebbe, la conversazione sarebbe già avanzata.

La maggior parte delle applicazioni preferisce quindi mascherare la perdita (interpolazione, silenzio, correzione d'errore) piuttosto che attendere la ritrasmissione.

Lo stesso ragionamento si applica:

  • ai giochi multiplayer in tempo reale;

  • allo streaming video;

  • ai flussi di telemetria;

  • ai sensori IoT;

  • ai dati di posizione GPS.

Un valore recente è quasi sempre più utile di un valore vecchio perfettamente affidabile.

Livello 2: la crittografia, TLS

TLS (Transport Layer Security, successore di SSL) non sostituisce TCP, si aggiunge sopra. Concretamente, TLS stabilisce una connessione TCP normale, poi negozia una sessione crittografata all'interno: scambio di certificati, accordo su un algoritmo di crittografia, derivazione delle chiavi di sessione. Tutto ciò che transita successivamente è crittografato e autenticato.

Tre garanzie distinte, spesso confuse:

  • Riservatezza**: nessuno all'infuori delle due parti può leggere il contenuto.

  • Integrità**: qualsiasi alterazione dei dati in transito viene rilevata.

  • Autenticazione**: ma nella TLS classica, a senso unico: il client verifica che il server sia davvero chi dice di essere (tramite il suo certificato, firmato da un'autorità di fiducia), ma il server non verifica nulla sull'identità del client. Questo è esattamente il modello di HTTPS quando visitate un sito: il browser autentica il sito, il sito non autentica voi (l'autenticazione utente passa attraverso un meccanismo separato, cookie di sessione, token).

TLS 1.3 (la versione attuale raccomandata) ha ridotto l'handshake a un solo scambio di andata e ritorno nel caso comune, contro due per TLS 1.2, riducendo sensibilmente la latenza di connessione.

Livello 2bis: mTLS -- l'autenticazione diventa reciproca

mTLS (mutual TLS) è TLS con un vincolo aggiuntivo: il server richiede anche un certificato del client, e lo verifica. Entrambe le parti provano la propria identità tramite un certificato firmato da un'autorità di fiducia comune.

È il meccanismo naturale per la comunicazione servizio-a-servizio in un'architettura distribuita: laddove HTTPS classico è sufficiente perché un browser parli con un server pubblico, mTLS risponde a una domanda diversa; come fa un servizio interno a sapere di parlare davvero con un altro servizio interno autorizzato, e non con un attaccante che è finito sulla rete?

Client                                          Server
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificato server ──────────│
  │──── verifica il certificato server ────────────│
  │──── invia il PROPRIO certificato client ──────▶│
  │◀─── verifica il certificato client ────────────│
  │──── chiavi di sessione derivate, canale crittografato ──▶│

Il contro di mTLS è operativo: serve un'autorità di certificazione (CA) interna, un meccanismo di distribuzione dei certificati a ogni servizio, e una strategia di rotazione/revoca. In un ambiente monomacchina con pochi servizi, a volte è più complessità che beneficio -- mTLS diventa necessario dal momento in cui il traffico inter-servizi attraversa una rete che non si controlla interamente (più host, cloud multi-tenant), o appena si vuole una politica di tipo zero trust, dove nessun servizio è implicitamente affidabile solo perché è "all'interno" della rete.

Livello 3: i protocolli applicativi sopra TCP+TLS

Una volta in atto il trasporto e la crittografia, resta da definire come strutturare gli scambi. Questo è il ruolo dei protocolli applicativi.

HTTP / HTTPS

HTTP è un protocollo richiesta-risposta: il client apre una connessione (o ne riutilizza una, con il keep-alive), invia una richiesta, attende una risposta, la connessione può poi chiudersi o essere riutilizzata. HTTPS è semplicemente HTTP su TLS -- la S non cambia nulla nella semantica del protocollo, solo nel fatto che il trasporto è crittografato.

Il modello richiesta-risposta ha un limite strutturale: il server non può mai parlare per primo. Può solo rispondere a ciò che il client chiede. Per polling frequente (verificare "c'è qualcosa di nuovo?" ogni secondo), funziona ma spreca risorse -- ogni richiesta ricrea overhead protocollare per, la maggior parte del tempo, non avere nulla di nuovo da annunciare.

WebSocket (WS / WSS)

WebSocket risponde esattamente a questo limite. La connessione inizia come una richiesta HTTP classica (con un header Upgrade: websocket), ma una volta accettata la stretta di mano, la connessione TCP sottostante non è più un canale richiesta-risposta HTTP -- diventa un canale bidirezionale full-duplex dove client e server possono inviare messaggi in qualsiasi momento, senza dover riemettere un ciclo richiesta-risposta a ogni scambio.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS è semplicemente WebSocket su TLS, esattamente come HTTPS è HTTP su TLS. È il protocollo ideale per tutto ciò che richiede push server in tempo reale -- chat, notifiche, flussi di trading, eventi di gioco -- senza voler gestire da soli un protocollo binario sopra TCP nudo.

gRPC

Meno conosciuto al di fuori del mondo microservizi ma centrale nella comunicazione servizio-a-servizio: gRPC si basa su HTTP/2 (quindi TCP + TLS opzionale), serializza i messaggi in Protocol Buffers (binario, tipizzato, compatto - a differenza del JSON testuale della maggior parte delle API REST), e permette nativamente lo streaming bidirezionale grazie al multiplexing di HTTP/2 (più flussi logici su una singola connessione TCP, senza il head-of-line blocking che avrebbero più richieste HTTP/1.1 sequenziali).

QUIC / HTTP3

QUIC cambia le carte in tavola ripartendo da UDP invece che da TCP a livello di trasporto, reimplementando al contempo le garanzie di affidabilità che TCP offriva nativamente - ma flusso per flusso anziché globalmente, eliminando così l'head-of-line blocking a livello di trasporto (un pacchetto perso su un flusso non blocca più gli altri flussi della stessa connessione). TLS 1.3 è integrato direttamente in QUIC anziché aggiunto sopra, riducendo ulteriormente la latenza di handshake. HTTP/3 è HTTP su QUIC.

Panoramica: dove si colloca ogni protocollo

Livello Protocolli Ruolo Trasporto TCP, UDP Far viaggiare byte, affidabile o meno Trasporto (nuova generazione) QUIC UDP + affidabilità per flusso + TLS integrato Sicurezza TLS, mTLS Crittografia, integrità, autenticazione (uni o reciproca) Applicazione HTTP/HTTPS, WS/WSS, gRPC Strutturare gli scambi (richiesta-risposta, bidirezionale, RPC tipizzato)

Un esempio concreto per fissare le idee: un'architettura microservizi con una dashboard web e servizi interni potrebbe ragionevolmente combinare HTTPS (dashboard ↔ API pubblica, autenticazione uni-direzionale sufficiente lato browser), mTLS (servizio ↔ servizio internamente, autenticazione reciproca necessaria), e WSS (notifiche in tempo reale spinte verso la dashboard) -- tre protocolli applicativi diversi, tutti costruiti sulla stessa base TCP + TLS.

Come scegliere, in pratica

Tre domande sono generalmente sufficienti per decidere:

  1. Ho bisogno di affidabilità e ordine, o la freschezza del dato prevale sulla sua consegna garantita? → TCP se sì, UDP se no (o QUIC per avere entrambi tramite un compromesso diverso).

  2. Il server deve poter iniziare i messaggi, o il client fa sempre la prima richiesta? → WebSocket/gRPC streaming se il server deve spingere, HTTP classico altrimenti.

  3. Entrambe le parti devono provarsi reciprocamente l'identità, o solo una delle due ha bisogno di essere verificata? → mTLS per servizio-a-servizio in ambiente zero-trust, TLS semplice per client pubblico classico.

La complessità operativa aumenta a ogni livello aggiunto: TCP nudo non ha alcuna infrastruttura da gestire, TLS richiede certificati, mTLS richiede una CA e una strategia di rotazione, gRPC richiede una definizione di schema Protobuf condivisa. Il buon riflesso è aumentare la complessità solo quando il livello sottostante mostra un limite concreto, non per anticipazione.

Wie Maschinen miteinander sprechen: ein Überblick von TCP bis mTLS

Warum TCP, UDP, TLS, mTLS, HTTP und WebSocket keine konkurrierenden Alternativen sind, sondern gestapelte Schichten; ein hierarchischer Überblick über die Maschine-zu-Maschine-Kommunikation, vom reinen Transport bis zur gegenseitigen Authentifizierung.

Das Problem: zu viele Akronyme, zu wenig Hierarchie

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; die meisten Ressourcen, die darüber sprechen, stellen sie als eine flache Liste austauschbarer Optionen dar, "je nach Anwendungsfall zu wählen". In Wirklichkeit sind sie nicht auf derselben Ebene: einige sind Transportprotokolle, andere sind Sicherheitsschichten, die sich um den Transport legen, wieder andere sind Anwendungsprotokolle, die auf den ersten beiden aufbauen. Die Hierarchie zu verstehen bedeutet zu verstehen, warum man nie "zwischen" TCP und TLS "wählt": man wählt TCP, dann entscheidet man, ob man TLS darüber legt.

Dieser Artikel baut diese Hierarchie Schicht für Schicht auf, vom reinen Transport bis zur gegenseitigen Authentifizierung, mit für jede Ebene: was sie garantiert, was sie nicht garantiert, und wann sie ausreicht.

Ebene 1: der Transport (TCP gegen UDP)

Alles beginnt hier. TCP und UDP sind die beiden wichtigsten Protokolle der Transportschicht (Layer 4) des OSI-Modells. Ihre Rolle ist identisch: einen Datenstrom zwischen zwei Anwendungen zu transportieren, die auf verschiedenen Maschinen ausgeführt werden. Dennoch unterscheidet sich ihre Herangehensweise grundlegend.

Es ist wichtig zu verstehen, dass IP (Internet Protocol), das sich auf der Vermittlungsschicht (Layer 3) befindet, nur Pakete von einem Host zu einem anderen weiterleitet. Es garantiert weder ihre Ankunft, noch ihre Reihenfolge, noch ihre Eindeutigkeit. Router treffen einfach unabhängige Routing-Entscheidungen für jedes Paket.

Genau diese fehlenden Garantien gleicht TCP aus, während UDP bewusst darauf verzichtet, etwas hinzuzufügen, um extrem leichtgewichtig zu bleiben.

TCP: Zuverlässigkeit an erster Stelle

TCP (Transmission Control Protocol) ist ein verbindungsorientiertes Protokoll (connection-oriented). Bevor auch nur ein einziges Byte Daten ausgetauscht wird, müssen beide Maschinen eine logische Verbindung herstellen.

Diese Verbindung wird durch den berühmten Three-Way Handshake aufgebaut:


Client                           Server
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ---------------------------->
Verbindung hergestellt

Jeder Schritt hat ein bestimmtes Ziel:

  • SYN: Der Client kündigt an, dass er eine Verbindung öffnen möchte, und liefert eine erste Sequenznummer (Initial Sequence Number - ISN).

  • SYN-ACK: Der Server akzeptiert die Verbindung, bestätigt den Empfang des SYN und liefert seinerseits seine eigene Sequenznummer.

  • ACK: Der Client bestätigt den Empfang der Informationen des Servers.

Ab diesem Moment kennen beide Maschinen den Zustand der Verbindung und können mit dem Datenaustausch beginnen.

Die Sequenznummern

TCP betrachtet Daten nicht als eine Folge von Paketen, sondern als einen kontinuierlichen Bytestrom (byte stream).

Jedes gesendete Byte hat eine Sequenznummer.

Beispiel:

Nachricht:

Hallo

H = Byte 0
a = Byte 1
l = Byte 2
...

Wenn ein Segment mit den Bytes 1000 bis 1499 während des Transports verloren geht, kann der Empfänger genau erkennen, was fehlt.

Der Sender überträgt nur diesen Teil erneut.

Diese Granularität ist einer der Gründe für die Robustheit von TCP.

Die Bestätigungen (ACK)

Nach dem Empfang der Daten sendet der Empfänger eine ACK (Acknowledgment).

Entgegen der häufigen Annahme bedeutet ein ACK nicht:

"Ich habe dieses Paket empfangen"

Es bedeutet vielmehr:

"Ich habe alle Bytes bis zur Nummer X empfangen."

Zum Beispiel:

Client sendet:

0 → 999

Server antwortet:

ACK = 1000

Das bedeutet:

"Alles vor Byte 1000 ist gut angekommen."

Dieser Mechanismus ermöglicht die Bestätigung mehrerer Segmente auf einmal (kumulative Bestätigungen), wodurch die Anzahl der Kontrollpakete reduziert wird.

Die Neuübertragungen

Wenn nie ein ACK ankommt, nimmt TCP an, dass das Segment verloren ist.

Es überträgt es automatisch erneut.

Die Neuübertragungszeit (Retransmission Timeout – RTO) ist nicht fest.

TCP misst kontinuierlich die Umlaufzeit (RTT) anhand der empfangenen ACKs und berechnet dynamisch den RTO, um unnötige Neuübertragungen zu vermeiden.

Moderne Implementierungen verwenden auch Mechanismen wie Fast Retransmit: wenn ein Sender mehrere doppelte ACKs (in der Regel drei) empfängt, schließt er daraus, dass ein dazwischenliegendes Segment verloren gegangen ist, und sendet es sofort erneut, ohne auf den Ablauf des Timers zu warten.

Neuordnung der Pakete

Das Internet garantiert keineswegs, dass zwei Pakete denselben Weg nehmen.

Beispiel:

Paket 1
Paris
 ↓
London
 ↓
New York

Paket 2
Paris
 ↓
Frankfurt
 ↓
Chicago
 ↓
New York

Das zweite Paket kann vor dem ersten ankommen.

TCP speichert dann die ungeordnet empfangenen Segmente temporär in einem Puffer (Reassembly Buffer) und setzt sie wieder zusammen, bevor es sie an die Anwendung ausliefert.

Für die Anwendung scheint alles perfekt in der richtigen Reihenfolge anzukommen.

Flusskontrolle

Eine Verbindung hängt nicht nur vom Netzwerk ab.

Der Empfänger hat ebenfalls eine begrenzte Speicherkapazität.

Wenn er schneller empfängt, als er die Daten verarbeiten kann, laufen seine Puffer irgendwann über.

TCP löst dieses Problem mit einem Schiebefenster (Sliding Window).

Der Empfänger gibt in jedem ACK an:

Window = 32768 Bytes

Das bedeutet:

"Du kannst mir bis zu 32 KB mehr schicken."

Wenn dieses Fenster auf Null fällt:

Window = 0

Der Sender setzt die Übertragungen vorübergehend aus, bis der Empfänger ein neues verfügbares Fenster ankündigt.

Dieser Mechanismus ist die Flusskontrolle (Flow Control) und verhindert, dass ein schneller Host einen langsameren Host überflutet.

Überlastungskontrolle

Selbst wenn der Empfänger in der Lage ist, die Daten aufzunehmen, kann das Netzwerk selbst gesättigt sein.

Router verfügen über begrenzte Warteschlangen (Queues).

Wenn diese überlaufen, werden Pakete verworfen.

TCP interpretiert Verluste als Zeichen von Überlastung und passt seine Rate automatisch mithilfe eines Überlastungsfensters (Congestion Window – cwnd) an.

Moderne Algorithmen (wie Reno, CUBIC oder BBR, je nach Betriebssystem) passen dieses Fenster an, um ein Gleichgewicht zwischen maximalem Durchsatz und Netzwerkstabilität zu finden.

Die ersten Versionen von TCP verwendeten hauptsächlich zwei Mechanismen:

  • Slow Start: exponentielle Steigerung des Durchsatzes, bis eine Überlastung erkannt wird.

  • Congestion Avoidance: danach vorsichtigeres Wachstum, in der Regel linear.

Diese permanente Anpassung ist einer der Gründe, warum TCP trotz schwankender Netzwerkqualität leistungsfähig bleibt.

Verbindungsabbau

Im Gegensatz zu UDP hat eine TCP-Verbindung auch einen ordnungsgemäßen Abbau.

Jedes Ende schließt seinen Datenstrom unabhängig mit dem FIN-Flag.

Ein vollständiger Verbindungsabbau erfordert in der Regel vier Austausche:

FIN
ACK
FIN
ACK

Diese Prozedur stellt sicher, dass alle in Transit befindlichen Daten erfolgreich zugestellt wurden, bevor die Verbindung abgebaut wird.

UDP: maximale Einfachheit

UDP (User Datagram Protocol) verfolgt die umgekehrte Philosophie.

Es ist verbindungslos (connectionless).

Es existiert:

  • kein Handshake;

  • keine Sequenznummer;

  • keine Bestätigung;

  • keine Neuübertragung;

  • keine Flusskontrolle;

  • keine Überlastungskontrolle.

Jede Nachricht wird einfach in ein unabhängiges Datagramm gekapselt, an das Netzwerk gesendet und dann vom Sender vergessen.

Anwendung → UDP-Datagramm → IP → Internet

Das Protokoll bewahrt keinen Zustand zwischen zwei Sendungen.

Jedes Datagramm ist völlig unabhängig von den vorherigen.

Die Datenintegrität

Obwohl UDP weder die Zustellung noch die Reihenfolge garantiert, schützt es dennoch die Datenintegrität durch eine Prüfsumme (Checksum).

Beim Empfang wird die Prüfsumme neu berechnet.

  • Wenn die Werte übereinstimmen, wird das Datagramm akzeptiert.

  • Andernfalls wird es sofort verworfen.

UDP erkennt also beschädigte Daten, versucht aber nie, sie wiederherzustellen.

Warum ist UDP so schnell?

Der UDP-Header enthält nur 8 Bytes, gegenüber mindestens 20 Bytes bei TCP (ohne Optionen wie Timestamps, SACK oder Window Scaling).

Da keine Verbindung aufrechterhalten wird, muss das Betriebssystem den Status jedes Austauschs nicht verfolgen, was auch den Speicherverbrauch und die Verarbeitungskosten reduziert.

Die Anwendung erhält die Daten praktisch sofort nach ihrem Eintreffen, ohne auf eventuelle Neuübertragungen warten zu müssen.

Wann ein Datenverlust besser ist

Der grundlegende Gedanke ist einfach:

Eine alte Information kann weniger wert sein als eine verlorene Information.

Nehmen wir ein VoIP-Gespräch.

Jedes Paket transportiert etwa 20 ms Sprache.

Wenn ein Paket verloren geht, würde die Neuübertragung oft länger dauern als diese 20 ms.

Wenn es endlich ankäme, wäre das Gespräch bereits fortgeschritten.

Die meisten Anwendungen ziehen es daher vor, den Verlust zu überdecken (Interpolation, Stille, Fehlerkorrektur), anstatt auf die Neuübertragung zu warten.

Die gleiche Überlegung gilt für:

  • Echtzeit-Mehrspieler-Spiele;

  • Videostreaming;

  • Telemetriedaten;

  • IoT-Sensoren;

  • GPS-Positionsdaten.

Ein aktueller Wert ist fast immer nützlicher als ein alter, perfekt zuverlässiger Wert.

Ebene 2: die Verschlüsselung, TLS

TLS (Transport Layer Security, Nachfolger von SSL) ersetzt nicht TCP, sondern wird darüber gelegt. Konkret baut TLS eine normale TCP-Verbindung auf und handelt dann eine verschlüsselte Sitzung darin aus: Austausch von Zertifikaten, Einigung auf einen Verschlüsselungsalgorithmus, Ableitung von Sitzungsschlüsseln. Alles, was danach übertragen wird, ist verschlüsselt und authentifiziert.

Drei verschiedene Garantien, die oft verwechselt werden:

  • Vertraulichkeit: niemand außer den beiden Parteien kann den Inhalt lesen.

  • Integrität: jede Veränderung der Daten während des Transports wird erkannt.

  • Authentifizierung: aber beim klassischen TLS nur in eine Richtung: der Client überprüft, ob der Server wirklich der ist, der er vorgibt zu sein (über sein Zertifikat, signiert von einer vertrauenswürdigen Autorität), aber der Server überprüft nichts bezüglich der Identität des Clients. Das ist genau das Modell von HTTPS, wenn Sie eine Website besuchen: der Browser authentifiziert die Website, die Website authentifiziert Sie nicht (die Benutzerauthentifizierung erfolgt über einen separaten Mechanismus, Sitzungs-Cookie, Token).

TLS 1.3 (die aktuell empfohlene Version) hat den Handshake im Normalfall auf einen einzigen Hin- und Rückweg reduziert, gegenüber zwei bei TLS 1.2, was die Verbindungslatenz spürbar verringert.

Ebene 2b: mTLS -- die Authentifizierung wird gegenseitig

mTLS (mutual TLS) ist TLS mit einer zusätzlichen Anforderung: der Server verlangt ebenfalls ein Zertifikat vom Client und überprüft es. Beide Parteien beweisen ihre Identität durch ein von einer gemeinsamen vertrauenswürdigen Autorität signiertes Zertifikat.

Dies ist der natürliche Mechanismus für die Service-zu-Service-Kommunikation in einer verteilten Architektur: während klassisches HTTPS ausreicht, damit ein Browser mit einem öffentlichen Server spricht, beantwortet mTLS eine andere Frage: Woher weiß ein interner Dienst, dass er wirklich mit einem anderen autorisierten internen Dienst spricht und nicht mit einem Angreifer, der ins Netzwerk gelangt ist?

Client                                          Server
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + Serverzertifikat ────────────│
  │──── überprüft das Serverzertifikat ────────────│
  │──── sendet SEIN EIGENES Clientzertifikat ─────▶│
  │◀─── überprüft das Clientzertifikat ────────────│
  │──── abgeleitete Sitzungsschlüssel, verschlüsselter Kanal ──▶│

Die Kehrseite von mTLS ist operativer Natur: man benötigt eine interne Zertifizierungsstelle (CA), einen Mechanismus zur Verteilung der Zertifikate an jeden Dienst und eine Rotations-/Widerrufsstrategie. In einer Ein-Maschinen-Umgebung mit wenigen Diensten ist dies manchmal mehr Komplexität als Nutzen -- mTLS wird notwendig, sobald der Inter-Service-Verkehr ein Netzwerk durchquert, das man nicht vollständig kontrolliert (mehrere Hosts, Multi-Tenant-Cloud), oder sobald man eine Zero-Trust-Richtlinie möchte, bei der kein Dienst implizit vertrauenswürdig ist, nur weil er "innerhalb" des Netzwerks ist.

Ebene 3: die Anwendungsprotokolle über TCP+TLS

Sobald Transport und Verschlüsselung vorhanden sind, bleibt zu definieren, wie die Austausche strukturiert werden. Das ist die Aufgabe der Anwendungsprotokolle.

HTTP / HTTPS

HTTP ist ein Anfrage-Antwort-Protokoll: der Client öffnet eine Verbindung (oder verwendet eine bestehende mit Keep-Alive), sendet eine Anfrage, wartet auf eine Antwort, die Verbindung kann dann geschlossen oder wiederverwendet werden. HTTPS ist einfach HTTP über TLS -- das S ändert nichts an der Semantik des Protokolls, nur an der Tatsache, dass der Transport verschlüsselt ist.

Das Anfrage-Antwort-Modell hat eine strukturelle Grenze: der Server kann niemals von sich aus sprechen. Er kann nur auf das antworten, was der Client anfragt. Für häufiges Polling ("gibt es etwas Neues?" jede Sekunde) funktioniert das, verschwendet aber Ressourcen -- jede Anfrage erzeugt erneut protokollbedingten Overhead, meistens um nichts Neues mitzuteilen.

WebSocket (WS / WSS)

WebSocket adressiert genau diese Grenze. Die Verbindung startet als normale HTTP-Anfrage (mit einem Upgrade: websocket-Header), aber sobald der Handshake akzeptiert ist, ist der darunterliegende TCP-Kanal kein HTTP-Anfrage-Antwort-Kanal mehr -- er wird zu einem bidirektionalen Vollduplex-Kanal, über den Client und Server jederzeit Nachrichten senden können, ohne bei jedem Austausch einen neuen Anfrage-Antwort-Zyklus durchlaufen zu müssen.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS ist einfach WebSocket über TLS, genau wie HTTPS HTTP über TLS ist. Es ist das Protokoll der Wahl für alles, was Echtzeit-Push vom Server erfordert -- Chat, Benachrichtigungen, Handelsströme, Spieleereignisse -- ohne selbst ein binäres Protokoll über nacktem TCP verwalten zu müssen.

gRPC

Weniger bekannt außerhalb der Microservices-Welt, aber zentral für die Service-zu-Service-Kommunikation: gRPC baut auf HTTP/2 auf (also TCP + optionales TLS), serialisiert Nachrichten in Protocol Buffers (binär, typisiert, kompakt -- im Gegensatz zum textbasierten JSON der meisten REST-APIs) und ermöglicht nativ bidirektionales Streaming dank des Multiplexings von HTTP/2 (mehrere logische Ströme über eine einzige TCP-Verbindung, ohne das Head-of-Line-Blocking mehrerer sequentieller HTTP/1.1-Anfragen).

QUIC / HTTP3

QUIC ändert die Spielregeln, indem es auf UDP statt auf TCP auf der Transportschicht aufsetzt, gleichzeitig aber die Zuverlässigkeitsgarantien von TCP darüber implementiert -- jedoch Strom für Strom statt global, was das Head-of-Line-Blocking auf Transportebene beseitigt (ein verlorenes Paket in einem Strom blockiert nicht mehr die anderen Ströme derselben Verbindung). TLS 1.3 ist direkt in QUIC integriert, anstatt darüber gelegt zu werden, was die Handshake-Latenz weiter reduziert. HTTP/3 ist HTTP über QUIC.

Gesamtüberblick: wo sich jedes Protokoll einordnet

Schicht Protokolle Rolle Transport TCP, UDP Beförderung von Bytes, zuverlässig oder nicht Transport (neue Generation) QUIC UDP + Zuverlässigkeit pro Strom + integriertes TLS Sicherheit TLS, mTLS Verschlüsselung, Integrität, Authentifizierung (einseitig oder gegenseitig) Anwendung HTTP/HTTPS, WS/WSS, gRPC Strukturierung des Austauschs (Anfrage-Antwort, bidirektional, typisierte RPCs)

Ein konkretes Beispiel zur Veranschaulichung: eine Microservice-Architektur mit einem Web-Dashboard und internen Diensten könnte sinnvoll HTTPS (Dashboard ↔ öffentliche API, einseitige Authentifizierung browser-seitig ausreichend), mTLS (Service ↔ Service intern, gegenseitige Authentifizierung erforderlich) und WSS (Echtzeit-Benachrichtigungen, die an das Dashboard gesendet werden) kombinieren -- drei verschiedene Anwendungsprotokolle, alle auf derselben Basis TCP + TLS.

Wie man in der Praxis wählt

Drei Fragen reichen in der Regel aus, um zu entscheiden:

  1. Benötige ich Zuverlässigkeit und Reihenfolge, oder hat die Aktualität der Daten Vorrang vor ihrer garantierten Zustellung? → TCP wenn ja, UDP wenn nein (oder QUIC, um beides durch einen anderen Kompromiss zu erhalten).

  2. Muss der Server Nachrichten initiieren können, oder stellt der Client immer die erste Anfrage? → WebSocket/gRPC-Streaming, wenn der Server pushen muss, andernfalls klassisches HTTP.

  3. Müssen beide Parteien sich gegenseitig ihre Identität beweisen, oder muss nur eine der beiden überprüft werden? → mTLS für Service-zu-Service in einer Zero-Trust-Umgebung, einfaches TLS für klassische öffentliche Clients.

Die operationelle Komplexität nimmt mit jeder hinzugefügten Schicht zu: nacktes TCP erfordert keine Infrastrukturverwaltung, TLS erfordert Zertifikate, mTLS erfordert eine CA und eine Rotationsstrategie, gRPC erfordert eine gemeinsam genutzte Protobuf-Schemadefinition. Die richtige Herangehensweise ist, die Komplexität nur dann zu erhöhen, wenn die darunterliegende Schicht eine konkrete Grenze aufzeigt, nicht aus Voraussicht.

Как машины общаются: обзор от TCP до mTLS

Почему TCP, UDP, TLS, mTLS, HTTP и WebSocket -- это не конкурирующие альтернативы, а вложенные слои; иерархический обзор межмашинной коммуникации от сырой транспортировки до взаимной аутентификации.

Проблема: слишком много аббревиатур, недостаточно иерархии

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; большинство ресурсов, рассказывающих о них, преподносят их как плоский список взаимозаменяемых вариантов, «выбирай по ситуации». В реальности они находятся на разных уровнях: одни -- транспортные протоколы, другие -- слои безопасности, оборачивающиеся вокруг транспорта, третьи -- прикладные протоколы, опирающиеся на первые два. Понять иерархию -- значит понять, почему никогда не «выбирают» между TCP и TLS: выбирают TCP, а затем решают, накладывать ли поверх него TLS.

Эта статья восстанавливает эту иерархию слой за слоем, от сырой транспортировки до взаимной аутентификации, с указанием на каждом уровне: что он гарантирует, что не гарантирует и когда его достаточно.

Уровень 1: транспорт (TCP против UDP)

Всё начинается здесь. TCP и UDP -- два основных протокола транспортного уровня (Layer 4) модели OSI. Их роль идентична: транспортировать поток данных между двумя приложениями, выполняющимися на разных машинах. Однако их подход к этому радикально отличается.

Важно понимать, что IP (Internet Protocol), находящийся на сетевом уровне (Layer 3), лишь доставляет пакеты от одного узла к другому. Он не гарантирует ни их доставку, ни порядок, ни даже уникальность. Маршрутизаторы просто принимают независимые решения о маршрутизации для каждого пакета.

Именно это отсутствие гарантий TCP призван компенсировать, в то время как UDP намеренно выбирает ничего не добавлять, чтобы оставаться предельно лёгким.

TCP: надёжность превыше всего

TCP (Transmission Control Protocol) -- это протокол, ориентированный на соединение (connection-oriented). Прежде чем обменяться хотя бы одним байтом данных, две машины должны установить логическое соединение.

Это соединение создаётся с помощью знаменитого трёхэтапного рукопожатия (Three-Way Handshake):


Client                           Server
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Соединение установлено

Каждый этап имеет определённую цель:

  • SYN: клиент объявляет о желании открыть соединение и предоставляет начальный порядковый номер (Initial Sequence Number -- ISN).

  • SYN-ACK: сервер принимает соединение, подтверждает получение SYN и предоставляет свой собственный порядковый номер.

  • ACK: клиент подтверждает получение информации от сервера.

С этого момента обе машины знают состояние соединения и могут начать обмениваться данными.

Порядковые номера

TCP рассматривает данные не как последовательность пакетов, а как непрерывный поток байтов (byte stream).

Каждый отправленный байт имеет порядковый номер.

Пример:

Сообщение:

Bonjour

B = байт 0
o = байт 1
n = байт 2
...

Если сегмент, содержащий байты с 1000 по 1499, теряется при передаче, получатель может точно определить, чего не хватает.

Отправитель повторно передаёт только эту часть.

Такая гранулярность -- одна из причин надёжности TCP.

Подтверждения (ACK)

После получения данных получатель отправляет ACK (Acknowledgment).

Вопреки распространённому мнению, ACK не означает:

«Я получил этот пакет»

Он означает скорее:

«Я получил все байты вплоть до номера X.»

Например:

Клиент отправляет:

0 → 999

Сервер отвечает:

ACK = 1000

Это означает:

«Всё, что предшествует байту 1000, благополучно доставлено.»

Этот механизм позволяет подтверждать получение нескольких сегментов одновременно (cumulative acknowledgments), сокращая количество служебных пакетов.

Повторные передачи

Если ACK так и не приходит, TCP предполагает, что сегмент потерян.

Он автоматически повторно передаёт его.

Задержка повторной передачи (Retransmission Timeout -- RTO) не фиксирована.

TCP постоянно измеряет время оборота (RTT) по полученным ACK и динамически вычисляет RTO, чтобы избежать ненужных повторных передач.

Современные реализации также используют механизмы вроде Fast Retransmit: когда отправитель получает несколько дублированных ACK (обычно три), он делает вывод, что промежуточный сегмент был потерян, и немедленно отправляет его повторно, не дожидаясь истечения таймера.

Переупорядочивание пакетов

Интернет абсолютно не гарантирует, что два пакета пойдут по одному и тому же пути.

Пример:

Пакет 1
Париж
 ↓
Лондон
 ↓
Нью-Йорк

Пакет 2
Париж
 ↓
Франкфурт
 ↓
Чикаго
 ↓
Нью-Йорк

Второй пакет может прибыть раньше первого.

TCP временно сохраняет неупорядоченные сегменты в буфере (reassembly buffer), а затем собирает их в правильном порядке перед передачей приложению.

Для приложения всё выглядит так, будто данные приходят строго по порядку.

Управление потоком

Соединение зависит не только от сети.

Получатель также имеет ограниченный объём памяти.

Если он получает данные быстрее, чем может обработать, его буферы переполняются.

TCP решает эту проблему с помощью скользящего окна (Sliding Window).

Получатель указывает в каждом ACK:

Window = 32768 байт

Это означает:

«Ты можешь отправить мне ещё до 32 Кбайт.»

Если это окно падает до нуля:

Window = 0

Отправитель временно приостанавливает передачу, пока получатель не объявит о появлении нового доступного окна.

Этот механизм составляет управление потоком (Flow Control) и предотвращает затопление медленного узла быстрым.

Управление перегрузкой

Даже если получатель способен поглощать данные, сама сеть может быть перегружена.

Маршрутизаторы имеют ограниченные очереди.

Когда они переполняются, пакеты отбрасываются.

TCP интерпретирует потери как признак перегрузки и автоматически адаптирует свою пропускную способность с помощью окна перегрузки (Congestion Window -- cwnd).

Современные алгоритмы (такие как Reno, CUBIC или BBR, в зависимости от операционной системы) настраивают это окно, чтобы найти баланс между максимальной пропускной способностью и стабильностью сети.

Ранние версии TCP в основном использовали два механизма:

  • Slow Start: экспоненциальное увеличение скорости до обнаружения перегрузки.

  • Congestion Avoidance: затем более осторожный рост, как правило, линейный.

Эта постоянная адаптация -- одна из причин, почему TCP остаётся производительным, несмотря на колебания качества сети.

Закрытие соединения

В отличие от UDP, TCP-соединение также имеет чёткое закрытие.

Каждая сторона независимо закрывает свой поток с помощью флага FIN.

Полное закрытие обычно требует четырёх обменов:

FIN
ACK
FIN
ACK

Эта процедура гарантирует, что все данные в пути будут доставлены до разрушения соединения.

UDP: максимальная простота

UDP (User Datagram Protocol) придерживается противоположной философии.

Он не ориентирован на соединение (connectionless).

Не существует:

  • никакого рукопожатия;

  • никаких порядковых номеров;

  • никаких подтверждений;

  • никаких повторных передач;

  • никакого управления потоком;

  • никакого управления перегрузкой.

Каждое сообщение просто инкапсулируется в независимую датаграмму, передаётся в сеть и затем забывается отправителем.

Приложение → Датаграмма UDP → IP → Интернет

Протокол не сохраняет никакого состояния между двумя отправками.

Каждая датаграмма полностью независима от предыдущих.

Целостность данных

Хотя UDP не гарантирует ни доставку, ни порядок, он всё же защищает целостность данных с помощью контрольной суммы (checksum).

При получении контрольная сумма пересчитывается.

  • Если значения совпадают, датаграмма принимается.

  • В противном случае она немедленно отвергается.

Таким образом, UDP обнаруживает повреждённые данные, но никогда не пытается их восстановить.

Почему UDP так быстр?

Заголовок UDP содержит всего 8 байт против минимум 20 байт для TCP (не считая опций вроде timestamp, SACK или Window Scaling).

Поскольку соединение не поддерживается, операционной системе не нужно отслеживать состояние каждого обмена, что также снижает потребление памяти и вычислительные затраты.

Приложение получает данные практически сразу после их прибытия, не дожидаясь возможных повторных передач.

Когда потеря данных предпочтительна

Основная идея проста:

Устаревшая информация может быть менее ценной, чем информация потерянная.

Возьмём VoIP-разговор.

Каждый пакет переносит примерно 20 мс голоса.

Если пакет теряется, его повторная передача часто занимает больше времени, чем эти 20 мс.

Когда он наконец прибудет, разговор уже уйдёт вперёд.

Большинство приложений предпочитают маскировать потерю (интерполяция, тишина, коррекция ошибок), а не ждать повторной передачи.

Те же рассуждения применимы:

  • к многопользовательским играм в реальном времени;

  • к потоковому видео;

  • к потокам телеметрии;

  • к датчикам IoT;

  • к данным о местоположении GPS.

Свежее значение почти всегда полезнее, чем устаревшее, но безупречно точное.

Уровень 2: шифрование, TLS

TLS (Transport Layer Security, преемник SSL) не заменяет TCP, а добавляется поверх него. Конкретно, TLS устанавливает обычное TCP-соединение, а затем внутри него согласовывает зашифрованную сессию: обмен сертификатами, согласование алгоритма шифрования, вывод сессионных ключей. Всё, что передаётся далее, зашифровано и аутентифицировано.

Три различных гарантии, которые часто путают:

  • Конфиденциальность: никто, кроме двух сторон, не может прочитать содержимое.

  • Целостность: любое изменение данных в пути обнаруживается.

  • Аутентификация: но в классическом TLS -- односторонняя: клиент проверяет, что сервер действительно тот, за кого себя выдаёт (через его сертификат, подписанный доверенным центром), но сервер ничего не проверяет относительно личности клиента. Это в точности модель HTTPS, когда вы посещаете сайт: браузер аутентифицирует сайт, сайт не аутентифицирует вас (аутентификация пользователя осуществляется отдельным механизмом -- сессионным cookie, токеном).

TLS 1.3 (текущая рекомендуемая версия) сократил рукопожатие до одного обхода в обычном случае против двух для TLS 1.2, что заметно снижает задержку соединения.

Уровень 2бис: mTLS -- аутентификация становится взаимной

mTLS (mutual TLS) -- это TLS с дополнительным требованием: сервер также требует сертификат от клиента и проверяет его. Обе стороны доказывают свою личность с помощью сертификата, подписанного общим доверенным центром.

Это естественный механизм для связи сервис-к-сервису в распределённой архитектуре: там, где классического HTTPS достаточно, чтобы браузер общался с публичным сервером, mTLS отвечает на другой вопрос: как внутренний сервис узнаёт, что он общается именно с другим авторизованным внутренним сервисом, а не с атакующим, который оказался в сети?

Клиент                                           Сервер
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + сертификат сервера ──────────│
  │──── проверяет сертификат сервера ──────────────│
  │──── отправляет СВОЙ СОБСТВЕННЫЙ сертификат ───▶│
  │◀─── проверяет сертификат клиента ──────────────│
  │──── сессионные ключи выведены, канал зашифрован▶│

Оборотная сторона mTLS -- операционная: нужен внутренний удостоверяющий центр (CA), механизм распространения сертификатов на каждый сервис и стратегия ротации/отзыва сертификатов. В однопроцессной среде с небольшим количеством сервисов это иногда приносит больше сложности, чем пользы -- mTLS становится необходимым, когда межсервисный трафик проходит через сеть, которую мы не контролируем полностью (несколько хостов, мультитенантное облако), или как только мы хотим политику типа zero trust, где ни один сервис не считается доверенным по умолчанию только потому, что он «внутри» сети.

Уровень 3: прикладные протоколы поверх TCP+TLS

Когда транспорт и шифрование настроены, остаётся определить, как структурировать обмен. Это роль прикладных протоколов.

HTTP / HTTPS

HTTP -- это протокол запрос-ответ: клиент открывает соединение (или переиспользует его с keep-alive), отправляет запрос, ждёт ответ, соединение может быть закрыто или переиспользовано. HTTPS -- это просто HTTP поверх TLS -- буква S не меняет семантику протокола, только факт шифрования транспорта.

Модель запрос-ответ имеет структурное ограничение: сервер никогда не может заговорить первым. Он может только отвечать на то, что запрашивает клиент. Для частого опроса (проверка «есть ли что-то новое?» каждую секунду) это работает, но растрачивает ресурсы -- каждый запрос воссоздаёт протокольные накладные расходы, чаще всего не принося ничего нового.

WebSocket (WS / WSS)

WebSocket решает именно это ограничение. Соединение начинается как обычный HTTP-запрос (с заголовком Upgrade: websocket), но после принятия рукопожатия нижележащее TCP-соединение перестаёт быть каналом HTTP запрос-ответ -- оно становится двунаправленным full-duplex каналом, где клиент и сервер могут отправлять сообщения в любой момент, не возобновляя цикл запрос-ответ при каждом обмене.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS -- это просто WebSocket поверх TLS, точно так же, как HTTPS -- это HTTP поверх TLS. Это протокол выбора для всего, что требует серверного push в реальном времени -- чат, уведомления, торговые потоки, игровые события -- без необходимости самостоятельно реализовывать двоичный протокол поверх чистого TCP.

gRPC

Менее известный вне мира микросервисов, но центральный в коммуникации сервис-к-сервису: gRPC опирается на HTTP/2 (следовательно, TCP + TLS опционально), сериализует сообщения в Protocol Buffers (двоичный, типизированный, компактный -- в отличие от текстового JSON в большинстве REST API) и нативно поддерживает двунаправленный потоковый обмен благодаря мультиплексированию HTTP/2 (несколько логических потоков в одном TCP-соединении, без head-of-line blocking, который возникал бы при последовательных HTTP/1.1 запросах).

QUIC / HTTP3

QUIC меняет правила игры, отталкиваясь от UDP вместо TCP на транспортном уровне, при этом реализуя поверх него те же гарантии надёжности, которые TCP предоставлял нативно -- но отдельно для каждого потока, а не глобально, что устраняет head-of-line blocking на транспортном уровне (потерянный пакет в одном потоке больше не блокирует другие потоки того же соединения). TLS 1.3 встроен непосредственно в QUIC, а не добавляется поверх, что ещё больше снижает задержку рукопожатия. HTTP/3 -- это HTTP поверх QUIC.

Обзор: где находится каждый протокол

Уровень Протоколы Роль Транспорт TCP, UDP Перемещать байты, надёжно или нет Транспорт QUIC UDP + надёжность по потокам + встроенный TLS (новое поколение) Безопасность TLS, mTLS Шифрование, целостность, аутентификация (одно- или взаимная) Приложение HTTP/HTTPS, WS/WSS, gRPC Структурировать обмен (запрос-ответ, двунаправленный, типизированный RPC)

Конкретный пример для закрепления: архитектура микросервисов с веб-дашбордом и внутренними сервисами может разумно комбинировать HTTPS (дашборд ↔ публичное API, односторонней аутентификации достаточно со стороны браузера), mTLS (сервис ↔ сервис внутри, необходима взаимная аутентификация) и WSS (уведомления в реальном времени, отправляемые на дашборд) -- три разных прикладных протокола, все построенные на одном фундаменте TCP + TLS.

Как выбирать на практике

Трёх вопросов обычно достаточно для принятия решения:

  1. Нужны ли мне надёжность и порядок, или свежесть данных важнее гарантированной доставки? → TCP, если да, UDP, если нет (или QUIC, чтобы получить и то и другое через иной компромисс).

  2. Должен ли сервер иметь возможность инициировать сообщения, или клиент всегда делает первый запрос? → WebSocket/gRPC streaming, если сервер должен отправлять данные; обычный HTTP в противном случае.

  3. Должны ли обе стороны взаимно подтверждать свою личность, или только одна из них нуждается в проверке? → mTLS для сервис-к-сервису в zero-trust среде; обычный TLS для классического публичного клиента.

Операционная сложность возрастает с каждым добавленным слоем: чистый TCP не требует управления никакой инфраструктурой, TLS требует сертификатов, mTLS требует CA и стратегии ротации, gRPC требует определения общей Protobuf-схемы. Правильный подход -- повышать сложность только тогда, когда нижележащий слой проявляет конкретное ограничение, а не на опережение.

Cómo se comunican las máquinas: un panorama de TCP a mTLS

Por qué TCP, UDP, TLS, mTLS, HTTP y WebSocket no son alternativas competidoras sino capas apiladas; un recorrido jerárquico de la comunicación máquina a máquina, desde el transporte bruto hasta la autenticación mutua.

El problema: demasiados acrónimos, poca jerarquía

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; la mayoría de los recursos que hablan de ellos los presentan como una lista plana de opciones intercambiables, "para elegir según el caso de uso". En realidad no están al mismo nivel: algunos son protocolos de transporte, otros son capas de seguridad que se envuelven alrededor del transporte, y otros son protocolos de aplicación que se apoyan en los dos primeros. Entender la jerarquía es entender por qué nunca se "elige" entre TCP y TLS: se elige TCP, luego se decide si se pone TLS encima.

Este artículo reconstruye esta jerarquía capa por capa, desde el transporte bruto hasta la autenticación mutua, con para cada nivel: qué garantiza, qué no garantiza, y cuándo conformarse con ello.

Nivel 1: el transporte (TCP vs UDP)

Todo comienza aquí. TCP y UDP son los dos protocolos principales de la capa Transporte (Capa 4) del modelo OSI. Su función es idéntica: transportar un flujo de datos entre dos aplicaciones ejecutadas en máquinas diferentes. Sin embargo, su manera de lograrlo es radicalmente diferente.

Es importante entender que IP (Internet Protocol), situado en la capa de red (Capa 3), solo se encarga de enrutar paquetes de un host a otro. No garantiza ni su llegada, ni su orden, ni siquiera su unicidad. Los routers simplemente toman decisiones de enrutamiento independientes para cada paquete.

Es precisamente esta ausencia de garantías lo que TCP viene a compensar, mientras que UDP elige deliberadamente no añadir nada para mantenerse extremadamente ligero.

TCP: la fiabilidad ante todo

TCP (Transmission Control Protocol) es un protocolo orientado a conexión (connection-oriented). Antes de intercambiar el más mínimo octeto de datos, las dos máquinas deben establecer una conexión lógica.

Esta conexión se crea mediante el famoso Three-Way Handshake:

Client                           Servidor
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ---------------------------->
Conexión establecida

Cada paso tiene un objetivo preciso:

  • SYN: el cliente anuncia que desea abrir una conexión y proporciona un primer número de secuencia (Initial Sequence Number - ISN).

  • SYN-ACK: el servidor acepta la conexión, acusa recibo del SYN y proporciona a su vez su propio número de secuencia.

  • ACK: el cliente confirma la recepción de la información del servidor.

A partir de este momento, las dos máquinas conocen el estado de la conexión y pueden comenzar a intercambiar datos.

Los números de secuencia

TCP no ve los datos como una sucesión de paquetes, sino como un flujo continuo de octetos (byte stream).

Cada octeto enviado posee un número de secuencia.

Ejemplo:

Mensaje:

Hola

H = octeto 0
o = octeto 1
l = octeto 2
...

Si un segmento que contiene los octetos 1000 a 1499 se pierde durante el transporte, el receptor puede detectar exactamente lo que falta.

El emisor retransmite únicamente esa porción.

Esta granularidad es una de las razones de la robustez de TCP.

Los acuses de recibo (ACK)

Tras la recepción de los datos, el destinatario envía un ACK (Acknowledgment).

Contrariamente a lo que a menudo se imagina, un ACK no significa:

"He recibido este paquete"

Significa más bien:

"He recibido todos los octetos hasta el número X."

Por ejemplo:

Cliente envía:

0 → 999

Servidor responde:

ACK = 1000

Esto significa:

"Todo lo que precede al octeto 1000 ha llegado bien."

Este mecanismo permite acusar recibo de varios segmentos a la vez (cumulative acknowledgments), reduciendo así el número de paquetes de control.

Las retransmisiones

Si un ACK nunca llega, TCP supone que el segmento se perdió.

Lo retransmite automáticamente.

El tiempo de retransmisión (Retransmission Timeout – RTO) no es fijo.

TCP mide permanentemente el tiempo de ida y vuelta (RTT) gracias a los ACK recibidos y calcula dinámicamente el RTO para evitar retransmisiones innecesarias.

Las implementaciones modernas también utilizan mecanismos como Fast Retransmit: cuando un emisor recibe varios ACK duplicados (generalmente tres), deduce que un segmento intermedio se ha perdido y lo reenvía inmediatamente, sin esperar la expiración del temporizador.

Reordenación de paquetes

Internet no garantiza absolutamente que dos paquetes sigan el mismo camino.

Ejemplo:

Paquete 1
París
 ↓
Londres
 ↓
Nueva York

Paquete 2
París
 ↓
Fráncfort
 ↓
Chicago
 ↓
Nueva York

El segundo paquete puede llegar antes que el primero.

TCP almacena entonces temporalmente los segmentos recibidos fuera de orden en un búfer (reassembly buffer), y luego los reensambla antes de entregarlos a la aplicación.

Para la aplicación, todo parece llegar perfectamente en orden.

Control de flujo

Una conexión no depende únicamente de la red.

El receptor también posee una capacidad de memoria limitada.

Si recibe más rápido de lo que puede procesar los datos, sus búferes terminan saturándose.

TCP resuelve este problema mediante una ventana deslizante (Sliding Window).

El receptor indica en cada ACK:

Window = 32768 octetos

Esto significa:

"Puedes enviarme hasta 32 KB adicionales."

Si esta ventana cae a cero:

Window = 0

El emisor suspende temporalmente las transmisiones hasta que el receptor anuncie una nueva ventana disponible.

Este mecanismo constituye el control de flujo (Flow Control) y evita que un host rápido inunde a un host más lento.

Control de congestión

Incluso si el receptor es capaz de absorber los datos, la red misma puede saturarse.

Los routers disponen de colas (queues) limitadas.

Cuando se desbordan, los paquetes se eliminan.

TCP interpreta las pérdidas como una señal de congestión y adapta automáticamente su caudal mediante una ventana de congestión (Congestion Window – cwnd).

Los algoritmos modernos (como Reno, CUBIC o BBR, según los sistemas operativos) ajustan esta ventana para encontrar un equilibrio entre caudal máximo y estabilidad de la red.

Las primeras versiones de TCP utilizaban principalmente dos mecanismos:

  • Slow Start: aumento exponencial del caudal hasta detectar una congestión.

  • Congestion Avoidance: crecimiento posterior más prudente, generalmente lineal.

Esta adaptación permanente es una de las razones por las que TCP sigue siendo eficiente a pesar de las variaciones en la calidad de la red.

Cierre de conexión

A diferencia de UDP, una conexión TCP también posee un cierre propio.

Cada extremo cierra independientemente su flujo mediante la bandera FIN.

Un cierre completo requiere generalmente cuatro intercambios:

FIN
ACK
FIN
ACK

Este procedimiento garantiza que todos los datos en tránsito se hayan entregado antes de la destrucción de la conexión.

UDP: la máxima simplicidad

UDP (User Datagram Protocol) adopta la filosofía inversa.

Es sin conexión (connectionless).

No existe:

  • ningún handshake;

  • ningún número de secuencia;

  • ningún acuse de recibo;

  • ninguna retransmisión;

  • ningún control de flujo;

  • ningún control de congestión.

Cada mensaje se encapsula simplemente en un datagrama independiente, se transmite a la red, y luego el emisor lo olvida.

Aplicación → Datagrama UDP → IP → Internet

El protocolo no conserva ningún estado entre dos envíos.

Cada datagrama es totalmente independiente de los anteriores.

La integridad de los datos

Aunque UDP no garantiza ni la entrega ni el orden, protege de todos modos la integridad de los datos mediante un checksum.

Al recibir, el checksum se recalcula.

  • Si los valores coinciden, el datagrama se acepta.

  • De lo contrario, se rechaza inmediatamente.

UDP detecta entonces los datos corruptos, pero nunca intenta recuperarlos.

¿Por qué UDP es tan rápido?

La cabecera UDP contiene solo 8 octetos, frente a un mínimo de 20 octetos para TCP (sin contar las opciones como timestamps, SACK o Window Scaling).

Al no mantenerse ninguna conexión, el sistema operativo no tiene que seguir el estado de cada intercambio, lo que también reduce el consumo de memoria y el coste de procesamiento.

La aplicación recibe los datos casi inmediatamente después de su llegada, sin esperar posibles retransmisiones.

Cuándo es preferible perder un dato

La idea fundamental es simple:

Una información antigua puede tener menos valor que una información perdida.

Tomemos una conversación VoIP.

Cada paquete transporta aproximadamente 20 ms de voz.

Si un paquete se pierde, retransmitirlo a menudo llevaría más tiempo que esos 20 ms.

Cuando finalmente llegara, la conversación ya habría avanzado.

La mayoría de las aplicaciones prefieren entonces ocultar la pérdida (interpolación, silencio, corrección de errores) en lugar de esperar la retransmisión.

El mismo razonamiento se aplica:

  • a los juegos multijugador en tiempo real;

  • al streaming de vídeo;

  • a los flujos de telemetría;

  • a los sensores IoT;

  • a los datos de posición GPS.

Un valor reciente es casi siempre más útil que un valor antiguo perfectamente fiable.

Nivel 2: el cifrado, TLS

TLS (Transport Layer Security, sucesor de SSL) no reemplaza a TCP, se añade por encima. Concretamente, TLS establece una conexión TCP normal, luego negocia una sesión cifrada en su interior: intercambio de certificados, acuerdo sobre un algoritmo de cifrado, derivación de claves de sesión. Todo lo que transita después está cifrado y autenticado.

Tres garantías distintas, a menudo confundidas:

  • Confidencialidad: nadie más que las dos partes puede leer el contenido.

  • Integridad: cualquier alteración de los datos en tránsito es detectada.

  • Autenticación: pero en el TLS clásico, unidireccional: el cliente verifica que el servidor es realmente quien dice ser (mediante su certificado, firmado por una autoridad de confianza), pero el servidor no verifica nada sobre la identidad del cliente. Es exactamente el modelo de HTTPS cuando visitas un sitio: el navegador autentica al sitio, el sitio no te autentica a ti (la autenticación de usuario pasa por un mecanismo separado: cookie de sesión, token).

TLS 1.3 (la versión actual recomendada) ha reducido el handshake a una sola ida y vuelta en el caso común, frente a dos para TLS 1.2, lo que reduce sensiblemente la latencia de conexión.

Nivel 2bis: mTLS -- la autenticación se vuelve mutua

mTLS (mutual TLS) es TLS con una restricción adicional: el servidor exige también un certificado del cliente, y lo verifica. Ambas partes prueban su identidad mediante un certificado firmado por una autoridad de confianza común.

Es el mecanismo natural para la comunicación servicio-a-servicio en una arquitectura distribuida: donde el HTTPS clásico basta para que un navegador hable con un servidor público, mTLS responde a una pregunta diferente: ¿cómo sabe un servicio interno que está hablando realmente con otro servicio interno autorizado, y no con un atacante que ha llegado a la red?

Cliente                                          Servidor
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificado servidor ────────│
  │──── verifica el certificado servidor ──────────│
  │──── envía SU PROPIO certificado cliente ──────▶│
  │◀─── verifica el certificado cliente ────────────│
  │──── claves de sesión derivadas, canal cifrado ─▶│

La contrapartida de mTLS es operativa: se necesita una autoridad de certificación (CA) interna, un mecanismo de distribución de certificados a cada servicio, y una estrategia de rotación/revocación. En un entorno monomáquina con pocos servicios, a veces es más complejidad que beneficio -- mTLS se vuelve necesario a partir del momento en que el tráfico entre servicios atraviesa una red que no se controla completamente (varios hosts, cloud multi-tenant), o tan pronto como se quiere una política de tipo zero trust, donde ningún servicio es implícitamente digno de confianza simplemente por estar "dentro" de la red.

Nivel 3: los protocolos de aplicación sobre TCP+TLS

Una vez establecidos el transporte y el cifrado, falta definir cómo estructurar los intercambios. Ese es el papel de los protocolos de aplicación.

HTTP / HTTPS

HTTP es un protocolo de petición-respuesta: el cliente abre una conexión (o reutiliza una, con el keep-alive), envía una petición, espera una respuesta, la conexión puede luego cerrarse o reutilizarse. HTTPS es simplemente HTTP sobre TLS -- la S no cambia nada en la semántica del protocolo, solo el hecho de que el transporte está cifrado.

El modelo petición-respuesta tiene un límite estructural: el servidor nunca puede hablar primero. Solo puede responder a lo que el cliente solicita. Para sondeos frecuentes (verificar "¿hay algo nuevo?" cada segundo), funciona pero desperdicia recursos -- cada petición recrea overhead protocolario para, la mayoría de las veces, no tener nada nuevo que anunciar.

WebSocket (WS / WSS)

WebSocket responde exactamente a ese límite. La conexión comienza como una petición HTTP clásica (con una cabecera Upgrade: websocket), pero una vez que el apretón de manos es aceptado, la conexión TCP subyacente ya no es un canal de petición-respuesta HTTP -- se convierte en un canal bidireccional full-duplex donde cliente y servidor pueden enviar mensajes en cualquier momento, sin tener que reemitir un ciclo de petición-respuesta en cada intercambio.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS es simplemente WebSocket sobre TLS, exactamente como HTTPS es HTTP sobre TLS. Es el protocolo ideal para todo lo que requiere push del servidor en tiempo real -- chat, notificaciones, flujos de trading, eventos de juego -- sin tener que gestionar uno mismo un protocolo binario sobre TCP desnudo.

gRPC

Menos conocido fuera del mundo de microservicios pero central en la comunicación servicio-a-servicio: gRPC se apoya en HTTP/2 (por lo tanto TCP + TLS opcional), serializa los mensajes en Protocol Buffers (binario, tipado, compacto -- a diferencia del JSON textual de la mayoría de las API REST), y permite nativamente el streaming bidireccional gracias al multiplexado de HTTP/2 (múltiples flujos lógicos sobre una sola conexión TCP, sin el head-of-line blocking que tendrían varias peticiones HTTP/1.1 secuenciales).

QUIC / HTTP3

QUIC cambia las reglas del juego al partir de UDP en lugar de TCP a nivel de transporte, mientras reimplementa por encima las garantías de fiabilidad que TCP ofrecía nativamente -- pero flujo por flujo en lugar de globalmente, lo que elimina el head-of-line blocking a nivel de transporte (un paquete perdido en un flujo ya no bloquea los demás flujos de la misma conexión). TLS 1.3 está integrado directamente en QUIC en lugar de añadirse por encima, lo que reduce aún más la latencia del handshake. HTTP/3 es HTTP sobre QUIC.

Vista general: dónde se sitúa cada protocolo

Capa Protocolos Rol Transporte TCP, UDP Hacer viajar octetos, fiable o no Transporte (nueva generación) QUIC UDP + fiabilidad por flujo + TLS integrado Seguridad TLS, mTLS Cifrado, integridad, autenticación (uni o mutua) Aplicación HTTP/HTTPS, WS/WSS, gRPC Estructurar los intercambios (petición-respuesta, bidireccional, RPC tipado)

Un ejemplo concreto para fijar ideas: una arquitectura de microservicios con un dashboard web y servicios internos podría combinar razonablemente HTTPS (dashboard ↔ API pública, autenticación unidireccional suficiente del lado del navegador), mTLS (servicio ↔ servicio internamente, autenticación mutua necesaria), y WSS (notificaciones en tiempo real push hacia el dashboard) -- tres protocolos de aplicación diferentes, todos construidos sobre la misma base TCP + TLS.

Cómo elegir, en la práctica

Tres preguntas bastan generalmente para decidir:

  1. ¿Necesito fiabilidad y orden, o la frescura del dato prima sobre su entrega garantizada? → TCP si sí, UDP si no (o QUIC para tener ambas mediante un compromiso diferente).

  2. ¿Debe el servidor poder iniciar mensajes, o el cliente hace siempre la primera solicitud? → WebSocket/gRPC streaming si el servidor debe enviar, HTTP clásico en caso contrario.

  3. ¿Deben ambas partes probarse mutuamente su identidad, o solo una de ellas necesita ser verificada? → mTLS para servicio-a-servicio en entorno zero-trust, TLS simple para cliente público clásico.

La complejidad operativa aumenta con cada capa añadida: TCP desnudo no tiene ninguna infraestructura que gestionar, TLS exige certificados, mTLS exige una CA y una estrategia de rotación, gRPC exige una definición de esquema Protobuf compartida. El buen reflejo es aumentar la complejidad solo cuando la capa inferior muestra un límite concreto, no por anticipación.

Como as máquinas se comunicam: um panorama do TCP ao mTLS

Por que TCP, UDP, TLS, mTLS, HTTP e WebSocket não são alternativas concorrentes, mas camadas empilhadas; um panorama hierárquico da comunicação máquina a máquina, do transporte bruto à autenticação mútua.

O problema: muitas siglas, pouca hierarquia

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; a maioria dos recursos que falam sobre eles os apresentam como uma lista plana de opções intercambiáveis, "a escolher conforme o caso de uso". Na realidade, eles não estão no mesmo plano: alguns são protocolos de transporte, outros são camadas de segurança que se enrolam em torno do transporte, outros ainda são protocolos de aplicação que se apoiam nos dois primeiros. Compreender a hierarquia é compreender por que nunca se "escolhe" entre TCP e TLS: escolhe-se TCP, depois decide-se se coloca TLS por cima.

Este artigo reconstrói essa hierarquia camada por camada, do transporte bruto até a autenticação mútua, com para cada nível: o que ele garante, o que não garante, e quando se contentar com ele.

Nível 1: o transporte (TCP contra UDP)

Tudo começa aqui. TCP e UDP são os dois principais protocolos da camada Transporte (Camada 4) do modelo OSI. O papel deles é idêntico: transportar um fluxo de dados entre duas aplicações executadas em máquinas diferentes. No entanto, a maneira como fazem isso é radicalmente diferente.

É importante entender que o IP (Internet Protocol), situado na camada de rede (Camada 3), apenas encaminha pacotes de um host para outro. Ele não garante nem a chegada, nem a ordem, nem mesmo a unicidade deles. Os roteadores simplesmente tomam decisões de roteamento independentes para cada pacote.

É precisamente essa ausência de garantias que o TCP vem compensar, enquanto o UDP escolhe deliberadamente não adicionar nada para permanecer extremamente leve.

TCP: a confiabilidade acima de tudo

TCP (Transmission Control Protocol) é um protocolo orientado à conexão (connection-oriented). Antes de trocar o menor byte de dados, as duas máquinas devem estabelecer uma conexão lógica.

Essa conexão é criada através do famoso Three-Way Handshake:


Cliente                          Servidor
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Conexão estabelecida

Cada etapa possui um objetivo preciso:

  • SYN: o cliente anuncia que deseja abrir uma conexão e fornece um primeiro número de sequência (Initial Sequence Number - ISN).

  • SYN-ACK: o servidor aceita a conexão, confirma o recebimento do SYN e fornece por sua vez seu próprio número de sequência.

  • ACK: o cliente confirma o recebimento das informações do servidor.

A partir desse momento, as duas máquinas conhecem o estado da conexão e podem começar a trocar dados.

Os números de sequência

O TCP não vê os dados como uma sucessão de pacotes, mas como um fluxo contínuo de bytes (byte stream).

Cada byte enviado possui um número de sequência.

Exemplo:

Mensagem:

Bonjour

B = byte 0
o = byte 1
n = byte 2
...

Se um segmento contendo os bytes 1000 a 1499 for perdido durante o transporte, o receptor pode detectar exatamente o que está faltando.

O emissor retransmite apenas essa parte.

Essa granularidade é uma das razões da robustez do TCP.

As confirmações de recebimento (ACK)

Após o recebimento dos dados, o destinatário envia um ACK (Acknowledgment).

Ao contrário do que se imagina frequentemente, um ACK não significa:

"Recebi este pacote"

Ele significa sim:

"Recebi todos os bytes até o número X."

Por exemplo:

Cliente envia:

0 → 999

Servidor responde:

ACK = 1000

Isso significa:

"Tudo o que precede o byte 1000 chegou bem."

Esse mecanismo permite confirmar o recebimento de vários segmentos de uma só vez (cumulative acknowledgments), reduzindo assim o número de pacotes de controle.

As retransmissões

Se um ACK nunca chega, o TCP assume que o segmento foi perdido.

Ele o retransmite automaticamente.

O tempo de retransmissão (Retransmission Timeout – RTO) não é fixo.

O TCP mede permanentemente o tempo de ida e volta (RTT) graças aos ACKs recebidos e calcula dinamicamente o RTO para evitar retransmissões desnecessárias.

As implementações modernas também utilizam mecanismos como Fast Retransmit: quando um emissor recebe vários ACKs duplicados (geralmente três), ele deduz que um segmento intermediário foi perdido e o reenvia imediatamente, sem esperar a expiração do temporizador.

Reorganização dos pacotes

A Internet não garante absolutamente que dois pacotes sigam o mesmo caminho.

Exemplo:

Pacote 1
Paris
 ↓
Londres
 ↓
Nova York

Pacote 2
Paris
 ↓
Frankfurt
 ↓
Chicago
 ↓
Nova York

O segundo pacote pode chegar antes do primeiro.

O TCP então armazena temporariamente os segmentos recebidos fora de ordem em um buffer (reassembly buffer), e depois os remonta antes de entregá-los à aplicação.

Para a aplicação, tudo parece chegar perfeitamente em ordem.

Controle de fluxo

Uma conexão não depende apenas da rede.

O receptor também possui uma capacidade de memória limitada.

Se ele receber mais rápido do que consegue processar os dados, seus buffers acabam saturando.

O TCP resolve esse problema através de uma janela deslizante (Sliding Window).

O receptor indica em cada ACK:

Window = 32768 bytes

Isso significa:

"Você pode me enviar até 32 KB adicionais."

Se essa janela cair para zero:

Window = 0

O emissor suspende temporariamente as transmissões até que o receptor anuncie uma nova janela disponível.

Esse mecanismo constitui o controle de fluxo (Flow Control) e impede que um host rápido inunde um host mais lento.

Controle de congestionamento

Mesmo que o receptor seja capaz de absorver os dados, a própria rede pode ficar saturada.

Os roteadores dispõem de filas de espera (queues) limitadas.

Quando transbordam, os pacotes são descartados.

O TCP interpreta as perdas como um sinal de congestionamento e adapta automaticamente sua taxa de transmissão através de uma janela de congestionamento (Congestion Window – cwnd).

Os algoritmos modernos (como Reno, CUBIC ou BBR, dependendo dos sistemas operacionais) ajustam essa janela para encontrar um equilíbrio entre taxa máxima e estabilidade da rede.

As primeiras versões do TCP utilizavam principalmente dois mecanismos:

  • Slow Start: aumento exponencial da taxa até detectar um congestionamento.

  • Congestion Avoidance: crescimento depois mais prudente, geralmente linear.

Essa adaptação permanente é uma das razões pelas quais o TCP permanece performático apesar das variações de qualidade da rede.

Fechamento de conexão

Ao contrário do UDP, uma conexão TCP também possui um fechamento adequado.

Cada extremidade fecha independentemente seu fluxo através da flag FIN.

Um fechamento completo geralmente requer quatro trocas:

FIN
ACK
FIN
ACK

Esse procedimento garante que todos os dados em trânsito foram entregues antes da destruição da conexão.

UDP: a simplicidade máxima

UDP (User Datagram Protocol) adota a filosofia inversa.

Ele é sem conexão (connectionless).

Não existe:

  • nenhum handshake;

  • nenhum número de sequência;

  • nenhuma confirmação de recebimento;

  • nenhuma retransmissão;

  • nenhum controle de fluxo;

  • nenhum controle de congestionamento.

Cada mensagem é simplesmente encapsulada em um datagrama independente, transmitida à rede, e depois esquecida pelo emissor.

Aplicação → Datagrama UDP → IP → Internet

O protocolo não mantém nenhum estado entre dois envios.

Cada datagrama é totalmente independente dos anteriores.

A integridade dos dados

Embora o UDP não garanta nem a entrega nem a ordem, ele ainda protege a integridade dos dados através de um checksum.

No recebimento, o checksum é recalculado.

  • Se os valores coincidirem, o datagrama é aceito.

  • Caso contrário, é imediatamente rejeitado.

O UDP detecta portanto os dados corrompidos, mas nunca tenta recuperá-los.

Por que o UDP é tão rápido?

O cabeçalho UDP contém apenas 8 bytes, contra um mínimo de 20 bytes para o TCP (sem contar as opções como timestamps, SACK ou Window Scaling).

Nenhuma conexão sendo mantida, o sistema operacional não precisa acompanhar o estado de cada troca, o que também reduz o consumo de memória e o custo de processamento.

A aplicação recebe os dados quase que imediatamente após sua chegada, sem esperar por eventuais retransmissões.

Quando perder um dado é preferível

A ideia fundamental é simples:

Uma informação antiga pode ter menos valor do que uma informação perdida.

Vamos pegar uma conversa VoIP.

Cada pacote transporta aproximadamente 20 ms de voz.

Se um pacote for perdido, retransmiti-lo levaria muitas vezes mais tempo do que esses 20 ms.

Quando finalmente chegasse, a conversa já teria avançado.

A maioria das aplicações prefere então mascarar a perda (interpolação, silêncio, correção de erro) a esperar a retransmissão.

O mesmo raciocínio se aplica:

  • a jogos multijogador em tempo real;

  • ao streaming de vídeo;

  • a fluxos de telemetria;

  • a sensores IoT;

  • a dados de posição GPS.

Um valor recente é quase sempre mais útil do que um valor antigo perfeitamente confiável.

Nível 2: a criptografia, TLS

TLS (Transport Layer Security, sucessor do SSL) não substitui o TCP, ele se adiciona por cima. Concretamente, o TLS estabelece uma conexão TCP normal, depois negocia uma sessão criptografada em seu interior: troca de certificados, acordo sobre um algoritmo de criptografia, derivação de chaves de sessão. Tudo o que transita depois é criptografado e autenticado.

Três garantias distintas, frequentemente confundidas:

  • Confidencialidade: ninguém além das duas partes pode ler o conteúdo.

  • Integridade: qualquer alteração dos dados em trânsito é detectada.

  • Autenticação: mas no TLS clássico, unidirecional: o cliente verifica se o servidor é realmente quem ele diz ser (através de seu certificado, assinado por uma autoridade de confiança), mas o servidor não verifica nada sobre a identidade do cliente. É exatamente o modelo do HTTPS quando você visita um site: o navegador autentica o site, o site não autentica você (a autenticação do usuário passa por um mecanismo separado, cookie de sessão, token).

TLS 1.3 (a versão atual recomendada) reduziu o handshake a uma única ida e volta no caso comum, contra duas para TLS 1.2, o que reduz sensivelmente a latência de conexão.

Nível 2bis: mTLS -- a autenticação torna-se mútua

mTLS (mutual TLS) é TLS com uma restrição adicional: o servidor exige também um certificado do cliente, e o verifica. As duas partes provam sua identidade através de um certificado assinado por uma autoridade de confiança comum.

Esse é o mecanismo natural para a comunicação serviço-a-serviço em uma arquitetura distribuída: enquanto o HTTPS clássico basta para que um navegador fale com um servidor público, o mTLS responde a uma pergunta diferente: como um serviço interno sabe que está realmente falando com outro serviço interno autorizado, e não com um atacante que teria chegado à rede?

Cliente                                          Servidor
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificado do servidor ─────│
  │──── verifica o certificado do servidor ────────│
  │──── envia SEU PRÓPRIO certificado de cliente ─▶│
  │◀─── verifica o certificado do cliente ─────────│
  │──── chaves de sessão derivadas, canal cifrado ▶│

A contrapartida do mTLS é operacional: é necessária uma autoridade de certificação (CA) interna, um mecanismo de distribuição dos certificados para cada serviço, e uma estratégia de rotação/revogação. Em um ambiente de máquina única com poucos serviços, às vezes é mais complexidade do que benefício -- o mTLS se torna necessário a partir do momento em que o tráfego entre serviços atravessa uma rede que não controlamos completamente (vários hosts, cloud multi-tenant), ou assim que se deseja uma política do tipo zero trust, onde nenhum serviço é implicitamente digno de confiança simplesmente por estar "dentro" da rede.

Nível 3: os protocolos de aplicação sobre TCP+TLS

Uma vez o transporte e a criptografia em vigor, resta definir como estruturar as trocas. Esse é o papel dos protocolos de aplicação.

HTTP / HTTPS

HTTP é um protocolo requisição-resposta: o cliente abre uma conexão (ou reutiliza uma, com o keep-alive), envia uma requisição, aguarda uma resposta, a conexão pode então se fechar ou ser reutilizada. HTTPS é simplesmente HTTP sobre TLS -- o S não muda nada na semântica do protocolo, apenas no fato de que o transporte é criptografado.

O modelo requisição-resposta tem um limite estrutural: o servidor nunca pode falar primeiro. Ele só pode responder ao que o cliente pergunta. Para polling frequente (verificar "há novidades?" a cada segundo), funciona mas desperdiça recursos -- cada requisição recria uma sobrecarga protocolar para, na maioria das vezes, não ter nada de novo a anunciar.

WebSocket (WS / WSS)

WebSocket responde exatamente a esse limite. A conexão começa como uma requisição HTTP clássica (com um cabeçalho Upgrade: websocket), mas uma vez que o handshake é aceito, a conexão TCP subjacente não é mais um canal requisição-resposta HTTP -- ela se torna um canal bidirecional full-duplex onde cliente e servidor podem enviar mensagens a qualquer momento, sem ter que reemitir um ciclo requisição-resposta a cada troca.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS é simplesmente WebSocket sobre TLS, exatamente como HTTPS é HTTP sobre TLS. É o protocolo de escolha para tudo que necessita de push do servidor em tempo real -- chat, notificações, fluxo de trading, eventos de jogo -- sem querer gerenciar você mesmo um protocolo binário sobre TCP puro.

gRPC

Menos conhecido fora do mundo dos microsserviços mas central na comunicação serviço-a-serviço: o gRPC se apoia em HTTP/2 (portanto TCP + TLS opcional), serializa as mensagens em Protocol Buffers (binário, tipado, compacto -- ao contrário do JSON texto da maioria das APIs REST), e permite nativamente o streaming bidirecional graças ao multiplexação do HTTP/2 (vários fluxos lógicos em uma única conexão TCP, sem o head-of-line blocking que várias requisições HTTP/1.1 sequenciais teriam).

QUIC / HTTP3

QUIC muda o jogo ao partir do UDP em vez do TCP no nível do transporte, enquanto reimplementa por cima as garantias de confiabilidade que o TCP oferecia nativamente -- mas fluxo por fluxo em vez de globalmente, o que elimina o head-of-line blocking no nível do transporte (um pacote perdido em um fluxo não bloqueia mais os outros fluxos da mesma conexão). TLS 1.3 é integrado diretamente no QUIC em vez de adicionado por cima, o que reduz ainda mais a latência do handshake. HTTP/3 é HTTP sobre QUIC.

Visão geral: onde se situa cada protocolo

Camada Protocolos Papel Transporte TCP, UDP Fazer os bytes viajarem, confiável ou não Transporte (nova geração) QUIC UDP + confiabilidade por fluxo + TLS integrado Segurança TLS, mTLS Criptografia, integridade, autenticação (uni ou mútua) Aplicação HTTP/HTTPS, WS/WSS, gRPC Estruturar as trocas (requisição-resposta, bidirecional, RPC tipado)

Um exemplo concreto para fixar as ideias: uma arquitetura de microsserviços com um dashboard web e serviços internos poderia razoavelmente combinar HTTPS (dashboard ↔ API pública, autenticação unidirecional suficiente no lado do navegador), mTLS (serviço ↔ serviço internamente, autenticação mútua necessária), e WSS (notificações em tempo real empurradas para o dashboard) -- três protocolos de aplicação diferentes, todos construídos sobre a mesma base TCP + TLS.

Como escolher, na prática

Três perguntas geralmente bastam para decidir:

  1. Preciso de confiabilidade e ordem, ou a atualidade do dado é mais importante que sua entrega garantida? → TCP se sim, UDP se não (ou QUIC para ter ambos através de um compromisso diferente).

  2. O servidor precisa poder iniciar mensagens, ou o cliente faz sempre a primeira solicitação? → WebSocket/streaming gRPC se o servidor precisa empurrar, HTTP clássico caso contrário.

  3. As duas partes precisam provar mutuamente sua identidade, ou apenas uma das duas precisa ser verificada? → mTLS para serviço-a-serviço em ambiente zero-trust, TLS simples para cliente público clássico.

A complexidade operacional aumenta a cada camada adicionada: TCP puro não tem nenhuma infraestrutura para gerenciar, TLS exige certificados, mTLS exige uma CA e uma estratégia de rotação, gRPC exige uma definição de esquema Protobuf compartilhada. O bom reflexo é só aumentar a complexidade quando a camada inferior mostra um limite concreto, não por antecipação.

Bagaimana Mesin Saling Berbicara: Sebuah Tinjauan dari TCP hingga mTLS

Mengapa TCP, UDP, TLS, mTLS, HTTP, dan WebSocket bukanlah alternatif yang bersaing melainkan lapisan yang bertumpuk; sebuah tinjauan hierarkis komunikasi mesin-ke-mesin, dari transportasi mentah hingga otentikasi mutual.

Masalahnya: Terlalu Banyak Akronim, Kurang Hierarki

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; sebagian besar sumber yang membahasnya menyajikannya sebagai daftar datar opsi yang dapat dipertukarkan, "pilih sesuai kasus penggunaan". Pada kenyataannya mereka tidak berada pada bidang yang sama: beberapa adalah protokol transportasi, yang lain adalah lapisan keamanan yang membungkus transportasi, dan lainnya lagi adalah protokol aplikatif yang dibangun di atas dua lapisan pertama. Memahami hierarkinya berarti memahami mengapa kita tidak pernah "memilih" antara TCP dan TLS: kita memilih TCP, lalu memutuskan apakah akan menempatkan TLS di atasnya.

Artikel ini membangun hierarki tersebut lapis demi lapis, dari transportasi mentah hingga otentikasi mutual, dengan setiap level: apa yang dijamin, apa yang tidak dijamin, dan kapan cukup puas dengan itu.

Level 1: Transportasi (TCP vs UDP)

Semuanya dimulai di sini. TCP dan UDP adalah dua protokol utama pada lapisan Transportasi (Layer 4) model OSI. Peran mereka identik: mengangkut aliran data antara dua aplikasi yang berjalan di mesin yang berbeda. Namun, cara mereka melakukannya sangat berbeda.

Penting untuk dipahami bahwa IP (Internet Protocol), yang berada di lapisan jaringan (Layer 3), hanya mengirimkan paket dari satu host ke host lain. Ia tidak menjamin kedatangan, urutan, atau bahkan keunikan paket. Router hanya membuat keputusan routing independen untuk setiap paket.

Ketidakadaan jaminan inilah yang justru dikompensasi oleh TCP, sementara UDP secara sengaja memilih untuk tidak menambahkan apa pun agar tetap sangat ringan.

TCP: Keandalan di atas segalanya

TCP (Transmission Control Protocol) adalah protokol berorientasi koneksi (connection-oriented). Sebelum satu byte data pun dipertukarkan, kedua mesin harus membangun koneksi logis.

Koneksi ini dibuat melalui Three-Way Handshake yang terkenal:


Client                           Server
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Koneksi terbentuk

Setiap langkah memiliki tujuan yang spesifik:

  • SYN: klien mengumumkan bahwa ia ingin membuka koneksi dan memberikan nomor urut pertama (Initial Sequence Number - ISN).

  • SYN-ACK: server menerima koneksi, mengakui penerimaan SYN, dan memberikan nomor urutnya sendiri.

  • ACK: klien mengonfirmasi penerimaan informasi dari server.

Setelah titik ini, kedua mesin mengetahui status koneksi dan dapat mulai bertukar data.

Nomor Urut (Sequence Numbers)

TCP tidak melihat data sebagai rangkaian paket, melainkan sebagai aliran byte kontinu (byte stream).

Setiap byte yang dikirim memiliki nomor urut.

Contoh:

Pesan:

Halo

H = byte 0
a = byte 1
l = byte 2
o = byte 3

Jika sebuah segmen yang berisi byte 1000 hingga 1499 hilang selama pengiriman, penerima dapat mendeteksi dengan tepat apa yang hilang.

Pengirim hanya mentransmisikan ulang bagian tersebut.

Granularitas ini adalah salah satu alasan ketangguhan TCP.

Acknowledgments (ACK)

Setelah menerima data, penerima mengirimkan ACK (Acknowledgment).

Berlawanan dengan apa yang sering dibayangkan, sebuah ACK tidak berarti:

"Saya telah menerima paket ini"

Melainkan berarti:

"Saya telah menerima semua byte hingga nomor X."

Contoh:

Klien mengirim:

0 → 999

Server merespon:

ACK = 1000

Ini berarti:

"Semua yang mendahului byte 1000 telah tiba dengan selamat."

Mekanisme ini memungkinkan pengakuan penerimaan beberapa segmen sekaligus (cumulative acknowledgments), sehingga mengurangi jumlah paket kontrol.

Retransmisi

Jika sebuah ACK tidak pernah tiba, TCP menganggap segmen tersebut hilang.

Ia mentransmisikannya ulang secara otomatis.

Jeda retransmisi (Retransmission Timeout – RTO) tidak tetap.

TCP secara terus-menerus mengukur waktu perjalanan pulang-pergi (RTT) melalui ACK yang diterima dan menghitung RTO secara dinamis untuk menghindari retransmisi yang tidak perlu.

Implementasi modern juga menggunakan mekanisme seperti Fast Retransmit: ketika pengirim menerima beberapa ACK duplikat (biasanya tiga), ia menyimpulkan bahwa segmen di antaranya telah hilang dan segera mengirimkannya ulang, tanpa menunggu timer kedaluwarsa.

Pengurutan Ulang Paket

Internet sama sekali tidak menjamin bahwa dua paket akan mengikuti jalur yang sama.

Contoh:

Paket 1
Paris
 ↓
London
 ↓
New York

Paket 2
Paris
 ↓
Frankfurt
 ↓
Chicago
 ↓
New York

Paket kedua bisa tiba sebelum paket pertama.

TCP kemudian menyimpan sementara segmen yang diterima tidak berurutan dalam buffer (reassembly buffer), lalu menyusunnya kembali sebelum menyerahkannya ke aplikasi.

Bagi aplikasi, semuanya tampak tiba dengan sempurna dan berurutan.

Kontrol Aliran (Flow Control)

Koneksi tidak hanya bergantung pada jaringan.

Penerima juga memiliki kapasitas memori yang terbatas.

Jika ia menerima lebih cepat daripada kemampuannya memproses data, buffer-nya akan penuh.

TCP mengatasi masalah ini melalui jendela geser (Sliding Window).

Penerima menunjukkan dalam setiap ACK:

Window = 32768 byte

Ini berarti:

"Kamu dapat mengirimiku hingga 32 KB tambahan."

Jika jendela ini turun menjadi nol:

Window = 0

Pengirim menghentikan sementara transmisi hingga penerima mengumumkan jendela baru yang tersedia.

Mekanisme ini merupakan Kontrol Aliran (Flow Control) dan mencegah host yang cepat membanjiri host yang lebih lambat.

Kontrol Kemacetan (Congestion Control)

Bahkan jika penerima mampu menyerap data, jaringan itu sendiri bisa menjadi jenuh.

Router memiliki antrian (queues) yang terbatas.

Ketika antrian meluap, paket-paket dibuang.

TCP menginterpretasikan kehilangan sebagai tanda kemacetan dan secara otomatis menyesuaikan laju pengirimannya melalui jendela kemacetan (Congestion Window – cwnd).

Algoritme modern (seperti Reno, CUBIC, atau BBR, tergantung sistem operasi) menyesuaikan jendela ini untuk menemukan keseimbangan antara laju maksimum dan stabilitas jaringan.

Versi awal TCP terutama menggunakan dua mekanisme:

  • Slow Start: peningkatan laju secara eksponensial hingga kemacetan terdeteksi.

  • Congestion Avoidance: pertumbuhan yang lebih hati-hati setelahnya, biasanya linier.

Adaptasi yang berkelanjutan ini adalah salah satu alasan mengapa TCP tetap berkinerja baik meskipun terjadi variasi kualitas jaringan.

Penutupan Koneksi

Tidak seperti UDP, koneksi TCP juga memiliki penutupan yang rapi.

Setiap ujung menutup alirannya secara independen melalui bendera FIN.

Penutupan lengkap biasanya memerlukan empat pertukaran:

FIN
ACK
FIN
ACK

Prosedur ini memastikan bahwa semua data yang masih dalam perjalanan telah terkirim dengan selamat sebelum koneksi dihancurkan.

UDP: Kesederhanaan Maksimal

UDP (User Datagram Protocol) mengadopsi filosofi sebaliknya.

Ia tanpa koneksi (connectionless).

Tidak ada:

  • handshake;

  • nomor urut;

  • acknowledgment;

  • retransmisi;

  • kontrol aliran;

  • kontrol kemacetan.

Setiap pesan hanya dibungkus dalam datagram independen, dikirim ke jaringan, lalu dilupakan oleh pengirim.

Aplikasi → Datagram UDP → IP → Internet

Protokol ini tidak menyimpan status apa pun antara dua pengiriman.

Setiap datagram sepenuhnya independen dari datagram sebelumnya.

Integritas Data

Meskipun UDP tidak menjamin pengiriman maupun urutan, ia tetap melindungi integritas data melalui checksum.

Saat penerimaan, checksum dihitung ulang.

  • Jika nilainya cocok, datagram diterima.

  • Jika tidak, datagram segera ditolak.

UDP mendeteksi data yang rusak, tetapi tidak pernah mencoba memulihkannya.

Mengapa UDP Begitu Cepat?

Header UDP hanya berisi 8 byte, dibandingkan dengan minimal 20 byte untuk TCP (tanpa menghitung opsi seperti timestamp, SACK, atau Window Scaling).

Karena tidak ada koneksi yang dipertahankan, sistem operasi tidak perlu melacak status setiap pertukaran, yang juga mengurangi konsumsi memori dan biaya pemrosesan.

Aplikasi menerima data hampir segera setelah tiba, tanpa menunggu kemungkinan retransmisi.

Kapan Kehilangan Data Lebih Baik

Ide dasarnya sederhana:

Informasi lama bisa memiliki nilai yang lebih rendah daripada informasi yang hilang.

Ambil contoh percakapan VoIP.

Setiap paket membawa sekitar 20 ms suara.

Jika sebuah paket hilang, mentransmisikannya ulang seringkali membutuhkan waktu lebih lama dari 20 ms tersebut.

Ketika akhirnya tiba, percakapan sudah berlanjut.

Sebagian besar aplikasi lebih memilih untuk menyembunyikan kehilangan (interpolasi, silence, koreksi kesalahan) daripada menunggu retransmisi.

Pemikiran yang sama berlaku untuk:

  • game multipemain waktu nyata;

  • streaming video;

  • aliran telemetri;

  • sensor IoT;

  • data posisi GPS.

Nilai yang baru hampir selalu lebih berguna daripada nilai lama yang sempurna keandalannya.

Level 2: Enkripsi, TLS

TLS (Transport Layer Security, penerus SSL) tidak menggantikan TCP, ia ditambahkan di atasnya. Secara konkret, TLS membangun koneksi TCP normal, lalu menegosiasikan sesi terenkripsi di dalamnya: pertukaran sertifikat, kesepakatan algoritme enkripsi, derivasi kunci sesi. Semua yang kemudian melewatinya terenkripsi dan terautentikasi.

Tiga jaminan berbeda, yang sering tertukar:

  • Kerahasiaan (Confidentiality): tidak ada pihak lain selain kedua belah pihak yang dapat membaca isi.

  • Integritas (Integrity): setiap perubahan pada data yang sedang dalam perjalanan terdeteksi.

  • Otentikasi (Authentication): tetapi dalam TLS klasik, hanya satu arah: klien memverifikasi bahwa server benar-benar seperti yang diklaim (melalui sertifikatnya, yang ditandatangani oleh otoritas tepercaya), tetapi server tidak memverifikasi apa pun tentang identitas klien. Ini persis model HTTPS saat Anda mengunjungi situs: browser mengotentikasi situs, situs tidak mengotentikasi Anda (otentikasi pengguna dilakukan melalui mekanisme terpisah, cookie sesi, token).

TLS 1.3 (versi terkini yang direkomendasikan) telah mengurangi handshake menjadi satu kali perjalanan pulang-pergi dalam kasus biasa, dibandingkan dua kali untuk TLS 1.2, yang secara signifikan mengurangi latensi koneksi.

Level 2bis: mTLS -- Otentikasi Menjadi Mutual

mTLS (mutual TLS) adalah TLS dengan satu batasan tambahan: server juga memerlukan sertifikat dari klien, dan memverifikasinya. Kedua belah pihak membuktikan identitas mereka melalui sertifikat yang ditandatangani oleh otoritas tepercaya bersama.

Ini adalah mekanisme alami untuk komunikasi service-ke-service dalam arsitektur terdistribusi: di mana HTTPS klasik cukup untuk browser berbicara dengan server publik, mTLS menjawab pertanyaan yang berbeda; bagaimana sebuah layanan internal tahu bahwa ia benar-benar berbicara dengan layanan internal lain yang berwenang, dan bukan dengan penyerang yang kebetulan berada di jaringan?

Klien                                          Server
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + sertifikat server ──────────│
  │──── verifikasi sertifikat server ─────────────│
  │──── mengirim SERTIFIKAT KLIENNYA SENDIRI ────▶│
  │◀─── verifikasi sertifikat klien ──────────────│
  │──── kunci sesi diturunkan, saluran terenkripsi ▶

Konsekuensi dari mTLS bersifat operasional: diperlukan otoritas sertifikasi (CA) internal, mekanisme distribusi sertifikat ke setiap layanan, dan strategi rotasi/pencabutan. Dalam lingkungan satu mesin dengan sedikit layanan, ini terkadang lebih kompleks daripada manfaatnya -- mTLS menjadi diperlukan ketika lalu lintas antar-layanan melintasi jaringan yang tidak sepenuhnya kita kendalikan (beberapa host, cloud multi-tenant), atau ketika kita menginginkan kebijakan tipe zero trust, di mana tidak ada layanan yang secara implisit dapat dipercaya hanya karena berada "di dalam" jaringan.

Level 3: Protokol Aplikatif di atas TCP+TLS

Setelah transportasi dan enkripsi terpasang, selanjutnya adalah mendefinisikan bagaimana menstrukturkan pertukaran. Inilah peran protokol aplikatif.

HTTP / HTTPS

HTTP adalah protokol request-response: klien membuka koneksi (atau menggunakan kembali yang sudah ada, dengan keep-alive), mengirim permintaan, menunggu respons, koneksi kemudian dapat ditutup atau digunakan kembali. HTTPS hanyalah HTTP di atas TLS -- huruf S tidak mengubah semantik protokol, hanya fakta bahwa transportasinya dienkripsi.

Model request-response memiliki batasan struktural: server tidak pernah bisa berbicara terlebih dahulu. Server hanya dapat merespons apa yang diminta klien. Untuk polling yang sering (memeriksa "apa yang baru?" setiap detik), ini berfungsi tetapi memboroskan sumber daya -- setiap permintaan menciptakan overhead protokol hanya untuk, sebagian besar waktu, tidak ada hal baru yang perlu diumumkan.

WebSocket (WS / WSS)

WebSocket menjawab tepat batasan ini. Koneksi dimulai sebagai permintaan HTTP biasa (dengan header Upgrade: websocket), tetapi setelah jabat tangan diterima, koneksi TCP yang mendasarinya bukan lagi saluran request-response HTTP -- ia menjadi saluran dua arah full-duplex di mana klien dan server dapat mengirim pesan kapan saja, tanpa harus mengulangi siklus request-response setiap kali bertukar.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS hanyalah WebSocket di atas TLS, persis seperti HTTPS adalah HTTP di atas TLS. Ini adalah protokol pilihan untuk segala hal yang memerlukan push server waktu nyata -- chat, notifikasi, aliran trading, peristiwa game -- tanpa perlu mengelola sendiri protokol biner di atas TCP telanjang.

gRPC

Kurang dikenal di luar dunia microservice tetapi sentral dalam komunikasi service-ke-service: gRPC dibangun di atas HTTP/2 (jadi TCP + TLS opsional), men-serialisasi pesan dalam Protocol Buffers (biner, bertipe, ringkas -- berbeda dengan JSON teks dari kebanyakan API REST), dan secara native mendukung streaming dua arah berkat multipleksing HTTP/2 (beberapa aliran logis pada satu koneksi TCP, tanpa head-of-line blocking yang akan terjadi pada beberapa permintaan HTTP/1.1 berurutan).

QUIC / HTTP3

QUIC mengubah keadaan dengan kembali menggunakan UDP daripada TCP di level transportasi, sambil mengimplementasikan ulang di atasnya jaminan keandalan yang ditawarkan TCP secara native -- tetapi aliran per aliran, bukan secara global, yang menghilangkan head-of-line blocking di level transportasi (satu paket hilang pada satu aliran tidak lagi memblokir aliran lain pada koneksi yang sama). TLS 1.3 terintegrasi langsung ke dalam QUIC, bukan ditambahkan di atasnya, yang semakin mengurangi latensi handshake. HTTP/3 adalah HTTP di atas QUIC.

Gambaran Umum: Di Mana Setiap Protokol Berada

Lapisan Protokol Peran Transportasi TCP, UDP Membawa byte, andal atau tidak Transportasi (generasi baru) QUIC UDP + keandalan per aliran + TLS terintegrasi Keamanan TLS, mTLS Enkripsi, integritas, otentikasi (satu arah atau mutual) Aplikasi HTTP/HTTPS, WS/WSS, gRPC Menstrukturkan pertukaran (request-response, dua arah, RPC bertipe)

Contoh konkret untuk memperjelas: arsitektur microservice dengan dashboard web dan layanan internal dapat secara wajar menggabungkan HTTPS (dashboard ↔ API publik, otentikasi satu arah cukup di sisi browser), mTLS (service ↔ service secara internal, otentikasi mutual diperlukan), dan WSS (notifikasi waktu nyata yang didorong ke dashboard) -- tiga protokol aplikatif yang berbeda, semuanya dibangun di atas fondasi TCP + TLS yang sama.

Cara Memilih, dalam Praktik

Tiga pertanyaan biasanya sudah cukup untuk memutuskan:

  1. Apakah saya membutuhkan keandalan dan urutan, atau kesegaran data lebih penting daripada pengiriman yang terjamin? → TCP jika ya, UDP jika tidak (atau QUIC untuk mendapatkan keduanya melalui kompromi yang berbeda).

  2. Apakah server harus dapat memulai pengiriman pesan, atau apakah klien selalu yang mengajukan permintaan pertama? → WebSocket/gRPC streaming jika server harus mendorong, HTTP biasa jika tidak.

  3. Apakah kedua belah pihak harus saling membuktikan identitas, atau hanya satu yang perlu diverifikasi? → mTLS untuk service-ke-service di lingkungan zero-trust, TLS biasa untuk klien publik standar.

Kompleksitas operasional bertambah setiap kali lapisan ditambahkan: TCP telanjang tidak memiliki infrastruktur yang perlu dikelola, TLS memerlukan sertifikat, mTLS memerlukan CA dan strategi rotasi, gRPC memerlukan definisi skema Protobuf bersama. Refleks yang baik adalah hanya meningkatkan kompleksitas ketika lapisan di bawahnya menunjukkan batasan konkret, bukan karena antisipasi.

मशीनें आपस में कैसे बात करती हैं: TCP से mTLS तक एक व्यापक दृष्टिकोण

TCP, UDP, TLS, mTLS, HTTP और WebSocket प्रतिस्पर्धी विकल्प नहीं हैं बल्कि स्तरित परतें हैं; रॉ ट्रांसपोर्ट से लेकर आपसी प्रमाणीकरण तक मशीन-से-मशीन संचार का एक पदानुक्रमित दृष्टिकोण।

समस्या: बहुत सारे संक्षिप्ताक्षर, पर्याप्त पदानुक्रम नहीं

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; इनके बारे में अधिकांश संसाधन इन्हें विनिमेय विकल्पों की एक सपाट सूची के रूप में प्रस्तुत करते हैं, "जिसे उपयोग के मामले के अनुसार चुनना है"। वास्तव में ये एक ही स्तर पर नहीं हैं: कुछ ट्रांसपोर्ट प्रोटोकॉल हैं, कुछ सुरक्षा परतें हैं जो ट्रांसपोर्ट के चारों ओर लपेटी जाती हैं, और कुछ एप्लिकेशन प्रोटोकॉल हैं जो पहले दो पर निर्भर करते हैं। पदानुक्रम को समझने का मतलब है यह समझना कि कोई TCP और TLS के बीच कभी "चयन" क्यों नहीं करता: आप TCP चुनते हैं, फिर तय करते हैं कि उसके ऊपर TLS लगाना है या नहीं।

यह लेख इस पदानुक्रम को परत दर परत पुनर्निर्मित करता है, रॉ ट्रांसपोर्ट से लेकर आपसी प्रमाणीकरण तक, प्रत्येक स्तर के लिए: यह क्या गारंटी देता है, यह क्या गारंटी नहीं देता है, और कब इसके साथ काम चलाना चाहिए।

स्तर 1: ट्रांसपोर्ट (TCP बनाम UDP)

सब कुछ यहीं से शुरू होता है। TCP और UDP OSI मॉडल की ट्रांसपोर्ट (लेयर 4) परत के दो मुख्य प्रोटोकॉल हैं। इनकी भूमिका समान है: अलग-अलग मशीनों पर चल रहे दो अनुप्रयोगों के बीच डेटा प्रवाह को परिवहन करना। फिर भी, इसे करने का इनका तरीका मौलिक रूप से भिन्न है।

यह समझना महत्वपूर्ण है कि IP (Internet Protocol), जो नेटवर्क परत (लेयर 3) पर स्थित है, केवल पैकेट को एक होस्ट से दूसरे तक पहुँचाता है। यह न तो उनके आगमन की गारंटी देता है, न ही उनके क्रम की, और न ही उनकी अद्वितीयता की। राउटर प्रत्येक पैकेट के लिए स्वतंत्र रूप से रूटिंग निर्णय लेते हैं।

यह गारंटियों की यही कमी है जिसे TCP पूरा करने आता है, जबकि UDP अत्यधिक हल्का बने रहने के लिए जानबूझकर कुछ भी नहीं जोड़ने का चयन करता है।

TCP: विश्वसनीयता सबसे पहले

TCP (Transmission Control Protocol) एक कनेक्शन-उन्मुख (connection-oriented) प्रोटोकॉल है। डेटा का एक भी बाइट आदान-प्रदान करने से पहले, दोनों मशीनों को एक तार्किक कनेक्शन स्थापित करना होता है।

यह कनेक्शन प्रसिद्ध Three-Way Handshake के माध्यम से बनाया जाता है:

Client                           Serveur
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ---------------------------->
Connexion établie

प्रत्येक चरण का एक विशिष्ट उद्देश्य है:

  • SYN : क्लाइंट घोषणा करता है कि वह एक कनेक्शन खोलना चाहता है और एक प्रारंभिक अनुक्रम संख्या (Initial Sequence Number - ISN) प्रदान करता है।

  • SYN-ACK : सर्वर कनेक्शन स्वीकार करता है, SYN की प्राप्ति की पुष्टि करता है और बदले में अपनी स्वयं की अनुक्रम संख्या प्रदान करता है।

  • ACK : क्लाइंट सर्वर की जानकारी प्राप्त करने की पुष्टि करता है।

इस क्षण से, दोनों मशीनें कनेक्शन की स्थिति जानती हैं और डेटा का आदान-प्रदान शुरू कर सकती हैं।

अनुक्रम संख्याएँ (Sequence Numbers)

TCP डेटा को पैकेट के अनुक्रम के रूप में नहीं, बल्कि एक सतत बाइट स्ट्रीम (byte stream) के रूप में देखता है।

भेजे गए प्रत्येक बाइट की एक अनुक्रम संख्या होती है।

उदाहरण:

Message :

Bonjour

B = octet 0
o = octet 1
n = octet 2
...

यदि ट्रांसपोर्ट के दौरान बाइट 1000 से 1499 वाला एक सेगमेंट खो जाता है, तो रिसीवर ठीक से पता लगा सकता है कि क्या कमी है।

प्रेषक केवल उसी हिस्से को पुनर्भेजता है।

यह ग्रैन्युलैरिटी TCP की मजबूती के कारणों में से एक है।

पावती (ACK)

डेटा प्राप्त करने के बाद, प्राप्तकर्ता एक ACK (Acknowledgment) भेजता है।

आमतौर पर जैसा कल्पना की जाती है, उसके विपरीत, ACK का अर्थ यह नहीं है:

"मुझे यह पैकेट मिल गया"

इसका अर्थ है:

"मुझे संख्या X तक के सभी बाइट मिल गए हैं।"

उदाहरण:

Client envoie :

0 → 999

Serveur répond :

ACK = 1000

इसका अर्थ है:

"बाइट 1000 से पहले की सब कुछ अच्छी तरह से आ गई है।"

यह तंत्र एक साथ कई सेगमेंट की पावती (cumulative acknowledgments) की अनुमति देता है, जिससे नियंत्रण पैकेट की संख्या कम हो जाती है।

पुनर्भेजना (Retransmissions)

यदि ACK कभी नहीं आता है, तो TCP मान लेता है कि सेगमेंट खो गया है।

यह स्वचालित रूप से इसे पुनर्भेजता है।

पुनर्भेजना विलंब (Retransmission Timeout – RTO) स्थिर नहीं है।

TCP प्राप्त ACK के माध्यम से लगातार राउंड-ट्रिप समय (RTT) मापता है और अनावश्यक पुनर्भेजना से बचने के लिए गतिशील रूप से RTO की गणना करता है।

आधुनिक कार्यान्वयन Fast Retransmit जैसे तंत्रों का भी उपयोग करते हैं: जब कोई प्रेषक कई डुप्लिकेट ACK (आमतौर पर तीन) प्राप्त करता है, तो वह अनुमान लगाता है कि एक मध्यवर्ती सेगमेंट खो गया है और टाइमर समाप्त होने की प्रतीक्षा किए बिना तुरंत उसे पुनर्भेजता है।

पैकेट पुनर्क्रमण (Packet Reordering)

इंटरनेट बिल्कुल भी गारंटी नहीं देता कि दो पैकेट एक ही रास्ते का अनुसरण करेंगे।

उदाहरण:

Paquet 1
Paris
 ↓
Londres
 ↓
New York

Paquet 2
Paris
 ↓
Francfort
 ↓
Chicago
 ↓
New York

दूसरा पैकेट पहले से पहले आ सकता है।

TCP तब प्राप्त गलत क्रम वाले सेगमेंट को एक बफर (reassembly buffer) में अस्थायी रूप से संग्रहीत करता है, फिर उन्हें एप्लिकेशन को देने से पहले पुनः जोड़ता है।

एप्लिकेशन के लिए, सब कुछ पूरी तरह से क्रम में आता हुआ प्रतीत होता है।

प्रवाह नियंत्रण (Flow Control)

एक कनेक्शन केवल नेटवर्क पर निर्भर नहीं करता।

रिसीवर की भी सीमित मेमोरी क्षमता होती है।

यदि वह डेटा को संसाधित करने की तुलना में तेजी से प्राप्त करता है, तो उसके बफर अंततः संतृप्त हो जाते हैं।

TCP इस समस्या को स्लाइडिंग विंडो (Sliding Window) के माध्यम से हल करता है।

रिसीवर प्रत्येक ACK में इंगित करता है:

Window = 32768 octets

इसका अर्थ है:

"आप मुझे 32 KB अतिरिक्त भेज सकते हैं।"

यदि यह विंडो शून्य हो जाती है:

Window = 0

प्रेषक तब तक अस्थायी रूप से ट्रांसमिशन रोक देता है जब तक रिसीवर एक नई उपलब्ध विंडो की घोषणा नहीं करता।

यह तंत्र प्रवाह नियंत्रण (Flow Control) है और एक तेज़ होस्ट को धीमे होस्ट को डूबाने से रोकता है।

संकुलन नियंत्रण (Congestion Control)

भले ही रिसीवर डेटा को अवशोषित करने में सक्षम हो, नेटवर्क स्वयं संतृप्त हो सकता है।

राउटर के पास सीमित कतारें (queues) होती हैं।

जब वे ओवरफ्लो हो जाती हैं, तो पैकेट हटा दिए जाते हैं।

TCP नुकसान को संकुलन के संकेत के रूप में व्याख्या करता है और संकुलन विंडो (Congestion Window – cwnd) के माध्यम से स्वचालित रूप से अपनी दर को समायोजित करता है।

आधुनिक एल्गोरिदम (जैसे ऑपरेटिंग सिस्टम के अनुसार Reno, CUBIC या BBR) अधिकतम थ्रूपुट और नेटवर्क स्थिरता के बीच संतुलन खोजने के लिए इस विंडो को समायोजित करते हैं।

TCP के शुरुआती संस्करण मुख्य रूप से दो तंत्रों का उपयोग करते थे:

  • Slow Start : संकुलन का पता चलने तक थ्रूपुट में तेजी से वृद्धि।

  • Congestion Avoidance : फिर अधिक सतर्क वृद्धि, आमतौर पर रैखिक।

यह स्थायी अनुकूलन उन कारणों में से एक है जिनकी वजह से नेटवर्क गुणवत्ता में भिन्नता के बावजूद TCP प्रभावी बना रहता है।

कनेक्शन समापन (Connection Termination)

UDP के विपरीत, TCP कनेक्शन का एक उचित समापन भी होता है।

प्रत्येक छोर FIN फ्लैग के माध्यम से स्वतंत्र रूप से अपने प्रवाह को बंद करता है।

पूर्ण समापन के लिए आमतौर पर चार आदान-प्रदान की आवश्यकता होती है:

FIN
ACK
FIN
ACK

यह प्रक्रिया सुनिश्चित करती है कि कनेक्शन नष्ट होने से पहले सभी ट्रांज़िट डेटा अच्छी तरह से वितरित हो गया है।

UDP: अधिकतम सरलता

UDP (User Datagram Protocol) विपरीत दर्शन अपनाता है।

यह बिना कनेक्शन (connectionless) है।

इसमें निम्नलिखित में से कुछ भी नहीं है:

  • कोई हैंडशेक नहीं;

  • कोई अनुक्रम संख्या नहीं;

  • कोई पावती नहीं;

  • कोई पुनर्भेजना नहीं;

  • कोई प्रवाह नियंत्रण नहीं;

  • कोई संकुलन नियंत्रण नहीं।

प्रत्येक संदेश को बस एक स्वतंत्र डेटाग्राम में लपेटा जाता है, नेटवर्क को भेजा जाता है, और फिर प्रेषक द्वारा भुला दिया जाता है।

Application → Datagramme UDP → IP → Internet

प्रोटोकॉल दो भेजने के बीच कोई स्थिति बनाए नहीं रखता।

प्रत्येक डेटाग्राम पिछले वाले से पूरी तरह स्वतंत्र होता है।

डेटा अखंडता (Data Integrity)

हालांकि UDP न तो वितरण की गारंटी देता है और न ही क्रम की, फिर भी यह चेकसम के माध्यम से डेटा अखंडता की रक्षा करता है।

प्राप्त करने पर, चेकसम की पुनर्गणना की जाती है।

  • यदि मान मेल खाते हैं, तो डेटाग्राम स्वीकार किया जाता है।

  • अन्यथा, इसे तुरंत अस्वीकार कर दिया जाता है।

UDP इस प्रकार दूषित डेटा का पता लगाता है, लेकिन इसे पुनर्प्राप्त करने का कभी प्रयास नहीं करता।

UDP इतना तेज़ क्यों है?

UDP हेडर में केवल 8 बाइट होते हैं, जबकि TCP के लिए न्यूनतम 20 बाइट (टाइमस्टैम्प, SACK या Window Scaling जैसे विकल्पों की गणना किए बिना) होते हैं।

चूंकि कोई कनेक्शन बनाए नहीं रखा जाता, ऑपरेटिंग सिस्टम को प्रत्येक आदान-प्रदान की स्थिति पर नज़र रखने की आवश्यकता नहीं होती, जिससे मेमोरी खपत और प्रसंस्करण लागत भी कम हो जाती है।

एप्लिकेशन को डेटा लगभग उसके आगमन पर ही प्राप्त होता है, बिना संभावित पुनर्भेजना की प्रतीक्षा किए।

जब डेटा खोना बेहतर होता है

मूल विचार सरल है:

पुरानी जानकारी का मूल्य खोई हुई जानकारी से कम हो सकता है।

एक VoIP वार्तालाप लें।

प्रत्येक पैकेट लगभग 20 ms आवाज़ का परिवहन करता है।

यदि कोई पैकेट खो जाता है, तो उसे पुनर्भेजने में अक्सर इन 20 ms से अधिक समय लगेगा।

जब वह अंततः पहुँचेगा, तब तक वार्तालाप आगे बढ़ चुका होगा।

अधिकांश एप्लिकेशन पुनर्भेजना की प्रतीक्षा करने के बजाय नुकसान को छिपाना (इंटरपोलेशन, मौन, त्रुटि सुधार) पसंद करते हैं।

यही तर्क लागू होता है:

  • रीयल-टाइम मल्टीप्लेयर गेम्स पर;

  • वीडियो स्ट्रीमिंग पर;

  • टेलीमेट्री स्ट्रीम पर;

  • IoT सेंसर पर;

  • GPS स्थिति डेटा पर।

हालिया मूल्य लगभग हमेशा पूरी तरह से विश्वसनीय पुराने मूल्य से अधिक उपयोगी होता है।

स्तर 2: एन्क्रिप्शन, TLS

TLS (Transport Layer Security, SSL का उत्तराधिकारी) TCP को प्रतिस्थापित नहीं करता, यह उसके ऊपर जुड़ता है। वास्तव में, TLS एक सामान्य TCP कनेक्शन स्थापित करता है, फिर उसके अंदर एक एन्क्रिप्टेड सत्र पर बातचीत करता है: प्रमाणपत्रों का आदान-प्रदान, एन्क्रिप्शन एल्गोरिदम पर सहमति, सत्र कुंजियों का व्युत्पन्न। इसके बाद जो कुछ भी गुजरता है वह एन्क्रिप्टेड और प्रमाणित होता है।

तीन अलग-अलग गारंटियाँ, जिन्हें अक्सर भ्रमित किया जाता है:

  • गोपनीयता (Confidentiality) : दोनों पक्षों के अलावा कोई और सामग्री नहीं पढ़ सकता।

  • अखंडता (Integrity) : डेटा में किसी भी बदलाव का पता लगाया जाता है।

  • प्रमाणीकरण (Authentication) : लेकिन क्लासिक TLS में, यह एकतरफा है: क्लाइंट जाँचता है कि सर्वर वही है जो वह होने का दावा करता है (अपने प्रमाणपत्र के माध्यम से, जो एक विश्वसनीय प्राधिकारी द्वारा हस्ताक्षरित है), लेकिन सर्वर क्लाइंट की पहचान के बारे में कुछ भी सत्यापित नहीं करता। यह बिल्कुल HTTPS का मॉडल है जब आप किसी साइट पर जाते हैं: ब्राउज़र साइट को प्रमाणित करता है, साइट आपको प्रमाणित नहीं करती (उपयोगकर्ता प्रमाणीकरण एक अलग तंत्र, सत्र कुकी या टोकन के माध्यम से होता है)।

TLS 1.3 (अनुशंसित वर्तमान संस्करण) ने सामान्य मामले में हैंडशेक को एक राउंड-ट्रिप तक कम कर दिया है, जबकि TLS 1.2 में दो थे, जिससे कनेक्शन विलंबता काफी कम हो गई है।

स्तर 2bis: mTLS -- प्रमाणीकरण आपसी हो जाता है

mTLS (mutual TLS) एक अतिरिक्त बाधा के साथ TLS है: सर्वर क्लाइंट से भी प्रमाणपत्र की मांग करता है और उसे सत्यापित करता है। दोनों पक्ष एक सामान्य विश्वसनीय प्राधिकारी द्वारा हस्ताक्षरित प्रमाणपत्र के माध्यम से अपनी पहचान साबित करते हैं।

यह वितरित आर्किटेक्चर में सेवा-से-सेवा संचार के लिए स्वाभाविक तंत्र है: जहाँ क्लासिक HTTPS एक ब्राउज़र को सार्वजनिक सर्वर से बात करने के लिए पर्याप्त है, वहीं mTLS एक अलग प्रश्न का उत्तर देता है -- एक आंतरिक सेवा को कैसे पता चलेगा कि वह किसी अन्य अधिकृत आंतरिक सेवा से बात कर रहा है, न कि किसी हमलावर से जो नेटवर्क पर आ गया है?

Client                                          Serveur
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificat serveur ──────────│
  │──── vérifie le certificat serveur ─────────────│
  │──── envoie SON PROPRE certificat client ──────▶│
  │◀─── vérifie le certificat client ───────────────│
  │──── clés de session dérivées, canal chiffré ──▶│

mTLS की कमी परिचालनात्मक है: एक आंतरिक प्रमाणपत्र प्राधिकरण (CA), प्रत्येक सेवा को प्रमाणपत्र वितरित करने का तंत्र, और रोटेशन/रद्दीकरण रणनीति की आवश्यकता होती है। कम सेवाओं वाले एकल-मशीन वातावरण में, यह कभी-कभी लाभ की तुलना में अधिक जटिलता होती है -- mTLS तब आवश्यक हो जाता है जब अंतर-सेवा ट्रैफ़िक ऐसे नेटवर्क से गुज़रता है जिसे आप पूरी तरह से नियंत्रित नहीं करते (कई होस्ट, मल्टी-टेनेंट क्लाउड), या जैसे ही आप zero trust प्रकार की नीति चाहते हैं, जहाँ कोई भी सेवा केवल नेटवर्क के "अंदर" होने के कारण स्वाभाविक रूप से विश्वसनीय नहीं है।

स्तर 3: TCP+TLS के ऊपर एप्लिकेशन प्रोटोकॉल

एक बार ट्रांसपोर्ट और एन्क्रिप्शन स्थापित हो जाने के बाद, यह परिभाषित करना बाकी है कि आदान-प्रदान को कैसे संरचित किया जाए। यह एप्लिकेशन प्रोटोकॉल की भूमिका है।

HTTP / HTTPS

HTTP एक अनुरोध-प्रतिक्रिया प्रोटोकॉल है: क्लाइंट एक कनेक्शन खोलता है (या कीप-अलाइव के साथ इसे पुनः उपयोग करता है), एक अनुरोध भेजता है, प्रतिक्रिया की प्रतीक्षा करता है, कनेक्शन फिर बंद या पुनः उपयोग किया जा सकता है। HTTPS, बस TLS पर HTTP है -- S प्रोटोकॉल की सिमैंटिक्स में कुछ भी नहीं बदलता, केवल इस तथ्य में कि ट्रांसपोर्ट एन्क्रिप्टेड है।

अनुरोध-प्रतिक्रिया मॉडल की एक संरचनात्मक सीमा है: सर्वर कभी पहले बात नहीं कर सकता। वह केवल क्लाइंट द्वारा माँगी गई चीज़ का उत्तर दे सकता है। बार-बार पोलिंग (हर सेकंड "क्या कुछ नया है?" जाँचना) के लिए, यह काम करता है लेकिन संसाधन बर्बाद करता है -- प्रत्येक अनुरोध प्रोटोकॉल ओवरहेड को फिर से बनाता है, जबकि अधिकांश समय घोषित करने के लिए कुछ भी नया नहीं होता।

WebSocket (WS / WSS)

WebSocket इस सीमा का सटीक समाधान है। कनेक्शन एक सामान्य HTTP अनुरोध के रूप में शुरू होता है (एक Upgrade: websocket हेडर के साथ), लेकिन एक बार हैंडशेक स्वीकार हो जाने के बाद, अंतर्निहित TCP कनेक्शन HTTP अनुरोध-प्रतिक्रिया चैनल नहीं रह जाता -- यह एक पूर्ण-द्वैध द्विदिश चैनल बन जाता है जहाँ क्लाइंट और सर्वर किसी भी समय संदेश भेज सकते हैं, बिना हर आदान-प्रदान पर अनुरोध-प्रतिक्रिया चक्र को फिर से जारी किए।

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS बस TLS पर WebSocket है, ठीक वैसे ही जैसे HTTPS, TLS पर HTTP है। यह हर उस चीज़ के लिए पसंदीदा प्रोटोकॉल है जिसमें रीयल-टाइम सर्वर पुश की आवश्यकता होती है -- चैट, सूचनाएँ, ट्रेडिंग फ़ीड, गेम इवेंट -- बिना खुद नंगे TCP के ऊपर बाइनरी प्रोटोकॉल प्रबंधित किए।

gRPC

माइक्रोसर्विसेज़ की दुनिया के बाहर कम ज्ञात लेकिन सेवा-से-सेवा संचार में केंद्रीय: gRPC HTTP/2 पर आधारित है (इसलिए TCP + वैकल्पिक TLS), संदेशों को Protocol Buffers (बाइनरी, टाइप किया हुआ, कॉम्पैक्ट -- अधिकांश REST API के टेक्स्ट JSON के विपरीत) में सीरियलाइज़ करता है, और HTTP/2 के मल्टीप्लेक्सिंग के माध्यम से मूल रूप से द्विदिश स्ट्रीमिंग की अनुमति देता है (एक ही TCP कनेक्शन पर कई तार्किक प्रवाह, क्रमिक HTTP/1.1 अनुरोधों के हेड-ऑफ-लाइन ब्लॉकिंग के बिना)।

QUIC / HTTP3

QUIC ट्रांसपोर्ट स्तर पर TCP के बजाय UDP से शुरू करके खेल बदलता है, साथ ही शीर्ष पर TCP की मूल विश्वसनीयता गारंटियों को फिर से लागू करता है -- लेकिन वैश्विक रूप से नहीं बल्कि प्रवाह-दर-प्रवाह, जो ट्रांसपोर्ट स्तर पर हेड-ऑफ-लाइन ब्लॉकिंग को समाप्त करता है (एक प्रवाह पर खोया गया पैकेट उसी कनेक्शन के अन्य प्रवाह को अवरुद्ध नहीं करता)। TLS 1.3 सीधे QUIC में एकीकृत है न कि ऊपर जोड़ा गया, जो हैंडशेक विलंबता को और कम करता है। HTTP/3, QUIC के ऊपर HTTP है।

समग्र दृश्य: प्रत्येक प्रोटोकॉल कहाँ स्थित है

परत प्रोटोकॉल भूमिका ट्रांसपोर्ट TCP, UDP बाइट्स की यात्रा कराना, विश्वसनीय या नहीं ट्रांसपोर्ट (नई पीढ़ी) QUIC UDP + प्रवाह-दर-प्रवाह विश्वसनीयता + एकीकृत TLS सुरक्षा TLS, mTLS एन्क्रिप्शन, अखंडता, प्रमाणीकरण (एकतरफा या आपसी) एप्लिकेशन HTTP/HTTPS, WS/WSS, gRPC आदान-प्रदान को संरचित करना (अनुरोध-प्रतिक्रिया, द्विदिश, टाइप की गई RPC)

एक ठोस उदाहरण विचारों को स्पष्ट करने के लिए: एक वेब डैशबोर्ड और आंतरिक सेवाओं वाली माइक्रोसर्विसेज़ आर्किटेक्चर उचित रूप से HTTPS (डैशबोर्ड ↔ सार्वजनिक API, ब्राउज़र की ओर से एकतरफा प्रमाणीकरण पर्याप्त), mTLS (आंतरिक रूप से सेवा ↔ सेवा, आपसी प्रमाणीकरण आवश्यक), और WSS (डैशबोर्ड पर पुश की गई रीयल-टाइम सूचनाएँ) को जोड़ सकती है -- तीन अलग-अलग एप्लिकेशन प्रोटोकॉल, सभी एक ही TCP + TLS आधार पर निर्मित।

व्यवहार में कैसे चुनें

तीन प्रश्न आमतौर पर निर्णय लेने के लिए पर्याप्त होते हैं:

  1. क्या मुझे विश्वसनीयता और क्रम की आवश्यकता है, या डेटा की ताज़गी इसकी गारंटीकृत डिलीवरी पर प्राथमिकता रखती है? → हाँ होने पर TCP, नहीं होने पर UDP (या दोनों को एक अलग समझौते के माध्यम से पाने के लिए QUIC)।

  2. क्या सर्वर को संदेश शुरू करने में सक्षम होना चाहिए, या क्लाइंट हमेशा पहला अनुरोध करता है? → सर्वर को पुश करना हो तो WebSocket/gRPC स्ट्रीमिंग, नहीं तो क्लासिक HTTP।

  3. क्या दोनों पक्षों को एक-दूसरे को अपनी पहचान साबित करनी होगी, या केवल एक को सत्यापित करने की आवश्यकता है? → zero-trust वातावरण में सेवा-से-सेवा के लिए mTLS, सामान्य सार्वजनिक क्लाइंट के लिए सादा TLS।

प्रत्येक जोड़ी गई परत के साथ परिचालन जटिलता बढ़ती है: नंगे TCP को किसी बुनियादी ढाँचे की आवश्यकता नहीं होती, TLS के लिए प्रमाणपत्र चाहिए, mTLS के लिए CA और रोटेशन रणनीति चाहिए, gRPC के लिए साझा Protobuf स्कीमा परिभाषा चाहिए। सही आदत यह है कि जटिलता तभी बढ़ाएँ जब नीचे की परत कोई ठोस सीमा दिखाती हो, न कि पहले से अनुमान लगाकर।

كيف تتحدث الآلات فيما بينها: جولة من TCP إلى mTLS

لماذا TCP و UDP و TLS و mTLS و HTTP و WebSocket ليست بدائل متنافسة بل طبقات متراكبة؛ جولة هرمية في التواصل بين الآلات، من النقل الخام إلى المصادقة المتبادلة.

المشكلة: كثرة الاختصارات وغياب التسلسل الهرمي

TCP، UDP، TLS، mTLS، WebSocket، HTTP، HTTPS، gRPC، QUIC؛ معظم المصادر التي تتحدث عنها تقدّمها كقائمة مسطّحة من خيارات قابلة للتبديل، "تُختار حسب حالة الاستخدام". في الواقع، ليست كلها على نفس المستوى: بعضها بروتوكولات نقل، وأخرى طبقات أمان تُلفّ حول النقل، وبعضها الآخر بروتوكولات تطبيقية تستند إلى الأولين. فهم التسلسل الهرمي يعني فهم لماذا لا "نختار" أبدًا بين TCP وTLS: نختار TCP، ثم نقرر ما إذا كنا سنضع TLS فوقه.

هذه المقالة تعيد بناء هذا التسلسل الهرمي طبقة بطبقة، من النقل الخام إلى المصادقة المتبادلة، مع شرح لكل مستوى: ما يضمنه، وما لا يضمنه، ومتى نكتفي به.

المستوى 1: النقل (TCP مقابل UDP)

كل شيء يبدأ من هنا. TCP وUDP هما البروتوكولان الرئيسيان لطبقة النقل (Layer 4) في نموذج OSI. دورهما متطابق: نقل تيار من البيانات بين تطبيقين يعملان على جهازين مختلفين. لكن طريقتهما في تحقيق ذلك مختلفة جذريًا.

من المهم أن نفهم أن IP (بروتوكول الإنترنت)، الموجود في طبقة الشبكة (Layer 3)، يقوم فقط بتوجيه الحزم من مضيف إلى آخر. إنه لا يضمن وصولها ولا ترتيبها ولا حتى تفردها. أجهزة التوجيه تتخذ قرارات توجيه مستقلة لكل حزمة.

هذا الغياب التام للضمانات هو ما يأتي TCP لتعويضه، بينما يختار UDP عمدًا عدم إضافة أي شيء ليبقى خفيفًا للغاية.

TCP: الموثوقية قبل كل شيء

TCP (بروتوكول التحكم بالنقل) هو بروتوكول موجَّه الاتصال (connection-oriented). قبل تبادل أي بايت من البيانات، يجب على الجهازين إنشاء اتصال منطقي.

يتم إنشاء هذا الاتصال عبر مصافحة الثلاث خطوات الشهيرة:


Client                           Serveur
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Connexion établie

لكل خطوة هدف محدد:

  • SYN: يعلن العميل رغبته في فتح اتصال ويوفّر رقم تسلسل أولي (Initial Sequence Number - ISN).

  • SYN-ACK: يقبل الخادم الاتصال، ويؤكد استلام SYN، ويوفّر بدوره رقم تسلسله الخاص.

  • ACK: يؤكد العميل استلام معلومات الخادم.

من هذه اللحظة، يعرف كلا الجهازين حالة الاتصال ويمكنهما البدء في تبادل البيانات.

أرقام التسلسل

لا يرى TCP البيانات كسلسلة من الحزم، بل كـ تيار مستمر من البايتات (byte stream).

كل بايت يتم إرساله له رقم تسلسل.

مثال:

Message :

Bonjour

B = octet 0
o = octet 1
n = octet 2
...

إذا فُقد جزء يحتوي على البايتات 1000 إلى 1499 أثناء النقل، يمكن للمستقبل تحديد المفقود بدقة.

يقوم المُرسِل بإعادة إرسال هذا الجزء فقط.

هذه الدقّة هي أحد أسباب متانة TCP.

تأكيدات الاستلام (ACK)

بعد استلام البيانات، يُرسل المستقبل ACK (Acknowledgment).

خلافًا لما يُتصوّر غالبًا، فإن ACK لا يعني:

"لقد استلمت هذه الحزمة"

بل يعني:

"لقد استلمت جميع البايتات حتى الرقم X."

مثال:

Client envoie :

0 → 999

Serveur répond :

ACK = 1000

هذا يعني:

"كل ما يسبق البايت 1000 قد وصل بنجاح."

هذه الآلية تسمح بتأكيد استلام عدة أجزاء في وقت واحد (cumulative acknowledgments)، مما يقلل عدد حزم التحكم.

إعادة الإرسال

إذا لم يصل ACK أبدًا، يفترض TCP أن الجزء قد فُقد.

فيُعيد إرساله تلقائيًا.

مهلة إعادة الإرسال (Retransmission Timeout – RTO) ليست ثابتة.

يقيس TCP باستمرار زمن الرحلة ذهابًا وإيابًا (RTT) عبر ACK المستلمة ويحسب RTO ديناميكيًا لتجنب عمليات إعادة إرسال غير ضرورية.

تستخدم التطبيقات الحديثة أيضًا آليات مثل Fast Retransmit: عندما يتلقى المُرسِل عدة ACK مكررة (عادة ثلاث)، يستنتج أن جزءًا وسيطًا قد فُقد ويعيد إرساله فورًا، دون انتظار انتهاء المؤقت.

إعادة ترتيب الحزم

الإنترنت لا يضمن إطلاقًا أن تسلك حزمتان نفس المسار.

مثال:

Paquet 1
Paris
 ↓
Londres
 ↓
New York

Paquet 2
Paris
 ↓
Francfort
 ↓
Chicago
 ↓
New York

قد تصل الحزمة الثانية قبل الأولى.

عندها يخزّن TCP مؤقتًا الأجزاء المستلمة خارج الترتيب في مخزن مؤقت (reassembly buffer)، ثم يعيد تجميعها قبل تسليمها للتطبيق.

بالنسبة للتطبيق، يبدو كل شيء وكأنه يصل بالترتيب تمامًا.

التحكم في التدفق

الاتصال لا يعتمد على الشبكة فقط.

المستقبل لديه أيضًا سعة ذاكرة محدودة.

إذا استلم بيانات أسرع مما يستطيع معالجتها، فإن مخازنه المؤقتة تمتلئ في النهاية.

يحل TCP هذه المشكلة عبر نافذة منزلقة (Sliding Window).

يشير المستقبل في كل ACK إلى:

Window = 32768 octets

هذا يعني:

"يمكنك إرسال حتى 32 كيلوبايت إضافية إلي."

إذا انخفضت هذه النافذة إلى الصفر:

Window = 0

يُعلّق المُرسِل عمليات الإرسال مؤقتًا حتى يُعلن المستقبل عن نافذة جديدة متاحة.

تشكل هذه الآلية التحكم في التدفق (Flow Control) وتمنع مضيفًا سريعًا من إغراق مضيف أبطأ.

التحكم في الازدحام

حتى إذا كان المستقبل قادرًا على استيعاب البيانات، فقد تصبح الشبكة نفسها مشبعة.

تمتلك أجهزة التوجيه طوابير انتظار (queues) محدودة.

عندما تفيض، يتم حذف الحزم.

يفسّر TCP الفقدان كعلامة على الازدحام ويُكيّف معدله تلقائيًا عبر نافذة ازدحام (Congestion Window – cwnd).

الخوارزميات الحديثة (مثل Reno و CUBIC و BBR، حسب أنظمة التشغيل) تضبط هذه النافذة لإيجاد توازن بين أقصى معدل واستقرار الشبكة.

استخدمت الإصدارات الأولى من TCP آليتين رئيسيتين:

  • Slow Start: زيادة أسية في المعدل حتى اكتشاف ازدحام.

  • Congestion Avoidance: نمو أكثر حذرًا بعد ذلك، عادة خطي.

هذا التكيّف المستمر هو أحد الأسباب التي تجعل TCP يحافظ على أدائه رغم تقلبات جودة الشبكة.

إغلاق الاتصال

على عكس UDP، فإن اتصال TCP له إغلاق منظم أيضًا.

يُغلق كل طرف تدفقه بشكل مستقل عبر العلم FIN.

يتطلب الإغلاق الكامل عادة أربعة تبادلات:

FIN
ACK
FIN
ACK

يضمن هذا الإجراء أن جميع البيانات العابرة قد تم تسليمها بنجاح قبل تدمير الاتصال.

UDP: البساطة القصوى

UDP (بروتوكول بيانات المستخدم) يتبنى الفلسفة المعاكسة.

إنه عديم الاتصال (connectionless).

لا يوجد:

  • أي مصافحة؛

  • أي أرقام تسلسل؛

  • أي تأكيد استلام؛

  • أي إعادة إرسال؛

  • أي تحكم في التدفق؛

  • أي تحكم في ازدحام.

كل رسالة تُغلّف ببساطة في رزمة بيانات (datagramme) مستقلة، تُرسَل إلى الشبكة، ثم يُنسَاها المُرسِل.

Application → Datagramme UDP → IP → Internet

البروتوكول لا يحتفظ بأي حالة بين عمليتي إرسال.

كل رزمة بيانات مستقلة تمامًا عن سابقاتها.

سلامة البيانات

رغم أن UDP لا يضمن التسليم ولا الترتيب، إلا أنه يحمي سلامة البيانات عبر مجموع اختباري (checksum).

عند الاستلام، يُعاد حساب المجموع الاختباري.

  • إذا تطابقت القيم، تُقبل رزمة البيانات.

  • وإلا، تُرفض فورًا.

إذاً، UDP يكتشف البيانات التالفة لكنه لا يحاول أبدًا استعادتها.

لماذا UDP سريع جدًا؟

رأس UDP يحتوي فقط على 8 بايتات، مقابل 20 بايتًا على الأقل لـ TCP (بدون احتساب الخيارات مثل الطوابع الزمنية أو SACK أو Window Scaling).

نظرًا لعدم الحفاظ على أي اتصال، لا يحتاج نظام التشغيل إلى تتبع حالة كل تبادل، مما يقلل أيضًا من استهلاك الذاكرة وتكلفة المعالجة.

يتلقى التطبيق البيانات فور وصولها تقريبًا، دون انتظار إعادة إرسال محتملة.

متى يكون فقدان البيانات أفضل

الفكرة الأساسية بسيطة:

المعلومة القديمة قد تكون أقل قيمة من المعلومة المفقودة.

لنأخذ محادثة VoIP.

كل حزمة تحمل حوالي 20 مللي ثانية من الصوت.

إذا فُقدت حزمة، فإن إعادة إرسالها ستستغرق غالبًا وقتًا أطول من هذه الـ 20 مللي ثانية.

عندما تصل أخيرًا، تكون المحادثة قد تقدّمت بالفعل.

تفضّل معظم التطبيقات عندها إخفاء الفقدان (استيفاء، صمت، تصحيح أخطاء) بدلاً من انتظار إعادة الإرسال.

ينطبق نفس المنطق على:

  • الألعاب متعددة اللاعبين في الوقت الفعلي؛

  • البث المباشر للفيديو؛

  • تدفقات القياس عن بُعد؛

  • مستشعرات إنترنت الأشياء؛

  • بيانات تحديد المواقع GPS.

القيمة الحديثة دائمًا تقريبًا أكثر فائدة من القيمة القديمة الموثوقة تمامًا.

المستوى 2: التشفير، TLS

TLS (أمان طبقة النقل، خليفة SSL) لا يستبدل TCP، بل يُضاف فوقه. عمليًا، ينشئ TLS اتصال TCP عادي، ثم يتفاوض على جلسة مشفّرة داخله: تبادل الشهادات، الاتفاق على خوارزمية تشفير، اشتقاق مفاتيح الجلسة. كل ما ينتقل بعد ذلك يكون مشفّرًا وموثّقًا.

ثلاثة ضمانات متميزة، غالبًا ما يُخلط بينها:

  • السرية (Confidentiality) : لا يمكن لأي طرف غير الطرفين قراءة المحتوى.

  • السلامة (Intégrité) : أي تغيير في البيانات أثناء النقل يتم اكتشافه.

  • المصادقة (Authentification) : لكن في TLS التقليدي، هي في اتجاه واحد: يتحقق العميل من أن الخادم هو حقًا من يدّعي (عبر شهادته، الموقّعة من جهة موثوقة)، لكن الخادم لا يتحقق من هوية العميل. هذا هو بالضبط نموذج HTTPS عندما تزور موقعًا: المتصفح يوثّق الموقع، الموقع لا يوثّقك (مصادقة المستخدم تمر عبر آلية منفصلة، ملف تعريف ارتباط الجلسة، رمز مميز).

قلّص TLS 1.3 (الإصدار الحالي الموصى به) المصافحة إلى رحلة ذهاب واحدة في الحالة العادية، مقابل رحلتين لـ TLS 1.2، مما يقلل زمن وصول الاتصال بشكل ملحوظ.

المستوى 2 مكرر: mTLS -- المصادقة تصبح متبادلة

mTLS (TLS المتبادل) هو TLS مع شرط إضافي: يطلب الخادم أيضًا شهادة من العميل، ويتحقق منها. يثبت كلا الطرفين هويتهما عبر شهادة موقّعة من جهة توثيق مشتركة.

هذه هي الآلية الطبيعية للتواصل بين الخدمات في بنية موزّعة: حيث يكفي HTTPS التقليدي لمتصفح ليتحدث مع خادم عام، فإن mTLS يجيب على سؤال مختلف؛ كيف يعرف خدمة داخلي أنه يتحدث بالفعل مع خدمة داخلي آخر مصرّح له، وليس مع مهاجم تسلل إلى الشبكة؟

Client                                          Serveur
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + certificat serveur ──────────│
  │──── vérifie le certificat serveur ─────────────│
  │──── envoie SON PROPRE certificat client ──────▶│
  │◀─── vérifie le certificat client ───────────────│
  │──── clés de session dérivées, canal chiffré ──▶│

الجانب المقابل لـ mTLS هو تشغيلي: تحتاج إلى مرجعية تصديق (CA) داخلية، وآلية توزيع الشهادات لكل خدمة، واستراتيجية تدوير/إلغاء. في بيئة أحادية الجهاز مع عدد قليل من الخدمات، قد يكون هذا تعقيدًا أكثر من الفائدة -- يصبح mTLS ضروريًا عندما يعبر حركة المرور بين الخدمات شبكة لا نتحكم فيها بالكامل (مضيفين متعددين، سحابة متعددة المستأجرين)، أو بمجرد أن نريد سياسة من نوع الثقة المعدومة (zero trust)، حيث لا توجد خدمة تُعتبر جديرة بالثقة ضمنيًا لمجرد أنها "داخل" الشبكة.

المستوى 3: بروتوكولات التطبيق فوق TCP + TLS

بمجرد أن يصبح النقل والتشفير في مكانهما، يبقى تعريف كيفية تنظيم التبادلات. هذا هو دور بروتوكولات التطبيق.

HTTP / HTTPS

HTTP هو بروتوكول طلب-استجابة: يفتح العميل اتصالاً (أو يعيد استخدام واحد، مع keep-alive)، يُرسل طلبًا، ينتظر ردًا، ثم يمكن إغلاق الاتصال أو إعادة استخدامه. HTTPS هو ببساطة HTTP فوق TLS -- حرف S لا يغير شيئًا في دلالات البروتوكول، فقط في حقيقة أن النقل مشفّر.

نموذج الطلب-الاستجابة له حد هيكلي: لا يمكن للخادم أبدًا التحدث أولاً. يمكنه فقط الرد على ما يطلبه العميل. بالنسبة للاستعلام المتكرر (التحقق "هل هناك جديد؟" كل ثانية)، فهذا يعمل لكنه يهدر الموارد -- كل طلب يعيد إنشاء تكلفة بروتوكولية لمعظم الوقت دون أن يكون هناك جديد للإعلان عنه.

WebSocket (WS / WSS)

يجيب WebSocket بالضبط على هذا الحد. يبدأ الاتصال كطلب HTTP عادي (مع ترويسة Upgrade: websocket)، لكن بمجرد قبول المصافحة، لم يعد اتصال TCP الأساسي قناة طلب-استجابة HTTP -- بل يصبح قناة ثنائية الاتجاه كاملة الدوبلكس حيث يمكن للعميل والخادم إرسال رسائل في أي وقت، دون الحاجة إلى إعادة دورة طلب-استجابة لكل تبادل.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS هو ببساطة WebSocket فوق TLS، تمامًا كما أن HTTPS هو HTTP فوق TLS. إنه البروتوكول المثالي لكل ما يتطلب دفعًا فوريًا من الخادم -- دردشة، إشعارات، تدفقات تداول، أحداث لعب -- دون الرغبة في إدارة بروتوكول ثنائي بنفسك فوق TCP الخام.

gRPC

أقل شهرة خارج عالم الخدمات المصغرة لكنه محوري في التواصل بين الخدمات: يعتمد gRPC على HTTP/2 (وبالتالي TCP + TLS اختياري)، يُسلسل الرسائل في Protocol Buffers (ثنائي، مقولب، مضغوط - على عكس JSON النصي لمعظم REST APIs)، ويدعم أصلاً التدفق ثنائي الاتجاه بفضل تعدد الإرسال في HTTP/2 (عدة تدفقات منطقية على اتصال TCP واحد، دون حظر الرأس (head-of-line blocking) الذي قد يحدث مع عدة طلبات HTTP/1.1 متتابعة).

QUIC / HTTP3

يغير QUIC قواعد اللعبة بالانطلاق من UDP بدلاً من TCP في طبقة النقل، مع إعادة تطبيق ضمانات الموثوقية التي كان TCP يوفّرها أصلاً - لكن تدفقًا تلو الآخر بدلاً من التطبيق الشامل، مما يزيل حظر الرأس على مستوى النقل (حزمة مفقودة على تدفق لا تمنع التدفقات الأخرى لنفس الاتصال). TLS 1.3 مدمج مباشرة في QUIC بدلاً من إضافته فوقه، مما يقلل زمن وصول المصافحة بشكل أكبر. HTTP/3 هو HTTP فوق QUIC.

نظرة عامة: أين يقع كل بروتوكول

الطبقة البروتوكولات الدور النقل TCP, UDP نقل البايتات، موثوق أو لا النقل (الجيل الجديد) QUIC UDP + موثوقية لكل تدفق + TLS مدمج الأمان TLS, mTLS التشفير، السلامة، المصادقة (أحادية أو متبادلة) التطبيق HTTP/HTTPS, WS/WSS, gRPC تنظيم التبادلات (طلب-استجابة، ثنائي الاتجاه، RPC مقولب)

مثال ملموس لتثبيت الأفكار: بنية خدمات مصغرة مع لوحة تحكم ويب وخدمات داخلية قد تجمع بشكل معقول بين HTTPS (لوحة التحكم ↔ API عام، مصادقة أحادية الاتجاه كافية من جانب المتصفح)، mTLS (خدمة ↔ خدمة داخليًا، مصادقة متبادلة ضرورية)، وWSS (إشعارات فورية تُدفع إلى لوحة التحكم) -- ثلاثة بروتوكولات تطبيق مختلفة، جميعها مبنية على نفس القاعدة TCP + TLS.

كيف تختار، عمليًا

ثلاثة أسئلة تكفي عادةً للحسم:

  1. هل أحتاج إلى الموثوقية والترتيب، أم أن نضارة البيانات تتفوق على ضمان تسليمها؟ → TCP إذا نعم، UDP إذا لا (أو QUIC للحصول على كليهما معًا عبر حل وسط مختلف).

  2. هل يجب أن يكون الخادم قادرًا على بدء الرسائل، أم أن العميل دائمًا من يقوم بالطلب الأول؟ → WebSocket/gRPC streaming إذا كان على الخادم الدفع، HTTP تقليدي فيما عدا ذلك.

  3. هل يجب على كلا الطرفين إثبات هويتهما بشكل متبادل، أم طرف واحد فقط يحتاج إلى التحقق؟ → mTLS للتواصل بين الخدمات في بيئة عدم الثقة، TLS بسيط لعميل عام تقليدي.

التعقيد التشغيلي يزداد مع كل طبقة تُضاف: TCP الخام ليس لديه أي بنية تحتية لإدارتها، TLS يتطلب شهادات، mTLS يتطلب CA واستراتيجية تدوير، gRPC يتطلب تعريف مخطط Protobuf مشترك. رد الفعل الصحيح هو عدم زيادة التعقيد إلا عندما تُظهر الطبقة السفلى حدًا ملموسًا، وليس استباقيًا.

Cách các máy tính nói chuyện với nhau: tổng quan từ TCP đến mTLS

Tại sao TCP, UDP, TLS, mTLS, HTTP và WebSocket không phải là những lựa chọn thay thế cạnh tranh mà là các tầng xếp chồng; một tổng quan phân cấp về giao tiếp máy tính, từ vận chuyển thô đến xác thực lẫn nhau.

Vấn đề: quá nhiều từ viết tắt, không đủ thứ bậc

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; hầu hết các tài liệu nói về chúng đều trình bày như một danh sách phẳng các lựa chọn có thể thay thế, "tùy trường hợp sử dụng mà chọn". Thực tế, chúng không cùng một cấp độ: một số là giao thức vận chuyển, số khác là tầng bảo mật bọc quanh vận chuyển, lại có những giao thức ứng dụng dựa trên hai tầng đầu. Hiểu được thứ bậc là hiểu tại sao ta không bao giờ "chọn" giữa TCP và TLS: ta chọn TCP, rồi quyết định có đặt TLS lên trên hay không.

Bài viết này xây dựng lại thứ bậc đó từng tầng một, từ vận chuyển thô đến xác thực lẫn nhau, với mỗi cấp độ: nó đảm bảo điều gì, nó không đảm bảo điều gì, và khi nào thì dùng nó là đủ.

Cấp độ 1: vận chuyển (TCP so với UDP)

Mọi thứ bắt đầu từ đây. TCP và UDP là hai giao thức chính của tầng Vận chuyển (Layer 4) trong mô hình OSI. Vai trò của chúng giống hệt nhau: vận chuyển một luồng dữ liệu giữa hai ứng dụng chạy trên các máy khác nhau. Tuy nhiên, cách thức thực hiện của chúng hoàn toàn khác biệt.

Điều quan trọng cần hiểu là IP (Internet Protocol), nằm ở tầng mạng (Layer 3), chỉ làm nhiệm vụ chuyển tiếp các gói tin từ một máy chủ này sang máy chủ khác. Nó không đảm bảo việc gói tin đến nơi, không đảm bảo thứ tự, thậm chí không đảm bảo tính duy nhất. Các bộ định tuyến chỉ đơn giản đưa ra các quyết định định tuyến độc lập cho mỗi gói tin.

Chính sự thiếu vắng các đảm bảo này là điều TCP đến để bù đắp, trong khi UDP cố tình không thêm gì cả để giữ cho nó cực kỳ nhẹ.

TCP: độ tin cậy lên hàng đầu

TCP (Transmission Control Protocol) là một giao thức hướng kết nối (connection-oriented). Trước khi trao đổi bất kỳ byte dữ liệu nào, hai máy phải thiết lập một kết nối logic.

Kết nối này được tạo ra nhờ Bắt tay ba bước (Three-Way Handshake) nổi tiếng:


Client                           Server
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Kết nối được thiết lập

Mỗi bước có một mục tiêu cụ thể:

  • SYN: client thông báo muốn mở một kết nối và cung cấp số thứ tự đầu tiên (Initial Sequence Number - ISN).

  • SYN-ACK: server chấp nhận kết nối, xác nhận đã nhận SYN và cung cấp số thứ tự của riêng mình.

  • ACK: client xác nhận đã nhận thông tin từ server.

Kể từ thời điểm này, cả hai máy đều biết trạng thái của kết nối và có thể bắt đầu trao đổi dữ liệu.

Các số thứ tự

TCP không xem dữ liệu như một chuỗi các gói tin, mà như một luồng byte liên tục (byte stream).

Mỗi byte được gửi đều có một số thứ tự.

Ví dụ:

Tin nhắn:

Bonjour

B = byte 0
o = byte 1
n = byte 2
...

Nếu một segment chứa các byte 1000 đến 1499 bị mất trong quá trình vận chuyển, bên nhận có thể phát hiện chính xác phần nào bị thiếu.

Bên gửi chỉ truyền lại phần đó.

Mức độ chi tiết này là một trong những lý do tạo nên sự mạnh mẽ của TCP.

Các xác nhận (ACK)

Sau khi nhận được dữ liệu, bên nhận gửi một ACK (Acknowledgment).

Trái với suy nghĩ thông thường, một ACK không có nghĩa là:

"Tôi đã nhận được gói tin này"

Nó có nghĩa là:

"Tôi đã nhận được tất cả các byte cho đến số X."

Ví dụ:

Client gửi:

0 → 999

Server trả lời:

ACK = 1000

Điều này có nghĩa là:

"Mọi thứ trước byte 1000 đã đến nơi an toàn."

Cơ chế này cho phép xác nhận nhiều segment cùng một lúc (cumulative acknowledgments), giảm số lượng gói tin điều khiển.

Các lần truyền lại

Nếu một ACK không bao giờ đến, TCP cho rằng segment đã bị mất.

Nó tự động truyền lại.

Thời gian chờ truyền lại (Retransmission Timeout – RTO) không cố định.

TCP liên tục đo thời gian khứ hồi (RTT) nhờ các ACK đã nhận và tính toán động RTO để tránh các lần truyền lại không cần thiết.

Các triển khai hiện đại cũng sử dụng các cơ chế như Fast Retransmit: khi bên gửi nhận được nhiều ACK trùng lặp (thường là ba), nó suy ra rằng một segment ở giữa đã bị mất và gửi lại ngay lập tức, không cần chờ hết thời gian.

Sắp xếp lại các gói tin

Internet hoàn toàn không đảm bảo rằng hai gói tin sẽ đi cùng một đường.

Ví dụ:

Gói tin 1
Paris
 ↓
London
 ↓
New York

Gói tin 2
Paris
 ↓
Frankfurt
 ↓
Chicago
 ↓
New York

Gói tin thứ hai có thể đến trước gói tin thứ nhất.

TCP tạm thời lưu trữ các segment nhận được không đúng thứ tự trong một bộ đệm (reassembly buffer), sau đó sắp xếp lại trước khi chuyển cho ứng dụng.

Đối với ứng dụng, mọi thứ dường như đến một cách hoàn hảo theo đúng thứ tự.

Kiểm soát luồng

Một kết nối không chỉ phụ thuộc vào mạng.

Bên nhận cũng có dung lượng bộ nhớ hạn chế.

Nếu nó nhận nhanh hơn khả năng xử lý dữ liệu, các bộ đệm của nó sẽ bị tràn.

TCP giải quyết vấn đề này nhờ một cửa sổ trượt (Sliding Window).

Bên nhận chỉ ra trong mỗi ACK:

Window = 32768 bytes

Điều này có nghĩa là:

"Bạn có thể gửi cho tôi thêm tới 32 KB."

Nếu cửa sổ này giảm xuống 0:

Window = 0

Bên gửi tạm thời dừng truyền cho đến khi bên nhận thông báo có cửa sổ mới.

Cơ chế này tạo nên kiểm soát luồng (Flow Control) và ngăn không cho một máy chủ nhanh làm ngập một máy chủ chậm hơn.

Kiểm soát tắc nghẽn

Ngay cả khi bên nhận có khả năng hấp thụ dữ liệu, bản thân mạng cũng có thể bị bão hòa.

Các bộ định tuyến có hàng đợi (queues) hạn chế.

Khi chúng tràn, các gói tin bị loại bỏ.

TCP coi các mất mát là dấu hiệu của tắc nghẽn và tự động điều chỉnh tốc độ nhờ một cửa sổ tắc nghẽn (Congestion Window – cwnd).

Các thuật toán hiện đại (như Reno, CUBIC hoặc BBR, tùy theo hệ điều hành) điều chỉnh cửa sổ này để tìm sự cân bằng giữa tốc độ tối đa và sự ổn định của mạng.

Các phiên bản đầu của TCP chủ yếu sử dụng hai cơ chế:

  • Slow Start: tăng tốc độ theo cấp số nhân cho đến khi phát hiện tắc nghẽn.

  • Congestion Avoidance: sau đó tăng trưởng thận trọng hơn, thường là tuyến tính.

Sự thích ứng liên tục này là một trong những lý do TCP vẫn hoạt động tốt mặc dù chất lượng mạng có biến động.

Đóng kết nối

Không giống như UDP, một kết nối TCP cũng có một quy trình đóng riêng.

Mỗi đầu mút đóng luồng của mình một cách độc lập nhờ cờ FIN.

Một lần đóng hoàn chỉnh thường cần bốn lần trao đổi:

FIN
ACK
FIN
ACK

Thủ tục này đảm bảo rằng tất cả dữ liệu đang trên đường đều được giao trước khi kết nối bị hủy.

UDP: sự đơn giản tối đa

UDP (User Datagram Protocol) áp dụng triết lý ngược lại.

Nó không kết nối (connectionless).

Không có:

  • handshake nào;

  • số thứ tự nào;

  • xác nhận nào;

  • truyền lại nào;

  • kiểm soát luồng nào;

  • kiểm soát tắc nghẽn nào.

Mỗi thông điệp chỉ đơn giản được đóng gói vào một datagram độc lập, gửi lên mạng, rồi bên gửi bỏ đi.

Application → UDP Datagram → IP → Internet

Giao thức không lưu giữ bất kỳ trạng thái nào giữa hai lần gửi.

Mỗi datagram hoàn toàn độc lập với các datagram trước đó.

Tính toàn vẹn dữ liệu

Mặc dù UDP không đảm bảo việc giao hàng hay thứ tự, nó vẫn bảo vệ tính toàn vẹn của dữ liệu nhờ một checksum.

Khi nhận, checksum được tính toán lại.

  • Nếu các giá trị khớp nhau, datagram được chấp nhận.

  • Nếu không, nó bị từ chối ngay lập tức.

UDP do đó phát hiện dữ liệu bị hỏng, nhưng không bao giờ cố gắng khôi phục chúng.

Tại sao UDP lại nhanh như vậy?

Tiêu đề UDP chỉ chứa 8 byte, so với tối thiểu 20 byte cho TCP (chưa kể các tùy chọn như timestamps, SACK hay Window Scaling).

Không có kết nối nào được duy trì, hệ điều hành không phải theo dõi trạng thái của mỗi lần trao đổi, điều này cũng làm giảm mức tiêu thụ bộ nhớ và chi phí xử lý.

Ứng dụng nhận được dữ liệu gần như ngay khi chúng đến, không cần chờ các lần truyền lại có thể xảy ra.

Khi nào mất dữ liệu lại tốt hơn

Ý tưởng cơ bản rất đơn giản:

Một thông tin cũ có thể có giá trị thấp hơn một thông tin bị mất.

Hãy xem xét một cuộc trò chuyện VoIP.

Mỗi gói tin chứa khoảng 20 ms giọng nói.

Nếu một gói tin bị mất, việc truyền lại nó thường mất nhiều thời gian hơn 20 ms đó.

Khi nó cuối cùng đến nơi, cuộc trò chuyện đã tiếp diễn.

Hầu hết các ứng dụng thích che giấu sự mất mát (nội suy, im lặng, sửa lỗi) hơn là chờ truyền lại.

Lập luận tương tự cũng áp dụng cho:

  • các trò chơi đa người thời gian thực;

  • phát trực tiếp video;

  • các luồng dữ liệu từ xa;

  • các cảm biến IoT;

  • dữ liệu vị trí GPS.

Một giá trị gần đây hầu như luôn hữu ích hơn một giá trị cũ hoàn toàn đáng tin cậy.

Cấp độ 2: mã hóa, TLS

TLS (Transport Layer Security, kế thừa của SSL) không thay thế TCP, nó được thêm vào bên trên. Cụ thể, TLS thiết lập một kết nối TCP bình thường, sau đó thương lượng một phiên mã hóa bên trong: trao đổi chứng chỉ, thỏa thuận về thuật toán mã hóa, dẫn xuất khóa phiên. Mọi thứ truyền đi sau đó đều được mã hóa và xác thực.

Ba đảm bảo riêng biệt, thường bị nhầm lẫn:

  • Bảo mật (Confidentiality): không ai ngoài hai bên có thể đọc được nội dung.

  • Toàn vẹn (Integrity): mọi sự thay đổi dữ liệu trong quá trình truyền đều bị phát hiện.

  • Xác thực (Authentication): nhưng trong TLS cổ điển, chỉ một chiều: client xác minh rằng server đúng là người nó tuyên bố (thông qua chứng chỉ, được ký bởi một tổ chức đáng tin cậy), nhưng server không xác minh gì về danh tính của client. Đây chính xác là mô hình của HTTPS khi bạn truy cập một trang web: trình duyệt xác thực trang web, trang web không xác thực bạn (việc xác thực người dùng thông qua một cơ chế riêng, cookie phiên, token).

TLS 1.3 (phiên bản hiện tại được khuyến nghị) đã giảm handshake xuống chỉ còn một vòng khứ hồi trong trường hợp thông thường, so với hai vòng của TLS 1.2, giúp giảm đáng kể độ trễ kết nối.

Cấp độ 2bis: mTLS -- xác thực trở nên lẫn nhau

mTLS (mutual TLS) là TLS với một ràng buộc bổ sung: server cũng yêu cầu một chứng chỉ từ client và xác minh nó. Cả hai bên đều chứng minh danh tính của mình thông qua một chứng chỉ được ký bởi một tổ chức chứng thực chung đáng tin cậy.

Đây là cơ chế tự nhiên cho giao tiếp service-à-service trong một kiến trúc phân tán: nơi HTTPS cổ điển đủ để trình duyệt nói chuyện với một server công cộng, mTLS trả lời một câu hỏi khác; làm thế nào một dịch vụ nội bộ biết rằng nó đang nói chuyện với một dịch vụ nội bộ được ủy quyền khác, chứ không phải với một kẻ tấn công đã xâm nhập vào mạng?

Client                                        Server
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + chứng chỉ server ────────────│
  │──── xác minh chứng chỉ server ─────────────────│
  │──── gửi CHỨNG CHỈ CỦA CHÍNH NÓ ───────────────▶│
  │◀─── xác minh chứng chỉ client ──────────────────│
  │──── khóa phiên được dẫn xuất, kênh mã hóa ────▶│

Mặt trái của mTLS là về mặt vận hành: cần một cơ quan cấp chứng chỉ (CA) nội bộ, một cơ chế phân phối chứng chỉ cho mỗi dịch vụ, và một chiến lược luân chuyển/thu hồi. Trong một môi trường một máy với ít dịch vụ, đôi khi nó phức tạp hơn là lợi ích -- mTLS trở nên cần thiết từ thời điểm lưu lượng giữa các dịch vụ đi qua một mạng mà ta không kiểm soát hoàn toàn (nhiều máy chủ, cloud đa đối tác), hoặc ngay khi ta muốn một chính sách kiểu zero trust, nơi không có dịch vụ nào được mặc nhiên tin tưởng chỉ vì nó nằm "bên trong" mạng.

Cấp độ 3: các giao thức ứng dụng trên TCP+TLS

Khi đã có vận chuyển và mã hóa, còn phải xác định cấu trúc các trao đổi như thế nào. Đây là vai trò của các giao thức ứng dụng.

HTTP / HTTPS

HTTP là một giao thức yêu cầu-phản hồi: client mở một kết nối (hoặc tái sử dụng một kết nối, với keep-alive), gửi một yêu cầu, chờ phản hồi, kết nối sau đó có thể đóng lại hoặc được tái sử dụng. HTTPS, đơn giản là HTTP trên TLS -- chữ S không thay đổi gì về ngữ nghĩa của giao thức, chỉ thay đổi việc vận chuyển được mã hóa.

Mô hình yêu cầu-phản hồi có một giới hạn cấu trúc: server không bao giờ có thể nói trước. Nó chỉ có thể trả lời những gì client yêu cầu. Đối với việc polling thường xuyên (kiểm tra "có gì mới không?" mỗi giây), nó hoạt động nhưng lãng phí tài nguyên -- mỗi yêu cầu tạo ra chi phí giao thức, và phần lớn thời gian, chẳng có gì mới để thông báo.

WebSocket (WS / WSS)

WebSocket giải quyết chính xác giới hạn này. Kết nối bắt đầu như một yêu cầu HTTP thông thường (với header Upgrade: websocket), nhưng một khi bắt tay được chấp nhận, kết nối TCP bên dưới không còn là một kênh yêu cầu-phản hồi HTTP nữa -- nó trở thành một kênh hai chiều full-duplex nơi client và server có thể gửi thông điệp bất cứ lúc nào, mà không cần phải phát lại một chu trình yêu cầu-phản hồi cho mỗi lần trao đổi.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS đơn giản là WebSocket trên TLS, giống hệt như HTTPS là HTTP trên TLS. Đây là giao thức được lựa chọn cho mọi thứ cần push server thời gian thực -- chat, thông báo, luồng giao dịch, sự kiện trò chơi -- mà không muốn tự quản lý một giao thức nhị phân trên TCP trần.

gRPC

Ít được biết đến ngoài thế giới microservices nhưng là trung tâm trong giao tiếp service-à-service: gRPC dựa trên HTTP/2 (do đó TCP + TLS tùy chọn), tuần tự hóa các thông điệp bằng Protocol Buffers (nhị phân, có kiểu, nhỏ gọn - trái ngược với JSON dạng văn bản của hầu hết các API REST), và hỗ trợ streaming hai chiều một cách tự nhiên nhờ ghép kênh của HTTP/2 (nhiều luồng logic trên một kết nối TCP duy nhất, không có head-of-line blocking như nhiều yêu cầu HTTP/1.1 tuần tự).

QUIC / HTTP3

QUIC thay đổi cuộc chơi bằng cách quay lại dùng UDP thay vì TCP ở tầng vận chuyển, đồng thời tái triển khai các đảm bảo độ tin cậy mà TCP vốn có - nhưng theo từng luồng thay vì toàn cục, điều này loại bỏ head-of-line blocking ở tầng vận chuyển (một gói tin bị mất trên một luồng không còn chặn các luồng khác của cùng kết nối). TLS 1.3 được tích hợp trực tiếp vào QUIC thay vì được thêm lên trên, giúp giảm thêm độ trễ handshake. HTTP/3 là HTTP trên QUIC.

Tổng quan: mỗi giao thức nằm ở đâu

Tầng Giao thức Vai trò Vận chuyển TCP, UDP Đưa các byte đi, có tin cậy hoặc không Vận chuyển (thế hệ mới) QUIC UDP + độ tin cậy theo luồng + TLS tích hợp Bảo mật TLS, mTLS Mã hóa, toàn vẹn, xác thực (một chiều hoặc lẫn nhau) Ứng dụng HTTP/HTTPS, WS/WSS, gRPC Cấu trúc các trao đổi (yêu cầu-phản hồi, hai chiều, RPC có kiểu)

Một ví dụ cụ thể để cố định ý tưởng: một kiến trúc microservices với dashboard web và các dịch vụ nội bộ có thể kết hợp HTTPS (dashboard ↔ API công cộng, xác thực một chiều là đủ về phía trình duyệt), mTLS (dịch vụ ↔ dịch vụ nội bộ, cần xác thực lẫn nhau), và WSS (thông báo thời gian thực đẩy đến dashboard) -- ba giao thức ứng dụng khác nhau, tất cả đều được xây dựng trên cùng một nền tảng TCP + TLS.

Cách chọn, trong thực tế

Ba câu hỏi thường đủ để phân định:

  1. Tôi có cần độ tin cậy và thứ tự, hay tính tươi mới của dữ liệu quan trọng hơn việc giao hàng đảm bảo? → TCP nếu có, UDP nếu không (hoặc QUIC để có cả hai thông qua một sự đánh đổi khác).

  2. Server có cần có khả năng chủ động gửi tin nhắn, hay client luôn là bên yêu cầu trước? → WebSocket/gRPC streaming nếu server cần push, HTTP cổ điển nếu không.

  3. Cả hai bên có cần chứng minh danh tính lẫn nhau, hay chỉ một bên cần được xác minh? → mTLS cho service-à-service trong môi trường zero-trust, TLS đơn giản cho client công cộng cổ điển.

Độ phức tạp vận hành tăng lên theo mỗi tầng được thêm vào: TCP trần không có hạ tầng nào để quản lý, TLS cần chứng chỉ, mTLS cần một CA và chiến lược luân chuyển, gRPC cần một định nghĩa lược đồ Protobuf dùng chung. Phản xạ đúng đắn là chỉ tăng độ phức tạp khi tầng bên dưới cho thấy một giới hạn cụ thể, chứ không phải do phòng trước.

เครื่องจักรสื่อสารกันอย่างไร: ภาพรวมจาก TCP ถึง mTLS

ทำไม TCP, UDP, TLS, mTLS, HTTP และ WebSocket ไม่ใช่ทางเลือกที่แข่งขันกัน แต่เป็นชั้นที่ซ้อนทับกัน ภาพรวมเชิงลำดับชั้นของการสื่อสารระหว่างเครื่อง จากการขนส่งดิบไปจนถึงการพิสูจน์ตัวตนร่วมกัน

ปัญหา: คำย่อมากเกินไป ลำดับชั้นไม่เพียงพอ

TCP, UDP, TLS, mTLS, WebSocket, HTTP, HTTPS, gRPC, QUIC; แหล่งข้อมูลส่วนใหญ่ที่พูดถึงโปรโตคอลเหล่านี้มักนำเสนอเป็นรายการราบของตัวเลือกที่ใช้แทนกันได้ "ให้เลือกตามกรณีการใช้งาน" แต่ในความเป็นจริงแล้วพวกมันไม่ได้อยู่ในระนาบเดียวกัน บางตัวเป็นโปรโตคอลการขนส่ง บางตัวเป็นชั้นความปลอดภัยที่ห่อหุ้มอยู่รอบการขนส่ง และบางตัวเป็นโปรโตคอลระดับแอปพลิเคชันที่ทำงานบนสองประเภทแรก การเข้าใจลำดับชั้นคือการเข้าใจว่าทำไมเราไม่เคย "เลือก" ระหว่าง TCP กับ TLS: เราเลือก TCP จากนั้น จึงตัดสินใจว่าจะใส่ TLS ทับลงไปหรือไม่

บทความนี้สร้างลำดับชั้นนี้ขึ้นทีละชั้น จากการขนส่งดิบไปจนถึงการพิสูจน์ตัวตนร่วมกัน โดยในแต่ละระดับจะอธิบายว่า: มันรับประกันอะไรบ้าง, ไม่ได้รับประกันอะไรบ้าง, และเมื่อใดควรพอใจกับมัน

ระดับ 1: การขนส่ง (TCP เทียบกับ UDP)

ทุกอย่างเริ่มต้นที่นี่ TCP และ UDP เป็นโปรโตคอลหลักสองตัวของชั้น Transport (Layer 4) ในแบบจำลอง OSI บทบาทของพวกมันเหมือนกัน: ขนส่งสตรีมข้อมูลระหว่างสองแอปพลิเคชันที่ทำงานบนเครื่องคนละเครื่อง แต่วิธีการทำให้สำเร็จนั้นแตกต่างกันอย่างสิ้นเชิง

สิ่งสำคัญคือต้องเข้าใจว่า IP (Internet Protocol) ซึ่งอยู่ในชั้นเครือข่าย (Layer 3) นั้นทำเพียงส่งต่อแพ็กเกตจากโฮสต์หนึ่งไปยังอีกโฮสต์หนึ่ง มันไม่รับประกันว่าข้อมูลจะถึงปลายทาง ไม่รับประกันลำดับ หรือแม้แต่ความไม่ซ้ำกันของแพ็กเกต เราเตอร์จะตัดสินใจเส้นทางอย่างอิสระสำหรับแต่ละแพ็กเกต

การขาดการรับประกันนี้คือสิ่งที่ TCP เข้ามาชดเชย ในขณะที่ UDP เลือกที่จะไม่เพิ่มสิ่งใดเข้าไปโดยเจตนาเพื่อให้คงความเบาอย่างยิ่ง

TCP: ความน่าเชื่อถือเหนือสิ่งอื่นใด

TCP (Transmission Control Protocol) เป็นโปรโตคอล แบบเชื่อมต่อ (connection-oriented) ก่อนที่จะแลกเปลี่ยนข้อมูลแม้แต่ไบต์เดียว ทั้งสองเครื่องต้องสร้างการเชื่อมต่อเชิงตรรกะก่อน

การเชื่อมต่อนี้ถูกสร้างขึ้นผ่าน Three-Way Handshake อันโด่งดัง:

Client                           Server
SYN ---------------------------->
        <--------------------- SYN + ACK
ACK ----------------------------> 
Connection established

แต่ละขั้นตอนมีวัตถุประสงค์ที่ชัดเจน:

  • SYN: ไคลเอนต์ประกาศว่าต้องการเปิดการเชื่อมต่อและให้หมายเลขลำดับเริ่มต้น (Initial Sequence Number - ISN)

  • SYN-ACK: เซิร์ฟเวอร์ยอมรับการเชื่อมต่อ รับทราบ SYN และให้หมายเลขลำดับของตนเอง

  • ACK: ไคลเอนต์ยืนยันการรับข้อมูลของเซิร์ฟเวอร์

จากจุดนี้เป็นต้นไป ทั้งสองเครื่องจะรู้สถานะของการเชื่อมต่อและสามารถเริ่มแลกเปลี่ยนข้อมูลได้

หมายเลขลำดับ (Sequence Numbers)

TCP ไม่มองข้อมูลเป็นลำดับของแพ็กเกต แต่มองเป็น สตรีมไบต์ต่อเนื่อง (byte stream)

แต่ละไบต์ที่ส่งไปจะมีหมายเลขลำดับ

ตัวอย่าง:

Message:

Bonjour

B = byte 0
o = byte 1
n = byte 2
...

หากเซกเมนต์ที่มีไบต์ 1000 ถึง 1499 สูญหายไประหว่างการขนส่ง ผู้รับสามารถตรวจจับได้อย่างแม่นยำว่าส่วนใดหายไป

ผู้ส่งจะส่งซ้ำเฉพาะส่วนนั้นเท่านั้น

ความละเอียดระดับนี้เป็นหนึ่งในเหตุผลที่ทำให้ TCP มีความแข็งแกร่ง

การตอบรับ (ACK)

หลังจากรับข้อมูลแล้ว ผู้รับจะส่ง ACK (Acknowledgment)

ตรงกันข้ามกับสิ่งที่หลายคนมักคิด ACK ไม่ได้หมายความว่า:

"ฉันได้รับแพ็กเกตนี้แล้ว"

แต่หมายถึง:

"ฉันได้รับไบต์ทั้งหมดจนถึงหมายเลข X แล้ว"

ตัวอย่าง:

Client sends:

0 → 999

Server responds:

ACK = 1000

นั่นหมายถึง:

"ทุกอย่างที่อยู่ก่อนไบต์ที่ 1000 มาถึงแล้ว"

กลไกนี้ช่วยให้สามารถรับทราบหลายเซกเมนต์พร้อมกันได้ (cumulative acknowledgments) ซึ่งลดจำนวนแพ็กเกตควบคุม

การส่งซ้ำ (Retransmissions)

หาก ACK ไม่เคยมาถึง TCP จะถือว่าเซกเมนต์นั้นสูญหาย

มันจะส่งซ้ำโดยอัตโนมัติ

ระยะเวลารอก่อนส่งซ้ำ (Retransmission Timeout – RTO) ไม่ใช่ค่าคงที่

TCP จะวัดระยะเวลาไป-กลับ (RTT) อย่างต่อเนื่องจาก ACK ที่ได้รับ และคำนวณ RTO แบบไดนามิกเพื่อหลีกเลี่ยงการส่งซ้ำที่ไม่จำเป็น

การใช้งานสมัยใหม่ยังใช้กลไกเช่น Fast Retransmit: เมื่อผู้ส่งได้รับ ACK ซ้ำๆ หลายครั้ง (โดยทั่วไปสามครั้ง) มันจะสรุปว่าเซกเมนต์ที่อยู่ระหว่างกลางสูญหายและส่งซ้ำทันที โดยไม่ต้องรอให้ตัวจับเวลาหมดอายุ

การจัดเรียงแพ็กเกตใหม่ (Packet Reordering)

อินเทอร์เน็ตไม่รับประกันอย่างเด็ดขาดว่าแพ็กเกตสองแพ็กเกตจะเดินทางตามเส้นทางเดียวกัน

ตัวอย่าง:

Packet 1
Paris
 ↓
London
 ↓
New York

Packet 2
Paris
 ↓
Frankfurt
 ↓
Chicago
 ↓
New York

แพ็กเกตที่สองอาจมาถึงก่อนแพ็กเกตแรก

TCP จะเก็บเซกเมนต์ที่ได้รับ แบบไม่เรียงลำดับ ไว้ชั่วคราวในบัฟเฟอร์ (reassembly buffer) จากนั้นจึงประกอบกลับเข้าที่ก่อนส่งให้แอปพลิเคชัน

สำหรับแอปพลิเคชันแล้ว ทุกอย่างดูเหมือนมาถึงอย่างถูกต้องตามลำดับ

การควบคุมการไหล (Flow Control)

การเชื่อมต่อไม่ได้ขึ้นอยู่กับเครือข่ายเท่านั้น

ผู้รับก็มีความจุหน่วยความจำที่จำกัดเช่นกัน

หากได้รับข้อมูลเร็วกว่าที่จะประมวลผลได้ บัฟเฟอร์จะเต็มในที่สุด

TCP แก้ปัญหานี้ด้วย หน้าต่างเลื่อน (Sliding Window)

ผู้รับจะระบุในทุก ACK:

Window = 32768 bytes

นั่นหมายถึง:

"คุณสามารถส่งเพิ่มได้อีกถึง 32 KB"

หากหน้าต่างนี้ลดลงเป็นศูนย์:

Window = 0

ผู้ส่งจะหยุดส่งชั่วคราวจนกว่าผู้รับจะประกาศว่ามีหน้าต่างว่างอีกครั้ง

กลไกนี้คือ การควบคุมการไหล (Flow Control) และป้องกันไม่ให้โฮสต์ที่เร็วท่วมโฮสต์ที่ช้า

การควบคุมความแออัด (Congestion Control)

แม้ว่าผู้รับจะสามารถรับข้อมูลได้ แต่เครือข่ายเองก็อาจอิ่มตัวได้

เราเตอร์มีคิว (queues) ที่จำกัด

เมื่อคิวล้น แพ็กเกตจะถูกลบทิ้ง

TCP ตีความการสูญหายเป็นสัญญาณของความแออัดและปรับอัตราการส่งโดยอัตโนมัติผ่าน หน้าต่างความแออัด (Congestion Window – cwnd)

อัลกอริทึมสมัยใหม่ (เช่น Reno, CUBIC หรือ BBR ขึ้นอยู่กับระบบปฏิบัติการ) จะปรับหน้าต่างนี้เพื่อหาสมดุลระหว่างอัตราการส่งสูงสุดและเสถียรภาพของเครือข่าย

TCP รุ่นแรกๆ ใช้กลไกหลักสองอย่าง:

  • Slow Start: เพิ่มอัตราการส่งแบบทวีคูณจนกระทั่งตรวจพบความแออัด

  • Congestion Avoidance: จากนั้นเติบโตอย่างระมัดระวังมากขึ้น โดยทั่วไปเป็นแบบเส้นตรง

การปรับตัวอย่างต่อเนื่องนี้เป็นหนึ่งในเหตุผลที่ TCP ยังคงมีประสิทธิภาพแม้คุณภาพเครือข่ายจะผันผวน

การปิดการเชื่อมต่อ

ต่างจาก UDP การเชื่อมต่อ TCP มีการปิดที่ชัดเจน

แต่ละปลายทางจะปิดสตรีมของตนเองอย่างอิสระผ่านแฟล็ก FIN

การปิดสมบูรณ์จำเป็นต้องมีการแลกเปลี่ยนสี่ครั้ง:

FIN
ACK
FIN
ACK

ขั้นตอนนี้รับประกันว่าข้อมูลทั้งหมดที่กำลังเดินทางอยู่จะถูกส่งถึงก่อนที่จะทำลายการเชื่อมต่อ

UDP: ความเรียบง่ายสูงสุด

UDP (User Datagram Protocol) ใช้ปรัชญาตรงกันข้าม

มัน ไม่ต้องมีการเชื่อมต่อ (connectionless)

ไม่มี:

  • ไม่มีการจับมือ (handshake)

  • ไม่มีหมายเลขลำดับ

  • ไม่มีการตอบรับ

  • ไม่มีการส่งซ้ำ

  • ไม่มีการควบคุมการไหล

  • ไม่มีการควบคุมความแออัด

แต่ละข้อความจะถูกห่อหุ้มใน ดาตาแกรม (datagram) อิสระ ส่งไปยังเครือข่าย แล้วผู้ส่งก็ลืมมัน

Application → UDP Datagram → IP → Internet

โปรโตคอลไม่เก็บสถานะใดๆ ระหว่างการส่งสองครั้ง

แต่ละดาตาแกรมเป็นอิสระจากดาตาแกรมก่อนหน้าอย่างสมบูรณ์

ความสมบูรณ์ของข้อมูล (Data Integrity)

แม้ว่า UDP จะไม่รับประกันการส่งถึงหรือลำดับ แต่มันก็ยังปกป้องความสมบูรณ์ของข้อมูลด้วย checksum

เมื่อรับข้อมูลแล้ว checksum จะถูกคำนวณใหม่

  • หากค่าตรงกัน ดาตาแกรมจะถูกยอมรับ

  • หากไม่ตรงกัน ดาตาแกรมจะถูกปฏิเสธทันที

UDP จึงตรวจจับข้อมูลที่เสียหายได้ แต่ไม่เคยพยายามกู้คืน

ทำไม UDP ถึงเร็วขนาดนี้?

ส่วนหัว UDP มีเพียง 8 ไบต์ เทียบกับขั้นต่ำ 20 ไบต์ สำหรับ TCP (ไม่นับตัวเลือกต่างๆ เช่น timestamps, SACK หรือ Window Scaling)

ไม่มีการรักษาการเชื่อมต่อ ระบบปฏิบัติการจึงไม่ต้องติดตามสถานะของการแลกเปลี่ยนแต่ละครั้ง ซึ่งลดการใช้หน่วยความจำและต้นทุนการประมวลผล

แอปพลิเคชันได้รับข้อมูลเกือบจะทันทีที่มาถึง โดยไม่ต้องรอการส่งซ้ำที่อาจเกิดขึ้น

เมื่อใดที่การสูญเสียข้อมูลดีกว่า

แนวคิดพื้นฐานนั้นง่าย:

ข้อมูลที่เก่าอาจมีค่าน้อยกว่าข้อมูลที่สูญหาย

ลองนึกถึงการสนทนา VoIP

แต่ละแพ็กเกตนำส่งเสียงประมาณ 20 ms

หากแพ็กเกตสูญหาย การส่งซ้ำมักใช้เวลานานกว่า 20 ms เหล่านั้น

เมื่อมันมาถึงในที่สุด การสนทนาก็เดินหน้าไปแล้ว

แอปพลิเคชันส่วนใหญ่จึงเลือกที่จะปกปิดการสูญหาย (การแทรกสัญญาณ, ความเงียบ, การแก้ไขข้อผิดพลาด) แทนที่จะรอการส่งซ้ำ

เหตุผลเดียวกันนี้ใช้กับ:

  • เกมแบบหลายผู้เล่นเวลาจริง

  • การสตรีมวิดีโอ

  • สตรีมเทเลเมทรี

  • เซ็นเซอร์ IoT

  • ข้อมูลตำแหน่ง GPS

ค่าใหม่ล่าสุดมักจะมีประโยชน์มากกว่าค่าเก่าที่สมบูรณ์แบบเสมอ

ระดับ 2: การเข้ารหัส, TLS

TLS (Transport Layer Security, ผู้สืบทอดของ SSL) ไม่ได้แทนที่ TCP แต่มาเพิ่มทับไว้ข้างบน ในทางปฏิบัติ TLS จะสร้างการเชื่อมต่อ TCP ปกติ จากนั้นจึงเจรจาเซสชันที่เข้ารหัสภายใน: แลกเปลี่ยนใบรับรอง, ตกลงเกี่ยวกับอัลกอริทึมการเข้ารหัส, สร้างคีย์เซสชัน ทุกสิ่งที่ส่งผ่านหลังจากนั้นจะถูกเข้ารหัสและรับรองความถูกต้อง

การรับประกันสามประการที่แตกต่างกัน ซึ่งมักถูกสับสน:

  • การรักษาความลับ (Confidentiality): ไม่มีใครอื่นนอกจากทั้งสองฝ่ายสามารถอ่านเนื้อหาได้

  • ความสมบูรณ์ (Integrity): การเปลี่ยนแปลงใดๆ ของข้อมูลระหว่างการส่งจะถูกตรวจจับ

  • การพิสูจน์ตัวตน (Authentication): แต่ใน TLS แบบทั่วไป เป็นแบบทิศทางเดียว: ไคลเอนต์ตรวจสอบว่าเซิร์ฟเวอร์เป็นอย่างที่มันอ้างจริง (ผ่านใบรับรองที่ลงนามโดยหน่วยงานที่เชื่อถือได้) แต่เซิร์ฟเวอร์ไม่ได้ตรวจสอบอะไรเกี่ยวกับตัวตนของไคลเอนต์ นี่คือโมเดลของ HTTPS เมื่อคุณเยี่ยมชมเว็บไซต์: เบราว์เซอร์ยืนยันตัวตนของเว็บไซต์ เว็บไซต์ไม่ได้ยืนยันตัวตนของคุณ (การยืนยันตัวตนผู้ใช้จะผ่านกลไกแยกต่างหาก เช่น คุกกี้เซสชัน หรือโทเค็น)

TLS 1.3 (เวอร์ชันปัจจุบันที่แนะนำ) ได้ลดการจับมือเหลือเพียงหนึ่งรอบไป-กลับในกรณีปกติ เทียบกับสองครั้งใน TLS 1.2 ซึ่งช่วยลดความหน่วงในการเชื่อมต่อได้อย่างมาก

ระดับ 2bis: mTLS -- การพิสูจน์ตัวตนกลายเป็นร่วมกัน

mTLS (mutual TLS) คือ TLS ที่มีข้อกำหนดเพิ่มเติม: เซิร์ฟเวอร์จะ ต้องการ ใบรับรองจากไคลเอนต์ด้วย และตรวจสอบมัน ทั้งสองฝ่ายพิสูจน์ตัวตนผ่านใบรับรองที่ลงนามโดยหน่วยงานที่เชื่อถือได้ร่วมกัน

นี่คือกลไกธรรมชาติสำหรับการสื่อสารระหว่างบริการในสถาปัตยกรรมแบบกระจาย: ในขณะที่ HTTPS ทั่วไปเพียงพอสำหรับให้เบราว์เซอร์คุยกับเซิร์ฟเวอร์สาธารณะ mTLS ตอบคำถามที่แตกต่างออกไป บริการภายในจะรู้ได้อย่างไรว่ามันกำลังคุยกับบริการภายในอื่นที่ได้รับอนุญาตจริงๆ ไม่ใช่ผู้โจมตีที่เข้ามาในเครือข่าย?

Client                                          Server
  │──── ClientHello ─────────────────────────────▶│
  │◀─── ServerHello + server certificate ──────────│
  │──── verifies server certificate ──────────────│
  │──── sends ITS OWN client certificate ────────▶│
  │◀─── verifies client certificate ──────────────│
  │──── session keys derived, encrypted channel ─▶│

ข้อเสียของ mTLS คือในทางปฏิบัติ: ต้องมีหน่วยงานออกใบรับรอง (CA) ภายใน, กลไกการแจกจ่ายใบรับรองให้แต่ละบริการ, และกลยุทธ์การหมุนเวียน/เพิกถอน ในสภาพแวดล้อมเครื่องเดียวที่มีบริการไม่กี่ตัว บางครั้งก็ซับซ้อนเกินกว่าประโยชน์ที่ได้ -- mTLS จำเป็นเมื่อการรับส่งระหว่างบริการต้องผ่านเครือข่ายที่เราไม่ได้ควบคุมอย่างสมบูรณ์ (หลายโฮสต์, คลาวด์แบบหลายผู้เช่า) หรือเมื่อต้องการนโยบายแบบ zero trust ที่ไม่มีบริการใดได้รับความไว้วางใจโดยปริยายเพียงเพราะมัน "อยู่ใน" เครือข่าย

ระดับ 3: โปรโตคอลระดับแอปพลิเคชันบน TCP+TLS

เมื่อมีการขนส่งและการเข้ารหัสแล้ว ก็ถึงเวลากำหนด วิธีการจัดโครงสร้างการแลกเปลี่ยน นี่คือบทบาทของโปรโตคอลระดับแอปพลิเคชัน

HTTP / HTTPS

HTTP เป็นโปรโตคอลแบบร้องขอ-ตอบกลับ: ไคลเอนต์เปิดการเชื่อมต่อ (หรือใช้ซ้ำกับ keep-alive), ส่งคำขอ, รอการตอบกลับ, จากนั้นการเชื่อมต่อจะปิดหรือถูกใช้ซ้ำ HTTPS ก็คือ HTTP บน TLS -- S ไม่ได้เปลี่ยนแปลงความหมายของโปรโตคอล เพียงแต่การขนส่งถูกเข้ารหัส

โมเดลร้องขอ-ตอบกลับมีข้อจำกัดเชิงโครงสร้าง: เซิร์ฟเวอร์ไม่สามารถพูดก่อนได้เลย มันทำได้เพียงตอบสนองต่อสิ่งที่ไคลเอนต์ขอ สำหรับการสอบถามถี่ๆ (ตรวจสอบ "มีอะไรใหม่ไหม?" ทุกวินาที) มันใช้ได้แต่สิ้นเปลืองทรัพยากร -- แต่ละคำขอสร้างค่าใช้จ่ายของโปรโตคอลซ้ำแล้วซ้ำเล่า โดยส่วนใหญ่แล้วก็ไม่มีอะไรใหม่จะประกาศ

WebSocket (WS / WSS)

WebSocket ตอบโจทย์ข้อจำกัดนี้พอดี การเชื่อมต่อเริ่มต้นเป็นคำขอ HTTP ทั่วไป (ด้วยส่วนหัว Upgrade: websocket) แต่เมื่อการจับมือได้รับการยอมรับแล้ว การเชื่อมต่อ TCP ที่อยู่ข้างใต้จะไม่ใช่ช่องทางร้องขอ-ตอบกลับแบบ HTTP อีกต่อไป -- มันกลายเป็นช่องทางสองทิศทางแบบ full-duplex ที่ทั้งไคลเอนต์และเซิร์ฟเวอร์สามารถส่งข้อความได้ตลอดเวลา โดยไม่ต้องส่งรอบร้องขอ-ตอบกลับซ้ำในทุกการแลกเปลี่ยน

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WSS ก็คือ WebSocket บน TLS เช่นเดียวกับ HTTPS คือ HTTP บน TLS เป็นโปรโตคอลที่เหมาะสมสำหรับทุกอย่างที่ต้องการ push จากเซิร์ฟเวอร์แบบเวลาจริง -- แชท, การแจ้งเตือน, สตรีมการซื้อขาย, อีเวนต์เกม -- โดยไม่ต้องจัดการโปรโตคอลไบนารีเองบน TCP เปลือย

gRPC

รู้จักกันน้อยนอกโลกไมโครเซอร์วิสแต่เป็นศูนย์กลางในการสื่อสารระหว่างบริการ: gRPC ทำงานบน HTTP/2 (ดังนั้น TCP + TLS เลือกได้), ทำให้ข้อความเป็นอนุกรมด้วย Protocol Buffers (ไบนารี, มีชนิด, กะทัดรัด - ตรงข้ามกับ JSON ข้อความของ API REST ส่วนใหญ่), และรองรับสตรีมมิ่งสองทิศทางโดยธรรมชาติผ่านการมัลติเพล็กซ์ของ HTTP/2 (หลายสตรีมเชิงตรรกะบนการเชื่อมต่อ TCP เดียว โดยไม่มี head-of-line blocking ที่เกิดจากคำขอ HTTP/1.1 แบบเรียงลำดับหลายรายการ)

QUIC / HTTP3

QUIC เปลี่ยนเกมด้วยการเริ่มจาก UDP แทนที่จะเป็น TCP ในระดับการขนส่ง ขณะเดียวกันก็ใช้การรับประกันความน่าเชื่อถือที่ TCP มีมาแต่เดิมขึ้นมาใหม่บน UDP -- แต่ทำทีละสตรีมแทนที่จะทำโดยรวม ซึ่งช่วยขจัด head-of-line blocking ในระดับการขนส่ง (แพ็กเกตที่สูญหายในสตรีมหนึ่งจะไม่บล็อกสตรีมอื่นในการเชื่อมต่อเดียวกัน) TLS 1.3 ถูกรวมเข้าไปใน QUIC โดยตรงแทนที่จะเพิ่มทับข้างบน ซึ่งช่วยลดความหน่วงในการจับมือลงอีก HTTP/3 คือ HTTP บน QUIC

ภาพรวม: โปรโตคอลแต่ละตัวอยู่ที่ไหน

Layer Protocols Role Transport TCP, UDP ขนส่งไบต์ ไม่ว่าจะเชื่อถือได้หรือไม่ Transport (รุ่นใหม่) QUIC UDP + ความน่าเชื่อถือต่อสตรีม + TLS ในตัว Security TLS, mTLS การเข้ารหัส, ความสมบูรณ์, การพิสูจน์ตัวตน (ทางเดียวหรือร่วมกัน) Application HTTP/HTTPS, WS/WSS, gRPC จัดโครงสร้างการแลกเปลี่ยน (ร้องขอ-ตอบกลับ, สองทิศทาง, RPC แบบมีชนิด)

ตัวอย่างที่เป็นรูปธรรม: สถาปัตยกรรมไมโครเซอร์วิสที่มี dashboard เว็บและบริการภายในอาจใช้ HTTPS ร่วมกันอย่างเหมาะสม (dashboard ↔ API สาธารณะ, การยืนยันตัวตนทางเดียวก็เพียงพอสำหรับฝั่งเบราว์เซอร์), mTLS (บริการ ↔ บริการภายใน, จำเป็นต้องยืนยันตัวตนร่วมกัน), และ WSS (การแจ้งเตือนเวลาจริงที่ push ไปยัง dashboard) -- โปรโตคอลระดับแอปพลิเคชันสามแบบที่แตกต่างกัน แต่ทั้งหมดสร้างบนฐาน TCP + TLS เดียวกัน

วิธีเลือกในทางปฏิบัติ

คำถามสามข้อก็เพียงพอที่จะตัดสินใจ:

  1. ฉันต้องการความน่าเชื่อถือและลำดับ หรือความสดของข้อมูลสำคัญกว่าการรับประกันการส่งถึง? → TCP ถ้าใช่, UDP ถ้าไม่ใช่ (หรือ QUIC เพื่อได้ทั้งสองอย่างผ่านการประนีประนอมที่แตกต่าง)

  2. เซิร์ฟเวอร์ต้องสามารถเริ่มส่งข้อความได้ หรือไคลเอนต์เป็นฝ่ายร้องขอแรกเสมอ? → WebSocket/gRPC streaming ถ้าเซิร์ฟเวอร์ต้อง push, HTTP ทั่วไปถ้าไม่

  3. ทั้งสองฝ่ายต้องพิสูจน์ตัวตนร่วมกัน หรือแค่ฝ่ายเดียวที่ต้องถูกตรวจสอบ? → mTLS สำหรับบริการถึงบริการในสภาพแวดล้อม zero-trust, TLS ธรรมดาสำหรับไคลเอนต์สาธารณะทั่วไป

ความซับซ้อนในทางปฏิบัติเพิ่มขึ้นในทุกชั้นที่เพิ่มเข้าไป: TCP เปลือยไม่มีโครงสร้างพื้นฐานใดต้องจัดการ, TLS ต้องใช้ใบรับรอง, mTLS ต้องใช้ CA และกลยุทธ์การหมุนเวียน, gRPC ต้องใช้คำจำกัดความสคีมา Protobuf ที่ใช้ร่วมกัน สัญชาตญาณที่ดีคือเพิ่มความซับซ้อนเมื่อชั้นล่างแสดงข้อจำกัดที่เป็นรูปธรรมเท่านั้น ไม่ใช่โดยการคาดการณ์ล่วงหน้า