Wall of Text #14: Information security for dev

อยากเขียนเรื่อง security บ้าง หลังๆ ทำงานกับ security team เยอะขึ้น แล้วรู้สึกว่าจริงๆ มันไม่ยากอย่างที่คิด

Threat

ตอนที่เรียน information security ชอบรูปนี้มาก รู้สึกว่าอธิบายได้ดี เคยเจอรูปต้นฉบับในเน็ต แต่เข้าใจว่าหนังสือมีลิขสิทธิ์เลยหายาก ก็เลยวาดให้ใหม่ใน Paint

Security มีองค์ประกอบอยู่ 3 อย่าง

  1. Threat (ภัยอันตราย) ในรูปก็คือน้ำจะท่วมแล้ว
  2. Vulnerability (จุดอ่อน) ในรูปก็คือ กำแพงกันน้ำมีรอยรั่ว
  3. Control (การควบคุม) ในรูปก็คือเอามือปิดรอยรั่วไว้

ถ้ากำแพงรั่วแล้วเอามือปิดไว้ ผลคือน้ำไม่ท่วม เท่ากับว่าบรรลุเป้าหมาย แปลว่ามี security แต่ถ้าเกิดน้ำสูงกว่ากำแพงก็สร้างปัญหาได้อยู่ดี

CIA Triad

Security จริงๆ แล้วมีสมบัติ 3 อย่างหลักๆ ซึ่งอาจจะซอยข้อย่อยได้อีก 3 อย่างหลักๆ นี้คือ

  1. Confidentiality (ลับ) คือคนที่จะเห็นข้อมูลได้ต้องเป็นคนที่ตั้งใจจะให้เห็นเท่านั้น
  2. Integrity (สมบูรณ์) คือข้อมูลถูกต้องครบถ้วน เช่น ถ้ามี hacker เข้ามาเปลี่ยนหน้าเว็บเป็น rickroll ถือว่าเสีย Integrity
  3. Availability (ใช้งานได้) เช่น โดนยิง DDoS คนเข้าใช้งานไม่ได้เลย ถึงจะไม่ทำให้ข้อมูลหลุดหรือโดนแก้ไขข้อมูลก็เป็นปัญหา security เหมือนกัน

ซึ่งก็มีมาตรการต่างๆ ที่ช่วยรักษาสมบัติพวกนี้ เช่น

  1. Confidentiality
    • Access control ไม่ให้คนที่ไม่อนุญาตเข้าถึงได้ เช่นระบบ user account, firewall
    • Encryption เข้าถึงได้แต่เปิดอ่านไม่ได้
    • Contract เซ็นสัญญาไม่เปิดเผยความลับ ก็ใช้ควบคุมได้ถ้าไม่ได้อยู่ในระบบคอมพิวเตอร์
    • Monitoring ตรวจจับว่ามีผู้บุกรุก
  2. Integrity
    • Checksum คือสามารถยืนยันได้ว่าข้อมูลถูกต้องครบถ้วน
    • Signing คือจำกัดให้ checksum สร้างได้จำกัดคน ป้องกัน hacker สร้าง checksum ใหม่
    • Backup
    • Access control จำกัดคนที่แก้ไขข้อมูลได้ก็ช่วยได้เช่นกัน
    • Monitoring ก็ช่วยได้อีกเช่นกัน
  3. Availability
    • Spare มีระบบสำรองกรณีระบบหลักมีปัญหา
    • Scale out มีหลายๆ ระบบทำงานพร้อมกันเพื่อลดคอขวดจากจุดเดียว
    • Monitoring ว่าระบบยังทำงานได้ปกติ ไม่มีการใช้งานผิดปกติ

Security assessment

