ทำไมติดตั้ง SSL แล้ว ยังไม่พอ
หลายคนติดตั้ง SSL Certificate ด้วย Let’s Encrypt แล้วเห็นรูปแม่กุญแจบน Browser ก็คิดว่าเว็บไซต์ปลอดภัยแล้ว แต่ในมุมของ SysAdmin คำว่า “เปิด HTTPS ได้” กับ “ตั้งค่า HTTPS ให้ปลอดภัย” เป็นคนละเรื่องกันครับ
ถ้า Web Server ยังเปิด TLS เวอร์ชันเก่า เช่น TLS 1.0 หรือ TLS 1.1, ใช้ Cipher Suite ที่ล้าสมัย, ไม่เปิด HSTS หรือไม่มีการตรวจสอบ Chain/OCSP ที่เหมาะสม เว็บไซต์อาจยังถูกจัดเกรดต่ำจากเครื่องมือตรวจสอบ เช่น SSL Labs และยังมีความเสี่ยงจากการโจมตีที่อาศัยการ Downgrade หรือ Protocol เก่าได้
บทความนี้จะพา Harden SSL/TLS บน Ubuntu Server 26.04 ทั้งฝั่ง Nginx และ Apache แบบใช้งานจริง โดยเน้นค่าที่เหมาะกับเว็บไซต์ทั่วไปในปี 2026 คือรองรับ TLS 1.2 และ TLS 1.3 ตามแนวทาง Intermediate Configuration ของ Mozilla SSL Configuration Generator ซึ่งออกแบบมาสำหรับ Server ที่ต้องรองรับ Client หลากหลายประเภท
สิ่งที่ต้องมีก่อนเริ่ม
บทความนี้ทดสอบบนสภาพแวดล้อมดังนี้
-
OS: Ubuntu Server 26.04 LTS
-
Web Server: Nginx หรือ Apache จาก Ubuntu Repository
-
Certificate: Let’s Encrypt ผ่าน Certbot
-
OpenSSL: ใช้เวอร์ชันจาก Ubuntu Repository โดย Ubuntu 26.04 มีแพ็กเกจ OpenSSL 3.5.5 ใน repository สาย resolute/security
-
Domain: มี DNS ชี้มายัง Server แล้ว
-
Firewall: เปิด Port 80 และ 443
ตรวจสอบเวอร์ชันระบบก่อนเริ่ม
# ตรวจสอบ Ubuntu version
lsb_release -a
# ตรวจสอบ OpenSSL version
openssl version
# ตรวจสอบ Nginx version
nginx -v
# ตรวจสอบ Apache version
apache2 -v
หากใช้ Certbot แบบ HTTP challenge เว็บไซต์ควรเข้าถึงได้ทาง Port 80 ก่อน เพราะ Certbot สำหรับ Nginx/Apache ต้องการเว็บที่ Online และเข้าถึงจาก Internet ได้ทาง HTTP ตามเอกสารของ Certbot
แนวคิดสำคัญของ SSL/TLS Hardening
การ Harden SSL/TLS คือการปรับค่าความปลอดภัยของ HTTPS ให้เหมาะสมขึ้น เช่น
-
ปิด Protocol เก่า เช่น SSLv2, SSLv3, TLS 1.0, TLS 1.1
-
เปิดเฉพาะ TLS 1.2 และ TLS 1.3
-
ใช้ Cipher Suite ที่รองรับ Forward Secrecy และ AEAD
-
ปิด Session Ticket หากไม่ต้องการความเสี่ยงจาก Key Reuse
-
เปิด HSTS เพื่อบังคับให้ Browser ใช้ HTTPS
-
เปิด OCSP Stapling เพื่อช่วยตรวจสอบสถานะ Certificate
-
ตรวจสอบผลด้วย SSL Labs
ตั้งแต่ SSL Labs Rating Guide รุ่นใหม่ หาก Server ยังไม่รองรับ TLS 1.3 จะมี Warning และคะแนนอาจถูกจำกัดไว้ที่ A- ขณะที่ HSTS ที่ปิดหรือไม่ถูกต้องก็ทำให้มี Warning และคะแนนถูกตั้งไว้ที่ A- ได้เช่นกัน
สำรองไฟล์ก่อนแก้ไข
ก่อนแก้ไข Production Server ควร Backup configuration เดิมเสมอ
สำหรับ Nginx
# สำรอง config ทั้งโฟลเดอร์ nginx
sudo cp -a /etc/nginx /etc/nginx.backup.$(date +%F-%H%M)
สำหรับ Apache
# สำรอง config ทั้งโฟลเดอร์ apache2
sudo cp -a /etc/apache2 /etc/apache2.backup.$(date +%F-%H%M)
⚠️ คำเตือน: อย่าแก้ไฟล์ SSL/TLS บน Production Server โดยไม่ Backup และไม่ทดสอบ Syntax เพราะหากพิมพ์ผิดเพียงบรรทัดเดียว Web Server อาจ Reload ไม่ขึ้นทันที
วิธีที่ 1: Harden SSL/TLS บน Nginx
สมมติว่าเว็บไซต์ใช้โดเมน
example.com
www.example.com
และ Certificate อยู่ที่
/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/privkey.pem
สร้างไฟล์ SSL Hardening Snippet
# สร้างไฟล์ snippet สำหรับรวมค่า SSL/TLS hardening
sudo nano /etc/nginx/snippets/ssl-hardening.conf
ใส่ค่าต่อไปนี้
# เปิดเฉพาะ TLS 1.2 และ TLS 1.3
ssl_protocols TLSv1.2 TLSv1.3;
# Cipher Suite สำหรับ TLS 1.2
# TLS 1.3 จะใช้ Cipher ที่จัดการโดย OpenSSL/Server เอง
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
# ให้ Client เลือก Cipher ที่เหมาะสม
ssl_prefer_server_ciphers off;
# Session Cache ช่วยลดภาระ TLS Handshake
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# ปิด Session Tickets เพื่อลดความเสี่ยงจากการใช้ Key ซ้ำ
ssl_session_tickets off;
# Elliptic Curves ที่เหมาะกับการใช้งานทั่วไป
ssl_ecdh_curve X25519:prime256v1:secp384r1;
# เปิด OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
# Resolver สำหรับตรวจสอบ OCSP
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
# Security Headers พื้นฐาน
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
เพิ่ม HSTS อย่างระมัดระวัง
HSTS ช่วยบังคับให้ Browser เข้าผ่าน HTTPS เสมอ แต่ต้องระวังมาก โดยเฉพาะตัวเลือก includeSubDomains และ preload
เริ่มจากค่าปลอดภัยก่อน
# เริ่มต้น HSTS แบบระยะสั้นก่อน
add_header Strict-Transport-Security "max-age=300" always;
เมื่อทดสอบแล้วว่า HTTPS ใช้งานได้ครบทุกหน้า ค่อยเพิ่มเป็น
# ใช้เมื่อมั่นใจว่าเว็บหลักและ subdomain พร้อมใช้ HTTPS แล้ว
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
⚠️ คำเตือน: อย่าใส่ preload หากยังไม่มั่นใจว่า Domain และ Subdomain ทั้งหมดรองรับ HTTPS ครบแล้ว เพราะเมื่อ Browser จำค่า HSTS แล้ว ผู้ใช้จะไม่สามารถเข้าเว็บผ่าน HTTP ได้อีกในช่วงเวลาที่กำหนด
นำ Snippet ไปใช้กับ Nginx Server Block
แก้ไฟล์ Virtual Host
sudo nano /etc/nginx/sites-available/example.com
ตัวอย่าง configuration
server {
listen 80;
server_name example.com www.example.com;
# Redirect HTTP ไป HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.htm index.php;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# เรียกใช้ SSL/TLS hardening snippet
include snippets/ssl-hardening.conf;
location / {
try_files $uri $uri/ =404;
}
}
ทดสอบ Syntax และ Reload
# ทดสอบ config nginx
sudo nginx -t
# หากไม่มี error ให้ reload
sudo systemctl reload nginx
แนะนำ Screenshot:
-
ภาพ
nginx -tแสดงผล successful -
ภาพเว็บไซต์เปิดผ่าน HTTPS
-
ภาพผลทดสอบจาก SSL Labs
วิธีที่ 2: Harden SSL/TLS บน Apache
สำหรับ Apache ให้เปิด Module ที่จำเป็นก่อน
# เปิด SSL module
sudo a2enmod ssl
# เปิด Headers module สำหรับ Security Headers
sudo a2enmod headers
# เปิด HTTP/2 หากต้องการใช้งาน
sudo a2enmod http2
# เปิด module สำหรับ SSL Stapling Cache
sudo a2enmod socache_shmcb
จากนั้นสร้างไฟล์ Hardening Config
sudo nano /etc/apache2/conf-available/ssl-hardening.conf
ใส่ค่าต่อไปนี้
# เปิดเฉพาะ TLS 1.2 และ TLS 1.3
SSLProtocol -all +TLSv1.2 +TLSv1.3
# Cipher Suite สำหรับ TLS 1.2
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
# ให้ Client เลือก Cipher ที่เหมาะสม
SSLHonorCipherOrder off
# ปิด Session Ticket
SSLSessionTickets off
# เปิด OCSP Stapling
SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
# Security Headers พื้นฐาน
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# เริ่มต้น HSTS แบบระยะสั้นก่อน
Header always set Strict-Transport-Security "max-age=300"
เปิดใช้งาน Config
# Enable ssl-hardening config
sudo a2enconf ssl-hardening
# ทดสอบ config apache
sudo apachectl configtest
# หากขึ้น Syntax OK ให้ reload
sudo systemctl reload apache2
ตัวอย่าง Apache VirtualHost
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
# Redirect HTTP ไป HTTPS
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
<Directory /var/www/example.com/html>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
ตรวจสอบว่า TLS 1.0 และ TLS 1.1 ถูกปิดแล้วหรือไม่
ใช้ OpenSSL ทดสอบจากเครื่อง Client หรือจาก Server เองก็ได้
# ทดสอบ TLS 1.0 ควรเชื่อมต่อไม่สำเร็จ
openssl s_client -connect example.com:443 -tls1
# ทดสอบ TLS 1.1 ควรเชื่อมต่อไม่สำเร็จ
openssl s_client -connect example.com:443 -tls1_1
# ทดสอบ TLS 1.2 ควรเชื่อมต่อสำเร็จ
openssl s_client -connect example.com:443 -tls1_2
# ทดสอบ TLS 1.3 ควรเชื่อมต่อสำเร็จ
openssl s_client -connect example.com:443 -tls1_3
ผลที่ต้องการคือ TLS 1.0 และ TLS 1.1 ต้องไม่สามารถเชื่อมต่อได้ ส่วน TLS 1.2 และ TLS 1.3 ต้องเชื่อมต่อสำเร็จ
ตรวจสอบ Certificate และวันหมดอายุ
# ตรวจสอบ Certificate chain และวันหมดอายุ
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -issuer -subject -dates
ตัวอย่างผลลัพธ์
issuer=C = US, O = Let's Encrypt, CN = E7
subject=CN = example.com
notBefore=Jul 1 00:00:00 2026 GMT
notAfter=Sep 29 23:59:59 2026 GMT
หากใช้ Certbot ควรทดสอบระบบต่ออายุอัตโนมัติด้วย
# ทดสอบต่ออายุ certificate แบบ dry-run
sudo certbot renew --dry-run
Certbot ระบุว่าสามารถทดสอบ Automatic Renewal ได้ด้วยคำสั่ง certbot renew --dry-run และระบบจะใช้ cron job หรือ systemd timer ในการต่ออายุ Certificate อัตโนมัติเมื่อถึงเวลา
ตรวจสอบด้วย SSL Labs
หลัง Reload Web Server แล้ว ให้ใช้ SSL Labs SSL Server Test ตรวจสอบ Domain ของเรา เครื่องมือนี้เป็นบริการฟรีสำหรับวิเคราะห์ SSL Web Server แบบละเอียด
สิ่งที่ควรตรวจสอบในผลลัพธ์:
-
Certificate Chain ต้องถูกต้อง
-
Protocol ควรเหลือ TLS 1.2 และ TLS 1.3
-
ไม่ควรมี TLS 1.0 / TLS 1.1
-
Cipher Suite ไม่ควรมี RC4, 3DES, CBC เก่า หรือ SHA-1
-
Forward Secrecy ต้องรองรับ
-
HSTS ควรเปิดหลังทดสอบระบบครบแล้ว
-
คะแนนควรอยู่ระดับ A หรือ A+
ถ้าคะแนนยังไม่ขึ้น A/A+ ให้ดูรายละเอียดในส่วน Protocol Support, Key Exchange, Cipher Strength และ HTTP Strict Transport Security
Checklist สำหรับ Harden SSL/TLS
ใช้รายการนี้ตรวจสอบก่อนปิดงาน
[ ] ใช้ Certificate ที่ถูกต้องและไม่หมดอายุ
[ ] เปิด HTTPS บน Port 443
[ ] Redirect HTTP ไป HTTPS
[ ] ปิด SSLv2, SSLv3, TLS 1.0, TLS 1.1
[ ] เปิด TLS 1.2 และ TLS 1.3
[ ] ใช้ Cipher Suite ที่ปลอดภัย
[ ] เปิด Forward Secrecy
[ ] ปิด Session Tickets หากไม่จำเป็น
[ ] เปิด OCSP Stapling
[ ] เปิด Security Headers พื้นฐาน
[ ] เปิด HSTS หลังทดสอบครบ
[ ] ทดสอบด้วย SSL Labs
[ ] ทดสอบ Certbot Renewal
[ ] มี Backup config ก่อนแก้ไข
Troubleshooting ที่พบบ่อย
1. Nginx Reload ไม่ขึ้น
ตรวจสอบ Syntax
sudo nginx -t
ดู Log เพิ่มเติม
sudo journalctl -u nginx --no-pager -n 50
ปัญหาที่พบบ่อยคือใส่ directive ซ้ำ เช่น ssl_protocols ถูกกำหนดทั้งในไฟล์ Virtual Host และไฟล์ที่ Certbot สร้างไว้ ให้ตรวจสอบไฟล์เหล่านี้
grep -R "ssl_protocols" /etc/nginx/
grep -R "ssl_ciphers" /etc/nginx/
2. Apache ขึ้น Syntax Error
sudo apachectl configtest
sudo journalctl -u apache2 --no-pager -n 50
ถ้าเจอปัญหาเกี่ยวกับ SSLStaplingCache ให้ตรวจสอบว่าเปิด module แล้วหรือยัง
sudo a2enmod socache_shmcb
sudo systemctl reload apache2
3. เปิด HSTS แล้วบาง Subdomain เข้าไม่ได้
หากตั้งค่า includeSubDomains แล้ว Subdomain บางตัวไม่มี HTTPS ผู้ใช้จะเข้า Subdomain นั้นไม่ได้ผ่าน Browser สมัยใหม่ วิธีแก้คือทำ HTTPS ให้ครบทุก Subdomain ก่อนเปิด includeSubDomains
4. SSL Labs ยังเตือน HSTS
เริ่มจากเพิ่ม max-age ให้สูงขึ้นหลังทดสอบครบ เช่น
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
หรือฝั่ง Apache
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
ควรใช้ Modern หรือ Intermediate TLS Profile?
ถ้าเป็นเว็บไซต์ทั่วไป แนะนำใช้ Intermediate Profile เพราะยังรองรับ Client ที่หลากหลาย เช่น Browser รุ่นเก่าบางรุ่น, อุปกรณ์มือถือบางกลุ่ม หรือระบบองค์กรที่ยังใช้ TLS 1.2 อยู่
ถ้าเป็นระบบภายในองค์กรที่ควบคุม Client ได้ทั้งหมด เช่น Internal API, Dashboard, Monitoring System หรือระบบที่กำหนด Browser/Client ชัดเจน อาจพิจารณา Modern Profile ที่รองรับเฉพาะ TLS 1.3 ได้ แต่ต้องทดสอบ Compatibility ก่อนเสมอ Mozilla SSL Configuration Generator แบ่งแนวทางเป็น Modern สำหรับ Client ที่รองรับ TLS 1.3 และ Intermediate สำหรับ Server ที่ต้องรองรับ Client หลากหลาย
สรุป
การ Harden SSL/TLS เป็นงานพื้นฐานที่ SysAdmin ไม่ควรมองข้าม เพราะการมี Certificate เพียงอย่างเดียวไม่ได้หมายความว่าเว็บไซต์ปลอดภัยที่สุด สิ่งที่ต้องทำต่อคือปิด Protocol เก่า เลือก Cipher Suite ที่เหมาะสม เปิด TLS 1.3 เปิด HSTS อย่างระมัดระวัง และตรวจสอบผลด้วยเครื่องมือภายนอก เช่น SSL Labs
สำหรับเว็บไซต์ทั่วไปบน Ubuntu Server 26.04 แนะนำให้ใช้แนวทาง Intermediate คือเปิด TLS 1.2 และ TLS 1.3 พร้อมปิด TLS 1.0/1.1 ทั้งหมด วิธีนี้ให้สมดุลที่ดีระหว่างความปลอดภัยและความเข้ากันได้กับผู้ใช้งานจริง
Next Steps: หลังจาก Harden SSL/TLS แล้ว ควรทำ Security Headers เพิ่มเติม เช่น Content-Security-Policy, Rate Limiting, Fail2ban, Web Application Firewall และระบบ Monitoring Certificate Expiry เพื่อให้เว็บไซต์ปลอดภัยครบวงจรมากขึ้น
—
Write by Dr.Arnut Ruttanatirakul
SysAdmin Knowledge
https://www.sysadmin.in.th
July 2, 2026

