# ๐Ÿ›ก๏ธ TLS์—์„œ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ Pingclair์˜ TLS ํ‘œ๋ฉด์€ ์˜๋„์ ์œผ๋กœ ์ž‘์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„์€ ์ž๋™์œผ๋กœ ์ธ์ฆ์„œ๋ฅผ ๋ฐ›๊ณ , ๊ทธ ๋ฐฉ์‹ ์„ ๊ฒฐ์ •ํ•˜๋Š” ์„ค์ •์ด ์—ฌ๊ธฐ ์ ํžŒ ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค. Caddy๊ฐ€ ๋ฐ›์•„๋“ค์ด๋Š” ๋‚˜๋จธ์ง€๋Š” ์กฐ์šฉํžˆ ๋ฌด์‹œ๋˜์ง€ ์•Š๊ณ  ์ด๋ฆ„์„ ๋Œ€๋ฉฐ ๊ฑฐ๋ถ€๋˜๋ฏ€๋กœ, ์„ค์ •์ด ์ด๋ฆ„๋ณด๋‹ค ์กฐ์šฉํžˆ ์ ๊ฒŒ ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ด ํŽ˜์ด์ง€๋Š” ์‹ค์ œ ํ˜ธ์ŠคํŠธ์—์„œ ์ธก์ •ํ•œ "์‹ค์ œ๋กœ ๋˜๋Š” ๊ฒƒ"๊ณผ "์•ˆ ๋˜๋Š” ๊ฒƒ"์„ ๋ชจ์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ## ๐Ÿงพ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— - Pingclair๊ฐ€ ์„ค์น˜๋˜์–ด ์‹คํ–‰ ์ค‘์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค([์„ค์น˜](/ko/start/install/)). - ์ธ์ฆ ๊ธฐ๊ด€๊ณผ ๊ด€๋ จ๋œ ๋ถ€๋ถ„์—์„œ๋Š” ํ˜ธ์ŠคํŠธ๋กœ ํ•ด์„๋˜๋Š” ์ด๋ฆ„, ๋˜๋Š” ์‹คํ—˜์šฉ ๋‚ด๋ถ€ ์ธ์ฆ ๊ธฐ๊ด€ ([HTTPS](/ko/start/https/)). ## ๐ŸŒ ์–ด๋–ค ํ”„๋กœํ† ์ฝœ์„ ์„œ๋น„์Šคํ•˜๋Š”๊ฐ€ ํ”„๋กœํ† ์ฝœ ์ง‘ํ•ฉ์€ ์ „์—ญ `servers` ๋ธ”๋ก์— ์žˆ์Šต๋‹ˆ๋‹ค. ```caddyfile { servers { protocols h1 h2 h3 } } ``` `sudo ss -lun | grep ':443 '`๋กœ ์ธก์ •: | ์„ค์ • | UDP 443 ๋ฆฌ์Šค๋„ˆ | | --- | --- | | `protocols h1 h2` | 0 โ€” HTTP/3 ์—†์Œ | | `protocols h1 h2 h3` | 1 โ€” HTTP/3 ์ผœ์ง | โš ๏ธ ์ด ๋ชฉ๋ก์ด ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์€ **HTTP/3**๋ฟ์ž…๋‹ˆ๋‹ค. `h1`๋งŒ ์ ์–ด๋„ HTTP/2๋Š” ๋น ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. `protocols h1`์—์„œ๋„ ALPN์œผ๋กœ `h2`๋ฅผ ์ œ์‹œํ•œ ํด๋ผ์ด์–ธํŠธ๋Š” HTTP/2๋ฅผ ํ˜‘์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด ๋ชฉ๋ก์„ HTTP/3 ์Šค์œ„์น˜์— ๋Œ€์‘์‹œํ‚ฌ ๋ฟ์ž…๋‹ˆ๋‹ค (`config.global.http3 = protocols.contains(H3)`). ์ด๋ฆ„๋ณ„๋กœ HTTP/2๋ฅผ ๋„๋Š” ์„ค์ •์€ ์—†์Šต๋‹ˆ๋‹ค. ์‚ฌ์ดํŠธ ๋‹จ์œ„์—์„œ๋Š” `http3 off`๊ฐ€ QUIC ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  ๊ทธ ์ด๋ฆ„์„ HTTP/3์—์„œ ๋นผ๋ƒ…๋‹ˆ๋‹ค. ```caddyfile https://internal.test { tls { internal http3 off } file_server /srv/site } ``` ## ๐Ÿ›๏ธ ์ธ์ฆ์„œ ์ถœ์ฒ˜ ์„ธ ๊ฐ€์ง€์ด๋ฉฐ ๋ชจ๋‘ [HTTPS ํŽ˜์ด์ง€](/ko/start/https/)์— ์žˆ์Šต๋‹ˆ๋‹ค. | ์ถœ์ฒ˜ | ์„ค์ • | ์šฉ๋„ | | --- | --- | --- | | Let's Encrypt | ๊ณต๊ฐœ ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ | ๊ณต๊ฐœ ์ด๋ฆ„. ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๊ฐฑ์‹ . | | ๋‚ด๋ถ€ ์ธ์ฆ ๊ธฐ๊ด€ | `tls internal` | ์‹คํ—˜์šฉ ์ด๋ฆ„, ์‚ฌ์„ค ์˜ค๋ฆฌ์ง„, ํ„ฐ๋„. | | ์ง์ ‘ ๋งŒ๋“  ํŒŒ์ผ | `tls { cert โ€ฆ key โ€ฆ }` | ๋‹ค๋ฅธ ๊ณณ์—์„œ ๋ฐœ๊ธ‰ํ•œ ์ธ์ฆ์„œ. | ๊ฐฑ์‹ ์€ ์Šค์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ์ „์—ญ ์˜ต์…˜์˜ `renewal_window_ratio`๋Š” ๊ฐ ์ธ์ฆ์„œ ์ˆ˜๋ช…์˜ ์–ผ๋งˆ๋‚˜ ์ผ์ฐ ๊ฐฑ์‹ ์„ ์‹œ์ž‘ํ• ์ง€๋ฅผ ๋น„์œจ๋กœ ์ •ํ•ฉ๋‹ˆ๋‹ค. ## ๐Ÿ” ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ `client_auth`๋Š” ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ๋ฅผ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค. `openssl`๋กœ ์ž‘์€ ์ธ์ฆ ๊ธฐ๊ด€๊ณผ ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ๋ฅผ ๋งŒ๋“ค๊ณ , ์‚ฌ์ดํŠธ๋ฅผ ์ธ์ฆ ๊ธฐ๊ด€ **ํŒŒ์ผ**๋กœ ํ–ฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ```caddyfile https://internal.test { tls { internal client_auth { mode require_and_verify trusted_ca_cert_file /etc/pingclair/client-ca.crt } } file_server /srv/site } ``` ์ธก์ •: ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ ์—†๋Š” ์š”์ฒญ์€ ํ•ธ๋“œ์…ฐ์ดํฌ์—์„œ ์‹คํŒจํ•˜๊ณ , `--cert client.crt --key client.key`๋ฅผ ๋ถ™์ธ ๊ฐ™์€ ์š”์ฒญ์€ `200`์„ ๋‹ตํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“œ๋Š” `request`, `require`, `verify_if_given`, `require_and_verify`์ด๋ฉฐ ๋Œ€์ฒด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ฒ ์ž๋ฅผ ํ‹€๋ฆฌ๋ฉด `(expected request, require, verify_if_given or require_and_verify)`๋ผ๋Š” ๋ชฉ๋ก๊ณผ ํ•จ๊ป˜ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค. โš ๏ธ `trusted_ca_cert`๋Š” ์ธ์ฆ์„œ๋ฅผ **์ธ๋ผ์ธ**์œผ๋กœ ๋ฐ›๊ณ , `trusted_ca_cert_file`์€ ๊ฒฝ๋กœ๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ „์ž์— ๊ฒฝ๋กœ๋ฅผ ์ฃผ๋ฉด ์ปดํŒŒ์ผ์€ ๋˜๊ณ  ์‹œ์ž‘ํ•  ๋•Œ `trusted_ca_cert is not a certificate: not valid base64: Invalid symbol 45`๋กœ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค(`-----BEGIN`์˜ `-`). ํŒŒ์ผ์€ `pingclair` ์‚ฌ์šฉ์ž๊ฐ€ ์ฝ์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ## ๐Ÿ“ฆ ์ธ์ฆ์„œ ์ €์žฅ์†Œ ์˜ฎ๊ธฐ๊ธฐ ์ €์žฅ์†Œ์—๋Š” ๋ฐœ๊ธ‰๋œ ์ธ์ฆ์„œ, ACME ๊ณ„์ •, ๋‚ด๋ถ€ ์ธ์ฆ ๊ธฐ๊ด€์ด ๋“ค์–ด ์žˆ๊ณ , ๊ทธ ์ž๋ฆฌ๋Š” `/var/lib/pingclair/.local/share/pingclair`โ€”โ€”์„œ๋น„์Šค ๊ณ„์ •์˜ ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋กœ ๋Œ๋ฆด ๋•Œ `PINGCLAIR_TLS_STORE`๊ฐ€ ๊ทธ๊ฒƒ์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค(์•„๋ž˜ ์˜ˆ์‹œ๊ฐ€ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์ด๋Š” ์ด์œ ์ด๊ณ , root์˜ ๊ธฐ๋ณธ๊ฐ’์€ `/root/.local/share/pingclair`์ž…๋‹ˆ๋‹ค). `storage-export`์™€ `storage-import`๊ฐ€ ๊ทธ๊ฒƒ์„ ์˜ฎ๊น๋‹ˆ๋‹ค. ```bash sudo PINGCLAIR_TLS_STORE=/var/lib/pingclair/.local/share/pingclair pingclair storage-export -o /tmp/store.tar sudo systemctl stop pingclair sudo rm -rf /var/lib/pingclair/.local/share/pingclair sudo mkdir -p /var/lib/pingclair/.local/share/pingclair && sudo chown pingclair:pingclair /var/lib/pingclair/.local/share/pingclair sudo PINGCLAIR_TLS_STORE=/var/lib/pingclair/.local/share/pingclair pingclair storage-import -i /tmp/store.tar sudo systemctl start pingclair ``` ```text โœ… Store exported to /tmp/store.tar โœ… Store imported into /var/lib/pingclair/.local/share/pingclair ``` ์‹คํ–‰์—์„œ ๋‚˜์˜จ ์„ธ ๊ฐ€์ง€. ์•„์นด์ด๋ธŒ๋Š” ์ด๋ฆ„๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ **๊ทธ๋ƒฅ tar**์ด๊ณ  ๋ชจ๋“œ `600`์œผ๋กœ ์“ฐ์ด๋ฏ€๋กœ ๋‹ค์‹œ ์ฝ์œผ๋ ค๋ฉด root๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์ ธ์˜ค๊ธฐ๋Š” ์•„์นด์ด๋ธŒ์— ๊ธฐ๋ก๋œ ์†Œ์œ ๊ถŒ์„ ๊ทธ๋Œ€๋กœ ๋ณต์›ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ €์žฅ์†Œ์—๋Š” `autosave.json`(Admin API๊ฐ€ ๋งˆ์ง€๋ง‰์œผ๋กœ ์ ์šฉํ•œ ์„ค์ •)๋„ ๋“ค์–ด ์žˆ์–ด ํ•จ๊ป˜ ๋Œ์•„์˜ต๋‹ˆ๋‹ค. ๊ทธ ๋’ค ์„œ๋น„์Šค๊ฐ€ `Internal CA I/O error: Permission denied`๋กœ ์‹œ์ž‘์„ ๊ฑฐ๋ถ€ํ•˜๋ฉด ์ €์žฅ์†Œ ํŒŒ์ผ์„ ์„œ๋น„์Šค ๊ณ„์ •์ด ์“ธ ์ˆ˜ ์—†๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. `sudo chown -R pingclair:pingclair /var/lib/pingclair/.local/share/pingclair`๋กœ ๊ณ ์ณ์ง€๊ณ  ์‚ฌ์ดํŠธ๊ฐ€ ๋‹ค์‹œ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. ## ๐Ÿšซ ์กฐ์ •ํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ ๋‹ค์Œ์€ Pingclair๊ฐ€ ์ธ์‹ํ•˜๊ณ  ๊ฑฐ๋ถ€ํ•˜๋Š” Caddy ์„ค์ •์ž…๋‹ˆ๋‹ค. ์„ค์ •์ด ์กฐ์šฉํžˆ ๋น ์ง„ ์ฑ„ ์‹คํ–‰๋˜๋Š” ์ผ์€ ์—†์Šต๋‹ˆ๋‹ค. ```text Caddy-compatible directive 'tls ciphers' is not supported by Pingclair yet: Pingclair does not implement this TLS option yet Caddy-compatible directive 'tls curves' is not supported by Pingclair yet: Pingclair does not implement this TLS option yet Caddy-compatible directive 'tls alpn' is not supported by Pingclair yet: Pingclair does not implement this TLS option yet Caddy-compatible directive 'tls on_demand' is not supported by Pingclair yet: Pingclair does not implement this TLS option yet ``` ์ฆ‰ ์•”ํ˜ธ ์Šค์œ„ํŠธ, ๊ณก์„ , ALPN ๋ชฉ๋ก, ์˜จ๋””๋งจ๋“œ ๋ฐœ๊ธ‰์€ ์„ค์ •์ด ์•„๋‹ˆ๋ผ ๋นŒ๋“œ์˜ ์„ ํƒ์ž…๋‹ˆ๋‹ค. OCSP ์Šคํ…Œ์ดํ”Œ๋ง๊ณผ `preferred_chains`๋„ ๊ตฌํ˜„๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์ค‘ ํ•˜๋‚˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด ์„ค์ • ์‹ค์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ ๊ธฐ๋Šฅ ์š”์ฒญ์ž…๋‹ˆ๋‹ค. ## โš ๏ธ ์ž˜ ๋˜์ง€ ์•Š์„ ๋•Œ - **`client_auth`๊ฐ€ `not valid base64`๋กœ ์‹œ์ž‘์„ ๊ฑฐ๋ถ€.** `trusted_ca_cert`์— ๊ฒฝ๋กœ๋ฅผ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ์šฉ ์ฒ ์ž๋Š” `trusted_ca_cert_file`์ž…๋‹ˆ๋‹ค. - **์œ ํšจํ•œ ์ธ์ฆ์„œ๋ฅผ ๊ฐ€์ง„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฑฐ๋ถ€๋จ.** ์„œ๋ช…ํ•œ ์ธ์ฆ ๊ธฐ๊ด€์ด `trusted_ca_cert_file`์˜ ๊ทธ๊ฒƒ์ธ์ง€, ์ธ์ฆ์„œ๊ฐ€ ๋งŒ๋ฃŒ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. - **`tls ciphers` / `tls curves` / `tls alpn` / `tls on_demand`๊ฐ€ ํŒŒ์ผ์„ ๊ฑฐ๋ถ€.** ๊ตฌํ˜„๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ„ ์ ˆ์„ ๋ณด์‹ญ์‹œ์˜ค. - **`protocols h1 h2`์ธ๋ฐ HTTP/3๊ฐ€ ๊ณ„์† ๋™์ž‘.** ๊ทธ๋ž˜์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ์ •ํ•˜๋Š” ๊ฒƒ์ด ์ด ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. UDP 443์ด ์•„์ง ๋“ฃ๊ณ  ์žˆ๋‹ค๋ฉด ์‹คํ–‰ ์ค‘์ธ ํŒŒ์ผ์ด ํŽธ์ง‘ํ•œ ํŒŒ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค([์žฌ์ ์šฉ์˜ ์˜๋ฏธ](/ko/start/service/#-์žฌ์ ์šฉ์˜-์˜๋ฏธ)). - **์ €์žฅ์†Œ๋ฅผ ์˜ฎ๊ธด ๋’ค ์„œ๋น„์Šค๊ฐ€ ์‹œ์ž‘ํ•˜์ง€ ์•Š์Œ.** ์œ„์˜ ์†Œ์œ ๊ถŒ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ## ๐Ÿงญ ๋‹ค์Œ ๋‹จ๊ณ„ - [HTTPS](/ko/start/https/): ์ธ์ฆ์„œ๋ฅผ ์–ป๋Š” ๋„ค ๊ฐ€์ง€ ๋ฐฉ๋ฒ•๊ณผ ๊ทธ๋Œ€๋กœ์˜ ๋กœ๊ทธ ์ค„. - [HTTP/3](/ko/guides/http3/): ์ผœ๊ณ , ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‹ค์ œ๋กœ ์ผ์Œ์„ ์ฆ๋ช…ํ•˜๋Š” ๋ฐฉ๋ฒ•. - [`tls`](/ko/reference/directives/#tls): ์ง€์‹œ์–ด ๋ ˆํผ๋Ÿฐ์Šค.