🍣

[SadServers] 解説 "Lisbon": etcd SSL cert troubles

2023/02/07に公開

"Lisbon": etcd SSL cert troubles

SadServersの "Lisbon": etcd SSL cert troubles の解説です。

SadServers って何? って人は、 SadServers解説 を見てください。
一言でいうと、LeetCode (コーディング問題集) の Linuxサーバ設定版のようなものです。

問題

問題を見ていきます。 > の箇所は DeepLでの翻訳です。

Scenario: "Lisbon": etcd SSL cert troubles

Level: Medium

Description: There's an etcd server running on https://localhost:2379 , get the value for the key "foo", ie etcdctl get foo or curl https://localhost:2379/v2/keys/foo
> https://localhost:2379 で etcd サーバーが動いているので、キー "foo" の値を取得します。etcdctl get foo または curl https://localhost:2379/v2/keys/foo です。

Test: etcdctl get foo returns bar.

Time to Solve: 20 minutes.

OS: Debian 11

etcd'etcd とは'を読むと、Key Value Store の サーバのようです。
etcdctletcd専用のクライアントのようです。が、curlでも叩けるので、HTTPサーバということがわかります。

解説

早速、etcdctlを実行します。

admin@ip-10-0-0-138:/$ etcdctl get foo
Error:  client: etcd cluster is unavailable or misconfigured; error #0: x509: certificate has expired or is not yet valid: current time 2024-02-05T14:12:40Z is after 2023-01-30T00:02:48Z

error #0: x509: certificate has expired or is not yet valid: current time 2024-02-05T14:12:40Z is after 2023-01-30T00:02:48Z

error #0: x509: certificate has expired or is not yet valid: current time 2024-02-05T14:12:40Z is after 2023-01-30T00:02:48Z

エラー内容と見ると、SSL証明書の有効期限が2023-01-30T00:02:48Zですが、現在時刻が2024-02-05T14:12:40Zのため、SSL証明書の有効期限切れ(expired)です。

dateコマンドで、システムの現在日時を確認します。

admin@ip-10-0-0-138:/$ date
Mon Feb  5 14:12:52 UTC 2024

たしかに、Feb 5 2024となっているので、SSL証明書の有効期限2023-01-30を満たすように、date -sコマンドで日時を2023-01-01に変更します。
(実際に実施した日時は、2023 Feb 5なので、どうやらこのVMの日時は一年後になっているようです。)

admin@ip-10-0-0-138:/$ sudo date -s "01/01 13:00 2023"
Sun Jan  1 13:00:00 UTC 2023

その後、再度 ectctlを実施します。

admin@ip-10-0-0-138:/$ etcdctl get foo
Error:  client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint.

エラー内容が変わりました。不正なJSONを返しているとエラーは言っています。
ちょっと、わからないので、curlも実行してみます。

admin@ip-10-0-0-138:/$ curl -v https://localhost:2379/v2/keys/foo
*   Trying 127.0.0.1:2379...
* Connected to localhost (127.0.0.1) port 2379 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* 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 to use http/1.1
* Server certificate:
*  subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd; CN=localhost
*  start date: Dec 31 00:02:48 2022 GMT
*  expire date: Jan 30 00:02:48 2023 GMT
*  common name: localhost (matched)
*  issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd; CN=localhost
*  SSL certificate verify ok.
> GET /v2/keys/foo HTTP/1.1
> Host: localhost:2379
> User-Agent: curl/7.74.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Server: nginx/1.18.0
< Date: Sun, 01 Jan 2023 13:00:25 GMT
< Content-Type: text/html
< Content-Length: 153
< Connection: keep-alive
< 
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
* Connection #0 to host localhost left intact

404が返ってきています。また、レスポンスヘッダーから、

< Server: nginx/1.18.0

と、etcdではなく nginx がレスポンスを変えているようです。 これはどういうことでしょうか??

lsofで、port 2379を使っているプロセスを調べます。 が、残念ながらlsofは入っていません。

admin@ip-10-0-0-138:/$ lsof -i:2379
bash: lsof: command not found

systemctl status etcdで、ectdの状態を確認します。

admin@ip-10-0-0-138:/$ systemctl status etcd
● etcd.service - etcd - highly-available key value store
     Loaded: loaded (/lib/systemd/system/etcd.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2023-02-05 14:22:39 UTC; 1 months 4 days left
       Docs: https://etcd.io/docs
             man:etcd
   Main PID: 580 (etcd)
      Tasks: 8 (limit: 521)
     Memory: 25.5M
        CPU: 1.022s
     CGroup: /system.slice/etcd.service
             └─580 /usr/bin/etcd --cert-file /etc/ssl/certs/localhost.crt --key-file /etc/ssl/certs/loca>

Feb 05 14:22:38 ip-10-0-0-138 etcd[580]: ClientTLS: cert = /etc/ssl/certs/localhost.crt, key = /etc/ssl/>
Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: 8e9e05c52164694d is starting a new election at term 18
Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: 8e9e05c52164694d became candidate at term 19
Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: 8e9e05c52164694d received MsgVoteResp from 8e9e05c52164694d at >
Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: 8e9e05c52164694d became leader at term 19
Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at >
Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: ready to serve client requests
Feb 05 14:22:39 ip-10-0-0-138 systemd[1]: Started etcd - highly-available key value store.
Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: published {Name:ip-10-0-0-138 ClientURLs:[https://localhost:237>
Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: serving client requests on 127.0.0.1:2379

Feb 05 14:22:39 ip-10-0-0-138 etcd[580]: serving client requests on 127.0.0.1:2379

etcdが、port 2379で待っていることは確認できます。

admin@ip-10-0-0-138:/$ sudo /usr/sbin/iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
REDIRECT   tcp  --  anywhere             anywhere             tcp dpt:2379 redir ports 443
DOCKER     all  --  anywhere            !ip-127-0-0-0.us-east-2.compute.internal/8  ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  ip-172-17-0-0.us-east-2.compute.internal/16  anywhere            

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            

REDIRECT tcp -- anywhere anywhere tcp dpt:2379 redir ports 443

port 2379が、 port 443にリダイレクトされています。 そのため、nginxが返答していたのです。

iptables -t nat -F で、設定をリセットします。

admin@ip-10-0-0-138:/$ sudo /usr/sbin/iptables -t nat -F

# リセット後確認
admin@ip-10-0-0-138:/$ sudo /usr/sbin/iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (0 references)
target     prot opt source               destination        

で、再度、 etcdctl を実施します。

admin@ip-10-0-0-138:/$ etcdctl get foo
bar

正しく動きました。

Discussion