วันอังคารที่ 1 ตุลาคม พ.ศ. 2562

แนวทางการใช้ proxy ของ NGINX

แนวทางการใช้ proxy ของ NGINX
บันทึกที่เขียนนี้เป็น ส่วนที่ศึกษาจากหนังสือ Master Nginx ซึ่งนำส่วนที่สนใจมาเขียนตามความเข้าใจเท่านั้น จะรวบรวมข้อมูลทั้งหมดเพื่อทำความเข้าใจก่อน จากนั้นจะลองทำการทดสอบตามที่ได้อ่าน และจะใช้ curl ในการทดสอบ
ประโยชน์ของการใช้ NGINX ทำเป็น Proxy
  1. เพื่อเปลี่ยนเส้นทาง
location /uri { proxy_pass http://localhost:8080/newuri; }
ยกตัวอย่างในกรณี สมมติ สร้าง location /web/admin ขึ้นมา แต่ต้องการให้ไปยัง /web/loginadmin จึงทำการ config ไว้ที่ไฟล์ login.conf ดังนี้

ทำการทดสอบ script ดูว่าใช้งานได้หรือไม่

ทำการ reload service nginx

ทดสอบด้วย curl ใช้ curl -I http://localhost:8080/web/admin

2018/08/05 10:08:23 [error] 2236#2236: *143613 open() "/etc/nginx/html/web/loginadmin" failed (2: No such file or directory), client: 192.168.10.2, server: , request: "GET /web/loginadmin HTTP/1.0", host: "192.168.10.2:8080"<html><head><title>404 Not Found</title></head><body bgcolor="white"><center><h1>404 Not Found</h1></center><hr><center>nginx/1.15.1</center></body></html>
มันพยายามเปลี่ยนไปเป็น /web/loginadmin แต่มันฟ้องว่า ไม่มีไฟล์นี้อยู่ เดี๋ยวลองทำให้มันเห็นจริงๆ ดู โดยเข้าไปเพิ่ม virturl server ขึ้นอีก ชุดนึง







ลองทดสอบ




คราวนี้ลองเปิดผ่านหน้าเว็บดู แต่พอดีว่า docker ที่ใช้กับ loadbalance ที่เคยทำเอาไว้ในบันทึกก่อนๆ นั้นไม่ได้เปิด port 8080 ให้เข้าไว้ดังนั้นจึงต้อง listen 80 ให้สามารถเข้าถึงแล้ว proxy ไปยัง 8080 ตามที่ต้องการ








ตามนี้

 
การเปลี่ยน URI จะมีข้อยกเว้นอยู่ 2 ข้อด้วยกัน คือ
ข้อยกเว้นที่ 1
ในกรณีที่ใช้ regex ตัวอย่างข้างต้นที่ผ่านมาไม่สามารถทำได้ ตามกฏ อย่างเช่น ถ้าต้องการจะเขียนตาม script ด้านล่างนี้
location ~ ^/local { proxy_pass http://localhost:8080/foreign; }
ก็จะปรากฏข้อความตามนี้

2018/08/05 11:01:55 [emerg] 3107#3107: "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /etc/nginx/conf.d/Login.conf:11nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /etc/nginx/conf.d/Login.conf:11nginx: configuration file /etc/nginx/nginx.conf test failed

ข้อยกเว้นที่ 2
ถ้าใช้คำสั่ง rewrite ใน context ของ location นั้นจะเป็นการเปลี่ยน uri ซึ่ง nginx ก็เอาไปประมวลผลตามปกติ ตามที่มี request เข้ามา แต่จะไม่ได้เปลี่ยนแปลง uri ตามที่ rewrite เอาไว้ ลองดูตามตัวอย่างด้านล่าง มันจะส่ง rewrite ไปยัง upstream แล้ว จริงๆควรจะเปลี่ยนหน้าไปตาม $1
location / { rewrite /(.*)$ /index.php?page=$1 break; proxy_pass http://localhost:8080/index; }













ลองดูผลลัพท์กัน

หมายเหตุ : break ใช้สำหรับต้องการหยุดหลังจากที่ป้อน URL นั้นเข้ามาทันที
 
คำสั่งต่างๆ ที่ใช้ใน module proxy
  • proxy_connect_timeout : nginx เชื่อมต่อไปยัง upstream server จนกว่าเวลาจะหมด
  • proxy_cookie_domain : ค่าที่ใส่จะแทนที่ domain จากคำสั่ง Set-cookie ที่ส่งไปหาคำสั่ง upstream server โดยที่ domain จะถูกเปลี่ยนเป็น string หรือตัวแปรที่ได้จาก parameter และ regex
  • proxy_cookie_path : เป็นคำสั่งสำหรับเอา path ของ set-cookie จาก upstream ซึ่ง path จะเป็น string หรือ regex ก็ได้
  • proxy_headers_hash_bucket_size : คำสั่งที่กำหนดขนาดสูงสุดของ header name
  • proxy_headers_hash_max_size : คำสั่งที่ที่กำหนดขนาดทั้งหมดที่รับจาก upstream server
  • proxy_hide_header : รายการ header จาก client ที่ไม่ให้ผ่านเข้ามา
  • proxy_http_version : กำหนด http protocol จะใช้เป็นเวอร์ชัน 1.1 สำหรับเปิดใช้งาน keepalive
  • proxy_ignore_client_abort : ถ้าตั้งว่า on ให้กับคำสั่งนี้ nginx จะยกเลิกการเชื่อมต่อไปยัง upstream ถ้า client ยกเลิกการเชื่อมต่อ
  • proxy_ignore_headers : เป็นคำสั่งที่กำหนดให้ไม่ต้องสนใจ header ที่ได้รับ response มาจาก upstream
  • proxy_intercept_errors : ถ้าคำสั่งนี้ตั้งว่า enable nginx จะส่งค่า error_page แทนการ response มาโดยตรงจาก upstream server
  • proxy_max_temp_file_size : คำสั่งที่กำหนดขนาดสูงสุดของ overflow file เมื่อ memory ไม่พอ
  • proxy_pass : เป็นคำสั่งที่ระบุ upstream server ที่ต้องการส่งข้อมูลไปให้
  • proxy_pass_header : เป็นคำสั่งที่ตรงข้ามกับคำสั่ง proxy_hide_header โดยที่สามารถระบุตามเงื่อนไข เพื่อให้สามารถส่งข้อมูล header ไปยัง client ได้
  • proxy_pass_request_body : เป็นคำสั่งที่ป้องกันการส่ง body ของ request ไปยัง upstream server ถ้าถูกตั้งให้เป็น off
  • proxy_pass_request_headers : เป็นคำสั่งที่ป้องกันการส่ง header ของ request ไปยัง upstream server ถ้าถูกตั้งให้เป็น off
  • proxy_read_timeout : เป็นคำสั่งที่กำหนดระยะเวลาอ่านข้อมูลที่ผ่านไปในแต่ละรอบอย่างต่อเนื่อง จาก upstream server ก่อนที่การเชื่อมต่อจะปิด ควรจะตั้งค่านี้เอาไว้ให้สูง ถ้า upstream server มีการประมวลผลช้า
  • proxy_redirect : คำสั่งนี้ใช้สำหรับแก้ไข header ใน context ของ location และ refresh ที่ได้รับมา จาก upstream server ซึ่งจะมีประโยชน์หากใช้กับพวก framework ต่างๆ
  • proxy_send_timeout : เป็นคำสั่งที่กำหนดระยะเวลาเขียนข้อมูลที่ผ่านไปในแต่ละรอบอย่างต่อเนื่อง จาก upstream server ก่อนที่การเชื่อมต่อจะปิด
  • proxy_set_body : เป็นคำสั่งที่กำหนด body request ไปยัง upstream server อาจจะมีการแก้ไขจากคำสั่งนี้
  • proxy_set_header : เป็นคำสั่งที่แก้ไขข้อมูล ค่าคงที่ต่างๆที่อยู่ใน header ส่งไปยัง upstream server นอกจากนี้ยังสามารถกำหนดไม่ให้ส่ง header บางส่วนได้โดยกำหนดให้เป็นค่าว่างก็ได้
  • proxy_temp_file_write_size : เป็นคำสั่งที่จำกัดจำนวนของข้อมูลที่ถูก buffer ไปยัง temporary file ในครั้งเดียว เพื่อให้ nginx ไม่สามารถ block ข้อมูลนานเกินไปในแต่ละครั้งของ request
  • proxy_temp_path : เป็นคำสั่งที่กำหนด directory ที่เก็บไฟล์ชั่วคราวและอาจจะเก็บ buffer เอาไว้เนื่องจาก proxy จาก upstream server ต้นทางมีหลายระดับ
ลองพิจารณาตัวอย่าง proxy.conf ด้านล่างนี้
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 30;
proxy_send_timeout 15;
proxy_read_timeout 15;
proxy_send_lowat 12000;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

สามารถอธิบายได้ว่า
  • proxy_redirect ตั้งค่าให้เป็น off เพราะว่า ไม่จำเป็นที่จะต้องแก้ไขอะไร
  • คำสั่ง proxy_set_header ในส่วนคำสั่ง Host คือค่าตั้งเอาไว้สำหรับ map เป็นตัวแปรเพื่อ request ไปยัง server ตามที่ user ป้อน URL เข้ามา
  • คำสั่ง proxy_set_header ในส่วนคำสั่ง X-Real-IP และ X-Forwarded-For เพื่อให้ส่งข้อมูลการเชื่อมต่อของ client เช่น IP Address ไปยัง server
    • $remote_adde เป็นตัวแปรที่ใช้ในคำสั่ง X-Real-IP เป็น IP address ของ client
    • $proxy_add_x_forwarded_for เป็นตัวแปรที่ใช้ในคำสั่ง X-Forwarded-For เอาข้อมูล Header ที่ได้จาก Client ที่ request เข้ามาตาม IP ที่ ตัวแปร $remote_addr ได้รับ
  • คำสั่ง client_max_body_size แม้ว่าถ้าไม่ได้ใช้ proxy คำสั่งนี้ก็ต้องถูกพูดถึง เพราะมีความสัมพันธ์ต่อการ config proxy คือ ถ้าค่าที่ตั้งเอาไว้ต่ำมากๆ ไฟล์ที่อัพโหลดจะไม่ถูก upstream ไปยัง server จงจำเอาไว้ว่า หาก upload file ผ่านเว็บ จะต้องตั้งค่าให้มากกว่าใน filesystem
  • คำสั่ง proxy_connect_timeout เป็นคำสั่งที่ระบุระยะเวลาของ Nginx ว่าให้รอหากการเชื่อมต่อหลุด เพื่อรักษาการเชื่อมต่อระหว่าง client นั้นเอาไว้
  • คำสั่ง proxy_read_timeout และ proxy_send_timeout เป็นคำสั่งกำหนดระยะเวลาที่ Nginx จะรอการเชื่อมต่อกับ server
  • คำสั่ง proxy_send_lowat เป็นคำสั่งได้ผลเฉพาะบนระบบ FreeBSD และสามารถระบุจำนวน Bytes ที่ Buffer เอาไว้ได้
  • คำสั่ง proxy_buffer_size, proxy_buffers และ proxy_busy_buffers_size กล่าวถึงในบทถัดไป (ตามที่ Master Nginx กล่าว)
  • คำสั่ง proxy_temp_file_write_size เป็นคำสั่งที่ควบคุม worker process ขณะที่ spooling data หากค่ายิ่งสูงก็จะยิ่งประมวลผลเป็น block นาน
ให้ทำการสร้างไฟล์ proxy.conf แล้ววางไว้ที่ไหนก็ตามให้ใส่ คำสั่ง include และ path ของไฟล์ให้เรียบร้อย

location / { include proxy.conf; proxy_pass http://localhost:8080; }



ลองทดสอบ



พบว่า proxy_send_lowat ไม่ support ซึ่งก็เพราะ ใช้ได้สำหรับ FrerBSD จึงต้องไป comment



ลองทดสอบดูใหม่



ใช้ได้เรียบร้อย จากนั้นก็ทดสอบว่าเป็นอย่างไร



ลองทดสอบแก้ไข header โดยใช้คำสั่ง
proxy_set_header Accept-Encoding "";



ผลที่ได้












ลองเพิ่ม header โดยใช้คำสั่ง
proxy_set_header Connection "";












คำสั่งที่อยู่ในบันทึกนี้ ไม่ได้มีเพียงเท่านี้ ยังมีให้ config มีเยอะก็ค่อยๆ ลองกันไป


ไม่มีความคิดเห็น:

แสดงความคิดเห็น

Set MongoDB in the windows path environment

  Let’s set MongoDB in the windows environment in just a few steps. Step 1: First download a suitable MongoDB version according to your mach...