การเข้ารหัสการส่งข้อมูล-ssl/tls
คำถาม:
จะทำอย่างไรให้การสื่อสารระหว่าง Workerman มีความปลอดภัย?
คำตอบ:
วิธีที่สะดวกคือการเพิ่มชั้นการเข้ารหัส SSL ขึ้นอยู่กับโปรโตคอลการสื่อสาร เช่น wss, https โปรโตคอลทั้งสองนี้ใช้การส่งข้อมูลที่เข้ารหัสผ่าน SSL มีความปลอดภัยสูง Workerman มีการสนับสนุน SSL (ต้องใช้ Workerman>=3.3.7) เพียงแค่ตั้งค่าคุณสมบัติบางประการก็สามารถเปิดใช้งาน SSL ได้
แน่นอนว่านักพัฒนาสามารถสร้างกลไกการเข้ารหัสและถอดรหัสของตนเองได้โดยอิงจากอัลกอริธึมการเข้ารหัสบางประเภท
วิธีเปิดใช้งาน ssl ใน Workerman มีดังนี้:
การเตรียมการ:
-
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();
เปิดใช้งาน SNI (Server Name Indication) ใน Workerman SNI(Server Name Indication)
เพื่อให้สามารถผูกใบรับรองหลายใบในที่อยู่ IP และพอร์ตเดียวกันได้
การรวมไฟล์ใบรับรอง .pem และ .key:
รวมเนื้อหาของไฟล์ .pem และไฟล์ .key ของแต่ละใบรับรองเข้าด้วยกัน โดยใส่เนื้อหาของไฟล์ .key ที่ส่วนท้ายของไฟล์ .pem (ถ้าไฟล์ .pem มี private key อยู่แล้วสามารถข้ามได้)
โปรดทราบว่าเป็นใบรับรองเดียว ไม่ต้องรวมใบรับรองทั้งหมดไว้ในไฟล์เดียว
ตัวอย่างเนื้อหาในไฟล์ pem ที่รวมแล้วของ host1.com.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();