Nginx Basic Authen via LDAP

Punyapat Sessomboon
2 min readJun 19, 2020

--

บทความที่แล้วเราลองทำ Basic Authen ด้วย Apache ผ่าน LDAP Server กันแล้ว วันนี้เราจะมาทำบน Nginx กันบ้างครับ แต่เนื่องจาก Nginx ไม่มี Native support ก็เลยต้องพลิกแพลงนิดหน่อย

ใครที่ยังไม่ได้อ่านบทความเรื่อง LDAP พื้นฐาน แนะนำให้อ่านและลองทำตามให้คล่องก่อนนะครับ เพราะว่าหลายๆ ส่วนในบทความนี้จะไม่ได้อธิบายรายละเอียดของวิธีการ config ที่ได้กล่าวถึงไปแล้วในบทความแรก

ส่วนใครที่สนใจอยากอ่านเรื่องการทำ Basic Authen บน Apache ลองอ่านได้ที่บทความนี้ครับ แนะนำให้อ่านก่อนเหมือนกันครับ ถึงจะไม่ได้ใช้ Apache แต่เนื้อหาที่ Advance ของ LDAP หลายอย่างก็เขียนไว้ในบทความนี้ครับ

พร้อมแล้วก็มาเริ่มกันเลย

การทำ Basic authen บน Nginx เราจะอาศัยตัวช่วยของ Nginx อย่าง module auth_request หลัการทำงานง่ายมากครับ ถ้า path ที่อยู่ข้างหลัง auth_request คืน HTTP 200 มาแปลว่า auth ผ่าน ถ้าคืนอย่างอื่นมาคือ authen ไม่ผ่าน

ที่นี้เราก็เข้าไปแก้ไข config ของ Nginx กันครับ ใครที่ยังแก้ไข config ของ Nginx ไม่คล่องแนะนำให้ลองศึกษาวิธีการ config ทั่วๆ ไปก่อนครับ สามารถหาบทความใน Google หรือ course online ได้มีเยอะมากเลย โดยเฉพาะ config ที่เกี่ยวกับการทำ virtual host

ผมจะแปะตัวอย่าง config สุดท้ายไว้ก่อนเลยนะครับ แล้วเดี๋ยวมาอธิบายว่าแต่ละส่วนหมายความว่ายังไงข้างล่างครับ

location /secure_area/ {
if ($http_authorization = "") {
add_header WWW-Authenticate 'Basic realm="Secure Area"'
always;
return 401;
}
auth_request /ldap_auth; proxy_pass http://localhost:12004/; # actual resource
}
location /ldap_auth {
internal;
proxy_pass http://10.1.0.90:9009;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Group "sale";
proxy_set_header X-Original-URI $request_uri;
}

Config ก้อนบน (location /secure_area/) หมายความว่า

  • ถ้า user คนไหนต้องการเข้ามาที่ path นี้ จะต้องส่ง username, password มาด้วยเสมอ ถ้าไม่ส่งมา server จะคืน 401 ไป พร้อมกับ header WWW-Authenticate Basic realm=”Secure Area” ซึ่งจะทำให้ฝั่ง browser เห็นหน้าต่างแบบนี้ครับ
Basic authentication required in Chrome
  • ถ้าส่ง username/password มาแล้ว Nginx จะส่ง request ส่งไปเช็คที่ path /ldap_auth ถ้า /ldap_auth คืน HTTP Status 200 มา Nginx จะส่ง request ไปที่ http://localhost:12004/ ซึ่งเป็นที่ๆ resource จริงๆ ที่ผู้ใช้ต้องการอยู่ เช่น อาจจะเป็นหน้าเว็บ หรือเป็น API เป็นต้น แต่ถ้า /ldap_auth ไม่ได้คืน HTTP 200 มาก็ให้ส่งค่าที่ /ldap_auth คืนมา ไปให้ผู้ใช้แทน
  • แปลว่า http://10.1.0.90:9009 ต้องคืน HTTP status 200 มาเมื่อ authen ผ่าน และคืน 401 พร้อม header WWW-Authenticate Basic realm=”Secure Area” เมื่อ authen ไม่ผ่าน เพื่อให้ browser แสดง popup เพื่อถาม username และ password ใหม่

เขียนโปรแกรม

ต่อไปเราก็จะมาเขียนโปรแกรมง่ายๆ เพื่อทำหน้าที่เป็น http://10.1.0.90:9009 โดยผมเลือกที่จะใช้ภาษา Golang ครับ จริงๆ ใช้ภาษาอะไรก็ได้ แต่พอดีผมอยากให้ผลลัพธ์ออกมาเป็น executable ที่เอาไป run ได้เลยโดยไม่ต้องลง runtime ก็เลยเลือก Golang

ลองดูตัวอย่าง code จาก repo นี้ครับ
https://github.com/perthcpe23/nginx-auth-request-ldap

หลังจากที่ run โปรแกรม ก็จะเห็นหน้าตาประมาณนี้ครับ จะเห็นว่าโปรแกรม listen ที่ port 9009 เหมือนในตัวอย่าง

ผลลัพธ์การ run โปรแกรม nginx-ldap

ตอนใช้งานจริงต้องแก้ 10.1.0.90 เป็น ip ของเครื่องจริงนะครับ

เท่านี้เลยครับ เมื่อ setup ทุกอย่างเสร็จแล้ว เราก็สั่ง

sudo nginx -t

เพื่อเช็คว่า config ถูก format แล้ว และสั่ง

sudo nginx -s reload

เพื่อ reload configuration ใหม่

เมื่อเราเข้าหน้าเว็บที่อยู่ใน /secure_area/ ก็จะเห็น popup เด้งขึ้นมาถาม username/password ครับ

--

--