ไม่แน่ใจว่าตำรา security จะเขียนแตกต่างจากนี้ไหม แต่โดยทั่วๆ ไปแล้วเวลาผมประเมินความเสี่ยงจาก security จะทำตามขั้นตอนนี้ ซึ่งจริงๆ ผมว่ามันจะคล้ายๆ กับการทำ Persona ของ UX

  1. Threat modeling พูดง่ายๆ คือ กลัวอะไรอยู่ หลักๆ ก็อาจจะเป็น
    • กลัวคนนอก (hacker)
    • กลัวคนใน (insider attack, data loss)
    • กลัว user อื่น (spammer)
    • กลัวแอพพลิเคชั่นอื่น (lateral movement)
    • กลัวโปรแกรมเมอร์คนอื่น (defensive coding)
    • ซึ่งเราอาจจะไม่ต้องกลัวทุกอย่างก็ได้ เช่นเว็บเล็กๆ มีทีมงานเห็นๆ กันอยู่ 2-3 คน โอกาสที่คนในจะเป็นหนอนอาจจะน้อยก็ไม่จำเป็นต้องทำเรื่อง insider attack
  2. Vulnerability – ลอง list ออกมาว่าเขาจะทำอะไรมิดีมิร้ายได้บ้าง ผมคิดว่า list ทั้งหมดน่าจะยาวมากไม่สามารถเขียนมาได้ ต้องใช้ประสบการณ์ที่จะเห็นแล้วพอนึกออกว่ามีข้อไหนบ้างที่ apply เช่น
    • คนนอกอาจจะ port scan, เอาช่องโหว่มา scan, ทำ SQL injection หรือ XSS, เดารหัสผ่าน หรือ credential stuffing
    • คนในที่มี admin อาจจะใช้อำนาจในทางที่ผิด เช่น โกรธแฟนเลยแอบดูข้อมูลการใช้งานของแฟน (insider attack) โดนหลอกให้ทำ (phishing) หรือขโมยข้อมูลไปให้คู่แข่ง (data loss)
    • user อาจจะส่ง spam หากันเอง
    • คนใน หรือ application ใน network โดนฝัง shell แล้ว scan หา application ภายในเพื่อ hack ต่อ (lateral movement)
    • โปรแกรมเมอร์คนอื่นที่มาเรียกฟังค์ชั่นนี้อาจจะส่ง parameter มาผิดวิธีแล้วทำให้เกิดช่องโหว่ เช่นเรียก sql query แต่ไม่ได้ escape quote
  3. Control เป็นส่วนสำคัญที่สุด ถ้าเรามี control เพียงพอจะ run Ubuntu 8.04 ใน production ก็ได้ ตัวอย่างของ control เช่น
    • ทำ input validation ถ้าเป็นค่าที่ไม่ถูกต้องไม่ให้ประมวลผล
    • อัพเดต Application ให้ล่าสุดเพื่อไม่ให้โดน hack จาก library ที่ไม่อัพเดต เช่น Log4shell, Apache Struts
    • แต่บางที vendor อาจจะยังออก patch ไม่ทัน ก็ต้องกันจากด้านนอกเช่นใช้ WAF SaaS เพื่อตรวจจับการยิง
    • แต่ WAF ก็ bypass ได้ อาจจะเพิ่ม firewall ไปอีกเพื่อจำกัด IP ที่เข้าใช้งานได้กรณีที่เป็นระบบปิด
    • เพิ่ม firewall ขาออกด้านในด้วยเพื่อที่ว่ายิงเข้ามาได้ก็อาจจะส่งข้อมูลออกไป internet ยาก และเข้าไปโจมตี application อื่นๆ ยาก
    • สุดท้ายเพิ่ม access log เพื่อที่ว่าถ้ามีคนทะลุทุกอย่างมาได้จริงยังสามารถจับมือคนดมได้

“Control ที่เพียงพอ” เป็นคำถามที่ตอบยากมากๆ เพราะระบบที่ปลอดภัย 100% ไม่มีจริง ยิ่งทำมากยิ่งเสียเวลา (diminishing return) และทำให้ใช้งานลำบากด้วย อีกส่วนหนึ่งคือมูลค่าของระบบที่จะปกป้องกับระบบรักษาความปลอดภัยควรจะเหมาะสมกัน เช่นถ้าเป็นเว็บ company profile ธรรมดาๆ การซื้อ WAF, L7 firewall มาติดตั้งอาจจะมูลค่าหลักแสนหรือหลักล้าน แต่ความเสียหายคือแค่ restore จาก backup ก็กลับมาใช้งานได้แล้ว แบบนี้ก็ถือว่า backup เป็น control ที่เพียงพอแล้ว

