전송 계층 보안(TLS)은 매우 널리 사용되는 암호화 프로토콜입니다. 커널에 TLS를 구현한 kTLS는 사용자 공간과 커널 간의 복사 작업 필요성을 크게 줄여 성능을 향상합니다.
kTLS와 sendfile()을 함께 사용하면 데이터가 전송을 위해 네트워크 스택으로 전달되기 전에 커널 공간에서 직접 암호화됩니다. 따라서 TLS 라이브러리로 암호화하기 위해 데이터를 사용자 공간으로 복사한 다음, 전송을 위해 다시 커널 공간으로 복사할 필요가 없습니다. 또한 kTLS를 사용하면 TLS 대칭 암호화 처리를 네트워크 장치로 오프로드하는 것을 비롯해 TLS 처리를 하드웨어로 오프로드할 수 있습니다.
최신 Linux 및 FreeBSD 커널은 TLS 처리를 커널로 오프로드하는 기능을 지원하며, 이제 NGINX Open Source도 이를 지원합니다! NGINX 1.21.4에서는 kTLS 지원이 도입되었습니다 이를 통해 정적 파일과 캐시된 응답을 SSL_sendfile()로 제공할 때 성능을 크게 향상할 수 있습니다. 아래에서 자세히 설명하듯이 NGINX에서 SSL_sendfile()을 사용하려면 커널과 OpenSSL 모두 kTLS를 지원하도록 빌드되어야 합니다.
이 블로그에서는 kTLS를 지원하는 운영 체제 및 OpenSSL 버전을 자세히 살펴보고, kTLS를 사용하도록 커널과 NGINX를 빌드하고 구성하는 방법을 설명합니다. 또한 kTLS를 통해 기대할 수 있는 성능 향상 수준을 가늠할 수 있도록 FreeBSD와 Ubuntu에서 진행한 테스트의 사양과 결과도 공유합니다.
참고: kTLS 구현은 비교적 최근에 등장했으며 빠르게 발전하고 있습니다. 이 블로그에서는 2021년 11월 기준의 kTLS 지원 현황을 설명합니다. 여기에 제공된 정보와 지침의 변경 사항은 nginx.org 및 NGINX 블로그<.htmla>의 공지를 계속 확인하시기 바랍니다.
일반 요구 사항
- 운영 체제 – 다음 중 하나:
- FreeBSD 13.0 이상. 2021년 11월 기준으로 FreeBSD 13.0 이상은 OpenSSL 3.0.0 이상을 포함하도록 NGINX를 수동으로 빌드하지 않고도 NGINX에서 kTLS를 지원하는 유일한 운영 체제입니다. 자세한 내용은 FreeBSD에서 kTLS를 사용하도록 NGINX 설정을 참조하세요.
- Linux 커널 버전 4.17 이상을 기반으로 빌드된 Linux 배포판. 단, 가능하면 버전 5.2 이상을 기반으로 빌드된 배포판을 사용하는 것이 좋습니다. (실제로 kTLS는 버전 4.13부터 지원되지만, OpenSSL 3.0.0에는 커널 헤더 버전 4.17 이상이 필요합니다.)
- OpenSSL – 버전 3.0.0 이상
- NGINX – 버전 1.21.4 이상(mainline)[편집자 – NGINX Plus R27 이상에서는 지원되는 Linux 기반 운영 체제 버전에서 kTLS를 지원하며, NGINX Plus R26 이상에서는 지원되는 FreeBSD 버전에서 kTLS를 지원합니다. 지원되는 OS에 대한 자세한 내용은 NGINX Plus 릴리스 페이지를 참조하십시오.]
운영 체제 지원
kTLS를 지원하는 운영 체제
2021년 11월 기준으로, NGINX Open Source에서 지원하는 OS 중 다음 OS가 kTLS 및 명시된 암호화 스위트를 지원합니다. 암호화 스위트 지원에 대한 자세한 내용은 TLS 프로토콜 및 암호화 스위트 지원을 참조하세요.
| TLSv1.2 암호 | TLSv1.3 암호 스위트 | TLS_CHACHA20_POLY1305_SHA256 암호 | Linux 커널 버전 | |
|---|---|---|---|---|
| Amazon Linux 2* | ✅ | ✅ | ❌ | 5.10 |
| CentOS 8** | ✅ | ❌ | ❌ | 4.18 |
| FreeBSD 13.x | ✅ | ✅ | ❌ *** | 해당 없음 |
| RHEL 8 | ✅ | ❌ | ❌ | 4.18 |
| SLES 15 SP2 | ✅ | ✅ | ✅ | 5.3 |
| Ubuntu 20.04 LTS | ✅ | ❌ | ❌ | 5.4 |
| Ubuntu 21.04 | ✅ | ✅ | ✅ | 5.11 |
| Ubuntu 21.10 | ✅ | ✅ | ✅ | 5.13 |
* 커널 버전은 4.14가 아닌 5.10이어야 합니다. 자세한 내용은 kTLS를 지원하지 않는 OS 및 Amazon Linux 2 FAQ
** 업스트림 소스인 RHEL 8의 kTLS 지원 상태를 따릅니다.
*** 자세한 내용은 FreeBSD 커밋 로그를 참조하세요.
kTLS를 지원하지 않는 운영 체제
다음 운영 체제는 명시된 이유로 kTLS를 지원하지 않습니다:
- Alpine Linux 3.11–3.14 – 커널은
CONFIG_TLS=n옵션으로 빌드되므로 kTLS를 모듈 또는 커널의 일부로 빌드할 수 없습니다. - Amazon Linux 2 – 기본 Amazon Linux 2 AMI의 Linux 커널 버전은 4.14입니다(Amazon Linux 2 FAQ 참조).
- CentOS 7.4+ – Linux 커널 버전은 3.10입니다. 업스트림 소스인 RHEL 7.4+의 kTLS 지원 상태를 따릅니다.
- Debian 10 및 11 – 커널은
CONFIG_TLS=n옵션으로 빌드됩니다(Debian 버그 보고서 로그 참조). - RHEL 7.4+ – Linux 커널 버전은 3.10입니다.
- SLES 12 SP5+ – Linux 커널 버전은 4.12입니다.
- Ubuntu 18.04 LTS – Linux 커널 버전은 4.15입니다.
TLS 프로토콜 및 암호화 스위트 지원
앞서 자세히 설명한 내용과 같이, kTLS를 지원하는 OS마다 지원하는 TLS 프로토콜과 암호화 방식이 다릅니다.
TLSv1.2에서 kTLS 모듈은 다음 암호화 스위트를 지원합니다:
AES128-GCM-SHA256AES256-GCM-SHA384ECDHE-RSA-AES128-GCM-SHA256ECDHE-RSA-AES256-GCM-SHA384
TLSv1.3에서 kTLS 모듈은 다음 암호화 스위트를 지원합니다:
TLS_AES_128_GCM_SHA256TLS_AES_256_GCM_SHA384TLS_CHACHA20_POLY1305_SHA256(kTLS를 지원하는 OS에 명시된 일부 OS만 해당)
OpenSSL에서 지원하는 TLS 암호화 스위트 중 NGINX 바이너리에서 활성화된 항목을 확인하려면 NGINX를 빌드한 디렉터리(예: 홈 디렉터리)에서 openssl-3.0.0/.openssl/bin/openssl ciphers 명령을 실행합니다.
NGINX에서 kTLS 활성화
서론에서 언급했듯이, kTLS는 모든 암호화와 복호화를 커널에서 수행하므로 NGINX의 성능을 향상시킵니다. 데이터는 전송을 위해 네트워크 스택으로 전달되기 전에 커널 공간에서 직접 암호화되므로, TLS 라이브러리로 암호화하기 위해 데이터를 사용자 공간으로 복사한 다음 전송을 위해 다시 커널 공간으로 복사할 필요가 없습니다.

