คำแนะนำขั้นสูงสุดในการรักษาความปลอดภัย เสริมประสิทธิภาพ และปรับปรุงประสิทธิภาพของเว็บเซิร์ฟเวอร์ Nginx
จากสิ่งมหัศจรรย์ที่คุณเคยได้ยินเกี่ยวกับ Nginx บางทีคุณอาจตัดสินใจลองดู คุณอาจชอบมันมากจนกำลังพิจารณาแทนที่การติดตั้ง Apache ของคุณด้วย Nginx หลังจากอ่านบทความบางส่วนในหัวข้อที่เราเผยแพร่บนเว็บไซต์นี้
หากเป็นเช่นนั้น ฉันแน่ใจว่าคุณยินดียินดีกับคู่มือนี้ด้วยความยินดี เนื่องจากเราจะกล่าวถึง เคล็ดลับ 12 ประการในการเพิ่มความปลอดภัยของเซิร์ฟเวอร์ Nginx (ตั้งแต่การทำให้ Nginx อัปเดตอยู่เสมอไปจนถึง โดยใช้ TLS และเปลี่ยนเส้นทาง HTTP เป็น HTTPS) และคุณจะสังเกตว่าบางส่วนมีความคล้ายคลึงกับสิ่งที่คุณทำกับ Apache มาก
อย่าพลาด:
13 เคล็ดลับความปลอดภัยและความแข็งแกร่งของ Apache Web Server
25 เคล็ดลับ Apache Htaccess เพื่อรักษาความปลอดภัยเว็บเซิร์ฟเวอร์ Apache
สภาพแวดล้อมการทดสอบ Nginx
เราจะใช้สภาพแวดล้อมต่อไปนี้ในคู่มือนี้:
- Debian GNU/Linux 8.1 (เจสซี่)
-
ที่อยู่ IP: 192.168.0.25 (tecmintlovesnginx.com) และ 192.168.0.26 (nginxmeanspower.com) ตามที่อธิบายไว้ใน IP เสมือนจริง ส่วนเจ้าภาพได้ที่
- “วิธีตั้งค่าโฮสต์เสมือนตามชื่อและตาม IP (บล็อกเซิร์ฟเวอร์) ด้วย Nginx”
โดยคำนึงถึงสิ่งนั้นมาเริ่มกันเลย
เคล็ดลับ #1: อัปเดต Nginx ให้ทันสมัยอยู่เสมอ
ในขณะที่เขียนบทความนี้ เวอร์ชัน Nginx ล่าสุดใน CentOS (ใน EPEL) และที่เก็บ Debian คือ 1.6.3 และ 1.6.2-5แข็งแกร่ง> ตามลำดับ
อย่าพลาด: ติดตั้ง Nginx เวอร์ชันเสถียรล่าสุดจาก Repositories และ Source
แม้ว่าการติดตั้งซอฟต์แวร์จากแหล่งเก็บข้อมูลจะง่ายกว่าการรวบรวมโปรแกรมจากซอร์สโค้ด แต่ตัวเลือกสุดท้ายนี้มีข้อดีสองประการ: 1) ช่วยให้คุณสร้างโมดูลเพิ่มเติมลงใน Nginx (เช่น mod_security) และ 2) จะมีเวอร์ชันที่ใหม่กว่าเสมอ กว่าที่เก็บ (1.9.9 ณ วันนี้) บันทึกประจำรุ่นจะมีอยู่ในเว็บไซต์ Nginx เสมอ
อย่าพลาด:
ปกป้อง Apache จากการโจมตีแบบ Brute Force และ DDoS โดยใช้ Mod_Security และ Mod_Evasive
เคล็ดลับ #2: ลบโมดูลที่ไม่จำเป็นใน Nginx
หากต้องการลบโมดูลออกจาก Nginx อย่างชัดเจนขณะติดตั้งจากแหล่งที่มา ให้ทำดังนี้
./configure --without-module1 --without-module2 --without-module3
ตัวอย่างเช่น:
./configure --without-http_dav_module --withouthttp_spdy_module
ดังที่คุณอาจเดาได้ การลบโมดูลออกจากการติดตั้ง Nginx ก่อนหน้าจากแหล่งที่มาจำเป็นต้องทำการคอมไพล์อีกครั้ง
คำเตือน: คำสั่งการกำหนดค่ามีให้โดยโมดูล ตรวจสอบให้แน่ใจว่าคุณไม่ได้ปิดการใช้งานโมดูลที่มีคำสั่งที่คุณต้องการในเร็วๆ นี้! คุณควรตรวจสอบเอกสาร nginx เพื่อดูรายการคำสั่งที่มีอยู่ในแต่ละโมดูลก่อนตัดสินใจปิดการใช้งานโมดูล
เคล็ดลับ #3: ปิดใช้งานคำสั่ง server_tokens ใน Nginx
คำสั่ง server_tokens
บอกให้ Nginx แสดงเวอร์ชันปัจจุบันบนหน้าข้อผิดพลาด สิ่งนี้ไม่เป็นที่พึงปรารถนาเนื่องจากคุณไม่ต้องการเปิดเผยข้อมูลนั้นกับโลกเพื่อป้องกันการโจมตีที่เว็บเซิร์ฟเวอร์ของคุณที่เกิดจากช่องโหว่ที่ทราบในเวอร์ชันนั้น
หากต้องการปิดการใช้งานคำสั่ง server_tokens
ให้ตั้งค่าเป็นปิดภายในบล็อกเซิร์ฟเวอร์:
server {
listen 192.168.0.25:80;
server_tokens off;
server_name tecmintlovesnginx.com www.tecmintlovesnginx.com;
access_log /var/www/logs/tecmintlovesnginx.access.log;
error_log /var/www/logs/tecmintlovesnginx.error.log error;
root /var/www/tecmintlovesnginx.com/public_html;
index index.html index.htm;
}
รีสตาร์ท nginx และตรวจสอบการเปลี่ยนแปลง:
เคล็ดลับ #4: ปฏิเสธตัวแทนผู้ใช้ HTTP ใน Nginx
ตัวแทนผู้ใช้ HTTP คือซอฟต์แวร์ที่ใช้สำหรับการเจรจาเนื้อหากับเว็บเซิร์ฟเวอร์ นอกจากนี้ยังรวมถึงบอทและโปรแกรมรวบรวมข้อมูลมัลแวร์ที่อาจส่งผลกระทบต่อประสิทธิภาพของเว็บเซิร์ฟเวอร์ของคุณโดยการสิ้นเปลืองทรัพยากรระบบ
เพื่อให้ง่ายต่อการรักษารายการตัวแทนผู้ใช้ที่ไม่ต้องการ ให้สร้างไฟล์ (เช่น /etc/nginx/blockuseragents.rules
) โดยมีเนื้อหาดังต่อไปนี้:
map $http_user_agent $blockedagent {
default 0;
~*malicious 1;
~*bot 1;
~*backdoor 1;
~*crawler 1;
~*bandit 1;
}
ถัดไป วางบรรทัดต่อไปนี้ก่อนคำนิยามบล็อกเซิร์ฟเวอร์:
include /etc/nginx/blockuseragents.rules;
และคำสั่ง if เพื่อส่งคืนการตอบสนอง 403 หากสตริงตัวแทนผู้ใช้อยู่ในบัญชีดำที่กำหนดไว้ด้านบน:
รีสตาร์ท nginx และตัวแทนผู้ใช้ทั้งหมดที่มีสตริงตรงกับข้างต้นจะถูกบล็อกไม่ให้เข้าถึงเว็บเซิร์ฟเวอร์ของคุณ แทนที่ 192.168.0.25 ด้วย IP ของเซิร์ฟเวอร์ของคุณ และเลือกสตริงอื่นสำหรับสวิตช์ --user-agent
ของ wget:
wget http://192.168.0.25/index.html
wget --user-agent "I am a bandit haha" http://192.168.0.25/index.html
เคล็ดลับ #5: ปิดการใช้งานวิธี HTTP ที่ไม่ต้องการใน Nginx
หรือที่รู้จักในชื่อคำกริยา วิธีการ HTTP ระบุการดำเนินการที่ต้องการกับทรัพยากรที่ให้บริการโดย Nginx สำหรับเว็บไซต์และแอปพลิเคชันทั่วไป คุณควรอนุญาตเฉพาะ GET, POST และ HEAD และปิดการใช้งานอื่นๆ ทั้งหมด
โดยวางบรรทัดต่อไปนี้ภายในบล็อกเซิร์ฟเวอร์ การตอบสนอง HTTP 444 หมายถึงการตอบสนองที่ว่างเปล่า และมักใช้ใน Nginx เพื่อหลอกการโจมตีของมัลแวร์:
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}
ในการทดสอบ ให้ใช้ curl เพื่อส่งคำขอ DELETE และเปรียบเทียบผลลัพธ์กับเมื่อคุณส่ง GET ปกติ:
curl -X DELETE http://192.168.0.25/index.html
curl -X POST http://192.168.0.25/index.html
เคล็ดลับ #6: ตั้งค่าขีดจำกัดขนาดบัฟเฟอร์ใน Nginx
เพื่อป้องกันการโจมตีบัฟเฟอร์ล้นต่อเว็บเซิร์ฟเวอร์ Nginx ของคุณ ให้ตั้งค่าคำสั่งต่อไปนี้ในไฟล์แยกต่างหาก (สร้างไฟล์ใหม่ชื่อ /etc/nginx/conf.d/buffer.conf
เป็นต้น):
client_body_buffer_size 1k;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
คำสั่งข้างต้นจะช่วยให้มั่นใจได้ว่าคำขอที่ส่งไปยังเว็บเซิร์ฟเวอร์ของคุณจะไม่ทำให้เกิดบัฟเฟอร์ล้นในระบบของคุณ โปรดดูเอกสารอีกครั้งเพื่อดูรายละเอียดเพิ่มเติมว่าแต่ละเอกสารทำอะไรได้บ้าง
จากนั้นเพิ่มคำสั่งรวมในไฟล์กำหนดค่า:
include /etc/nginx/conf.d/*.conf;
เคล็ดลับ #7: จำกัดจำนวนการเชื่อมต่อด้วย IP ใน Nginx
หากต้องการจำกัดการเชื่อมต่อด้วย IP ให้ใช้คำสั่ง limit_conn_zone
(ในบริบท http หรืออย่างน้อยก็อยู่นอกบล็อกเซิร์ฟเวอร์) และคำสั่ง Limit_conn (ใน http, บล็อกเซิร์ฟเวอร์ หรือบริบทตำแหน่ง)
อย่างไรก็ตาม โปรดทราบว่าไม่ได้นับการเชื่อมต่อทั้งหมด - แต่เฉพาะการเชื่อมต่อที่มีคำขอที่ประมวลผลโดยเซิร์ฟเวอร์และส่วนหัวคำขอทั้งหมดเท่านั้นที่จะถูกอ่าน
ตัวอย่างเช่น ลองตั้งค่าจำนวนการเชื่อมต่อสูงสุดเป็น 1
(ใช่ มันเป็นการพูดเกินจริง แต่จะทำงานได้ดีในกรณีนี้) ในโซนชื่อ addr (คุณสามารถตั้งค่านี้เป็นอะไรก็ได้ ชื่อที่คุณต้องการ):
limit_conn_zone $binary_remote_addr zone=addr:5m;
limit_conn addr 1;
การทดสอบง่ายๆ ด้วย Apache Benchmark (ดำเนินการโหลด Nginx) โดยที่การเชื่อมต่อทั้งหมด 10
ถูกสร้างขึ้นด้วยคำขอพร้อมกัน 2
จะช่วยให้เราแสดงให้เห็นถึงประเด็นของเรา:
ab -n 10 -c 2 http://192.168.0.25/index.html
ดูเคล็ดลับถัดไปสำหรับรายละเอียดเพิ่มเติม
เคล็ดลับ #8: ตั้งค่าบันทึกการตรวจสอบสำหรับ Nginx
เมื่อคุณดำเนินการทดสอบที่อธิบายไว้ในเคล็ดลับก่อนหน้านี้แล้ว ให้ตรวจสอบบันทึกข้อผิดพลาดที่กำหนดไว้สำหรับบล็อกเซิร์ฟเวอร์:
คุณอาจต้องการใช้ grep เพื่อกรองบันทึกสำหรับคำขอที่ล้มเหลวซึ่งทำกับโซน เพิ่มr ที่กำหนดไว้ใน เคล็ดลับ #7:
grep addr /var/www/logs/tecmintlovesnginx.error.log --color=auto
ในทำนองเดียวกัน คุณสามารถกรองบันทึกการเข้าถึงเพื่อดูข้อมูลที่น่าสนใจ เช่น:
- ไอพีไคลเอ็นต์
- ประเภทเบราว์เซอร์
- ประเภทคำขอ HTTP
- ทรัพยากรที่ร้องขอ
- บล็อกเซิร์ฟเวอร์ที่ตอบรับคำขอ (มีประโยชน์หากโฮสต์เสมือนหลายโฮสต์บันทึกลงในไฟล์เดียวกัน)
และดำเนินการตามความเหมาะสมหากคุณตรวจพบกิจกรรมที่ผิดปกติหรือไม่พึงประสงค์
เคล็ดลับ #9: ป้องกันภาพ Hotlinking ใน Nginx
ฮอตลิงก์รูปภาพเกิดขึ้นเมื่อมีคนแสดงรูปภาพที่โฮสต์อยู่ในไซต์อื่นในเว็บไซต์อื่น สิ่งนี้ทำให้การใช้แบนด์วิดท์ของคุณเพิ่มขึ้น (ซึ่งคุณจ่าย) ในขณะที่บุคคลอื่นแสดงภาพอย่างมีความสุขราวกับว่ามันเป็นทรัพย์สินของเขาหรือเธอ กล่าวอีกนัยหนึ่ง มันเป็นการสูญเสียสองเท่าสำหรับคุณ
ตัวอย่างเช่น สมมติว่าคุณมีไดเร็กทอรีย่อยชื่อ img
ภายในบล็อกเซิร์ฟเวอร์ของคุณ ซึ่งเป็นที่ที่คุณจัดเก็บรูปภาพทั้งหมดที่ใช้ในโฮสต์เสมือนนั้น เพื่อป้องกันไม่ให้ไซต์อื่นใช้รูปภาพของคุณ คุณจะต้องแทรกบล็อกตำแหน่งต่อไปนี้ภายในคำจำกัดความโฮสต์เสมือนของคุณ:
location /img/ {
valid_referers none blocked 192.168.0.25;
if ($invalid_referer) {
return 403;
}
}
จากนั้นแก้ไขไฟล์ index.html
ในแต่ละโฮสต์เสมือนดังนี้:
192.168.0.26
192.168.0.25
<!DOCTYPE html>
<html>
<head>
<meta charset=”utf-8″>
<title>Nginx means power</title>
</head>
<body>
<h1>Nginx means power!</h1>
<img src=”http://192.168.0.25/img/nginx.png” />
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset=”utf-8″>
<title>Tecmint loves Nginx</title>
</head>
<body>
<h1>Tecmint loves Nginx!</h1>
<img src=”img/nginx.png” />
</body>
</html>
ตอนนี้เรียกดูแต่ละไซต์ และอย่างที่คุณเห็น รูปภาพจะแสดงอย่างถูกต้องใน 192.168.0.25 แต่ถูกแทนที่ด้วยการตอบสนอง 403 ใน 192.168.0.26 แข็งแกร่ง>:
โปรดทราบว่าเคล็ดลับนี้ขึ้นอยู่กับเบราว์เซอร์ระยะไกลที่ส่งฟิลด์ผู้อ้างอิง
เคล็ดลับ #10: ปิดการใช้งาน SSL และเปิดใช้งาน TLS ใน Nginx เท่านั้น
เมื่อเป็นไปได้ ให้ทำทุกอย่างเพื่อหลีกเลี่ยง SSL ในเวอร์ชันใดๆ และใช้ TLS แทน ssl_protocols
ต่อไปนี้ควรอยู่ในเซิร์ฟเวอร์หรือบริบท http ในไฟล์โฮสต์เสมือนของคุณ หรือเป็นไฟล์แยกต่างหากผ่านคำสั่งรวม (บางคนใช้ไฟล์ชื่อ ssl.conf
แต่ทั้งหมดขึ้นอยู่กับคุณ):
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ตัวอย่างเช่น:
เคล็ดลับ #11: สร้างใบรับรองใน Nginx
ก่อนอื่น สร้างคีย์และใบรับรอง คุณสามารถใช้การเข้ารหัสประเภทอื่นได้ตามต้องการหากคุณต้องการ:
openssl genrsa -aes256 -out tecmintlovesnginx.key 1024
openssl req -new -key tecmintlovesnginx.key -out tecmintlovesnginx.csr
cp tecmintlovesnginx.key tecmintlovesnginx.key.org
openssl rsa -in tecmintlovesnginx.key.org -out tecmintlovesnginx.key
openssl x509 -req -days 365 -in tecmintlovesnginx.csr -signkey tecmintlovesnginx.key -out tecmintlovesnginx.crt
จากนั้นเพิ่มบรรทัดต่อไปนี้ภายในบล็อกเซิร์ฟเวอร์ที่แยกจากกันเพื่อเตรียมพร้อมสำหรับเคล็ดลับถัดไป (การเปลี่ยนเส้นทาง http --> https
) และย้ายคำสั่งที่เกี่ยวข้องกับ SSL ไปยังบล็อกใหม่ด้วย:
server {
listen 192.168.0.25:443 ssl;
server_tokens off;
server_name tecmintlovesnginx.com www.tecmintlovesnginx.com;
root /var/www/tecmintlovesnginx.com/public_html;
ssl_certificate /etc/nginx/sites-enabled/certs/tecmintlovesnginx.crt;
ssl_certificate_key /etc/nginx/sites-enabled/certs/tecmintlovesnginx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
}
ในเคล็ดลับถัดไป เราจะตรวจสอบว่าขณะนี้ไซต์ของเราใช้ใบรับรองที่ลงนามด้วยตนเองและ TLS อย่างไร
เคล็ดลับ #12: เปลี่ยนเส้นทางการรับส่งข้อมูล HTTP ไปยัง HTTPS ใน Nginx
เพิ่มบรรทัดต่อไปนี้ในบล็อกเซิร์ฟเวอร์แรก:
return 301 https://$server_name$request_uri;
คำสั่งข้างต้นจะส่งกลับการตอบสนอง 301 (ย้ายอย่างถาวร) ซึ่งใช้สำหรับการเปลี่ยนเส้นทาง URL แบบถาวรเมื่อใดก็ตามที่มีการร้องขอไปยังพอร์ต 80 ของโฮสต์เสมือนของคุณ และจะเปลี่ยนเส้นทางคำขอไปยังบล็อกเซิร์ฟเวอร์ที่เรา เพิ่มในเคล็ดลับก่อนหน้า
รูปภาพด้านล่างแสดงการเปลี่ยนเส้นทางและยืนยันความจริงที่ว่าเราใช้ TLS 1.2 และ AES-256 สำหรับการเข้ารหัส:
สรุป
ในบทความนี้ เราได้แบ่งปันเคล็ดลับบางประการในการรักษาความปลอดภัยเว็บเซิร์ฟเวอร์ Nginx ของคุณ เรายินดีรับฟังความคิดเห็นของคุณ และหากคุณมีเคล็ดลับอื่นๆ ที่ต้องการแชร์กับคนอื่นๆ ในชุมชน โปรดแจ้งให้เราทราบโดยส่งข้อความถึงเราโดยใช้แบบฟอร์มแสดงความคิดเห็นด้านล่าง