เวลาเขียนโค้ด โค้ดทุกบรรทัดต้องทำ security assessment แบบนี้เสมอ ซึ่งคนส่วนมากน่าจะคิดว่าโอเวอร์เกินไปแล้วไม่ทำเลย แต่ผมคิดว่าถ้ามีประสบการณ์ security มาบ้างจะเริ่มจับทางได้เหมือนเป็น code smell ประเภทหนึ่งว่าในจุดนี้ต้องเริ่มวิเคราะห์ threat modeling อย่างละเอียดแล้ว ทำให้ทำงานได้เร็วขึ้น เช่น

  • ทุกจุดที่ใช้ตัวแปรที่ user ป้อนเข้ามา (โดนแฮคได้หลายแบบ ตามด้านล่างนี้)
  • โค้ดเกี่ยวกับ password (ตรวจดูว่า hash รหัสด้วยอัลกอริธึมและพารามิเตอร์ที่เหมาะสม และเปรียบเทียบรหัสผ่านโดยใช้เวลาคงที่ (constant time comparison))
  • โค้ดที่เกี่ยวกับวิทยาการรหัสลับ (ไม่แนะนำให้ใช้ algorithm โดยตรง ควรจะใช้ use case based library)
  • โค้ดที่ยิง URL แล้ว user กำหนดค่าเองได้ (อาจสุ่มเสี่ยง SSRF หรือ logic ในการ parse กับ validate ไม่ตรงกัน)
  • โค้ดที่รันสคริปต์ที่ user ส่งเข้ามา (ควรจะทำ sandbox ให้เหมาะสม)
  • โค้ดที่ใช้ตรวจสอบข้อมูล (data validation)
  • โค้ดที่จัดการข้อมูลขนาดใหญ่ในครั้งเดียว (ระวังไม่ให้ user ใช้งาน memory หรือ disk ใหญ่เกินไป)

Defense in Depth

ในอุตสาหกรรมการบินจะมีการใช้ Swiss cheese model

By BenAveling – Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=91881875

โมเดลนี้ใช้แนวคิดว่าเราไม่สามารถป้องกันความเสี่ยงได้ 100% ถ้าไม่อยากให้ชีสมีรูทะลุไปอีกฝั่ง การมีชีสเรียงกันหลายๆ ชั้นก็ลดโอกาสที่ชีสทุกแผ่นจะมีรูเดียวกันหมดได้ ในฝั่ง security มักจะเรียกว่า defense in depth

Not security

บางอย่างไม่ทำให้เกิด security

Security theater

เล่นละครไม่ทำให้เกิด security

เช่น นโยบายบอกว่าต้องตรวจสัมภาระก่อนเข้าสู่สถานที่ แต่คนตรวจเปิดอยู่ช่องเดียวแล้วส่องไฟผ่านๆ แบบนี้ไม่เกิดความปลอดภัย

Security is not a product

คนที่ไม่เข้าใจ security มักจะโดนเซลเป่าหูให้ซื้อ security product แต่ไม่ทำให้เกิด security จริง เปรียบเสมือนเช่ายันต์และห้อยพระเครื่องไว้ที่ server ให้อึด ถึก ทน ยิงไม่เข้า (ถ้า product มันเหนียวจริง ซื้อมาแล้วโดนแฮคควรจะฟ้องร้อง vendor ให้ใช้ค่าเสียหายได้)

การซื้อ product อาจจะช่วยเพิ่ม security ได้จริง แต่ก็ต้องกลับไปมองที่ security assessment ว่าสิ่งที่ซื้อมา ซื้อเพราะกลัวอะไร ซื้อแล้วมันได้ผลจริงกี่ % ซึ่งมันไม่ใช่ 100% แน่ๆ ต้องมีแผนให้ชัดเจนว่า control ต้องเพิ่มอะไรอีกบ้างจึงจะเพียงพอ

Security is not a feature

Project manager ที่ไม่เข้าใจ security อาจคิดว่า security เป็น feature หนึ่งแล้วก็แยกเป็น ticket low priority ทำทีหลัง

ผ่านไป 1 ปีก็ยังไม่ได้ทำจนกระทั่งโดน hack แล้วบอกว่าลูกค้าด่าต้องทำให้เสร็จภายใน 1 สัปดาห์

ในความเป็นจริงแล้ว security เป็นส่วนหนึ่งของทุกๆ feature การ “เติม” security เข้าไปภายหลังสร้าง technical debt ได้รวดเร็วมากเพราะมันมักจะส่งผลต่อ design และการแก้ design flaw เป็นเรื่องยาก ใช้เวลานาน

Security by obscurity

Security ที่แท้จริงถ้าเฉลยกลให้ทั้งหมดแต่ไม่บอกรหัสลับก็ไม่สามารถผ่านเข้ามาได้ เช่นวิธีเข้ารหัส AES นั้นเป็นข้อมูลเปิดเผยหาอ่านได้ทั่วไป ถึงอย่างนั้นถ้าไม่บอกกุญแจเข้ารหัสปัจจุบันยังไม่มีใครถอดรหัสข้อความใดๆ ได้

โบราณว่า ทองแท้ไม่แพ้ไฟ

มีบางคนคิดว่า AES เป็นข้อมูลเปิดเผย มี paper มากมายที่ลดความปลอดภัยของ AES ถ้าอย่างนั้นเราออกแบบ algorithm ขึ้นมาเองเฉพาะภายในบริษัทแล้วก็เป็น algorithm ที่มีความปลอดภัยสูงสุด ไม่เคยมีผู้ใดในโลกถอดรหัสได้โดยไม่ต้องรู้กุญแจ

ผ่านไป 6 เดือน hacker reverse engineer โปรแกรมมาดูแล้วพบว่าเป็น XOR กับ hardcode key ธรรมดาๆ แล้วก็เอา key ไปแจกในเน็ต

People is the weakest link

xkcd 538

Cargo cult security

“อาจารย์บอกมา” ไม่ใช่ security ที่ดีเสมอไป เช่น

  • อาจารย์ให้ config มา ตั้งตามแบบนี้แล้วเหนียว ยิงไม่เข้า แต่พอใช้แล้ว CEO โดนบล็อกทำงานไม่ได้
  • อาจารย์สอนให้ต้องมี CSP header แล้วจะป้องกันการแฮคได้ แต่เปิด unsafe-eval ไว้เพราะ marketing จะใช้ Google Tag Manager
  • อาจารย์สอนวิธี encrypt รหัสผ่านด้วย MD5 แล้วทำให้รหัสผ่านปลอดภัย แฮคไม่ได้
  • ซื้อ Tool scan มา scan เจอ 500 ข้อ พอแก้ตามที่ tool แนะนำแล้ว application ใช้งานไม่ได้
  • ซื้อ Tool scan มา scan ก่อน release application ปรากฏว่าจะแก้ให้ผ่านเป็น breaking change ส่งมอบงานไม่ทันเวลา
  • ซื้อ Tool scan ช่องโหว่ 10 อันดับยอดนิยมมา scan แล้วไม่เจอสักรายการที่ต้องแก้ไขแสดงว่าปลอดภัย แต่โดน hack ด้วยช่องโหว่ยอดนิยมอันดับที่ 11

เขาว่ายอด consult จะบอกว่า It depends ซึ่ง security ก็เช่นกัน “อาจารย์บอกมา” อาจจะไม่ได้ผิด แต่ไม่สามารถคำนึงถึง It depends ได้ ต้องมีความเข้าใจที่ถูกต้องว่าทำไมอาจารย์ถึงบอกมา

Wall of Text #13: CGI

น้อง Intern บอกว่ากำลังหัดเขียน Web server อยู่ เลยสงสัยว่าแล้วจะทำให้ Web server รันโปรแกรมที่เป็น dynamic ได้ไง (สมมุติว่า Python)

