🐕
【Python】socket で TLS 対応の HTTP/1 サーバーをつくる
socket モジュールを使って C 言語のコードと似たような書き方をすると次のようなコードになる。Chrome でアクセスするとクラッシュしてしまうが、curl に対しては動く
import socket
import ssl
addr = '0.0.0.0'
port = 8000
server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((addr, port))
server.listen(5)
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain('localhost.pem', 'localhost-key.pem')
context.set_alpn_protocols(['http/1.1'])
print('serving at port', port)
msg =(
f"HTTP/1.1 200 OK\r\n"
f"Content-Type: text/html; charset=UTF-8\r\n"
f"Content-Length: 11\r\n"
f"Connection: Close\r\n"
f"\r\n"
f"Hello World"
).encode()
while True:
(client, addr2) = server.accept()
stream = context.wrap_socket(sock=client, server_side=True)
stream.sendall(msg)
stream.shutdown(socket.SHUT_RDWR)
stream.close()
server.close()
curl でリクエストを送信すると次のような結果が得られる
curl -v https://localhost:8000
* Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted http/1.1
* Server certificate:
* subject: O=mkcert development certificate; OU=masakielastic@penguin
* start date: Jul 3 04:52:09 2024 GMT
* expire date: Oct 3 04:52:09 2026 GMT
* subjectAltName: host "localhost" matched cert's "localhost"
* issuer: O=mkcert development CA; OU=masakielastic@penguin; CN=mkcert masakielastic@penguin
* SSL certificate verify ok.
* using HTTP/1.1
> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.88.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Content-Length: 11
< Connection: Close
<
* Closing connection 0
* Send failure: Broken pipe
Hello World
Discussion