Ktor 서버의 SSL 및 인증서
필수 의존성: io.ktor:ktor-network-tls-certificates
코드 예제: ssl-engine-main, ssl-embedded-server
대부분의 경우 Ktor 서비스는 Nginx나 Apache와 같은 역방향 프록시(reverse proxy) 뒤에 배치됩니다. 이는 역방향 프록시 서버가 SSL을 포함한 보안 관련 사항을 처리함을 의미합니다.
필요한 경우, 인증서 경로를 제공하여 Ktor가 직접 SSL을 서비스하도록 구성할 수 있습니다. Ktor는 인증서 저장 시설로 Java KeyStore (JKS)를 사용합니다. KeyStore에 저장된 인증서를 관리하고 변환하려면 keytool을 사용할 수 있습니다. 이는 인증 기관(CA)에서 발급한 PEM 인증서를 Ktor에서 지원하는 JKS 형식으로 변환해야 할 때 유용할 수 있습니다.
_Let's Encrypt_를 사용하여 Ktor에서
https://및wss://요청을 서비스하기 위한 무료 인증서를 얻을 수 있습니다.
자가 서명 인증서 생성
코드에서 인증서 생성
Ktor는 buildKeyStore 함수를 호출하여 테스트 목적으로 자가 서명 인증서(self-signed certificates)를 생성하는 기능을 제공하며, 이 함수는 KeyStore 인스턴스를 반환합니다. 이 함수를 사용하려면 빌드 스크립트에 ktor-network-tls-certificates 아티팩트를 추가해야 합니다:
아래의 코드 스니펫은 인증서를 생성하고 이를 키스토어 파일로 저장하는 방법을 보여줍니다:
private fun ApplicationEngine.Configuration.envConfig() {
val keyStoreFile = File("build/keystore.jks")
val keyStore = buildKeyStore {
certificate("sampleAlias") {
password = "foobar"
domains = listOf("127.0.0.1", "0.0.0.0", "localhost")
}
}
keyStore.saveToFile(keyStoreFile, "123456")
}Ktor는 시작할 때 인증서가 필요하므로, 서버를 시작하기 전에 인증서를 생성해야 합니다. 전체 예제는 여기에서 확인할 수 있습니다: ssl-embedded-server.
keytool을 사용하여 인증서 생성
keytool을 사용하여 자가 서명 인증서를 생성할 수 있습니다:
keytool -keystore keystore.jks -alias sampleAlias -genkeypair -keyalg RSA -keysize 4096 -validity 3 -dname 'CN=localhost, OU=ktor, O=ktor, L=Unspecified, ST=Unspecified, C=US'이 명령을 실행한 후, keytool은 키스토어 비밀번호를 지정하도록 안내하며 JKS 파일을 생성합니다.
PEM 인증서를 JKS로 변환
인증 기관에서 PEM 형식으로 인증서를 발급한 경우, Ktor에서 SSL을 구성하기 전에 이를 JKS 형식으로 변환해야 합니다. 이를 위해 openssl 및 keytool 유틸리티를 사용할 수 있습니다. 예를 들어, key.pem 파일에 개인 키가 있고 cert.pem에 공개 인증서가 있는 경우 변환 프로세스는 다음과 같습니다:
다음 명령어를 사용하여
openssl로 PEM을 PKCS12 형식으로 변환합니다:Bashopenssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 -name "sampleAlias"key.pem의 패스프레이즈와keystore.p12에 사용할 새 비밀번호를 입력하라는 메시지가 표시됩니다.keytool을 사용하여 PKCS12를 JKS 형식으로 변환합니다:Bashkeytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -destkeystore keystore.jkskeystore.p12파일의 비밀번호와keystore.jks에 사용할 새 비밀번호를 입력하라는 메시지가 표시됩니다.keystore.jks파일이 생성됩니다.
Ktor에서 SSL 구성
Ktor에서 SSL 설정을 지정하는 방법은 Ktor 서버를 구성하는 방식(설정 파일을 사용하거나 코드에서 embeddedServer 함수를 사용하는 방식)에 따라 달라집니다.
설정 파일
서버가 application.conf 또는 application.yaml 설정 파일에서 구성된 경우, 다음 속성을 사용하여 SSL을 활성화할 수 있습니다:
ktor.deployment.sslPort속성을 사용하여 SSL 포트를 지정합니다:shellktor { deployment { sslPort = 8443 } }yamlktor: deployment: sslPort: 8443별도의
security그룹에서 키스토어 설정을 제공합니다:shellktor { security { ssl { keyStore = keystore.jks keyAlias = sampleAlias keyStorePassword = foobar privateKeyPassword = foobar trustStore = truststore.jks trustStorePassword = foobar enabledProtocols = ["TLSv1.2", "TLSv1.3"] } } }yamlktor: security: ssl: keyStore: keystore.jks keyAlias: sampleAlias keyStorePassword: foobar privateKeyPassword: foobar trustStore: truststore.jks trustStorePassword: foobar enabledProtocols: ["TLSv1.2", "TLSv1.3"]
전체 예제는 ssl-engine-main을 참조하세요.
embeddedServer
서버를 실행하기 위해 embeddedServer 함수를 사용하는 경우, ApplicationEngine.Configuration에서 사용자 정의 환경을 구성하고 sslConnector를 사용하여 SSL 설정을 제공해야 합니다:
import io.ktor.network.tls.certificates.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import org.slf4j.*
import java.io.*
import java.security.KeyStore
fun main() {
embeddedServer(Netty, applicationEnvironment { log = LoggerFactory.getLogger("ktor.application") }, {
envConfig()
}, module = Application::module).start(wait = true)
}
private fun ApplicationEngine.Configuration.envConfig() {
val keyStoreFile = File("build/keystore.jks")
val keyStore = buildKeyStore {
certificate("sampleAlias") {
password = "foobar"
domains = listOf("127.0.0.1", "0.0.0.0", "localhost")
}
}
keyStore.saveToFile(keyStoreFile, "123456")
connector {
port = 8080
}
sslConnector(
keyStore = keyStore,
keyAlias = "sampleAlias",
keyStorePassword = { "123456".toCharArray() },
privateKeyPassword = { "foobar".toCharArray() }) {
port = 8443
keyStorePath = keyStoreFile
}
}전체 예제는 ssl-embedded-server를 참조하세요.