เรื่องที่น่าแปลกใจคือคนรุ่นใหม่เหมือนจะไม่มีประสบการณ์ใช้งาน PHP กันแล้ว เข้าใจว่าบางมหาวิทยาลัยนอกเหนือจาก Top 5 อาจจะยังมีการสอนอยู่บ้าง ตอนที่โชว์ให้ดูว่า PHP มันวางไฟล์แล้วใช้ได้เลยนี่มันเลยดูเท่มาก เพราะถ้าเขียนภาษาอื่นๆ อย่างน้อยก็ต้อง restart app server

CGI

ในสมัยโบราณ WWW มีแต่หน้าเว็บ static ต่อมาเราอยากให้หน้าเว็บมีการอัพเดตบ้าง เลยมีผู้ที่ออกแบบมาตรฐาน CGI ขึ้นมาเพื่อให้ Web server สามารถเรียกโปรแกรมอื่นได้

การทำงานของ CGI ก็ง่ายมาก คือเรากำหนดว่าที่ URL นี้แทนที่จะส่งไฟล์กลับไปให้ ให้เรียกโปรแกรมที่กำหนดให้ ที่นิยมกันก็คือจะกำหนดเป็น folder /cgi-bin ไปเลย

เมื่อเราเข้า URL ที่อยู่ใน cgi-bin แล้ว Web server จะไปเรียกโปรแกรมนั้นๆ โดยส่ง Header ไปทาง Environment variable และส่ง Request body ไปเป็น input ของโปรแกรม จากนั้นโปรแกรมจะ print สิ่งที่ต้องการให้แสดงบนหน้าเว็บออกมา ถ้าต้องการเซต Header มาด้วยก็ให้ print ก่อนเนื้อหาได้

วิธีนี้ค่อนข้างนิยมในสมัยก่อน ภาษาที่ใช้เขียนก็ได้ทุกภาษาขอให้เรียกเป็นโปรแกรมได้เท่านั้น เช่น C, Perl, PHP ก็ใช้ได้ทั้งหมด

ยกตัวอย่างเช่น Pantip ในยุคแรกใช้ภาษา Perl ในการพัฒนา ในหน้ากระทู้นั้นจะเป็น HTML ธรรมดาๆ เมื่อมีการโพสต์ comment ก็จะไปเรียก Perl script เข้าไปแก้ไขไฟล์ HTML (ซึ่งปัญหาที่ตามมาคือเมื่อ concurrent มากๆ แล้ว Script อาจจะแย่งกันเขียนทำให้ไฟล์พัง)

PHP SAPI

ปัญหาของ CGI คือทุกครั้งที่มีการเรียก CGI Script จะต้องเรียก process ย่อยๆ นั้นใหม่ ซึ่งถ้าเขียนด้วย C ก็ไม่มีปัญหาเท่าไร แต่บางภาษาอาจจะ start ช้ามากๆ เช่นสมัยก่อนผมเคยใช้ Python แล้วเซตไม่ถูกเลยไปใช้ CGI ก็เสียเวลา start python ทุก request เกือบ 2 วินาที

มันก็มีคนแก้ไขปัญหานี้หลายๆ ทาง อันหนึ่งคือก็เอา PHP ไปฝังไว้กับ Web server เลย โดย PHP จะมีส่วนที่เรียกว่า SAPI (Server API) ซึ่งเป็น library ที่เข้าไป integrate กับ web server (เช่น Apache) ให้เมื่อมีการเรียกหน้าที่กำหนดแล้วจะไปเรียก PHP API ที่สั่งให้ script ทำงาน

วิธีนี้ทำให้ไม่ต้อง start PHP ใหม่ทุก process เพราะ PHP จะอยู่กับ web server ไปเลย

ข้อเสียหลักๆ ของการทำแบบนี้คือ

  1. PHP library ไม่ได้พัฒนาให้ thread safe ดังนั้นจะใช้ Apache ได้แค่ใน mode prefork (แยก process แทน thread) ซึ่งเปลือง memory กว่า
  2. Code จะถูกรันด้วยสิทธิ์ของ web server ซึ่งในกรณีที่ใช้ share hosting แล้วจะทำให้เราสามารถเข้าไปอ่าน/แก้ไขไฟล์ของ user อื่นๆ บนเครื่องได้ทุกคน
  3. รัน PHP ได้แค่ version เดียวต่อ web server (ในกรณีที่มี legacy code ที่อัพเวอร์ชั่นไม่ได้)

