TLS/SSL을 통해 소켓 연결의 보안을 유지하는 방법(HTML)
[ 이 문서는 Windows 런타임 앱을 작성하는 Windows에서 8.x 및 Windows Phone 8.x 개발자를 대상으로 합니다. Windows 10용으로 개발하는 경우에는 최신 설명서를 참조하세요.]
이 항목에서는 Windows 스토어 앱에서 StreamSocket 기능을 사용할 경우 TLS/SSL을 통해 스트림 소켓 연결의 보안을 유지하는 방법을 보여 줍니다.
알아야 할 사항
기술
-
소켓 및 WebSocket을 사용하여 네트워크 통신을 사용하도록 설정합니다.
사전 요구 사항
- 이 항목의 다음 예제는 JavaScript로 제공됩니다. 소켓 및 SSL/TLS 사용에 대해 기본적으로 이해하고 있는 것이 좋습니다.
SSL/TLS 연결 개요
SSL(Secure Sockets Layer) 및 더 최근의 TLS(전송 계층 보안)는 네트워크 통신에 인증 및 암호화를 제공하도록 설계된 암호화 프로토콜입니다. 이러한 프로토콜은 네트워크 데이터를 보내고 받을 때 도청 및 변조를 방지하도록 설계되었습니다. 이러한 프로토콜은 프로토콜 교환에 클라이언트-서버 모델을 사용합니다. 이러한 프로토콜은 또한 디지털 인증서 및 인증 기관을 사용하여 서버가 인증이 필요한 개체인지 확인합니다. TLS 프로토콜에 대해서는 IETF RFC 5246에 설명되어 있습니다. 이전의 SSL 프로토콜은 Netscape Communications의 문서에 기록되어 있습니다. SSL은 일반적으로 이러한 프로토콜을 모두 나타내는 데 사용됩니다.
클라이언트와 서버 간 통신에 SSL/TLS를 사용하도록 StreamSocket 개체를 구성할 수 있습니다. SSL/TLS에 대한 이 지원은 클라이언트가 SSL/TLS 협상 중일 때 StreamSocket 개체를 사용하는 것으로 제한됩니다. 서버로서의 SSL/TLS 협상이 StreamSocket에 대해 구현되어 있지 않으므로 연결을 받을 때 StreamSocket이 생성되는 StreamSocketListener가 현재 SSL/TLS를 통해 StreamSocket에서 SSL/TLS를 사용하도록 설정할 수 없습니다. SSL/TLS에 대한 클라이언트 지원에 클라이언트 인증서를 사용하는 기능은 포함되지 않습니다.
SSL/TLS를 통해 StreamSocket 연결의 보안을 유지하는 방법은 다음 두 가지입니다.
- ConnectAsync - 네트워크 서비스에 대한 초기 연결을 설정하고 모든 통신에 SSL/TLS를 사용하도록 즉시 협상합니다.
- UpgradeToSslAsync - 처음에 암호화 없이 네트워크 서비스에 연결합니다. 앱은 데이터를 보내거나 받을 수 있습니다. 그런 다음 이후의 모든 통신에 SSL/TLS를 사용하도록 연결을 업그레이드합니다.
ConnectAsync 사용
네트워크 서비스에 대한 초기 연결을 설정한 다음 모든 통신에 SSL/TLS를 사용하도록 즉시 협상합니다. protectionLevel 매개 변수 전달을 지원하는 두 가지 ConnectAsync 메서드는 다음과 같습니다.
- ConnectAsync(EndpointPair, SocketProtectionLevel) - StreamSocket 개체에서 비동기 작업을 시작하여 EndpointPair 개체 및 SocketProtectionLevel로 지정된 원격 네트워크 대상에 연결합니다.
- ConnectAsync(HostName, String, SocketProtectionLevel) - StreamSocket 개체에서 비동기 작업을 시작하여 원격 호스트 이름, 원격 서비스 이름 및 SocketProtectionLevel로 지정한 원격 대상에 연결합니다.
위 ConnectAsync 메서드 중 하나를 호출할 때 protectionLevel 매개 변수가 Windows.Networking.Sockets.SocketProtectionLevel.Ssl로 설정되어 있으면 StreamSocket은 암호화에 SSL/TLS를 사용해야 합니다. 이 값에는 암호화가 필요하고 NULL 암호를 사용할 수 없습니다.
이러한 ConnectAsync 메서드 중 하나에 사용할 일반적인 순서는 동일합니다.
- StreamSocket을 만듭니다.
- 소켓에 대한 고급 옵션이 필요하면 StreamSocket.Control 속성을 사용하여 StreamSocket 개체와 연결된 StreamSocketControl 인스턴스를 가져옵니다. StreamSocketControl에 대한 속성을 설정합니다.
- 위 ConnectAsync 메서드 중 하나를 호출하여 원격 대상에 연결하는 작업을 시작하고 SSL/TLS를 사용하도록 즉시 협상합니다.
다음 예제에서는 StreamSocket을 만들고 네트워크 서비스에 대한 연결을 시도한 다음 SSL/TLS를 사용하도록 즉시 협상합니다. 협상에 성공하면 클라이언트와 네트워크 서버 간에 StreamSocket을 사용하는 모든 네트워크 통신이 암호화됩니다.
// Define some global variables that can be used from
// multiple functions as needed
var clientSocket = null;
var serverHostName = null;
var serverServiceName = null;
function openClient() {
clientSocket = new Windows.Networking.Sockets.StreamSocket();
// Try to connect to contoso using HTTPS (port 443)
serverHostName = new Windows.Networking.HostName("www.contoso.com");
serverServiceName = "https";
// Call connectAsync method with SSL
clientSocket.connectAsync(serverHostName, serverServiceName, Sockets.SocketProtectionLevel.Ssl).done(onClientAccept, onConnectError);
}
// For simplicity, the sample omits implementation of the
// displayStatus method used to display status and error messages
// If the client connection was accepted, display
// a message to the user
function onClientAccept() {
socketSample.displayStatus("Client: connection completed.");
}
// The connection failed so display an error message
// Could retry the connection, but for this simple example
// just close the socket.
function onConnectError(reason) {
socketsSample.displayStatus(reason);
clientSocket.close();
clientSocket = null;
}
UpgradeToSslAsync 사용
암호화하지 않고 네트워크 서비스에 대한 초기 연결을 설정합니다. 앱은 일부 데이터를 보내거나 받은 다음 이후의 모든 통신에 SSL/TLS를 사용하도록 연결을 업그레이드할 수 있습니다. 이때 다음 메서드를 사용합니다.
- UpgradeToSslAsync - 비동기 작업을 시작하여 StreamSocket 개체에서 SSL을 사용하도록 업그레이드합니다.
UpgradeToSslAsync 메서드는 두 개의 매개 변수를 사용합니다. protectionLevel 매개 변수는 원하는 보호 수준을 나타냅니다. validationHostName 매개 변수는 SSL로 업그레이드할 때 유효성 검사에 사용되는 원격 네트워크 대상의 호스트 이름입니다. 일반적으로 validationHostName은 앱이 처음에 연결을 설정하는 데 사용한 것과 같은 호스트 이름입니다. 위 UpgradeToSslAsync 메서드를 호출할 때 protectionLevel 매개 변수가 Windows.System.Socket.SocketProtectionLevel.Ssl로 설정되어 있으면 StreamSocket은 암호화에 SSL/TLS를 사용해야 합니다. 이 값에는 암호화가 필요하고 NULL 암호를 사용할 수 없습니다.
UpgradeToSslAsync 메서드에 사용하는 일반적인 순서는 다음과 같습니다.
- StreamSocket을 만듭니다.
- 소켓에 대한 고급 옵션이 필요하면 StreamSocket.Control 속성을 사용하여 StreamSocket 개체와 연결된 StreamSocketControl 인스턴스를 가져옵니다. StreamSocketControl에 대한 속성을 설정합니다.
- 데이터를 암호화하지 않은 상태로 보내고 받아야 할 경우 지금 보냅니다.
- UpgradeToSslAsync 메서드를 호출하여 작업을 시작하고 SSL/TLS를 사용하도록 연결을 업그레이드합니다.
다음 예제에서는 StreamSocket을 만들고 네트워크 서비스에 대한 연결을 시도한 후 일부 초기 데이터를 보내고 SSL/TLS를 사용하도록 협상합니다. 협상에 성공하면 클라이언트와 네트워크 서버 간에 StreamSocket을 사용하는 모든 네트워크 통신이 암호화됩니다.
// Define some global variables that can be used from
// multiple functions as needed
var clientSocket = null;
var serverHostName = null;
var serverServiceName = null;
function openClient() {
clientSocket = new Windows.Networking.Sockets.StreamSocket();
// Try to connect to contoso initially using HTTP
serverHostName = new Windows.Networking.HostName("www.contoso.com");
serverServiceName = "http";
// Call ConnectAsync method to establish initial connection
clientSocket.connectAsync(serverHostName, serverServiceName).done(onClientAccept, onConnectError);
}
// For simplicity, the sample omits implementation of the
// displayStatus method used to display status and error messages
// If the client connection was accepted, display
// a message to the user
function onClientAccept() {
socketSample.displayStatus("Client: connection completed.");
sendHello();
}
// The connection failed so display an error message
// We could retry the connection, but for this simple example
// we just close the socket.
function onConnectError(reason) {
socketsSample.displayStatus(reason);
clientSocket.close();
clientSocket = null;
}
// Send some data in a simple format that is
// the length of the string of data in a 4-byte integer
// followed by the string
function sendHello() {
if (!clientSocket) {
socketsSample.displayStatus("Client: you must connect the client before using it.");
return;
}
var writer = new Windows.Storage.Streams.DataWriter(socketsSample.clientSocket.outputStream);
var string = "Hello World ☺ ";
var len = writer.measureString(string); // Gets the UTF-8 string length.
writer.writeInt32(len);
writer.writeString(string);
socketsSample.displayStatus("Client: sending hello.");
writer.storeAsync().done(onStore, onSendError);
writer.detachStream(); // Detach stream, if not, DataWriter destructor will close it.
}
function onStore() {
socketsSample.displayStatus("Client: sent hello.");
upgradeClient();
}
function onSendError(reason) {
socketsSample.displayStatus(reason);
clientSocket.close();
clientSocket = null;
}
function upgradeClient() {
if (!clientSocket) {
socketsSample.displayStatus("Client: you must connect the client before using it.");
return;
}
var validationName = serverHostName;
upgradeToSslAsync(SocketProtectionLevel.Ssl, serverHostName).done(onUpgradeAccept, onUpgradeError);
}
// If upgrade to SSL was successful, display message to user
function onUpgradeAccept() {
socketSample.displayStatus("Client: upgrade to SSL completed.");
}
// The upgrade connection failed so display an error message
// We could retry the upgrade possibly changing the validationHostname,
// but for this simple example we just close the socket.
function onUpgradeError(reason) {
socketsSample.displayStatus(reason);
clientSocket.close();
clientSocket = null;
}
설명
SocketProtectionLevel 열거형에는 다음과 같이 여러 가지 가능한 값이 있습니다.
PlainSocket - 암호화되지 않은 일반 소켓입니다.
Ssl - 암호화에 SSL/TLS를 사용해야 하는 소켓입니다. 이 값에는 암호화가 필요하고 NULL 암호를 허용하지 않습니다.
이 값은 SSL 3.0 및 TLS 1.0 프로토콜과 시스템에 설치된 모든 암호화 암호(NULL 암호 제외)를 지원합니다.
SslAllowNullEncryption - 암호화에 기본적으로 SSL/TLS를 사용하는 소켓입니다. 이 값에는 기본적으로 전체 암호화가 사용되지만 서버 구성에 따라 NULL 암호(암호화 안 함)를 허용합니다.
BluetoothEncryptionAllowNullAuthentication - 기본적으로 해당 암호화를 사용하는 Bluetooth 소켓이지만 대상 서버의 구성에 따라 NULL 암호(암호화되지 않음)를 허용합니다.
BluetoothEncryptionWithAuthentication - 암호화를 사용해야 하는 Bluetooth 소켓입니다. 이 값에는 암호화가 필요하고 NULL 암호를 허용하지 않습니다.
Ssl3AllowWeakEncryption - 암호화에 SSL을 사용해야 하는 TCP 소켓입니다. 이 값은 SSL 3.0 프로토콜과 시스템에 설치된 모든 암호화 암호(NULL 암호 제외)를 지원합니다. 이 값은 RC4 및 기타 안전하지 않은 것으로 간주되는 약한 암호를 허용합니다.
Tls10 - 암호화에 SSL을 사용해야 하는 TCP 소켓입니다. 이 값은 TLS 1.0 프로토콜과 시스템에 설치된 모든 암호화 암호(RC4, 기타 약한 암호 및 NULL 암호 제외)를 지원합니다.
Tls11 - 암호화에 SSL을 사용해야 하는 TCP 소켓입니다. 이 값은 TLS 1.1 및 TLS 1.0 프로토콜과 시스템에 설치된 모든 암호화 암호(RC4, 기타 약한 암호 및 NULL 암호 제외)를 지원합니다.
Tls12 - 암호화에 SSL을 사용해야 하는 TCP 소켓입니다. 이 값은 TLS 1.2, TLS 1.1 및 TLS 1.0 프로토콜과 시스템에 설치된 모든 암호화 암호(RC4, 기타 약한 암호 및 NULL 암호 제외)를 지원합니다.
SslAllowNullEncryption 값은 NULL 암호를 사용하도록 허용하고 이는 암호화하지 않는 것을 의미하여 네트워크 통신이 암호화되지 않을 수 있으므로 이 값은 일반적으로 사용되지 않습니다. SslAllowNullEncryption 값은 서버 디지털 인증서 및 인증 기관을 기반으로 하여 SSL/TLS 협상에서 서버의 유효성을 검사하도록 허용합니다.
실제로 ConnectAsync 또는 UpgradeToSslAsync를 사용하여 협상된 SSL 수준은 StreamSocketinformation.ProtectionLevel 속성을 가져와서 결정할 수 있습니다.
관련 항목
기타
참조
StreamSocket.UpgradeToSslAsync
StreamSocketinformation.ProtectionLevel
샘플