Thiết lập máy chủ Reverse Proxy trên Linux Image Thiết lập máy chủ Reverse Proxy trên Linux

Bài viết này sẽ giới thiệu với các bạn về cách thiết lập máy chủ Reverse Proxy trên hệ điều hành Linux. Qua bài viết này giúp chúng ta có thể tự học Linux một cách dễ dàng hơn.

1. Giới thiệu reverse proxy

Reserse proxy có vai trò là cầu nối của client và server. Nó sẽ thực hiện nhận yêu cầu từ client và chuyển lên server và nhận câu trả lời từ server chuyển ngược lại client.

Ưu điểm của Reverse Proxy:

  • Đơn giản trong việc triển khai.
  • Tính bảo mật cao giúp ngăn chặn tấn công web server như DDoS và DoS.
  • Reverse proxy giúp cân bằng tải giữa nhiều server.
  • Reverse proxy cho các giao thức đa dạng: HTTP, HTTPS, TCP, UDP, SMTP, IMAP, và POP3.
  • Nó giúp tối ưu nội dung và nén chúng để giảm thời gian tải.
  • Hạn chế quyền truy cập từ các vị trí có thể là mục tiêu của các cuộc tấn công web server.
  • Làm giảm hiệu quả của các cuộc tấn công DDOS bằng cách giới hạn số lượng kết nối và tốc độ tải xuống trên mỗi địa chỉ IP.

2. Giới thiệu về nginx

Giới thiệu về nginx

Nginx là một HTTP web server mã nguồn mở phổ biến, mạnh mẽ và hiệu suất cao có thể mở rộng. Nó cũng có thể được sử dụng như một bộ cân bằng tải, mail proxy và HTTP cache do tốc độ, tính ổn định, cấu hình dễ dàng và sử dụng tài nguyên thấp.

3. Cài đặt nginx và thiết lập reverse proxy trên CentOS 8

3.1. Cài đặt nginx

👉 Bước 1: Cài đặt nginx

Để có thể cài đặt nginx và các gọi cần thiết chúng ta sử dụng lệnh yum để cài đặt:

[root@blogd-net-lab01 ~]# yum install nginx
Last metadata expiration check: 0:00:29 ago on Tue 03 Mar 2020 01:39:34 PM +07.
Dependencies resolved.
=============================================================================================================================
 Package                             Architecture   Version                                          Repository         Size
=============================================================================================================================
Installing:
 nginx                               x86_64         1:1.14.1-9.module_el8.0.0+184+e34fea82           AppStream         570 k

Các file configuration của nginx server:

  • Danh mục nginx config: /etc/nginx
  • File config của nginx: /etc/nginx/nginx.conf
  • Danh mục document root: /usr/share/nginx/html

Chúng ta có thể chỉnh sữa file config của nginx bằng cách sử dụng trình chỉnh sữa văn bản vi:

[root@blogd-net-lab01 ~]# vi /etc/nginx/nginx.conf
For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
...

Sau khi cài đặt thành công chúng ta khởi động nginx bằng lệnh bên dưới:

[root@blogd-net-lab01 ~]# systemctl start nginx

Chúng ta thực hiện kích hoạt nginx khởi động cùng lúc với hệ thống bằng lệnh bên dưới:

[root@blogd-net-lab01 ~]# systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.

Kiểm tra trạng thái của nginx bằng lệnh sau:

