ค้นหาเว็บไซต์

คำแนะนำขั้นสูงสุดในการรักษาความปลอดภัย เสริมประสิทธิภาพ และปรับปรุงประสิทธิภาพของเว็บเซิร์ฟเวอร์ Nginx


จากสิ่งมหัศจรรย์ที่คุณเคยได้ยินเกี่ยวกับ Nginx บางทีคุณอาจตัดสินใจลองดู คุณอาจชอบมันมากจนกำลังพิจารณาแทนที่การติดตั้ง Apache ของคุณด้วย Nginx หลังจากอ่านบทความบางส่วนในหัวข้อที่เราเผยแพร่บนเว็บไซต์นี้

หากเป็นเช่นนั้น ฉันแน่ใจว่าคุณยินดียินดีกับคู่มือนี้ด้วยความยินดี เนื่องจากเราจะกล่าวถึง เคล็ดลับ 12 ประการในการเพิ่มความปลอดภัยของเซิร์ฟเวอร์ Nginx (ตั้งแต่การทำให้ Nginx อัปเดตอยู่เสมอไปจนถึง โดยใช้ TLS และเปลี่ยนเส้นทาง HTTP เป็น HTTPS) และคุณจะสังเกตว่าบางส่วนมีความคล้ายคลึงกับสิ่งที่คุณทำกับ Apache มาก

อย่าพลาด:

13 เคล็ดลับความปลอดภัยและความแข็งแกร่งของ Apache Web Server

25 เคล็ดลับ Apache Htaccess เพื่อรักษาความปลอดภัยเว็บเซิร์ฟเวอร์ Apache

สภาพแวดล้อมการทดสอบ Nginx

เราจะใช้สภาพแวดล้อมต่อไปนี้ในคู่มือนี้:

  1. Debian GNU/Linux 8.1 (เจสซี่)
  2. ที่อยู่ IP: 192.168.0.25 (tecmintlovesnginx.com) และ 192.168.0.26 (nginxmeanspower.com) ตามที่อธิบายไว้ใน IP เสมือนจริง ส่วนเจ้าภาพได้ที่

    1. “วิธีตั้งค่าโฮสต์เสมือนตามชื่อและตาม IP (บล็อกเซิร์ฟเวอร์) ด้วย Nginx”
  3. เวอร์ชัน Nginx: nginx/1.6.2
  4. เพื่อความสะดวกของคุณ นี่คือไฟล์การกำหนดค่าขั้นสุดท้าย (ลิงก์ Pastebin)

โดยคำนึงถึงสิ่งนั้นมาเริ่มกันเลย

เคล็ดลับ #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

ในทำนองเดียวกัน คุณสามารถกรองบันทึกการเข้าถึงเพื่อดูข้อมูลที่น่าสนใจ เช่น:

  1. ไอพีไคลเอ็นต์
  2. ประเภทเบราว์เซอร์
  3. ประเภทคำขอ HTTP
  4. ทรัพยากรที่ร้องขอ
  5. บล็อกเซิร์ฟเวอร์ที่ตอบรับคำขอ (มีประโยชน์หากโฮสต์เสมือนหลายโฮสต์บันทึกลงในไฟล์เดียวกัน)

และดำเนินการตามความเหมาะสมหากคุณตรวจพบกิจกรรมที่ผิดปกติหรือไม่พึงประสงค์

เคล็ดลับ #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 ของคุณ เรายินดีรับฟังความคิดเห็นของคุณ และหากคุณมีเคล็ดลับอื่นๆ ที่ต้องการแชร์กับคนอื่นๆ ในชุมชน โปรดแจ้งให้เราทราบโดยส่งข้อความถึงเราโดยใช้แบบฟอร์มแสดงความคิดเห็นด้านล่าง