วิธีการติดตั้ง LEMP ใน Ubuntu 16.04 และการบังคับให้ user ใช้งานแต่ HTTPS เท่านั้น
LEMP คือกลุ่มของ Software ที่ใช้สำหรับการทำเว็บไซด์โดยประกอบไปด้วย Linux + Nginx + MySQL + PHP
โดยใน post นี้เราจะไม่เพียงแต่ setup LEMP เท่านั้น เรายังมีการบังคับให้ใช้งานเป็น HTTPS แทนที่จะใช้งานเป็น HTTP ธรรมอีกด้วย โดยตัวอย่างการ set นี้ผมทำใน Ubuntu 16.04 ครับ
1. Install Nginx + MySQL + PHP
1 |
apt-get install nginx mysql-server php-fpm php-mysql -y |
2. ตั้งรหัสผ่านของ root user ใน MySQL
3. เมื่อติดตั้ง software ทั้งหมดเรียบร้อยแล้ว ให้เข้าไปที่ /etc/php/7.0/fpm/php.ini
1 |
vim /etc/php/7.0/fpm/php.ini |
uncomment ในบรรทัดของ cgi.fix_pathinfo จากนั้น set ให้เป็น 0
เพื่อป้องกันให้ php ไปรันไฟล์ที่ชื่อและ path ที่ใกล้เคียงที่สุดเมื่อมีการเรียกไฟล์ php เข้ามาแล้วไม่มีไฟล์นั้นอยู่ เพราะหากเป็นแบบนั้นอาจจะเป็นการรันไฟล์ที่ไม่ถูกต้องจริงๆก็เป็นได้
4. Restart php7.0-fpm
1 |
service php7.0-fpm restart |
5. Configure ให้ Nginx execute PHP file
โดยปกติแล้ว Nginx Configuration ไม่ได้สั่งให้รัน PHP ไฟล์ตั้งแต่เริ่ม เราจำเป็นต้องไประบุใน configure ของ nginx ในการสั่งให้อ่านและ execute ไฟล์ php โดยเข้าไปที่ไฟล์
1 |
vim /etc/nginx/sites-enabled/default |
กำหนดภายใต้ส่วน Server ให้มีการาส่งไฟล์ php ไปให้ sock PHP-FPM ในการรันต่อ
1 2 3 4 |
<span class="highlight">location ~ \.php$ {</span> <span class="highlight">include snippets/fastcgi-php.conf;</span> <span class="highlight">fastcgi_pass unix:/run/php/php7.0-fpm.sock;</span> <span class="highlight">}</span> |
6. กำหนดให้ Nginx redirect User ไปใช้งาน SSL เท่านั้น
เมื่อเราต้องการให้ user ใช้งานแต่ https แล้ว ดังนั้นสิ่งที่เราทำได้คือการ redirect user ทั้งหมดที่เรียกมาเป็น http ให้ไปเรียกช่องทาง https ทั้งหมด
1 2 3 4 5 6 |
location / { root /var/www/html/; # Discourage deep links by using a permanent redirect to home page of HTTPS site return 301 https://$host$request_uri; #index index.php; } |
7. สร้าง Configuration การให้บริการ HTTPS ของ Nginx ขึ้นมา
สร้างไฟล์ที่คล้ายๆกับการกำหนดใน http ขึ้นมาแต่กำหนด listen เป็น
1 |
listen 443 ssl http2; |
คือกำหนดการให้บริการ ssl ที่ port 443 และมีการใช้งานเป็น http/2 แทน http/1.1 ครับ
8. สร้าง SSL key ให้กับเว็บไซด์
เราสามารถสร้าง key ที่เป็น Self Sign Certificate โดยใช้คำสั่ง
1 |
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt |
โดย option ของ openssl คือ
- req: เป็นการกำหนดให้ใช้ X.509 certificate signing request (CSR) management. โดย “X.509” จะเป็น public key infrastructure standard ที่ SSL และ TLS มีการใช้กันมาเนิ่นนานสำหรับการจัดการ key และ certificate.
- -x509: option นี้เป็นตัวขยายคำสั่ง req ว่าเราต้องการสร้าง self-signed certificate แทนที่จะสร้าง certificate signing request
- -nodes: กำหนดให้ OpenSSL ข้ามการกำหนด passphrase.
- -days 365: กำหนดระยะเวลาอายุของ certificate โดยในที่นี้เรา set เป็น 1 ปี
- -newkey rsa:2048: ใข้กำหนดในการสร้าง certificate และ key ในเวลาเดียวกัน ซึ่งเราไม่ได้สร้างให้ key จำเป็นต้อง sign certificate ใน Step ก่อนหน้านี้, เราต้องการสร้างให้มันมาพร้อมกับ certificate.โดย
rsa:2048
เป็นตัวระบุว่าให้สร้าง RSA key ที่มี 2048 บิท - -keyout: Option ระบุตำแหน่งที่จะวาง private key ที่เราสร้างขึ้น
- -out: Option ระบุตำแหน่งที่จะวาง certificate ที่เราสร้างขึ้น
เมื่อสร้างเสร็จแล้วเราจะได้ private key ออกมาเป็น nginx.key และ nginx.crt ใน path /etc/nginx/ssl/
9. สร้าง DHE (Ephemeral Diffie-Hellman)
สร้าง key สำหรับเมื่อมีการใช้งาน DHE
1 |
cd /etc/nginx/ssl/ & openssl dhparam -out dhparam.pem 2048 |
10. กำหนด HTTPS Service ใน /etc/nginx/site-available/ssl
1 |
vim /etc/nginx/site-available/ssl |
กำหนด option เป็น
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
server { listen 443 ssl http2; client_body_timeout 12; client_header_timeout 12; keepalive_timeout 15; send_timeout 10; client_body_buffer_size 20K; client_header_buffer_size 2k; #client_max_body_size 8m; large_client_header_buffers 2 2k; ## End of optimization ################################# add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; ### เพืม HSTS Header เข้าไปเพื่อให้ครั้งถัดไปที่เข้าเว็บไซด์จะมาที่ https เลย add_header Content-Security-Policy upgrade-insecure-requests; ### กำหนด CSP ให้เป็นการใช้งาน HTTPS server_name lab.techsuii.com; root /var/www/html/; ssl_dhparam /etc/nginx/ssl/dhparam.pem; ssl_certificate /etc/nginx/ssl/nginx.crt; # path ของ certificate ssl_certificate_key /etc/nginx/ssl/nginx.key; # path ของ private key ssl_protocols TLSv1.1 TLSv1.2; # กำหนดลักษณะการแลกเปลี่ยน ssl_prefer_server_ciphers on; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; # การเข้ารหัสที่ให้สามารถใช้ได้ ssl_ecdh_curve secp384r1; ssl_session_cache shared:TLS:2m; ssl_session_timeout 180m; ssl_session_tickets off; location / { root /var/www/html/l index index.php index.html index.htm; } location ~ \.php$ { root /var/www/html/; fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; } } |
11. สร้าง Symlink จาก /etc/nginx/site-available/default-ssl ไปไว้ที่ /etc/nginx/site-enable/default-ssl
1 |
ln -s /etc/nginx/sites-available/default-ssl /etc/nginx/sites-enabled/ |
12. สร้างไฟล์ php ใน /var/www/html
ทดสอบสร้างไฟล์ info.php โดยในที่นี้จะใช้เป็น
1 2 3 |
<?php phpinfo(); ?> |
จากนั้นทดสอบเข้าใช้งาน
http://target
จะพบว่าเมื่อเข้าไปยังเว็บไซด์จะมีการ redirect ไปที่ https://target แทน
แน่นอนว่า Certificate ของเราเป็นแบบ Self-sign Certificate ทำให้มีการแจ้งเตือนการเข้าใช้งานเว็บไซด์ ทีนี้หากใครอยากสร้าง certificate ที่มาจาก Trusted CA แบบฟรีๆ สามารถสร้างได้ผ่าน Let’s Encrypt ครับ
*** Update
หากต้องการเพิ่มเรื่อง compression เพื่อให้สามารถรับส่งข้อมูลได้เร็วมากขึ้นครับ โดยเพิ่มในส่วนของ Server ครับ
1 2 3 4 5 6 7 8 9 |
gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; <span class="highlight">gzip_min_length 256;</span> gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript <span class="highlight">application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;</span> |