커널에 kTLS 로드하기
최신 FreeBSD 및 Linux 배포판에서 kTLS는 일반적으로 모듈로 빌드됩니다(CONFIG_TLS=m 옵션 사용). NGINX를 시작하기 전에 kTLS 모듈을 커널에 명시적으로 로드해야 합니다.
- FreeBSD에서는 다음 명령을
root사용자로 실행합니다:
# kldload ktls_ocf.ko# sysctl kern.ipc.tls.enable=1- FreeBSD 명령 옵션에 대한 자세한 내용은
ktls(4)매뉴얼 페이지를 참조하십시오. - Linux 배포판에서는 다음 명령을
root사용자로 실행합니다:
# modprobe tlsFreeBSD에서 kTLS를 사용하도록 NGINX 활성화
FreeBSD의 NGINX에서 kTLS 지원을 활성화하려면 Linux 배포판과 동일한 지침을 사용할 수 있습니다. 하지만 FreeBSD 포트 컬렉션의 security/openssl-devel 포트에서 kTLS가 지원되도록 빌드된 NGINX를 활용하려면 다음 단계를 수행하는 것이 좋습니다. kTLS 개요를 비롯한 자세한 내용은 FreeBSD 웹사이트의 커널에서 TLS 오프로딩을 참조하세요.
- 구성 메뉴에서 적절한 옵션을 선택하여 kTLS를 지원하는 OpenSSL 3.0을 빌드합니다:
# cd /usr/ports/security/openssl-devel && make config && make install- 수정합니다. /etc/make.conf에서 openssl-devel을 기본 SSL 라이브러리로 사용하도록
# echo "DEFAULT_VERSIONS+=ssl=openssl-devel" >> /etc/make.conf- NGINX를 빌드합니다:
# cd /usr/ports/www/nginx-devel && make installLinux 배포판에서 kTLS를 지원하는 NGINX 빌드하기
현재 대부분의 Linux 배포판에는 3.0.0 이전 버전의 OpenSSL(일반적으로 버전 1.1)이 포함되어 있습니다. 따라서 OpenSSL 3.0.0을 사용하여 소스에서 NGINX를 빌드해야 합니다.
kTLS 지원을 활성화하는 configure 명령의 두 가지 핵심 옵션은 다음과 같습니다:
--with-openssl=../openssl-3.0.0--with-openssl-opt=enable-ktls
그 밖의 configure 옵션은 NGINX 공식 바이너리 패키지에 포함된 모듈을 위한 것입니다. 이 패키지는 nginx.org에서 제공됩니다. 원하는 모듈을 직접 지정할 수도 있습니다. 현재 사용 중인 NGINX 바이너리에 적용된 빌드 옵션을 확인하려면 nginx -V를 실행하세요.
OpenSSL 3.0.0으로 NGINX를 빌드하려면 다음 명령을 실행합니다:
$ wget https://nginx.org/download/nginx-1.21.4.tar.gz$ wget https://www.openssl.org/source/openssl-3.0.0.tar.gz$ tar xzf openssl-3.0.0.tar.gz$ cd nginx-1.21.4$ ./configure --with-debug --prefix=/usr/local --conf-path=/usr/local/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-openssl=../openssl-3.0.0 --with-openssl-opt=enable-ktls --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' -with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'$ make –j4$ make install참고: 생성된 NGINX 바이너리는 OpenSSL 3.0.0 라이브러리와 정적으로 링크됩니다. 나중에 OpenSSL을 패치해야 하는 경우 새 OpenSSL 소스 아카이브를 다운로드하여 압축을 푼 다음, 위의 명령을 실행해 NGINX 바이너리를 다시 빌드해야 합니다.
NGINX 구성
kTLS를 활성화하려면 ssl_conf_command 지시문에 Options KTLS 매개변수를 포함하고, 다음과 같이 server{} 컨텍스트에 설정합니다. 이 샘플 구성은 당사의 테스트에 사용되었습니다:
worker_processes auto;error_log /var/log/nginx/error.log debug;events {}http { sendfile on; server { listen 443 ssl; ssl_certificate ssl/example.crt; ssl_certificate_key ssl/example.key; ssl_conf_command Options KTLS; ssl_protocols TLSv1.3; location / { root /data; } }}kTLS 활성화 여부 확인
NGINX가 kTLS를 사용하고 있는지 확인하려면 디버깅 모드를 활성화하고 오류 로그에서 BIO_get_ktls_send() 및 SSL_sendfile()을 확인합니다.
$ grep BIO /var/log/nginx/error.log2021/11/10 16:02:46 [debug] 274550#274550: *2 BIO_get_ktls_send(): 12021/11/10 16:02:49 [debug] 274550#274550: *3 BIO_get_ktls_send(): 1 $ grep SSL_sendfile /var/log/nginx/error.log2021/11/10 16:02:46 [debug] 274550#274550: *2 SSL_sendfile: 10485762021/11/10 16:02:49 [debug] 274550#274550: *3 SSL_sendfile: 1048576참고: 이러한 확인 작업을 마친 후에는 디버깅 모드를 비활성화하는 것이 좋습니다. 특히 프로덕션 환경에서는 반드시 비활성화하십시오. 디버그 로깅은 대량의 쓰기 작업으로 인해 성능을 저하시킬 수 있으며, 디버그 로그의 크기가 매우 커져 디스크 파티션의 가용 공간을 빠르게 소진할 수도 있습니다.
kTLS를 통한 성능 향상
부하가 높은 상황에서 정적 파일과 캐시된 응답을 제공할 때 SSL_sendfile()은 사용자 공간 TLS에 비해 처리량을 최대 2배까지 높일 수 있지만 성능 향상 폭은 다양한 요인(디스크 성능, 시스템 부하 등)에 따라 크게 달라집니다. 네트워크 카드가 TLS 오프로딩을 지원하는 경우 CPU 사용량도 줄일 수 있습니다.
성능 테스트
사용 중인 환경에서 성능 향상 정도를 측정하려면 다음 지침에 따라 간단한 단일 스레드 테스트를 실행하세요. 아래에 자세히 설명된 테스트 결과에 따르면 별도의 튜닝 없이도 성능이 최대 약 30% 향상됩니다.
사용된 하드웨어 및 소프트웨어:
- 다음 사양의 AWS t3.medium 인스턴스:
- 4GB RAM
- 20GB 범용 SSD
- 2코어 Intel® Xeon® Platinum 8259CL CPU @ 2.50GHz
- FreeBSD 13.0 및 Ubuntu 21.10
- TLSv1.3 with the
TLS_AES_256_GCM_SHA384암호화 스위트를 사용하는 TLSv1.3 - NGINX에서 kTLS 활성화에 명시된 대로 빌드 및 구성된 NGINX 1.21.4.
테스트를 수행하려면 다음 단계를 따르세요:
- 디스크 캐시에 완전히 들어갈 만큼 큰 파일을 생성합니다:
# truncate -s 1g /data/1G- 이 명령을 실행하여 처리량을 확인합니다. 더 정확한 결과를 얻기 위해 기본 명령이 여러 번 반복됩니다. 출력 결과를
ministat유틸리티[FreeBSD][Ubuntu]로 파이프하여 기본적인 통계 분석을 수행합니다.
# for i in 'seq 1 100'; do curl -k -s -o /dev/null -w '%{speed_download}n' https://localhost/1G | ministat성능 테스트 결과
다음은 테스트 결과를 ministat 출력 형식으로 나타낸 것으로, 각 값은 초당 kBytes 단위의 다운로드 속도입니다. 가독성을 위해 출력 내용을 두 줄로 나누었습니다.
kTLS를 사용하지 않는 FreeBSD 13.0의 처리량:
N Min Max Median ...x 10 532225 573348 555616 ... ... Avg Stddev ... 555155.6 10239.137kTLS를 사용하는 FreeBSD 13.0의 처리량:
N Min Max Median ...x 10 629379 723164 717349 ... ... Avg Stddev ... 708600.4 28304.766kTLS를 사용하지 않는 Ubuntu 21.10의 처리량:
N Min Max Median ...x 10 529199 705720 662354 ... ... Avg Stddev ... 654321.6 48025.103kTLS를 사용하는 Ubuntu 21.10의 처리량:
N Min Max Median ...x 10 619105 760208 756278 ... ... Avg Stddev ... 741848.3 43255.246테스트 결과, kTLS는 Ubuntu보다 FreeBSD에서 성능을 더 크게 향상시켰습니다. 성능 향상률은 다음과 같습니다:
| 최솟값 | 최댓값 | 중앙값 | 평균값 | |
|---|---|---|---|---|
| FreeBSD 13.0 | 18% | 26% | 29% | 28% |
| Ubuntu 21.10 | 16% | 8% | 14% | 13% |
요약
NGINX 1.21.4에서는 정적 파일과 캐시된 응답을 SSL_sendfile()로 제공할 때 kTLS를 지원합니다. 테스트 결과, 운영 체제에 따라 성능이 8%에서 29%까지 향상되는 것으로 나타났습니다.
kTLS와 NGINX를 사용해 본 경험, 특히 다른 운영 체제에서 테스트한 결과를 들려주세요! 아래 댓글란에 공유해 주시기 바랍니다.
관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.