איך לסגור את האתר בשבת עם Haproxy ו Lua

13/06/2021

הפרוקסי (haproxy) היה הפרוקסי החביב עליי פחות או יותר מהרגע הראשון שהתחלתי להשתמש בו וככל שלמדתי עליו יותר כך רק מצאתי יותר דברים לאהוב. המטרה בגדול של haproxy היא לקבל תנועה שמגיעה מהעולם לתוך המערכת שלכם ולנתב אותה לשרתים הפנימיים כך שלא יהיה יותר מדי עומס על שרת ספציפי (מה שנקרא Load Balancing), וגם ובעיקר לזהות מאפיינים של בקשה ולנתב אותה לשרת הפנימי המתאים. הוא מתחרה ב nginx וב envoy ולדעתי הוא פשוט יותר משניהם.

טריק נחמד שאפשר לעשות עם haproxy הוא להרחיב אותו באמצעות Lua. באופן רגיל אנחנו יכולים להשתמש ב ACL-ים כדי לנווט בקשות לשירותים מסוימים לפי תוכן הבקשה, לדוגמה השורה הבאה בקובץ הקונפיגורציה:

http-request deny if { path -i -m beg /api/ } { src 10.0.0.0/16 }

תעצור בקשות שמגיעות מהרשת 10.0.0.0/16 ומיועדות לנתיב שמתחיל ב /api. או השורה הזאת:

redirect scheme https if !{ ssl_fc }

תשלח ללקוח HTTP Redirect אם הוא לא פנה ב HTTPS.

אבל הדבר הגדול באמת הוא שאנחנו יכולים להוסיף פונקציות כמו src ו path בעצמנו באמצעות קוד lua. לדוגמה קוד lua הבא:

core.register_fetches("dow", function(txn)
  return os.date("*t").wday
end)

מייצר ל Haproxy פונקציה חדשה בשם dow שמחזירה את היום בשבוע (מתחיל מ-1 ליום ראשון).

עכשיו נניח ששמרתי את קוד ה lua מהדוגמה בקובץ /usr/local/etc/haproxy/dow.lua, ונניח שיש לי שני שרתי אפליקציה על הרשת, אחד בשם web שמציג את התוכן האמיתי שלי והשני בשם closed שמציג דף שאומר שהאתר סגור כעת; אז אני יכול לכתוב את קובץ הגדרות ה haproxy.cfg הבא כדי לסגור את האתר בסופי שבוע:

global
  log /dev/log  local0
  log /dev/log  local1 notice
  user haproxy
  group haproxy
  daemon
  lua-load /usr/local/etc/haproxy/dow.lua

defaults
  log global
  mode  http
  timeout connect 10s
  timeout client 30s
  timeout server 30s
  option  httplog
  option  dontlognull

frontend default
  bind :80
  use_backend closed if { lua.dow() eq 6 } || { lua.dow() eq 7 }
  default_backend web

backend web
  server s1 web:80

backend closed
  server s1 closed:80

הבלוק המעניין הוא הבלוק frontend ובפרט השורות:

use_backend closed if { lua.dow() eq 6 } || { lua.dow() eq 7 }
default_backend web

הפונקציה lua.dow היא פונקציית ה lua שכתבתי שמחזירה את היום בשבוע, והשורה בבלוג הגלובל:

lua-load /usr/local/etc/haproxy/dow.lua

היא שהיתה אחראית לטעינת קובץ ה lua וציון הנתיב אליו.