Belajar Swoole - TLS/SSL, HTTPS & WSS
Episode 18 of 26

Belajar Swoole - TLS/SSL, HTTPS & WSS

Mengamankan lalu lintas Swoole dengan TLS/SSL: konfigurasi sertifikat di Http dan WebSocket server, enable HTTPS dan WSS, redirect HTTP ke HTTPS, hingga pengamanan cipher dan mutual TLS.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 17 kita mengamankan server dari serangan koneksi — pada episode kali ini kita mengamankan datanya. TLS/SSL adalah standar minimum di internet modern: tanpa HTTPS, data user (password, token, konten chat WebSocket) bisa dibaca siapa pun di jalur jaringan.

Mengapa episode ini penting? Karena Swoole sering dipakai tanpa reverse proxy — dan di situlah letak kesalahannya. Banyak tim membiarkan Swoole plaintext di balik Nginx dan tidak pernah belajar konfigurasi TLS di Swoole. Padahal Swoole bisa menangani HTTPS dan WSS secara native, dan kalian harus tahu caranya bila ingin standalone.

Prasyarat: Build Option dan Sertifikat

Pertama, pastikan Swoole dibangun dengan dukungan SSL:

Cek build option SSL
php --ri swoole | grep -i ssl

Harus menunjukkan swoole.enable-openssl => On. Bila tidak, install ulang dengan --enable-openssl (episode 3).

Kedua, kalian butuh sertifikat. Untuk production gunakan Let's Encrypt:

Dapatkan sertifikat Let's Encrypt
sudo certbot certonly --standalone -d api.example.com

File yang dipakai Swoole:

  • fullchain.pem → sertifikat + chain (sertifikat ssl_cert_file)
  • privkey.pem → private key (sertifikat ssl_key_file)

HTTPS Server dengan Swoole

Konfigurasi dasar HTTPS: listen dengan flag SWOOLE_SSL dan berikan path sertifikat:

https-server.php
<?php
use Swoole\Http\Server;
use Swoole\Http\Request;
use Swoole\Http\Response;
 
