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
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
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:
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.