ถึงใน PHP จะมีข้อจำกัดเยอะ แต่ในช่วงประมาณปี 2008 ที่คนเริ่มสนใจ Python/Ruby ทั้งสองภาษาก็ยัง deploy ด้วยท่านี้ได้ด้วย mod_wsgi หรือ Phusion Passenger

FastCGI

ท่าที่ค่อนข้างเวิร์คกว่าในการ Deploy web application คือ FastCGI ซึ่งเป็น standard อีกตัวหนึ่งที่เข้ามาแทน CGI

การทำงานของ FastCGI คือให้ web application นั้นเปิด socket ไว้ (อาจจะเป็น UNIX socket หรือ TCP ก็ได้) แล้ว Web server จะส่งต่อ request เข้ามาใน socket และเอาผลลัพท์กลับไปแสดง

วิธีนี้ทำให้เราสามารถ scale application server / web server แยกกันต่างหากได้ และรันเป็นคนละ user เพื่อความปลอดภัยได้

ปัจจุบันท่าที่นิยมใช้ Deploy PHP บน nginx ก็จะใช้ php-fpm ซึ่งจะรับ FastCGI connection เข้ามาประมวลผลด้วย PHP และช่วยจัดการเพิ่มลด process ให้อัตโนมัติ

Reverse proxy

ถ้า FastCGI คือการที่เรารับ HTTP request แล้วแปลงเป็น FastCGI request ส่งต่อ ทำไมเราไม่ส่ง request จริงไปเลยล่ะ?

ผมเข้าใจว่าท่า Reverse proxy เริ่มดังในช่วงหลังจากที่ Node.js เข้ามาแล้ว เพราะเป็นภาษา interpreted ภาษาแรกที่บอกว่าใช้ web server ในตัวมันรับโหลดได้เลยเพราะมันเป็น async ซึ่งเป็นจุดขายที่ว้าวมากในตอนนั้น

หลังจาก Node.js แล้ว Go ก็เป็นอีกภาษาหนึ่งที่บอกเหมือนกันว่าให้ใช้ web server ในตัวรับโหลดได้เลย

ความแตกต่างระหว่างการเปิด web server กับ FastCGI ที่จะเห็นได้ก็คือ

  • FastCGI เราเชื่อ web server ตัวหน้าทั้งหมด แต่การรันเป็น web server เราจะไม่เชื่อ web server ตัวหน้า ต้องเขียนโค้ดมาประมวลผลอีกที
  • เช่น web server จะมองเห็น IP คนที่ต่อเข้ามาและส่งให้ FastCGI ใน field พิเศษ แต่ถ้าเป็น reverse proxy นั้น application ต้องอ่านจาก X-Forwarded-For อีกทีหนึ่ง ซึ่งก็ต้องระวังความปลอดภัยด้วยเพราะ user ก็สามารถเซต header ได้
  • หรือถ้า web server ตัวหน้าใช้ HTTPS แล้วต่อเข้าด้านหลังด้วย HTTP ธรรมดาจะทำให้ application ไม่ทราบรายละเอียด connection เลยว่าเป็น HTTPS หรือไม่ (นอกจากจะเชื่อตาม header) และไม่สามารถใช้ฟีเจอร์อื่นๆ ได้เช่น Client certificate หรือ check cipher suite
  • Web server ของบางภาษาอาจจะรับโหลดไม่เก่งเท่า Web server จริงๆ เช่น Gunicorn แนะนำให้ใช้ web server คั่นหน้าเสมอ เนื่องจากถ้า client ทำงานช้า (Slowloris attack) จะเสีย thread ไปเปล่าๆ หรือโค้ดในการ serve static file ก็อาจจะไม่เก่งเท่า
  • Protocol HTTP นั้น parse ยากกว่า FastCGI protocol

What comes next