$server = new Server('0.0.0.0', 443, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$server->set([
    'ssl_cert_file' => '/etc/letsencrypt/live/api.example.com/fullchain.pem',
    'ssl_key_file'  => '/etc/letsencrypt/live/api.example.com/privkey.pem',
    'ssl_protocols' => SWOOLE_SSL_TLSV1_2 | SWOOLE_SSL_TLSV1_3,
]);
 
$server->on('Request', function (Request $req, Response $res) {
    $res->end('Koneksi aman: ' . ($req->server['https'] ?? 'no'));
});
 
$server->start();

Uji dengan curl:

Uji HTTPS
curl -v https://127.0.0.1:443/ --resolve api.example.com:443:127.0.0.1

Perhatikan $req->server['https'] — Swoole menandai koneksi SSL di sini; berguna untuk log dan logika redirect.

Redirect HTTP ke HTTPS

Pola standar: satu server di port 80 (plaintext) yang me-redirect semua request ke HTTPS:

Redirect HTTP ke HTTPS
<?php
use Swoole\Http\Server;
use Swoole\Http\Request;
use Swoole\Http\Response;
 
$https = new Server('0.0.0.0', 443, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$https->set([
    'ssl_cert_file' => '/etc/letsencrypt/live/api.example.com/fullchain.pem',
    'ssl_key_file'  => '/etc/letsencrypt/live/api.example.com/privkey.pem',
]);
 
$https->on('Request', function (Request $req, Response $res) {
    $res->end('Selamat datang di HTTPS!');
});
 
// Listener tambahan di port 80 — hanya redirect
$http = $https->addListener('0.0.0.0', 80, SWOOLE_SOCK_TCP);
 
// tangani port 80 lewat flag listener
$https->on('Request', function (Request $req, Response $res) use ($https) {
    $isPlain = ($req->server['server_port'] ?? 443) === 80;
    if ($isPlain) {
        $host = $req->header['host'] ?? 'localhost';
        $uri = $req->server['request_uri'] ?? '/';
        $res->redirect("https://$host$uri", 301);
        return;
    }
    $res->end('Selamat datang di HTTPS!');
});
 
$https->start();

Tip

Dua on('Request') di atas sebenarnya akan saling menimpa — cara yang benar adalah satu handler dengan cek port (contoh kedua). Pola satu listener 443 + satu listener 80 dengan if ($server_port === 80) redirect adalah yang paling umum di produksi. SEO juga lebih baik dengan redirect 301 permanen.

WebSocket Secure (WSS)

WebSocket pakai koneksi yang sama — tinggal nyalakan SSL di listener dan client memakai wss://:

WSS server
<?php
use Swoole\WebSocket\Server;
use Swoole\Http\Request;
use Swoole\WebSocket\Frame;
 
$server = new Server('0.0.0.0', 9503, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$server->set([
    'ssl_cert_file' => '/etc/letsencrypt/live/chat.example.com/fullchain.pem',
    'ssl_key_file'  => '/etc/letsencrypt/live/chat.example.com/privkey.pem',
    'ssl_protocols' => SWOOLE_SSL_TLSV1_2 | SWOOLE_SSL_TLSV1_3,
]);
 
$server->on('Open', function (Server $server, Request $req) {
    $server->push($req->fd, 'Terhubung aman (WSS)');
});
 
$server->on('Message', function (Server $server, Frame $frame) {
    $server->push($frame->fd, 'Echo: ' . $frame->data);
});
 
$server->start();

Client di browser kini menghubungi wss://chat.example.com:9503/ — browser menolak WebSocket plaintext dari halaman HTTPS (mixed content), jadi WSS adalah keharusan.

Hardening TLS

Beberapa setelan tambahan yang menaikkan keamanan koneksi:

SetelanFungsi
ssl_protocolsHanya izinkan TLS 1.2/1.3 — matikan TLS 1.0/1.1 yang sudah usang
ssl_verify_peerVerifikasi sertifikat client (untuk mutual TLS)
ssl_ciphersDaftar cipher suite yang diizinkan
ssl_cert_file fullchainSertifikat + chain sekaligus — hindari "incomplete chain"

Contoh mutual TLS (client juga perlu sertifikat):

Mutual TLS
$server->set([
    'ssl_verify_peer'    => true,
    'ssl_verify_depth'   => 3,
    'ssl_verify_peer'    => true,
    'ssl_client_cert_file' => '/etc/ssl/ca.crt', // CA untuk memverifikasi client
]);

Common Pitfalls

MasalahPenyebabSolusi
bad PEM filePath/format sertifikat salahPastikan fullchain + privkey; cek izin baca file
Browser "incomplete chain"Hanya sertifikat leaf, bukan fullchainGunakan fullchain.pem, bukan cert.pem
TLS 1.0 masih bisa konekssl_protocols tidak di-setSet hanya `SWOOLE_SSL_TLSV1_2
Sertifikat expired tidak ketahuanTidak ada pemantauanCron cek expiry + alert (bisa pakai Timer, episode 10)
wss:// gagal tapi https:// jalanPort/SSL di listener salahCek flag SWOOLE_SSL di listener WebSocket

Penutup

Pada episode 18 ini, kalian telah mengamankan lalu lintas Swoole dengan TLS.

Inti yang harus dibawa pulang:

  • Butuh build option --enable-openssl; cek dengan php --ri swoole.
  • HTTPS = listener dengan SWOOLE_SSL + ssl_cert_file/ssl_key_file.
  • Redirect HTTP→HTTPS: satu handler cek server_port.
  • WSS = WebSocket dengan SSL; client memakai wss://.
  • Hardening: ssl_protocols TLS 1.2/1.3, ssl_verify_peer untuk mTLS, dan fullchain certificate.

Di episode 19 selanjutnya, kita mengamati server dari luar: Monitoring, Logging & Debugging — stats, event loop metrics, Xdebug di coroutine, dan export ke Prometheus/OpenTelemetry. Sampai jumpa di episode 19!