๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ๐ŸŒฎ ๐Ÿ’ฌ
๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป

nginx์— mTLS ์ธ์ฆ์„œ ๋ฐœ๊ธ‰ํ•˜๊ณ  ๊ฒ€์ฆํ•˜๊ธฐ

by ๋ฐ”์ฟ„๋ฆฌ 2024. 8. 16.

mTLS ๋ž€?

mTLS๋Š” "Mutual Transport Layer Security"์˜ ์•ฝ์ž๋กœ, ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ์ƒํ˜ธ ์ธ์ฆ์„ ์œ„ํ•œ TLS(Transport Layer Security) ํ”„๋กœํ† ์ฝœ์˜ ํ™•์žฅ์ด๋‹ค. ์ผ๋ฐ˜์ ์ธ TLS๋Š” ์„œ๋ฒ„๋งŒ ์ธ์ฆํ•˜๋Š” ๋ฐ˜๋ฉด, mTLS๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๋ชจ๋‘๊ฐ€ ์„œ๋กœ๋ฅผ ์ธ์ฆํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋” ๋†’์€ ์ˆ˜์ค€์˜ ๋ณด์•ˆ์ด ์ œ๊ณต๋œ๋‹ค.

 

mTLS์˜ ์ž‘๋™ ๋ฐฉ์‹์€ ์„œ๋ฒ„ ์ธ์ฆ, ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ, ์ƒํ˜ธ ์ธ์ฆ ์™„๋ฃŒ ๋กœ ์ง„ํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค.

 

1. ์„œ๋ฒ„ ์ธ์ฆ : ํด๋ผ์ด์–ธํŠธ ์„œ๋ฒ„์˜ SSL/TLS ์ธ์ฆ์„œ๋ฅผ ํ™•์ธํ•˜์—ฌ ์„œ๋ฒ„์˜ ์‹ ์›์„ ๊ฒ€์ฆํ•œ๋‹ค. ์ด๋Š” ์ผ๋ฐ˜์ ์ธ TLS ์—ฐ๊ฒฐ์—์„œ ์ด๋ฃจ์–ด์ง€๋Š” ๋‹จ๊ณ„์ด๋‹ค.

2. ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ : ์„œ๋ฒ„ ๋˜ํ•œ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ธ์ฆ์„œ๋ฅผ ์š”์ฒญํ•œ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์ž์‹ ์˜ ์ธ์ฆ์„œ๋ฅผ ์„œ๋ฒ„์— ์ œ์ถœํ•˜์—ฌ ์‹ ์›์„ ์ฆ๋ช…ํ•œ๋‹ค.

3. ์ƒํ˜ธ ์ธ์ฆ ์™„๋ฃŒ : ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋กœ์˜ ์ธ์ฆ์„œ๋ฅผ ํ™•์ธํ•˜๊ณ  ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•˜๋ฉด, ์ƒํ˜ธ ์ธ์ฆ์ด ์™„๋ฃŒ๋˜๊ณ  ์•ˆ์ „ํ•œ ํ†ต์‹ ์ด ์‹œ์ž‘๋œ๋‹ค.

 

์ง„ํ–‰

1๏ธโƒฃ ca ์ธ์ฆ์„œ ๋ฐœ๊ธ‰

์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰ํ•˜๋Š” ๊ถŒํ•œ์„ ๊ฐ€์ง„ ์ธ์ฆ ๊ธฐ๊ด€(CA)์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt

 

Common Name(CN) ํ•„๋“œ์— ๋„ฃ์–ด์•ผํ•  ๋‚ด์šฉ : CA์˜ ์ด๋ฆ„ ๋˜๋Š” ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ๋‚˜ํƒ€๋‚ด๋Š” ๊ณ ์œ ํ•œ ์‹๋ณ„์ž๋ฅผ ๋„ฃ๋Š”๋‹ค.

- ์˜ˆ์‹œ : MyCompany Root CA, MyCompany Intermediate CA

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:MyCompany Root CA
Email Address []:

 

2๏ธโƒฃ server ์ธ์ฆ์„œ ๋ฐœ๊ธ‰

ํŠน์ • ์„œ๋ฒ„(์˜ˆ: ์›น ์„œ๋ฒ„)์— ๋Œ€ํ•ด ๋ฐœ๊ธ‰๋œ ์ธ์ฆ์„œ๋กœ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด ์„œ๋ฒ„์— ์ ‘๊ทผํ•  ๋•Œ ์„œ๋ฒ„์˜ ์‹ ์›์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256

 

Common Name(CN) ํ•„๋“œ์— ๋„ฃ์–ด์•ผํ•  ๋‚ด์šฉ : ํ•ด๋‹น ์„œ๋ฒ„๊ฐ€ ์„œ๋น„์Šคํ•˜๋Š” ๋„๋ฉ”์ธ ์ด๋ฆ„์„ ๋„ฃ์–ด์•ผํ•œ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด ๋„๋ฉ”์ธ์— ์ ‘๊ทผํ•  ๋•Œ, CN ๋˜๋Š” SAN(Subject Alternative Name) ํ•„๋“œ์— ์žˆ๋Š” ๋„๋ฉ”์ธ๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค.

- ์˜ˆ์‹œ : yourdomain.com

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:yourdomain.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

 

3๏ธโƒฃ client ์ธ์ฆ์„œ ๋ฐœ๊ธ‰

ํด๋ผ์ด์–ธํŠธ(์‚ฌ์šฉ์ž ๋˜๋Š” ์žฅ์น˜)์˜ ์‹ ์›์„ ์ธ์ฆํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ์ธ์ฆ์„œ

openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.csr
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256

 

Common Name(CN) ํ•„๋“œ์— ๋„ฃ์–ด์•ผํ•  ๋‚ด์šฉ : ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ ์œ ํ•œ ์ด๋ฆ„(์˜ˆ: ์‚ฌ์šฉ์ž ์ด๋ฆ„, ์ด๋ฉ”์ผ ์ฃผ์†Œ, ์žฅ์น˜ ์ด๋ฆ„)์„ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค.

- ์˜ˆ์‹œ : John Doe, johndoe@example.com, Device-001

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:Device-001
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

 

4๏ธโƒฃ nginx conf ์ˆ˜์ •

server {
        listen 443 ssl;
        server_name yourdomain.com;

        ssl_certificate /etc/nginx/auth/server.crt;
        ssl_certificate_key /etc/nginx/auth/server.key;
        ssl_client_certificate /etc/nginx/auth/ca.crt; # ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ ํ™•์ธ์„ ์œ„ํ•œ CA ์ธ์ฆ์„œ
        ssl_verify_client on; # ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ ๊ฒ€์ฆ ํ™œ์„ฑํ™”

        client_max_body_size 30M;
        location / {
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-NginX-Proxy true;

                proxy_redirect off;
                proxy_pass http://[ip_address]:[port];
                charset utf-8;

                access_log /var/log/nginx/access.log;
                error_log /var/log/nginx/error.log;
        }
}

 

 

โœ… ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ

ca ์ธ์ฆ์„œ(ca.crt), client ์ธ์ฆ์„œ(client.crt), client ํ‚ค(client.key) ์™€ ๊ฐ™์ด ์š”์ฒญํ•ด์•ผ ํ•œ๋‹ค !

 

โŒ ์ธ์ฆ์„œ ์—†์ด ์ ‘๊ทผํ•  ๊ฒฝ์šฐ

 

โญ•๏ธ ์ธ์ฆ์„œ์™€ ํ•จ๊ป˜ curl ์š”์ฒญ

curl -v --key client.key --cert client.crt --cacert ca.crt https://yourdomain.com
* Rebuilt URL to: https://ddeheart.com/
*   Trying [ip address]...
* Connected to yourdomain.com ([ip address]) port 443 (#0)
* found 1 certificates in ca.crt
* found 516 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
* 	 server certificate verification OK
* 	 server certificate status verification SKIPPED
* 	 common name: yourdomain.com (matched)
* 	 server certificate expiration date OK
* 	 server certificate activation date OK
* 	 certificate public key: RSA
* 	 certificate version: #1
* 	 subject: C=AU,ST=Some-State,O=Internet Widgits Pty Ltd,CN=yourdomain.com
* 	 start date: Fri, 16 Aug 2024 05:47:35 GMT
* 	 expire date: Sat, 16 Aug 2025 05:47:35 GMT
* 	 issuer: C=AU,ST=Some-State,O=Internet Widgits Pty Ltd,CN=MyCompany Root CA
* 	 compression: NULL
* ALPN, server accepted to use http/1.1
> GET / HTTP/1.1
> Host: yourdomain.com
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.10.3 (Ubuntu)
< Date: Fri, 16 Aug 2024 06:23:02 GMT
< Content-Type: application/json
< Content-Length: 18
< Connection: keep-alive
<
{"Hello":"World"}
* Connection #0 to host yourdomain.com left intact

 

โญ•๏ธ ์ธ์ฆ์„œ์™€ ํ•จ๊ป˜ python requests๋ฅผ ์ด์šฉํ•œ ์š”์ฒญ

import requests

url = "https://yourdomain.com"
cert = ("client.crt", "client.key")
ca_cert = "ca.crt"

response = requests.get(url, cert=cert, verify=ca_cert)
print(response.json())

CN์— ๋™์ผํ•œ ๋„๋ฉ”์ธ์„ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ 400 Bad Request๋กœ ์ ‘๊ทผ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค

  • ์‹๋ณ„ ๋ฌธ์ œ: ์ธ์ฆ์„œ ๊ฒ€์ฆ ๊ณผ์ •์—์„œ CN ํ•„๋“œ๊ฐ€ ๋™์ผํ•œ ์ธ์ฆ์„œ๋“ค์ด ์žˆ์„ ๊ฒฝ์šฐ, ํด๋ผ์ด์–ธํŠธ๋‚˜ ์„œ๋ฒ„๋Š” ์ด๋“ค ์ธ์ฆ์„œ๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ๋ฐ ์–ด๋ ค์›€์„ ๊ฒช์„ ์ˆ˜ ์žˆ๋‹ค. ํŠนํžˆ, ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„ ์ƒํ˜ธ ์ธ์ฆ(mTLS)์—์„œ ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ๋ฅผ ์„œ๋ฒ„ ์ธ์ฆ์„œ์™€ ํ˜ผ๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์‹ ๋ขฐ ๋ฌธ์ œ: CA ์ธ์ฆ์„œ, ์„œ๋ฒ„ ์ธ์ฆ์„œ, ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅด๊ฒŒ ๋ฐœ๊ธ‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, ๊ฐ๊ฐ์˜ ์—ญํ• ์— ๋”ฐ๋ผ ๊ณ ์œ ํ•œ CN์„ ๊ฐ€์ง€๋Š” ๊ฒƒ์ด ์›์น™์ด๋‹ค. ๋™์ผํ•œ CN์„ ์‚ฌ์šฉํ•˜๋ฉด ์ธ์ฆ์„œ ์ฒด๊ณ„๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ  ์‹ ๋ขฐ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค.