전송 암호화 - ssl/tls
질문:
Workerman 간의 통신이 안전하도록 보장하는 방법은 무엇입니까?
답변:
비교적 편리한 방법은 통신 프로토콜 위에 SSL 암호화 계층을 추가하는 것입니다. 예를 들어, wss, https 프로토콜은 모두 SSL 암호화 전송을 기반으로 하며, 매우 안전합니다. Workerman 자체는 SSL(Workerman>=3.3.7 필요)을 지원하며, 속성만 설정하면 SSL을 활성화할 수 있습니다.
물론 개발자는 특정 암호화 및 복호화 알고리즘을 기반으로 자신의 암호화 메커니즘을 구현할 수도 있습니다.
Workerman에서 ssl을 활성화하는 방법은 다음과 같습니다:
준비 작업:
- Workerman 버전이 3.3.7 이상이어야 합니다.
- PHP에 openssl 확장이 설치되어 있어야 합니다.
- 인증서를 신청하고 (pem/crt 파일 및 key 파일) /etc/nginx/conf.d/ssl 위치에 두어야 합니다.
코드:
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// 인증서는 가능하면 신청한 인증서를 사용합니다.
$context = array(
'ssl' => array(
'local_cert' => '/etc/nginx/conf.d/ssl/server.pem', // crt 파일도 사용 가능
'local_pk' => '/etc/nginx/conf.d/ssl/server.key',
'verify_peer' => false,
'allow_self_signed' => true, // 자가 서명된 인증서인 경우 이 옵션 활성화
)
);
// 여기서 설정한 것은 websocket 프로토콜로, http 프로토콜 또는 다른 프로토콜도 가능
$worker = new Worker('websocket://0.0.0.0:443', $context);
// transport를 ssl로 설정
$worker->transport = 'ssl';
$worker->onMessage = function(TcpConnection $con, $msg) {
$con->send('ok');
};
Worker::runAll();
Workerman에서 서버 이름 표시(SNI, Server Name Indication) 활성화
동일한 IP 및 포트에서 여러 인증서를 바인딩할 수 있습니다.
인증서.pem 및 .key 파일 병합:
각 인증서의 .pem 파일과 해당 .key 파일 내용을 병합하고, .key 파일 내용을 .pem 파일의 끝에 추가합니다. (만약 .pem 파일 내에 개인 키가 이미 포함되어 있다면, 이 단계는 무시할 수 있습니다.)
단일 인증서를 주의하세요. 모든 인증서를 하나의 파일에 복사하는 것이 아닙니다.
예를 들어, host1.com.pem 병합 후 pem 파일 내용은 대략 다음과 같을 것입니다:
-----BEGIN CERTIFICATE-----
MIIGXTCBA...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFBzCCA...
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAA....
-----END RSA PRIVATE KEY-----
코드:
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$context = array(
'ssl' => array(
'SNI_enabled' => true, // SNI 활성화
'SNI_server_certs' => [ // 여러 인증서 설정
'host1.com' => '/path/host1.com.pem', // 인증서 1
'host2.com' => '/path/host2.com.pem', // 인증서 2
],
'local_cert' => '/path/default.com.pem', // 기본 인증서
'local_pk' => '/path/default.com.key',
)
);
$worker = new Worker('websocket://0.0.0.0:443', $context);
$worker->transport = 'ssl';
$worker->onMessage = function(TcpConnection $con, $msg) {
$con->send('ok');
};
Worker::runAll();