[root@blogd-net-lab01 ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2020-03-03 13:41:35 +07; 43s ago
 Main PID: 6220 (nginx)
    Tasks: 3 (limit: 11348)
   Memory: 8.8M
   CGroup: /system.slice/nginx.service
           ├─6220 nginx: master process /usr/sbin/nginx
           ├─6221 nginx: worker process
           └─6222 nginx: worker process

Mar 03 13:41:35 blogd-net-lab01 systemd[1]: Starting The nginx HTTP and reverse proxy server...
Mar 03 13:41:35 blogd-net-lab01 nginx[6217]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Mar 03 13:41:35 blogd-net-lab01 nginx[6217]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Mar 03 13:41:35 blogd-net-lab01 systemd[1]: Started The nginx HTTP and reverse proxy server.

👉 Bước 2: Mở port 80 và port 443 sử dụng firewall-cmd

Kiểm tra các port đã được mở thực thi lệnh sau:

[root@blogd-net-lab01 ~]# firewall-cmd --list-services --zone=public
cockpit dhcpv6-client ssh

Sau đó chúng ta lần lượt mở port 80 (http) và port 443 (https):

[root@blogd-net-lab01 ~]# firewall-cmd --permanent --zone=public --add-service=http
success
[root@blogd-net-lab01 ~]# firewall-cmd --permanent --zone=public --add-service=https
success

Tiếp theo chúng ta cần phải reload lại firewall-cmd bằng lệnh sau:

[root@blogd-net-lab01 ~]# firewall-cmd --reload
success

Kiểm tra lại xem port http và https đã được mở chưa thực thi lệnh bên dưới:

[root@blogd-net-lab01 ~]# firewall-cmd --list-services --zone=public
cockpit dhcpv6-client http https ssh

Bây giờ chúng ta có thể xác minh Nginx web server đang hoạt động bằng cách truy cập địa chỉ IP public của máy chủ trong trình duyệt web của chúng ta. Nếu không biết địa chỉ IP của máy chủ chúng ta chạy lệnh ip add để xem:

[root@blogd-net-lab01 ~]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:01:80:d6 brd ff:ff:ff:ff:ff:ff
    inet 192.168.21.201/24 brd 192.168.21.255 scope global dynamic noprefixroute ens33
       valid_lft 1116sec preferred_lft 1116sec
    inet6 fe80::855d:6265:4496:fe93/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

Test nginx

Ngoài ra chúng ta có thể thực hiện test xem nginx có hoạt động không bằng cách sử dụng lệnh curl:

[root@blogd-net-lab01 ~]# curl -I http://192.168.21.198
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Tue, 03 Mar 2020 07:53:46 GMT
Content-Type: text/html
Content-Length: 4057
Last-Modified: Mon, 07 Oct 2019 21:16:24 GMT
Connection: keep-alive
ETag: "5d9bab28-fd9"
Accept-Ranges: bytes

Sử dụng lệnh curl lấy nội dung của URL và hiển thị kết quả như sau:

[root@blogd-net-lab01 ~]# curl http://192.168.21.198
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
        <title>Test Page for the Nginx HTTP Server on Red Hat Enterprise Linux</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <style type="text/css">
            /*<![CDATA[*/
            body {
                background-color: #fff;
                color: #000;
                font-size: 0.9em;
                font-family: sans-serif,helvetica;
                margin: 0;
                padding: 0;
            }
            :link {
                color: #c00;
            }
            :visited {
                color: #c00;
            }
            a:hover {
                color: #f50;
            }
...

Như vậy là chúng ta đã cài đặt thành công nginx trên CentOS 8.

Giả sử mục đích là khi lưu lượng truy cập đến lớn. Chúng ta muốn thiết lập một proxy ngược để chuyển hướng lưu lượng truy cập từ vị trí mặc định sang một vị trí khác. Trong bài viết này, chúng ta sử dụng Python HTTP server để minh họa về việc muốn chuyển hướng lưu lượng truy cập.

Đầu tiên, tạo một trang HTML đơn giản trong một thư mục:

[root@blogd-net-lab01 ~]# mkdir fakeserver
[root@blogd-net-lab01 ~]# cd fakeserver
[root@blogd-net-lab01 fakeserver]# echo "<html><head><title>Python3 http.server</title></head> \
> <body><p>Test website blogd.net</p> \
> </body></html>" > index.html

Tại thư mục fakeserver chúng ta thực hiện khởi động Python HTTP server bằng cách thực thi lệnh sau:

[root@blogd-net-lab01 fakeserver]# python3 -m http.server 8888

Mở trình duyệt và truy cập localhost:8888 để mở fakeserver của chúng ta:

Fakeserver

3.2. Thiết lập reverse proxy

Các proxy tiêu chuẩn proxy_pass thì cung cấp chức năng nginx với một reverse proxy. Để có thể sử dụng proxy_pass chúng ta cần phải biết nơi chúng ta muốn hướng lưu lượng truy cập. Trong bài viết này thì điểm đến là fakeserver Python3 HTTP server (nằm ở cổng 8888), chứ không phải trang mặc định NGINX.

Đối với web server được xác định trong file /etc/nginx/nginx.conf. Chúng ta xác định một location để đặt URI cụ thể. Trong trường hợp này, hãy đặt thư mục của server root và sử dụng chức năng proxy_pass để tạo thư mục gốc của web server thành proxy cho web Python tạm thời của chúng ta.

Tệp cấu hình NGINX mặc định /etc/nginx/nginx.conf để đảm bảo an toàn trước khi thực hiện các thay đổi chúng ta có thể di chuyển hoặc nó sang một vị trí khác bằng cách sử dụng lệnh mv để di chuyển hoặc lệnh cp để copy.

[root@blogd-net-lab01 ~]# cp /etc/nginx/nginx.conf /mnt/

Thực hiện chỉnh sữa file cấu hình NGINX mặc định bằng cách sử dụng trình soạn thảo vi như sau:

[root@blogd-net-lab01 ~]# cat /etc/nginx/nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location / {
	    proxy_pass http://localhost:8888/;
            index  index.html index.htm;
            } # end location
        } # end server
    } # end http

Trong thực tế thì giá trị server_name chính là tên miền của chúng ta. Còn proxy_pass là một vị trí mà chúng ta muốn chuyển hướng lưu lượng.

Kiểm tra file cấu hình reverse proxy nếu không báo lỗi chúng ta thực hiện restart nginx bằng cách thực thi lệnh sau:

[root@blogd-net-lab01 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

File cấu hình của chúng ta không có lỗi, trong một số trường hợp nếu thực thi lệnh trên báo lỗi thì chúng ta cần phải kiểm tra lại file cấu hình trước khi khởi động lại nginx:

[root@blogd-net-lab01 ~]# systemctl restart nginx

Chúng ta có thể thử các tùy chọn của nginx khác nhau nhưng khi đã thử nghiệm hoàn thành thì chắc chắn rằng SELinux HTTP server Boolean trở về 0:

[root@blogd-net-lab01 ~]# setsebool -P httpd_can_network_connect 0

4. Nhận địa chỉ IP real của client

Trong một số trường hợp, trình duyệt của client không kết nối trực tiếp với máy chủ để truy cập website vì có sử dụng CDN, WAF hoặc Anti-DDoS Pro ở giữa. Ví dụ về kiến ​​trúc phổ biến bên trên: Client -> CDN/WAF/Anti-DDoS Pro -> Origin server. Teong phần này chúng ta sẽ tìm hiểu làm thế nào server có thể có được địa chỉ IP real của client yêu cầu ban đầu đi qua nhiều acceleration.

Khi chuyển tiếp yêu cầu của người dùng đến máy chủ tiếp theo, máy chủ proxy mở và sẽ thêm bản ghi X-Forwarded-For vào HTTP header. X-Forwarded-For được sử dụng để ghi lại địa chỉ IP real của client có định dạng X-Forwarded-For: user IP. Nếu có nhiều Proxy server liên quan đến quá trình yêu cầu, bản ghi X-Forwarded-For sẽ có định dạng sau: X-Forwarded-For: user's IP address, Proxy 1-IP address, Proxy 2-IP address, Proxy 3-IP address....

Ví dụ 1: Thêm địa chỉ WAF IP vào file nginx configuration sử dụng trình soạn thảo vi chỉnh sửa file:

[root@blogd-net-lab01 ~]# vi /etc/nginx/nginx.conf

Sau đó chúng ta thực hiện thêm và sau location / {} với cú pháp như sau:

set_real_ip_from ip_range1;
set_real_ip_from ip_range2;
...
set_real_ip_from ip_rangex;
real_ip_header    X-Forwarded-For;

Ví dụ 2: Cách sữa đổi log_format

Log_fomat thường tồn tại dưới HTTP configuration trong file /etc/nginx/nginx.conf. Thêm x-forwarded-for trong log_format để thay thế remote-adddress. Sau khi sửa đổi, log_format như sau:

log_format  main  '$http_x_forwarded_for - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" ';

Sau khi sữa đổi chúng ta thực hiện reload lại nginx thực thi lệnh sau để server có thể ghi lại địa chỉ IP của client vào file X-Forwarded-For:

[root@blogd-net-lab01 ~]# nginx -s reload

Ví dụ 3: Khi chúng ta muốn lấy địa chỉ IP real của client đối với Linux chúng ta cần thực hiện các bước sau:

Đầu tiên chúng ta thực thi cách lệnh sau để cài đặt mod_rpaf:

[root@blogd-net-lab01 ~]# wget http://stderr.net/apache/rpaf/download/mod_rpaf-0.6.tar.gz
[root@blogd-net-lab01 ~]# tar zxvf mod_rpaf-0.6.tar.gz
[root@blogd-net-lab01 ~]# cd mod_rpaf-0.6
[root@blogd-net-lab01 ~]# /alidata/server/httpd/bin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c

Chỉnh sửa tệp cấu hình Apache /alidata/server/httpd/conf/httpd.conf để thêm nội dung sau vào cuối tệp:

LoadModule rpaf_module modules/mod_rpaf-2.0.so
RPAFenable On
RPAFsethostname On
RPAFproxy_ips ip addresses
RPAFheader X-Forwarded-For

Lưu ý tệp cấu hình:

  • RPAFenable: Kích hoạt chức năng rpaf.
  • RPAFproxy_ips: Ip của server reverse proxy đến Apache backend, nếu chúng ta cài đặt reverse proxy trên cùng 1 server/vps thì IP này chính là IP public/local của server hiện tại.
  • RPAFheader: Phụ thuộc vào Header HTTP mà chúng ta set ở phía reverse proxy nhằm cung cấp thông tin các IP thật đã đi qua proxy, thường là header X-Forwarded-For.

Chạy lệnh sau để khởi động lại Apache và đưa cấu hình vào hiệu lực.

[root@blogd-net-lab01 ~]# /alidata/server/httpd/bin/apachectl restart

5. Lời kết

Qua bài trên, giúp cho chúng ta biết cách thiết lập máy chủ Reverse Proxy dùng nginx trên CentOS 8 của hệ điều hành Linux. Từ đây giúp chúng ta có thể hạn chế dược các cuộc tấn công vào web server của chúng ta. Bảo vệ web server an toàn hơn.