전송 암호화 - ssl/tls

질문:

Workerman 간의 통신이 안전하도록 보장하는 방법은 무엇입니까?

답변:

비교적 편리한 방법은 통신 프로토콜 위에 SSL 암호화 계층을 추가하는 것입니다. 예를 들어, wss, https 프로토콜은 모두 SSL 암호화 전송을 기반으로 하며, 매우 안전합니다. Workerman 자체는 SSL(Workerman>=3.3.7 필요)을 지원하며, 속성만 설정하면 SSL을 활성화할 수 있습니다.

물론 개발자는 특정 암호화 및 복호화 알고리즘을 기반으로 자신의 암호화 메커니즘을 구현할 수도 있습니다.

Workerman에서 ssl을 활성화하는 방법은 다음과 같습니다:

준비 작업:

  1. Workerman 버전이 3.3.7 이상이어야 합니다.
  2. PHP에 openssl 확장이 설치되어 있어야 합니다.
  3. 인증서를 신청하고 (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();