mTLS 인증

Mutual TLS, 상호 TLS

웹서버를 통해 VPN의 효과를 얻는 방법

TLS ClientHello Extension(RFC7685)을 활용한 인증

TLS 서버와 클라이언트가 쌍방으로 서로를 확인한 후 통신하는 방식
(HTTPS는 HTTP over TLS이기 때문에 오래전 부터 지원한 방식)

AWS 및 GCP, CloudFlare 등 클라우드 플랫폼에서, REST API 에 접속하는 클라이언트를 제한하기 위해 이용됨

MIT 의 학사 시스템에 이용중

가장 강력한 웹 인증 방식 (해커들이 웹사이트 취약점 스캐닝을 원천적으로 차단, 허가된 사용자의 Audit 기록이 남음)

PKI 인프라를 운영 및 관리해야 하므로, 가장 운영하기 번거로운 방식




mTLS 의 장점

다음 문서가 가장 잘 설명하기에, 내용을 그대로 가져옴.
(출처) https://smallstep.com/hello-mtls

mTLS is fast, easy to use, and works everywhere

Nearly every language, server, database, client (and more!) already offers battle-tested TLS/SSL support. mTLS lets you replace countless fragile and frustrating bits of security infrastructure with a single consistent solution that's easier to understand, easier to scale, and easier to operate.

Avoid complicated VPN/VPC configurations

mTLS eliminates the need to use network boundaries, VPNs, and IP whiltelists to provide access to your applications. There is usually no need to do anything more than configure the tools and libraries you're already using in your applications to speak TLS.

Scale end-to-end encryption anywhere

Using proven cryptography and mTLS your applications talk directly to each other rather than bogging down inside a network tunnel or calling back to a central authority. Proven inside the largest distributed systems, mTLS makes it easy to scale your infrastructure securely.


웹 인증 시 사용되는 방식

Headless 웹 클라이언트에서 사용


웹브라우저에서 사용

MIT 학사 시스템

1년 단위로 MIT CertAid 를 통해 클라이언트 인증서를 발급받아 이용

클라이언트 인증서가 설치되지 않은 웹브라우저에서는 class_only 디렉터리에 접근할 수 없음

mTLS 사용 예

인증서가 없으면 웹브라우저에서 err_bad_ssl_client_auth_cert 에러 발생. 웹브라우저 또는 OS 키체인에 설치된 인증서를 선택하면 접속 가능



설정 방법

ROOT CA 구축

다음 문서 참고하여 다음 인증서들을 생성한다.

  • Self Signed Root CA
  • Intermediate CA
  • Client Certificate

(참고) OpenSSL Certificate Authority, 2015, Jamie Nguyen


HTTPS 서버 인증서 적용

mTLS 는 HTTPS 사이트만 적용 가능하다. 유료 서버 인증서를 구매하거나, 무료 인증기관인 Let’s Encrypt를 통해 적용해야 한다.


Apache HTTPD mTLS 설정

ROOT CA에서 생성된 ROOT CA 및 Intermediate 인증서의 키체인 및 CRL을 웹서버에 넣고 구동한다.

/etc/httpd/conf.d/example_net.conf
<VirtualHost *:443>
    ServerName example.net
    # ...
    <Location /secure>
        # Internal Network - mTLS not applied
        <If     "-R '192.168.0.0/24'">
        </If>
        # External Network - mTLS applied
        <Else>
            SSLVerifyClient require
            SSLVerifyDepth 10
        </Else>
    </Location>
    SSLVerifyClient      none
    SSLCACertificateFile client-cert/chain/kreonet-int-ca-1-chain.pem
    SSLCARevocationFile  client-cert/crl/kreonet-int-ca-1-crl.pem
</VirtualHost>

제약조건

인증서의 깊이(maximum number of intermediate certificate issuers), 인증서의 속성 등을 조건식으로 만들어 접근을 더 세밀하게 제한할 수 있다.

<Location /secure>
    SSLOptions +StdEnvVars
    <RequireAny>
        Require expr %{SSL_CLIENT_S_DN_CN} == "USER_A"
        Require expr %{SSL_CLIENT_S_DN_CN} == "USER_B"
        Require expr %{SSL_CLIENT_S_DN_CN} == "USER_C"
    </RequireAny>
</Location>

(참고) IP 및 조건부 인증

(참고) https://httpd.apache.org/docs/2.4/mod/mod_ssl.html

(참고) https://www.docusign.com/blog/dsdev-mutual-tls-stuff-know

감사 로그

IP 이외에 사용자를 특정할 수 있는 인증서 정보를 같이 로깅할 수 있다. 보안 사고가 발생하였을 때를 대비한 감사(audit)로그를 남길 수 있다.

(참고) RotateLogs

인증서 정보
Subject: C=KR, ST=Daejeon, L=Yuseong-gu, O=KISTI, OU=KREONET, CN=EXAMPLE_USER
Custom 로그 템플릿
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x [%{SSL_CLIENT_I_DN_CN}x][%{SSL_CLIENT_S_DN_CN}x] \"%r\" %b"
/var/log/httpd/example.kreonet.net/request_log.20201118
[18/Nov/2020:15:38:25 +0900] 223.1.190.3 TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 [KREONET INTERMEDIATE CA 1][EXAMPLE_USER] "GET /secure/restricted.html HTTP/1.1" 37582


참고

(mTLS 설명)

https://www.jacobbaek.com/1040

https://www.docusign.com/blog/dsdev-mutual-tls-stuff-know

https://developers.cloudflare.com/access/access-service-auth/mutual-tls-authentication

(mTLS 설정법)

https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html#accesscontrol

https://httpd.apache.org/docs/2.4/mod/core.html#elseif

https://superuser.com/questions/1055171/apache-and-support-for-per-directory-ca

https://www.cl.cam.ac.uk/~jw35/courses/using_https/html/x640.htm

https://httpd.apache.org/docs/2.4/ssl/ssl_compat.html