ทั้งหมดด้านบนคือ protocol หลักๆ ที่ยังใช้อยู่ในปัจจุบัน

แต่ในอนาคตก็เป็นไปได้ว่าอาจจะมีวิธีอื่นๆ เข้ามาก็ได้ ท่าที่เห็นในตอนนี้คือ event-driven เสียเป็นส่วนใหญ่

ASGI v1

ผมเคยอวย ASGI v1 มากๆ มันเป็นความพยายามที่จะทำให้ Django กลายเป็น async ทั้งๆ ที่มันเขียนเป็น sync มาทั้งหมด

วิธีการคือ web server ตัวหน้า (ASGI gateway) จะแปลง HTTP request ที่เข้ามาเป็น message แล้วยิงเข้าไปใน message queue จากนั้น ASGI server จะรันตาม request ที่ได้รับแล้วส่งผลลัพท์กลับไปใน message queue เช่นกัน

ท่านี้ผมเห็นครั้งแรกใน Mongrel2 ซึ่งใช้ ZeroMQ

วิธีนี้ยังสามารถประยุกต์ใช้งานกับ protocol อื่นๆ ได้อีก ซึ่งท่าที่ทำให้มันเท่มากคือ WebSocket โดย gateway จะยิง event ต่างๆ เช่น client connected, client message เข้าไปใน message queue ทำให้โค้ด scale ได้ง่ายเนื่องจากไม่มีการ hold connection เลย (นอกจาก MQ)

ด้วยความที่มันรันบน message queue มันทำให้การ scale ต่างๆ เหมือนการ scale message queue ทั่วไป รวมถึงว่าเราสามารถรัน gateway 1 server ที่ใช้ resource ไม่มากแล้วรัน ASGI server หลายๆ server ก็ได้

ปัญหาที่เจอในการใช้งานจริงคือเนื่องจากมันเป็น request-response ในครั้งเดียว web server เลยจะต้องรับ connection ทั้งหมดมาก่อนแล้วค่อยถาม application ว่าเอาไหม ซึ่งจะทำให้เกิดปัญหา queue backlog ยาวและ message queue บางประเภท cancel message ไม่ได้

อีกปัญหาหนึ่งคือถ้า user upload file ขนาดใหญ่มา เป็นปัญหาที่มันแก้ไม่ได้เลย เพราะส่งทั้งไฟล์ไปบน MQ ก็จะ overhead สูงมาก จะเขียนลงเครื่องก็อาจจะอยู่คนละเครื่อง จะเอาไปไว้ใน storage service ก็เพิ่ม dependency

Serverless

ถ้าย้อนกลับไปอ่านข้างบนจะพบว่า Serverless ที่กำลังฮิตอยู่ตอนนี้ จริงๆ มันคือ CGI กลับชาติมาเกิดเป๊ะๆ เลย แล้วปัญหาที่คนใช้ serverless เจออย่าง cold start นาน ก็คือปัญหาเดียวกับ CGI แถมมันยังรับได้แค่ 1 request per instance เหมือนกันด้วย

จะต่างกันแค่ว่า serverless application ไม่โดนบังคับให้ออกหลังจาก serve request จบแล้วแต่จะถูก freeze ไว้แทน ทำให้ครั้งถัดไปไม่เสีย cold start อีก

ไอเดียของ AWS Lambda ผมเข้าใจว่าเค้าน่าจะพยายามทำ code execution สำหรับ event ต่างๆ อยู่ (แบบที่ Twilio มี Functions) แล้วถึงพบว่ามันเอาไปรันเป็น web ได้ทีหลัง เวลาใช้ทำเว็บเลยจะเห็นว่าท่ามันยุ่งยากมาก คือต้องมี API Gateway/ALB แปลง request เป็น event เสียก่อนแล้วค่อยไป call lambda Invoke API ไม่สามารถเรียก function ตรงๆ ได้เลย (อย่างน้อยๆ ก็ต้องเรียกผ่าน Lambda API)

ก็จะเห็นมีแต่ Google Cloud Function ที่ทำกลับกันคือมี HTTP API แล้วเพิ่มให้รองรับ event ผ่าน webhook แทน