ติดตั้ง MFA (TOTP) บน ClearPass Guest Captive Portal
คู่มือทำมือ ทีละขั้น สำหรับ deploy ระบบ 2FA ที่ผ่านการทดสอบจริงแล้วจาก pilot site — ครอบคลุมทั้ง 3 ระบบที่ต้องแตะ พร้อม gotcha ทุกจุดที่เจอมาแล้ว จะได้ไม่ต้องไปเจอซ้ำที่ site ใหม่
FreeRADIUS + Enrollment VM
VM เดียว ทำหน้าที่ 2 อย่าง: (ก) OTP oracle — เก็บ seed file แล้วตรวจรหัส TOTP ผ่าน PAM (ข) เว็บ self-service enrollment ให้ user สแกน QR ตั้งค่าเองได้ — ไม่ต้องมี real Linux account หรือรหัสผ่านของใครเก็บอยู่ในนี้เลย
site-setup.sh — รันครั้งเดียว ใส่แค่ ClearPass IP, proxy secret, enroll secret, IP ของ VM เอง ก็จบ ทดสอบ idempotent แล้วบน site จริง (รันซ้ำ 3 รอบ ผลลัพธ์เหมือนเดิมทุกครั้ง)install-mfa-host.sh ทำขั้น 1.1–1.6 ทั้งหมดจากเครื่องเปล่า (apt install, PAM binding, systemd override, mfaenroll user + sudoers, deploy app.py + venv, systemd unit) แล้วต่อท้ายด้วย site-setup.sh logic เดิมในตัวเดียวกัน — ทดสอบครบ 2 รอบบนเครื่อง pilot ที่มี demo ทำงานอยู่จริง: รอบแรกส่วนติดตั้งทั่วไป (--skip-site-config) รอบสองส่วน site-specific จริง โดยดึงค่า secret ที่ตั้งไว้แล้วบนเครื่องมาป้อนกลับเข้าไปเอง (ไม่ใช่ค่าที่เดา) แล้วให้ script restart ทั้ง freeradius และ mfa-enroll จริง — ทุกขั้นออก [ok] ครบ, healthz ตอบ 200, radtest reject รหัสผิดถูกต้อง, clients.conf มี block client clearpass แค่ตัวเดียวไม่ซ้ำ ไม่กระทบ demo ที่ทำงานอยู่ก่อนเลย/etc/sudoers.d/mfaenroll ตอนแรกสคริปต์เขียนเป็นคนละชื่อ (mfaenroll-chown) — เนื้อหากฎเหมือนกันเป๊ะ แก้ให้ตรงชื่อเดิมแล้วหลังทดสอบ (2) deployment เดิมรัน Flask ด้วย system /usr/bin/python3 ตรงๆ ส่วนสคริปต์เปลี่ยนเป็น venv — restart แล้วทำงานปกติทั้งคู่ เก็บไว้แบบ venv ตามเดิมเพราะแยก dependency ได้สะอาดกว่าติดตั้ง FreeRADIUS + PAM module
apt-get update
apt-get install -y freeradius libpam-google-authenticator
mkdir -p /etc/freeradius/ga
chown freerad:freerad /etc/freeradius/ga
chmod 2770 /etc/freeradius/ga # setgid — enrollment app ต้อง join group freeradผูก PAM เข้ากับ seed file ต่อ user
user=freerad คือหัวใจของดีไซน์นี้ — บังคับให้ PAM อ่าน/เขียนไฟล์ด้วยสิทธิ์ของ user จริง "freerad" เสมอ ไม่ว่า RADIUS username ที่ล็อกอินจะเป็นใคร (จะได้ไม่ต้องสร้าง Linux account จริงให้ทุกคน)
auth required pam_google_authenticator.so secret=/etc/freeradius/ga/${USER} user=freerad
account required pam_permit.soลงทะเบียน ClearPass เป็น RADIUS client
client clearpass {
ipaddr = <clearpass-ip>
secret = <shared-secret>
require_message_authenticator = true # BlastRADIUS mitigation — ใส่ทั้ง 2 ฝั่ง
}
client localhost {
secret = testing123
require_message_authenticator = true
}Harden systemd (non-root, ยัง sudo ได้)
unit ของ distro บางตัวใส่ ReadOnlyDirectories=/etc/freeradius/ มาด้วย ซึ่งบล็อกการเขียน seed file — ต้อง override ทับ
[Service] ReadWriteDirectories=/etc/freeradius/ga
sudo ภายใน — flag นี้บล็อก sudo เงียบๆ ไม่มี error log ชัดเจน ไล่นานมากDeploy self-service enrollment app
Flask app เล็กๆ รันเป็น user แยก (เช่น mfaenroll) ที่ join group freerad ไว้ — endpoint หลักที่ต้องมี: /api/check (ตรวจรหัสผ่าน+สถานะ enroll), /enroll (แสดง QR), /enroll/confirm, /reset + /api/reset (self-service reset), /route-enroll-check (เช็คสถานะ enroll แบบ redirect เดียว ไม่ยิง fetch ข้าม origin)
useradd -r -s /usr/sbin/nologin mfaenroll
usermod -aG freerad mfaenroll
# narrow sudoers rule — ใช้แค่ chown ไฟล์ seed หลังสร้างใหม่
echo 'mfaenroll ALL=(root) NOPASSWD: /usr/bin/chown freerad\:freerad /etc/freeradius/ga/*' \
> /etc/sudoers.d/mfaenroll-chownVerify ก่อนไปต่อ — ห้ามข้าม
ต้องเห็น seed file, ต้อง radtest/radclient ผ่านจากเครื่องนี้เองก่อน ค่อยไปแตะ ClearPass
freeradius -X # รันแบบ foreground ดู log สดๆ ระหว่างเทส # terminal อีกอัน: radtest <username> <6-digit-otp> localhost 0 testing123
ClearPass Policy Manager
3 Service + 1 Enforcement Policy — เป็นส่วนที่พลาดง่ายที่สุดเรื่อง ลำดับ ของ Service list ดู Gotcha #1 ก่อนทำ
python3 generate-site-kit.py) กรอกค่าของ site นี้ครั้งเดียว (IP, secret 3 ชุด, ชื่อ object เดิมบน controller) จะได้คำสั่ง Part 1 พร้อมรัน, cheat sheet ค่าที่ต้องกรอกใน GUI ของ Part 2–3 ครบทุกช่อง, และ script dry-run/live ของ Part 4 ทันทีในเบราว์เซอร์ — ลดโอกาสพิมพ์ผิดหรือสลับ secret ระหว่างขั้นตอน (คำนวณในเบราว์เซอร์ล้วนๆ ไม่ส่งออกไปไหน แต่ผลลัพธ์มี secret จริง ไม่ commit เข้า git)Enforcement Policy — สร้างก่อน เพราะ 3 Service ในขั้นถัดไปจะอ้างอิงชื่อนี้
Configuration → Enforcement → Policies → Add
| Field | ค่า |
|---|---|
| Name | MFA-OTP-Passthrough-Allow |
| Enforcement Type | RADIUS |
| Default Profile | [Allow Access Profile] |
ไม่ต้องเพิ่ม rule ในแท็บ Rules — ปล่อยว่างไว้แล้ว Save ได้เลย (accept/reject ตัวจริงตัดสินที่ proxy target ใน 2.3 ไม่ใช่ที่นี่ ไม่ต้องมี accounting หรือ CoA ในดีไซน์นี้)
Network Device — ลงทะเบียน enrollment VM เป็น RADIUS client ของ ClearPass
Configuration → Network → Devices → Add
| Field | ค่า |
|---|---|
| Name | เช่น mfa-enroll-vm |
| IP or Subnet Address | <enrollment-vm-ip> (VM ใน Part 1) |
| RADIUS Shared Secret | secret ชุด "enroll" — ต้องตรงกับ CLEARPASS_RADIUS_SECRET ใน /opt/mfa-enroll/env บน VM |
| Vendor Name | Aruba |
| Enable RADIUS Dynamic Authorization | ✔ ติ๊ก, port 3799 |
Proxy Target → FreeRADIUS VM (ชี้ทางกลับ — ClearPass → VM)
Configuration → Network → Proxy Targets → Add
| Field | ค่า |
|---|---|
| Name | เช่น FreeRADIUS-MFA-OTP |
| Hostname | <enrollment-vm-ip> (เครื่องเดียวกับ 2.2) |
| Protocol | RADIUS |
| Shared Secret | secret ชุด "proxy" — ต้องตรงกับ client clearpass ใน clients.conf บน VM |
| RADIUS Auth / Acct Port | 1812 / 1813 (default ไม่ต้องแก้) |
สร้าง 3 Services
Configuration → Services → Add Service — ทำ 3 รอบตามตารางนี้ ทุก Service ผูก Enforcement Policy (แท็บ Enforcement) เป็น MFA-OTP-Passthrough-Allow จาก 2.1 เหมือนกันหมด
| Service | Type | Rule | ทำหน้าที่ |
|---|---|---|---|
| MFA-OTP-Verify- via-FreeRADIUS | RADIUS Proxy | NAD-IP-Address = <controller-ip> | ส่ง OTP ต่อไปให้ FreeRADIUS ตรวจ (Proxy Targets แท็บ → 2.3) |
| MFA-Step1- Password-LocalUser | RADIUS Enforcement (Generic) | NAD-IP-Address = 127.0.0.1 AND Radius:Aruba Aruba-Port-Id = mfa-step1-login | ตรวจรหัสผ่านตอน Guest page เรียก Pre-Auth Check เอง |
| MFA-Enroll- Password-Check | RADIUS Enforcement (Generic) | NAD-IP-Address = <enrollment-vm-ip> | ตรวจรหัสผ่านตอน enrollment app เรียกเอง |
2 Service ล่างใช้ Authentication Methods = [PAP], Authentication Sources = [Local User Repository] (หรือ directory จริงของ site นั้น) — เงื่อนไข Match ALL/ANY ตั้งที่แท็บ Service (ปุ่ม Add Rule), Methods/Sources ตั้งที่แท็บ Authentication
เรียงลำดับ Service ให้ถูก — ห้ามข้าม
ในหน้า Services ลาก MFA-OTP-Verify-via-FreeRADIUS ขึ้นไปอยู่เหนือ service เดิมทุกตัวที่อาจ match แบบกว้างๆ (เช่น service 802.1X wireless เก่าที่เช็คแค่ NAS-Port-Type) — กดปุ่ม Reorder มุมขวาบน แล้วลากบรรทัดขึ้น
clearpass-api-setup.py) แต่ยังใช้กับ pilot site นี้ไม่ได้ — root cause ยืนยันแล้วว่า ClearPass Guest's Apigility (PHP API framework) ขาดไฟล์ /opt/amigopod/www/_include/Apigility/config/application.config.php บน disk ของเครื่องนี้จริงๆ (เห็น error นี้ใน Guest → Administration → Support → Application Log ทุกครั้งที่ยิง API, ทดสอบซ้ำล่าสุด 8 ก.ย. 2026 ด้วย API Client ใหม่ก็ยังเป็นแบบเดิม — HTTP 200 body ว่างเปล่า ไม่ใช่ปัญหา client_id/secret) เป็นเรื่องที่ต้องแจ้งทีมดูแล ClearPass ตัวนี้ไปซ่อม/ติดตั้ง Apigility ใหม่ ระหว่างนี้ให้ทำตามขั้นตอน manual ด้านบนแทนClearPass Guest — 2 Web Login Pages
Step 1 เช็ครหัสผ่าน (ไม่แตะ controller จริง) → Step 2 เช็ค OTP (ยิงตรงไป controller จริง) — ทั้งคู่ skin เดียวกันได้ แต่ field setting ต่างกันชัดเจน
เปิดหน้าสร้าง Web Login
Menu → Guest (เปิด ClearPass Guest คนละหน้าต่างจาก Policy Manager) แล้ว Configuration → Pages → Web Logins → Create a new web login page — ทำ 2 รอบ ตามข้อ 3.2 และ 3.3
หน้าที่ 1 — mfa-step1-login (เช็ครหัสผ่าน)
| Field | ค่า |
|---|---|
| Name | MFA-Step1-Password-Login |
| Page Name | mfa-step1-login — ต้องตรงกับ Service MFA-Step1-Password-LocalUser ใน Part 2.4 เป๊ะ |
| Vendor Settings | Aruba |
| Login Method | Policy-initiated |
| Authentication | Credentials — Require a username and password |
| Pre-Auth Check | RADIUS → service ที่ match 127.0.0.1 |
| Default URL | URL ของหน้า Step 2 (3.3) — เช่น https://<clearpass-ip>/guest/mfa-otp-login.php |
| Force default destination | ✔ ต้องติ๊ก — ดู Gotcha #2 |
ใส่ลิงก์ "First time connecting?" ไปหน้า enroll และลิงก์ "Lost your authenticator? Reset it here" ไปหน้า reset ไว้ใน Header/Footer HTML เป็น <a href> ธรรมดา (ห้ามเป็น cross-origin fetch/form — ดู Gotcha #3–4)
หน้าที่ 2 — mfa-otp-login (เช็ค OTP)
| Field | ค่า |
|---|---|
| Name | MFA-OTP-Guest-Login |
| Page Name | mfa-otp-login |
| Vendor Settings | Aruba |
| Login Method | Controller-initiated |
| Address | IP ของ controller จริง |
| Authentication | Credentials — Require a username and password |
| Pre-Auth Check | None — ดู Gotcha #5 |
| Password Label | "OTP Code:" (custom label) |
UX เสริม (ไม่บังคับ แต่ประสบการณ์ user ดีขึ้นมาก)
สคริปต์เล็กๆ ใน Footer HTML ของทั้ง 2 หน้า ทำ 3 อย่าง โดยใช้ sessionStorage ล้วนๆ (ไม่ใช่ fetch ข้าม origin):
// หน้า Step 1 — ดัก username ตอนกด submit/Enter sessionStorage.setItem('mfa_username', usernameFieldValue) // หน้า Step 2 — โหลดปุ๊บ: 1) fill + ซ่อนช่อง username (เหลือแค่กรอก OTP) 2) redirect (ธรรมดา ไม่ใช่ fetch) ไปเช็คว่า enroll แล้วหรือยัง → enroll แล้ว: bounce กลับมาหน้าเดิมพร้อม ?checked=1 → ยังไม่ enroll: ส่งตรงไปหน้า enroll พร้อม prefill username
Aruba Controller (ArubaOS 8)
สมมติว่า SSID / AP-group / VLAN มีอยู่แล้ว — ส่วนนี้ทำแค่ 3 อย่าง: เปิด walled-garden ให้ guest คุยกับ VM ได้, ผูก RADIUS ไปหา ClearPass, sync secret
provision-controller.py — SSH เข้า controller เอง (10.69.11.63) ยิงคำสั่งตามลำดับด้วยชื่อ object จริงของ site นี้ (hpe-guest_cppm_prof, cppm-12, HPE-Guest_dot1_svg) และ secret จริง ปิดท้ายด้วย write memory — transcript ออกมาไม่มี % Invalid input เลยสักบรรทัด, Configuration Saved ชัดเจน หลังรันตรวจซ้ำด้วย show rights / show aaa server-group / show netdestination สดจาก CLI: mfa-enroll-whitelist ยังอยู่ตำแหน่ง 3 ตัวเดียวไม่ซ้ำ, server-group มี auth-server cppm-12 ตัวเดียว, netdestination มีแค่ 2 host ตามที่ตั้งไว้ — ยืนยันว่ารันซ้ำได้จริง ไม่สร้าง object ซ้ำWalled-garden — เปิดช่องให้ guest (ยังไม่ authenticate) คุยกับ ClearPass + enrollment VM ได้
netdestination "mfa-walled-garden"
host <clearpass-ip>
host <enrollment-vm-ip>
!
netservice svc-mfa-enroll tcp 8443
!
ip access-list session mfa-enroll-whitelist
user alias mfa-walled-garden svc-mfa-enroll permit
!
user-role <pre-auth-role-ของ-SSID>
access-list session mfa-enroll-whitelist position 3 # position 1-2 reserved ระบบผูก RADIUS server-group ให้ captive portal ยิงไป ClearPass
aaa authentication-server radius cppm-otp
host <clearpass-ip>
key <shared-secret> # ต้องตรงกับ Network Device ใน ClearPass เป๊ะ
!
aaa server-group mfa-otp-svg
auth-server cppm-otp position 1
!
aaa authentication captive-portal "<ชื่อ-cp-profile-ของ-SSID>"
server-group mfa-otp-svgVerify จาก controller เองก่อนลองมือถือจริง
aaa test-server pap cppm-otp <username> <otp-code>
→ ควรได้ "Authentication Successful" ก่อนไปทดสอบผ่าน Wi-Fi จริง-o KexAlgorithms=+diffie-hellman-group14-sha1 -o HostKeyAlgorithms=+ssh-rsaLive-Verified Configuration (Pilot Site)
เดินหน้าจอจริงผ่าน ClearPass Policy Manager, ClearPass Guest และ Aruba Controller GUI เมื่อ 5 ก.ย. 2026 เพื่อยืนยันว่าค่าที่ตั้งไว้ตรงกับที่ Part 2–4 อธิบาย — เก็บชื่อ object จริงไว้เป็นตัวอย่างอ้างอิงตอนไป deploy site ใหม่ (ชื่อจะไม่เหมือนกันทุก site แต่โครงสร้างเหมือนกัน)
site-setup.sh และ provision-controller.py รันจริงไปตอนตั้งค่าNetwork Device + Proxy Target (2 secret คนละทิศ — ดู Part 1)
| Object | ประเภท | ค่า |
|---|---|---|
| cppm-mfa-enroll | Network Device | |
| FreeRADIUS-MFA-OTP | Proxy Target |
3 Services (ตรวจแล้วอยู่เหนือ service เก่าทุกตัว — Gotcha #1 ผ่าน)
| Service | Rule จริง | Enforcement |
|---|---|---|
| MFA-OTP-Verify- via-FreeRADIUS | NAD-IP-Address = | MFA-OTP- Passthrough-Allow |
| MFA-Step1- Password-LocalUser | NAD-IP-Address = 127.0.0.1 AND Radius:Aruba Aruba-Port-Id = mfa-step1-login → [Local User Repository] + [Local SQL DB], PAP | |
| MFA-Enroll- Password-Check | NAD-IP-Address = |
MFA-OTP-Passthrough-Allow: Default Profile = [Allow Access Profile], rule เดียว (Date:Day-of-Week EXISTS) → allow เสมอ — accept/reject ตัวจริงตัดสินที่ proxy target (FreeRADIUS) ไม่ใช่ที่นี่
2 Web Login pages จริง (ClearPass Guest)
| Field | mfa-step1-login | mfa-otp-login |
|---|---|---|
| Login Method | Policy-initiated | Controller-initiated |
| Pre-Auth Check | RADIUS request | None |
| Address / Default URL | Default URL = https:// | Address = |
| Override Destination | ✔ Force default destination for all clients | — |
Footer HTML ของหน้า Step 1 ยืนยันมี mfaCaptureUser() เก็บ username ลง sessionStorage จริง และมีลิงก์ manual enroll (<a href> ธรรมดา) ไปหา enrollment VM ตามที่ Gotcha #3–4 อธิบายไว้
Aruba Controller — role และ RADIUS จริง
| Object | ค่า |
|---|---|
| Pre-auth role | HPE-Guest-guest-logon — session ACL mfa-enroll-whitelist (1 rule) ติดอยู่ครั้งเดียว ไม่ซ้ำแม้รันสคริปต์ซ้ำ 3 รอบ |
| Auth Server | cppm-12 · RADIUS · |
| Server Group | HPE-Guest_dot1_svg (คนละกลุ่มกับ default/internal ของระบบ) |
ชื่อจริงเหล่านี้ต่างจากค่า default ในสคริปต์ (mfa-walled-garden, cppm-otp, mfa-otp-svg) — ตอนรัน provision-controller.py กับ site นี้ต้องสั่งด้วย flag override เช่น --walled-garden-name hpe-guest_cppm_prof --radius-server-name cppm-12 --server-group-name HPE-Guest_dot1_svg เสมอ อย่าใช้ default เปล่าๆ กับ site ที่มี object เดิมอยู่แล้ว
Known Gotchas
9 จุดที่เจอมาแล้วจริงตอน pilot — เก็บไว้เป็น reference จะได้ไม่ไปเสียเวลาไล่ซ้ำที่ site ใหม่
Service ที่กว้างกว่าแต่มาก่อนใน list ชนะเสมอ
- อาการ
- OTP ที่ถูกต้อง กลับโดน Reject จาก controller จริง ทั้งที่ยิงจาก radtest ตรงๆ ผ่านสบาย
- สาเหตุ
- มี Service เก่า (เช่น 802.1X wireless) rule กว้างกว่า (เช็คแค่ NAS-Port-Type) อยู่เหนือ service ของเรา ClearPass หยุดที่ตัวแรกที่ match ไม่สนความเจาะจง
- แก้
- Reorder ให้ MFA-OTP-Verify-via-FreeRADIUS ขึ้นไปอยู่เหนือ service ที่กว้างกว่าทุกตัว
Login วนกลับหน้า Step 1 ทั้งที่รหัสผ่านถูก
- อาการ
- Access Tracker ยืนยันว่า ACCEPT ทุกครั้ง แต่มือถือ (iOS โดยเฉพาะ) เด้งกลับมาหน้า login เดิมวนไปเรื่อยๆ
- สาเหตุ
- มือถือมี background probe เช็คอินเทอร์เน็ต (เช่น
captive.apple.com) ที่ยิงไปก่อนเรามี session — ClearPass เอา URL นั้นมาใช้เป็นปลายทาง redirect หลัง login แทนที่จะใช้ Default URL ที่เราตั้ง แล้ว controller ก็ดัก URL นั้นซ้ำ กลายเป็นวน - แก้
- ติ๊ก "Force default destination for all clients" ในหน้า Step 1 — บังคับใช้ Default URL เสมอไม่สนว่า client ขอ URL อะไรมา
fetch() ข้าม origin จากหน้า HTTPS ไปหา backend ของเราไม่ทำงานบนมือถือจริง
- อาการ
- ทดสอบบน browser ปกติผ่านหมด แต่มือถือ guest ค้างที่ "Checking..." ตลอด
- สาเหตุ
- เบราว์เซอร์ไม่เชื่อ TLS cert ของ backend เรา (self-signed หรือ internal CA) เพราะ guest device ไม่เคยลง CA นั้น — ลง CA ให้ guest ทุกคนไม่ practical
- แก้
- เปลี่ยนจาก fetch()/XHR เป็น top-level GET redirect ธรรมดา (
<a href>หรือwindow.location.href) — ไม่โดน TLS-trust check แบบเดียวกัน
<form> POST จาก HTTPS ไป HTTP โดน browser เตือน "ฟอร์มไม่ปลอดภัย" บล็อกไปเลย
- อาการ
- เปลี่ยนมาใช้ plain HTML form (ไม่ใช่ fetch) แล้ว ยังใช้ไม่ได้ — เจอหน้าเตือนแทน
- สาเหตุ
- Chrome/Safari สมัยใหม่บล็อก mixed-content form submission (HTTPS page → HTTP action) โดยเฉพาะ ไม่ว่าจะ fetch หรือ form ธรรมดาก็โดน
- แก้
- เหมือน Gotcha #3 — ใช้ redirect/link ธรรมดาแทน form POST เสมอเมื่อข้าม origin แบบ https→http
OTP ถูกใช้ซ้ำ 2 ครั้งในการ login เดียว — reject รอบสอง
- อาการ
- กรอก OTP ถูก แต่โดน reject ที่ controller จริง ทั้งที่ ClearPass Guest บอกว่าผ่าน
- สาเหตุ
- Pre-Auth Check ของหน้า Step 2 (ตั้งเป็น RADIUS) แอบไปตรวจ+ใช้ OTP นั้นไปแล้วรอบนึง ก่อนที่ browser จะยิงไปเช็คจริงที่ controller (ใช้ซ้ำไม่ได้เพราะ DISALLOW_REUSE)
- แก้
- ตั้ง Pre-Auth Check ของหน้า Step 2 เป็น None — ให้ controller เป็นจุดตรวจ OTP จุดเดียวเท่านั้น
seed file ใหม่ สร้างเสร็จแต่ PAM reject ทันที
- อาการ
/var/log/auth.logฟ้อง "permissions (0640) are more permissive than 0600"- สาเหตุ
pam_google_authenticatorกับstrict_ownerต้องการไฟล์ mode 0600 เป๊ะ และเจ้าของต้องเป็น user ที่ระบุในuser=ของ pam.d- แก้
- สร้างไฟล์ด้วย mode 0600 เสมอ + chown เป็น freerad:freerad หลังสร้าง
systemd hardening บล็อก sudo ภายใน enrollment app
- อาการ
- chown ไฟล์ seed fail ด้วย exit 1 เฉพาะตอนรันผ่าน systemd (รันมือนอก service ผ่านปกติ)
- สาเหตุ
NoNewPrivileges=trueใน unit file บล็อกsudo -nเงียบๆ- แก้
- เอา
NoNewPrivilegesออกจาก service ที่ต้องเรียก sudo ภายใน
radtest ไม่สะท้อน NAS-IP จริง
- อาการ
- ทดสอบผ่าน radtest แล้วเงียบ ไม่โดน Service rule ไหนจับเลยใน Access Tracker
- สาเหตุ
radtestตั้ง NAS-IP-Address เป็น127.0.1.1เสมอ ไม่ใช่ IP เครื่องจริงที่รัน- แก้
- ใช้
radclientแล้วใส่NAS-IP-Addressเอง ให้ตรงกับ IP จริงที่ Service rule คาดหวัง
BlastRADIUS — อย่าลืม require_message_authenticator
- อาการ
- ไม่ใช่ bug ที่เจอตรงๆ แต่เป็นช่องโหว่ระดับ protocol (CVE-2024-3596) ที่ RADIUS classic เจอทั้งวงการ
- สาเหตุ
- RADIUS ดั้งเดิมตรวจสอบ integrity ของ response อ่อนเกินไป
- แก้
- ใส่
require_message_authenticator = trueในทุกclientblock ของ clients.conf — และเช็คว่าฝั่ง proxy ของ ClearPass เปิดเหมือนกัน
Go-Live Checklist
เช็คตามลำดับ ห้ามข้าม verification step ไปทำขั้นถัดไป — สถานะเซฟไว้ในเบราว์เซอร์นี้อัตโนมัติ