The labs on this site need JavaScript to run. The same content is written out below.
Fundamentals › Networking
How is HTTPS different from HTTP?
HTTP sends requests and responses onto the network as plain characters. Between the client and the server there are things like routers and carrier equipment, and if someone looks at the characters passing through there, even a password can be read as it is. HTTPS sends the same HTTP characters encrypted, and the address starts with https://. The code box on the screen has three parts. The first is the address the client connects to, the second is the content it sends (the body of a POST request), and the third is the server's certificate, which appears only for https. Before encryption starts, the server shows its certificate to prove that it is the owner of that name, and the client checks two things: whether the certificate is in its list of trusted certificates, and whether the name it connected to is written in the certificate. If a check fails, the client closes the connection and does not send the request. In this lab you change https:// to http://, stop trusting the certificate, or connect with a name that is not written in the certificate, and send the same content each time. You see what can be seen in the middle of the diagram and what the server receives. 8080 and 8443 on the screen are port numbers written as examples, and password=1234 is a string for testing.
Checked against real execution · Ran 8 combinations between an http/https server and client of Node.js 24.18.0 with a TCP relay placed between them, using a test certificate made with openssl, and checked them
# Address the client connects to https://localhost:8443/login # Content sent (body of the POST request) password=1234 # Server certificate Name: localhost Signed by an authority the client trusts
We ran all eight combinations for real, using only 127.0.0.1 on the PC used to write this lab, and checked against the results. We did not connect to any external network. The server is the http server or https server of Node.js 24.18.0 (its request-handling function records the body it received), and the client is http.request or https.request of the same Node.js. Between the server and the client we placed a TCP relay made by the Probe. The relay passes the bytes it receives to the other side as they are, while recording the bytes in both directions, and the "what can be seen in the middle (router, carrier equipment, and so on)" in the middle of the diagram was reproduced from this record. In all of the recorded bytes, we searched for the strings password=1234 and POST /login. In the four combinations that connect with http://, both strings were there, and in the combinations that connect with https://, both strings were absent, both for those that connected and for those that were closed. This is the result of the search in this run, and it is not proof that the encryption is safe. Also, in the combinations that connect to localhost with https://, the string localhost was visible in the bytes that start the connection, and in the combinations that connect to 127.0.0.1 it was not (we only observed this and did not check the cause in this lab). We made the certificate for testing with openssl 3.5.7 on the PC used to write this lab (self-signed, name localhost, subjectAltName only DNS:localhost, valid for 2 days, files in verify/out/https_basic/). "The client trusts it" was reproduced by giving this certificate to the ca option of https.request, and "does not trust it" by not giving the ca option (so that only the list of certificate authorities included in Node.js is trusted); we did not use rejectUnauthorized: false, which turns verification off. The two combinations that do not trust it were closed with the error DEPTH_ZERO_SELF_SIGNED_CERT, and the combination that trusts it but connects to 127.0.0.1 was closed with the error ERR_TLS_CERT_ALTNAME_INVALID (the message starts with Hostname/IP does not match certificate's altnames). In the combination where both apply (does not trust it and connects to 127.0.0.1), the untrusted certificate error came out, and the name mismatch error did not. In the combinations that were closed, the server's request-handling function was never called (the server recorded only the error ECONNRESET, meaning the connection was reset), and in the combinations that connected, the server received the body password=1234 of the POST /login request. The TLS version used by the combinations that connected was TLSv1.3, and the cipher suite was TLS_AES_256_GCM_SHA384; we could not measure the TLS version of the combinations that were closed. 8080 and 8443 on the screen are example numbers, and in the real runs we used free ports, and password=1234 is a string for testing. Real browsers and operating systems come with a list of trusted certificate authorities built in, and the server's certificate must be signed by one of those authorities, but this lab does not cover that and covers only "in the trusted list / not in the list". We did not run it with a real browser. What we checked in the documents is section 4.2.2 of RFC 9110 (the https URI scheme: a connection protected by TLS, the server is authenticated as acting on behalf of the authority, default port 443) and section 4.3.4 (https certificate verification: the identity in the certificate must be checked against the server at the address that was connected to, and the check needs a list of trusted certificates. If the certificate is not valid for that address, a user agent such as a browser must obtain confirmation from the user or terminate the connection, and for an automated client terminating the connection is recommended), and section 1 of RFC 8446 (the purpose of TLS is a secure channel between two peers, the data in the channel is visible only at the two ends, and tampering can be detected). The client in this lab is an automated program, so it closes the connection without asking the user. We did not cover the case where a browser shows a warning page and asks whether to continue. We did not cover how the key is agreed on before encryption, the order of the messages in the TLS handshake, or the validity period, revocation, and chain of certificates; those are covered in the in-depth lab "TLS handshake". The code on the screen shows the address the client connects to, the content it sends, and the state of the server's certificate, and it is not the program code of a server or a client.
Previous lab: JSON · Next lab: Proxy servers
Struck-through text was removed from the first version of the code; highlighted text was added.