Archive for the ‘Web Server’ Category

Về nginx caching

Posted: Tháng Mười 31, 2019 in Caching, Nginx, Web Server
Thẻ:

1. Tại sao lại Nginx static cache?

Nginx – ngoài việc phục vụ trực tiếp static file cực kỳ hiệu quả, nó còn có thể phục vụ với vai trò là proxy hoặc web server. Ngoài ra, Nginx còn có thể đảm nhận vai trò caching static file khi nó đứng trước một application server.

Có một số điểm cần biết:

  • Nginx phục vụ trực tiếp static file cực kỳ nhanh, tuy nhiên nó cũng ảnh hưởng đến mặt hiệu suất xử lý của Nginx khi số lượng request tăng cao (cụ thể về CPU và RAM)
  • Nếu sử dụng nginx như static cache thì chỉ tốn về mặt lưu trữ dữ liệu cache (liên quan phần storage), và sử dụng rất ít hiệu suất của server (cụ thể về CPU và RAM), do application server không cần phải xử lý page khi client request, mà nginx cache server sẽ phản hồi trực tiếp nội dung đã lưu cache.
  • Để tăng hơn nữa khả năng phục vụ static file, chúng ta cần lưu trữ cache với storage mà có khả năng read/write cao hơn như ổ SSD. Để phục vụ các tệp tin như audio, video với dung lượng lớn chúng ta lưu trữ cache qua SAN, NAS hoặc qua mạng như glusterfs.

2. Cách Nginx cache

  • Một client request nội dung đến application server
  • Cache kiểm tra xem nội dung đã tồn tại chưa?
    • Nếu kiểm tra phản hồi chưa có bản lưu nội dung được cache, kết quả là thông tin MISS cache, khi đó nội dung sẽ được lấy từ application server.
    • Nếu kiểm tra mà nội dung đã được cache, khi đó kết quả thông tin HIT cache, khi đó nội dung sẽ trả trực tiếp đến client mà không cần contact với application server
  • Một lần nội dung được cache, nó sẽ tiếp tục được phục vụ từ cache cho đến khi cache expire, hoặc khi cache bị clear/purge

3. Một số tùy chọn và tham số cấu hình

proxy_cache_path: Thiết lập vị trí lưu các cache file. Chúng ta thiết lập lưu trong đường dẫn /store/cache/example.com/

  • levels: Chị thì này dùng để thiết lập cách các cache file được lưu đến hệ thống tệp tin (hay là cấp độ tạo thư mục cho lưu cache file). Nếu không định nghĩa, cache file được lưu trực tiếp vào vị trí được định nghĩa. Nếu một số lượng lớn các tệp tin cache được lưu trực tiếp vào một thư mục, khi đó tốc độ truy cập đến tệp tin sẽ chậm đi. Vì vậy, chúng ta định nghĩa levels, ví dụ như trong cấu hình levels=1:2 nghĩa là thư mục được phân thành 2 cấp, khi đó cache file được lưu vào thư mục con của vị trí lưu cache, dựa trên mã md5 hashes.
  • keys_zone: dùng thiết lập shared memory zone cho lưu trữ cache keys và metadata. Một bản sao các keys trong memory sẽ làm cho Nginx nhanh hơn để xác định request nào là HIT hay MISS mà không phải truy cập xuống disk, mục đích tăng tốc độ check. Ở đây, chúng ta định nghĩa keys_zone với tên example.com. Với 1MB zone, có thể lưu trữ dữ liệu cho khoảng 8000 keys, vì thế mà chúng ta cấu hình 400MB, có thể lưu trữ đến 3200000 keys.
  • Inactive: Chỉ thị này được dùng để bảo nginx clear cache một số asset mà không được truy cập trong khoảng time được thiết lập mà không quan tâm đến là cache đó đã expire hay chưa. Inactive content khác với expire content. Nginx không tự động xóa nội dung mà đã expire được định nghĩa bởi một cache control header. Ở đây, chúng ta thiết lập inactive=10d (10 ngày). Mặc định inactive được thiết lập là 10 phút.
  • max_size: Thiết lập không gian disk tối đa mà nginx sử dụng để lưu cache. Nếu không định nghĩa, mặc định nó sử dụng toàn bộ không gian disk có sẵn để sử dụng cho việc lưu cache. Khi cache đạt đến giới hạn được định nghĩa, một tiến trình cache manager được sử dụng để remove các tệp mà được sử dụng gần nhất để đưa cache size về dưới giới hạn được định nghĩa.

proxy_cache_key: Định nghĩa key cho cache. Mặc định cấu hình với giá trị sau:

proxy_cache_key $scheme$proxy_host$uri$is_args$args;

Chúng ta có thể thay thế giá trị các biến sử dụng trong định nghĩa key, tùy thuộc giá trị mong muốn. Ví dụ định nghĩa key cho cache như sau:

proxy_cache_key "$scheme://$host$request_uri";

Khi đó key có kiểu giống như này: https://example.com/abc.jpg

proxy_cache_revalidate: Nếu chỉ thị này enable, Nginx xác minh nội dung cache hiện tại vẫn hợp lệ. Cái này cho phép tiết kiệm bandwidth bởi vì server chỉ gửi item đầy đủ nếu nó đã sửa đổi từ lần được khi lại trong header Last-Modified kèm theo tệp tin khi Nginx tổ chức cache nó.

proxy_cache_min_uses: Thiết lập số lần request một nội dung (item) của một client trước khi Nginx thực hiện cache nó. Mặc định giá trị proxy_cache_min_uses là 1.

proxy_cache_use_stale: Khi origin server down trong một khoảng thời gian (mà chưa refesh) gặp các mã lỗi 5xx, khi đó client request nội dung mà đã được cache từ nginx cache server nó sẽ vẫn nhận thông tin đã cache.

Để bật tính năng này, chúng ta cấu hình như sau:

location / {
    # ...
    proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}

proxy_next_upstream: Chỉ định trường hợp nào một request sẽ được chuyển qua nginx cache server tiếp theo. Chúng ta chỉ định các trường hợp lỗi sau:

proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

proxy_ignore_headers: Chỉ thị cho phép Nginx bỏ qua một số header. Ví dụ bỏ qua header Cache-Control và Set-Cookie

proxy_ignore_headers Cache-Control Set-Cookie;

proxy_cache_methods: Chỉ thị cho phép một số method được cache, mặc định GET và HEAD luôn được phép.

proxy_cache_lock: Tùy bật tùy chọn này với giá trị “on”, nếu nhiều client cùng request đến một file mà hiện tại chưa cache, khi đó chỉ có request đầu tiên được phép thực hiện contact với origin server và sau đó nội dung sẽ được cache.

4. Splitting the Cache Across Multiple Hard Drives

Nếu có nhiều hard disk, chúng ta có thể tách vị trí lưu cache đến nhiều vị trí khác nhau. Ví dụ cấu hình sau:

proxy_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m
                 max_size=10g inactive=60m use_temp_path=off;
proxy_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m
                 max_size=10g inactive=60m use_temp_path=off;

split_clients $request_uri $my_cache {
              50%          “my_cache_hdd1”;
              50%          “my_cache_hdd2”;
}

server {
    # ...
    location / {
        proxy_cache $my_cache;
        proxy_pass http://my_upstream;
    }
}

Ở đây, chúng ta tách vị trí lưu cache ra 2 hard disk và lưu ở 2 key zone. Sử dụng khối cấu hình “split_clients” định nghĩa key zone chung với biến $my_cache cho 2 key zone và cho phép mỗi hard disk sẽ cache một nửa số lượng request (50%). MD5 hash dựa trên biến $request_uri để xác định cache nào được sử dụng cho mỗi request

Read more

https://www.nginx.com/blog/nginx-caching-guide/

iFrame là gì? iFrame ( inline Frame) là một trang html được nhúng vào một trang html khác trên website. Thẻ iFrame thường được sử dụng để chèn nội dùng từ source khác, giống như các link ảnh, quảng cáo, .. Vì thế mà hacker có thể lợi dụng để insert mã iFrame với source bên ngoài và thực hiện ý đồ mong muốn.

Phương thức mà hacker khai thác khi người dùng click vào link được nhúng ở trên còn gọi là Clickjacking

Để hạn chế, hoặc chặn việc sử dụng iframe, chúng ta có thể sử dụng tham số “X-Frame-Options” HTTP response header trong cấu hình web server

Với X-Frame-Options, chúng ta có 3 giá trị có thể được áp dụng

X-Frame-Options: deny
X-Frame-Options: sameorigin
X-Frame-Options: allow-from uri

Nội dung các giá trị ở trên:

  • deny: Chặn toàn bộ việc đọc dữ liệu từ các trang có gắn frame, iframe

  • sameorigin: Chỉ cho phép đọc dữ liệu từ frame, iframe trong cùng domain

  • allow-from uri: Trang có thể thể đọc dữ liệu từ uri được định nghĩa (ví dụ allow-from uri: http://example.com)

Thiết lập X-Frame-Options trên một số web server phổ biến hiện nay

– Nginx

Tham số X-Frame-Options có thể them vào block http, server hoặc location trong tệp tin cấu hình nginx. Trong phạm vi ứng dụng đến toàn web server, tôi sẽ cấu hình vào block http{ } trong tệp tin cấu hình chính của nginx

add_header X-Frame-Options sameorigin;

Kiểm tra thông tin response header

nginx-frame-options

– Apache

Thêm đoạn sau vào tệp tin cấu hình chính Apache (ví dụ httpd.conf)

Header always set X-Frame-Options "sameorigin"

Kiểm tra thông tin response header

apache-x-frame-options

 

 

1. FastCGI, PHP-FPM là gì?

PHP Handler là module của web server, dùng để dịch và chạy website PHP. Có nhiều handler cho PHP hiện nay như: DSO, CGI, SuPHP, FastCGI.
FastCGI là phiên bản kế tiếp của CGI, ít tốn tài nguyên CPU và cho tốc độ tải trang php cao, với điều kiện cần một lượng RAM đủ lớn. FastCGI cho phép máy chủ xử lý được nhiều web page hơn tại cùng một thời điểm.
PHP-FPM giúp quản lý tiến trình PHP FastCGI. PHP-FPM là daemon do đó chúng ta có thể cài nó độc lập trên một server, default port là 9000.

2. Cài đặt và cấu hình Apache với PHP-FPM cho PHP 7

Để Apache web server phục vụ PHP với FastCGI và PHP-FPM cho hiệu suất cao nhất cần kết hợp Apache sử dụng Event MPM 
PHP 7 cho tốc độ thực thi code nhanh hơn và hiện đã được sử dụng rộng rãi. Vì vậy bài viết sẽ cài đặt và cấu hình Apache-2.4 với php-fpm cho PHP 7
– Cài đặt repolist
yum -y install epel-release
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
– Cài đặt Apache
yum -y install httpd
– Cài đặt module php7 và php-fpm
yum -y install php71w php71w-common php71w-gd php71w-phar php71w-xml php71w-cli php71w-mbstring php71w-tokenizer php71w-openssl php71w-pdo php71w-devel
yum -y install php71-fpm
– Cấu hình Apache để hỗ trợ PHP FastCGI
cat >>/etc/httpd/conf.d/php.conf <<EOF
<FilesMatch \.php$>
SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>
EOF
– Start & enable PHP-FPM
systemctl start php-fpm
systemctl enable php-fpm
– Restart Apache
systemctl restart httpd

3. Kiểm tra thông tin php handler

Tạo tệp tin info.php trong Document Root để kiểm tra PHP Handler đang sử dụng
<?php
phpinfo();
?>
Duyệt web và kiểm tra handler tại dòng “Server API
fastcgi php handler

Apache sử dụng Event MPM

Posted: Tháng Bảy 24, 2018 in Apache, Web Server
Thẻ:,

1. Multi-Processing Module (MPM) trong Apache

MPM (Multi-Processing Module):  là các module multi-processing mà quyết định cách thức Apache sẽ tiếp cận và xử lý các request từ client.
MPM là module trong Apache vì vậy mà ta có thể enable/disable trong cấu hình module của apache. Apache cũng yêu cầu và chỉ có thể sử dụng duy nhất 01 trong các module MPM cho cấu hình.
Hiện nay, Apache-2.4 hỗ trợ 03 modules multi-processing cho hệ thống Unix: worker, prefork và event

Worker MPM: Sử dụng nhiều child process với nhiều thread. Và mỗi thread sẽ xử lý một request tại một thời điểm.

Prefork MPM : Sử dụng nhiều child process với một thread. Tại một thời điểm thì mỗi process đó sẽ chỉ xử lý chỉ một request.

Event MPM : Sử dụng mô hình event-based, cho phép truy cập và xử lý các yêu cầu bất đồng bộ (asynchronous).
Event MPM dựa trên mô hình MPM worker, nên nó cũng gần giống với mpm worker.
Nó tạo ra nhiều child process, với nhiều thread. Mỗi parent process chịu trách nhiệm chạy các child process. Mỗi child process tạo ra một số lượng thread cố định (Số lượng thread được định nghĩa trong chỉ thị “ThreadsPerChild“).

Để biết được child process được sinh ra ta sử dụng:

ps -ef |grep httpd |grep -v grep

Chi tiết về MPM có thể tham khảo tại:
http://httpd.apache.org/docs/current/mpm.html

2. Cài đặt và cấu hình Apache sử dụng Event MPM

  • Cài đặt apache web server trên CentOS 7
yum -y install httpd
  • Kiểm tra phiên bản Apache và MPM đang hoạt động
apachectl -V |grep -i 'version\|MPM'

Server version: Apache/2.4.6 (CentOS)
Server MPM: prefork

Version hiện tại là Apache/2.4.6 và mặc định sử dụng MPM prefork
Thông số cấu hình mặc định của mpm prefork:

<IfModule prefork.c>
    StartServers 5
    ServerLimit 256
    MinSpareServers 5
    MaxSpareServers 10
    MaxRequestWorkers 256
    MaxConnectionsPerChild 0
</IfModule>

Cấu hình Apache sử dụng mpm event
– Comment dòng sau để disable module mod_mpm_prefork

sed -i 's/.*mod_mpm_prefork.so/#&/' /etc/httpd/conf.modules.d/00-mpm.conf 
  • Thêm dòng sau để enable mod_mpm_event
sed -i '/.*mod_mpm_event.so/s/^#//g' /etc/httpd/conf.modules.d/00-mpm.conf 
  • Restart Apache web server
systemctl restart httpd
  • Check MPM module
httpd -V | grep MPM 
Server MPM: event

Thông số cấu hình mpm event mặc định như sau:

    ThreadsPerChild           25
    StartServers               3
    ServerLimit               16
    MinSpareThreads           75
    MaxSpareThreads          250
    MaxRequestWorkers        400
    MaxConnectionsPerChild     0

Để tùy chỉnh Event MPM thêm đoạn sau vào tệp tin cấu hình httpd (/etc/httpd/conf/httpd.conf)

<IfModule mpm_event_module>
    ServerLimit              100
    StartServers             12
    MinSpareThreads          25
    MaxSpareThreads          250
    ThreadLimit              64
    ThreadsPerChild          25
    MaxRequestWorkers        2500
    MaxConnectionsPerChild   0
    AsyncRequestWorkerFactor 4
</IfModule>
  • Tùy chỉnh một số directive:
    MaxRequestWorkers = ServerLimit * ThreadsPerChild

Trong phần trước, mình có cấu hình Nginx làm reverse proxy cho Apache web server. Với giao thức http – một giao thức chưa được mã hóa. Để đảm bảo an toàn hơn trong giao tiếp giữa client và server qua trình duyệt, chúng ta cần cài đặt chứng chỉ SSL trên server.

Nginx reverse proxy with SSL for Apache webserver

1. Tự tạo self-signed certificate

Đây là certificate mà ta sẽ tự tạo ra trên chính server. Certificate này không được xác thực bởi các nhà cung cấp chứng chỉ số.

Các bước tạo self-signed certificate và cấu hình Nginx sử dụng SSL như sau:

Step1: Tạo private key

mkdir -p /etc/nginx/ssl/example
cd /etc/nginx/ssl/example
# Tạo key với mã hóa RSA
openssl genrsa -des3 -out server.key 2048
# Quá trình tạo key yêu cầu nhập pass phrase
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:
# Chúng ta sẽ remove passphrase bỏ qua quá trình hỏi passphare
openssl rsa -in server.key -out server.key
Enter pass phrase for server.key:
writing RSA key

Step2: Đăng ký certificate

openssl req -new -key server.key -out server.csr

Đăng ký certificate có thể như sau:

Country Name (2 letter code) [XX]:VN
State or Province Name (full name) []:HN
Locality Name (eg, city) [Default City]:HN
Organization Name (eg, company) [Default Company Ltd]:Example
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server’s hostname) []:example.local
Email Address []:

Step3:  Tạo certificate

Dựa vào CSR ở trên, chúng ta tạo một self-signed certificate, với hiệu lực 365 ngày

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Step4: Cấu hình Nginx reverse proxy với SSL cho website example.local

Tạo hay sửa đổi tệp tin cấu hình site example.local với nội dung sau:

(vim /etc/nginx/sites-enabled/example.conf)

server {
    listen 80;
    server_name example.local;
    rewrite ^(.*) https://example.local$1 permanent; #redirect from http to https
    #return 301 https://$host$request_uri;
    }
server {
    listen 443;
    server_name example.local;
    root /var/www/example;
    location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|txt|srt|swf|zip|rar|html|htm|pdf)$ {
      expires 30d; # caching, expire after 30 days
   }
    access_log /var/log/nginx/nginx.local-access.log;
    error_log /var/log/nginx/nginx.local-error.log;
    ssl on;
    #Only using some protocols, not use SSLv2, SSLv3
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_certificate /etc/nginx/ssl/example/server.crt;
    ssl_certificate_key /etc/nginx/ssl/example/server.key;
    location / {
        proxy_pass http://localhost:8080; #request to webserver
        include /etc/nginx/proxy_params;
   }
}

2. Sử dụng SSL Certificate miễn phí của Let’s Encrypt

Với self-signed certificate thì chúng ta chỉ sử dụng cho nội bộ công ty. Đối với website public mà cần độ tin tưởng từ người dùng, chúng ta cần phải sử dụng certificate được cung cấp từ CA (certificate authority) nào đó. Nếu là cá nhân hoặc để thử nghiệm website sử dụng SSL, chúng ta có thể sử dụng của Let’s Encrypt.

Let’s Encrypt là nhà cung cấp SSL miễn phí. Hiện tại thì Let’s Encrypt cho phép chúng ta đăng ký certificate miễn phí 3 tháng và sau đó yêu cầu renew.

Để lấy certificate từ Let’s Encrypt chúng ta sử dụng công cụ Certbot

Step1:  Cài đặt Certbot

yum install python-certbot-nginx

Step2: Thông tin cấu hình Nginx khi chưa có SSL

Certbot có thể tự động cấu hình SSL cho Nginx, tuy nhiên điều kiện cần là nó cần xác định được cấu hình website đã tồn tại. Thông tin cấu hình cơ bản như sau cho site vnsys.vn (thay site vnsys.vn với tên site phù hợp chúng ta sử dụng)

server {
  listen 80;
  server_name vnsys.vn;
  root /var/www/vnsys;
  # Select files to be deserved by nginx
  location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|txt|srt|swf|zip|rar|html|htm|pdf)$ {
      access_log        off;
      log_not_found     off;
      expires 30d; # caching, expire after 30 days
  }
  location / {
        proxy_pass http://localhost:8080;
        include /etc/nginx/proxy_params;
  }
  ## Only allow GET and HEAD request methods
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
        return 444;
    }
}

Step3:  Lấy một SSL Certificate

Certficate sẽ được xác thực qua internet đến CA, vì vậy yêu cầu sử dụng site public, trong trường hợp này ta sẽ lấy cert cho site vnsys.vn

certbot --nginx -d vnsys.vn

Thông tin lấy cert như sau:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for vnsys.vn
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/vnsys.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/vnsys.conf

-------------------------------------------------------------------------------
Congratulations! You have successfully enabled https://vnsys.vn

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=vnsys.vn
-------------------------------------------------------------------------------

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/vnsys.vn/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/vnsys.vn/privkey.pem

Step4: Tệp tin cấu hình Nginx của site vnsys.vn sau khi lấy certificate

server {
  server_name vnsys.vn;
  root /var/www/vnsys;
  # Select files to be deserved by nginx
  location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|txt|srt|swf|zip|rar|html|htm|pdf)$ {
      access_log        off;
      log_not_found     off;
      expires 30d; # caching, expire after 30 days
  }
  location / {
        proxy_pass http://localhost:8080;
        include /etc/nginx/proxy_params;
  }
  ## Only allow GET and HEAD request methods
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
        return 444;
    }
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.local/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.local/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    if ($host = vnsys.vn) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

  listen 80;
  server_name vnsys.vn;
    return 404; # managed by Certbot
}

3.  Cấu hình Apache web server

Trong phần đầu của bài viết “https://vnsys.wordpress.com/2018/07/17/su-dung-nginx-lam-reverse-proxy-cho-apache-web-server/” cũng đã hướng dẫn cài đặt và cấu hình cơ bản Apache web server.

Sau khi cài đặt Apache với hướng dẫn cấu hình Apache như vậy, khi duyệt web và kiểm tra chúng ta thấy có lỗi mixed-content như hình dưới

mixed-content

Để giải quyết mixed-content, cần báo cho Apache là chúng ta đang sử dụng giao thức https, khi Nginx reverse proxy đang phục vụ website mà sử dụng SSL

Thêm nội dung sau vào tệp tin cấu hình chính của Apache ( /etc/httpd/conf/httpd.conf)
<IfModule mod_setenvif.c>
    SetEnvIf X-Forwarded-Proto "^https$" HTTPS
</IfModule>