This is one of the most powerful features of centralized RADIUS authentication.
Key Concept
┌─────────────────────────────────────────────────────────────────┐
│ Different NAS devices (routers) = Different SECRETS │
│ Same RADCHECK users = Work on ALL routers │
└─────────────────────────────────────────────────────────────────┘
Visual Example
┌──────────────────────┐
│ RADIUS SERVER │
│ (192.168.0.100) │
│ │
│ User Database: │
│ ┌────────────────┐ │
│ │ john / Pass1 │ │
│ │ jane / Pass2 │ │
│ │ admin / Pass3 │ │
│ └────────────────┘ │
└──────────────────────┘
▲
┌────────────┼────────────┐
│ │ │
Secret: "ABC123" │ Secret: "XYZ789"
│ │ │
┌───────────▼──┐ ┌───▼──────────┐ ┌────▼─────────┐
│ Router A │ │ Router B │ │ Router C │
│ 192.168.1.1 │ │ 192.168.2.1 │ │ 192.168.3.1 │
│ (Branch 1) │ │ (Branch 2) │ │ (Branch 3) │
└──────────────┘ └──────────────┘ └──────────────┘
▲ ▲ ▲
│ │ │
User: john User: john User: admin
Pass: Pass1 Pass: Pass1 Pass: Pass3
✓ ✓ ✓
SUCCESS! SUCCESS! SUCCESS!
Real-World Example
-- Setup NAS table with different secrets per location
INSERT INTO nas (nasname, shortname, type, secret, description) VALUES
('192.168.1.1', 'bangkok-office', 'mikrotik', 'Bangkok@Secret2025', 'Bangkok Branch'),
('192.168.2.1', 'chiangmai-office', 'mikrotik', 'ChiangMai@Secret2025', 'Chiang Mai Branch'),
('192.168.3.1', 'phuket-office', 'mikrotik', 'Phuket@Secret2025', 'Phuket Branch'),
('192.168.4.1', 'pattaya-office', 'mikrotik', 'Pattaya@Secret2025', 'Pattaya Branch');
-- Create ONE user that works on ALL routers
INSERT INTO radcheck (username, attribute, op, value) VALUES
('john_admin', 'Cleartext-Password', ':=', 'Admin@Pass123');
INSERT INTO radusergroup (username, groupname, priority) VALUES
('john_admin', 'admin_users', 1);
INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES
('admin_users', 'Mikrotik-Rate-Limit', ':=', '50M/50M'),
('admin_users', 'Session-Timeout', ':=', '86400');
Result:
- User
john_admin
can login from Bangkok router (secret: Bangkok@Secret2025) - User
john_admin
can login from Chiang Mai router (secret: ChiangMai@Secret2025) - User
john_admin
can login from Phuket router (secret: Phuket@Secret2025) - User
john_admin
can login from Pattaya router (secret: Pattaya@Secret2025)
Same username/password everywhere!
Complete Multi-Location Example
USE radius;
-- ============================================
-- STEP 1: Setup NAS devices (different secrets)
-- ============================================
DELETE FROM nas;
INSERT INTO nas (nasname, shortname, type, secret, description) VALUES
-- Head Office
('10.10.1.1', 'hq-router', 'mikrotik', 'HQ@Secure!2025', 'Head Office Router'),
-- Regional Offices
('10.20.1.1', 'region1-router', 'mikrotik', 'Region1@Secure!2025', 'Region 1 Office'),
('10.30.1.1', 'region2-router', 'mikrotik', 'Region2@Secure!2025', 'Region 2 Office'),
-- Branches
('10.40.1.1', 'branch1-router', 'mikrotik', 'Branch1@Secure!2025', 'Branch 1'),
('10.40.2.1', 'branch2-router', 'mikrotik', 'Branch2@Secure!2025', 'Branch 2'),
('10.40.3.1', 'branch3-router', 'mikrotik', 'Branch3@Secure!2025', 'Branch 3'),
-- Hotels
('172.16.1.1', 'hotel-bangkok', 'mikrotik', 'HotelBKK@2025', 'Hotel Bangkok'),
('172.16.2.1', 'hotel-phuket', 'mikrotik', 'HotelPhuket@2025', 'Hotel Phuket'),
-- Cafes
('172.17.1.1', 'cafe-central', 'mikrotik', 'CafeCentral@2025', 'Cafe Central Plaza'),
('172.17.2.1', 'cafe-airport', 'mikrotik', 'CafeAirport@2025', 'Cafe Airport');
-- ============================================
-- STEP 2: Create user groups
-- ============================================
DELETE FROM radgroupreply WHERE groupname IN ('company_admin', 'company_staff', 'hotel_guest', 'cafe_customer');
DELETE FROM radgroupcheck WHERE groupname IN ('company_admin', 'company_staff', 'hotel_guest', 'cafe_customer');
-- Admin users (work everywhere)
INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES
('company_admin', 'Mikrotik-Rate-Limit', ':=', '100M/100M'),
('company_admin', 'Session-Timeout', ':=', '86400'),
('company_admin', 'Acct-Interim-Interval', ':=', '300');
INSERT INTO radgroupcheck (groupname, attribute, op, value) VALUES
('company_admin', 'Simultaneous-Use', ':=', '10');
-- Staff users (work at all company locations)
INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES
('company_staff', 'Mikrotik-Rate-Limit', ':=', '20M/20M'),
('company_staff', 'Session-Timeout', ':=', '28800'),
('company_staff', 'Idle-Timeout', ':=', '3600');
INSERT INTO radgroupcheck (groupname, attribute, op, value) VALUES
('company_staff', 'Simultaneous-Use', ':=', '3'),
('company_staff', 'Login-Time', ':=', 'Al0700-2000');
-- Hotel guests (work at all hotels)
INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES
('hotel_guest', 'Mikrotik-Rate-Limit', ':=', '5M/5M'),
('hotel_guest', 'Session-Timeout', ':=', '86400'),
('hotel_guest', 'Idle-Timeout', ':=', '1800'),
('hotel_guest', 'Mikrotik-Recv-Limit', ':=', '3221225472'), -- 3GB
('hotel_guest', 'Mikrotik-Xmit-Limit', ':=', '3221225472');
INSERT INTO radgroupcheck (groupname, attribute, op, value) VALUES
('hotel_guest', 'Simultaneous-Use', ':=', '3');
-- Cafe customers (work at all cafes)
INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES
('cafe_customer', 'Mikrotik-Rate-Limit', ':=', '10M/10M'),
('cafe_customer', 'Session-Timeout', ':=', '14400'), -- 4 hours
('cafe_customer', 'Idle-Timeout', ':=', '1800'),
('cafe_customer', 'Mikrotik-Recv-Limit', ':=', '2147483648'), -- 2GB
('cafe_customer', 'Mikrotik-Xmit-Limit', ':=', '2147483648');
INSERT INTO radgroupcheck (groupname, attribute, op, value) VALUES
('cafe_customer', 'Simultaneous-Use', ':=', '2');
-- ============================================
-- STEP 3: Create users (work on ALL locations)
-- ============================================
DELETE FROM radcheck WHERE username IN ('ceo', 'manager_john', 'staff_alice', 'staff_bob', 'room101', 'room201', 'cafe_daily001');
DELETE FROM radusergroup WHERE username IN ('ceo', 'manager_john', 'staff_alice', 'staff_bob', 'room101', 'room201', 'cafe_daily001');
-- Company Admin (can use ANY company router)
INSERT INTO radcheck (username, attribute, op, value) VALUES
('ceo', 'Cleartext-Password', ':=', 'CEO@Secure2025!');
INSERT INTO radusergroup (username, groupname, priority) VALUES
('ceo', 'company_admin', 1);
-- Company Manager (can use ANY company router)
INSERT INTO radcheck (username, attribute, op, value) VALUES
('manager_john', 'Cleartext-Password', ':=', 'Manager@John2025');
INSERT INTO radusergroup (username, groupname, priority) VALUES
('manager_john', 'company_admin', 1);
-- Company Staff (can use ANY company router)
INSERT INTO radcheck (username, attribute, op, value) VALUES
('staff_alice', 'Cleartext-Password', ':=', 'Staff@Alice2025'),
('staff_bob', 'Cleartext-Password', ':=', 'Staff@Bob2025');
INSERT INTO radusergroup (username, groupname, priority) VALUES
('staff_alice', 'company_staff', 1),
('staff_bob', 'company_staff', 1);
-- Hotel Guest (can use ANY hotel router)
INSERT INTO radcheck (username, attribute, op, value) VALUES
('room101', 'Cleartext-Password', ':=', 'Room-101-WiFi'),
('room201', 'Cleartext-Password', ':=', 'Room-201-WiFi');
INSERT INTO radusergroup (username, groupname, priority) VALUES
('room101', 'hotel_guest', 1),
('room201', 'hotel_guest', 1);
-- Cafe Customer (can use ANY cafe router)
INSERT INTO radcheck (username, attribute, op, value) VALUES
('cafe_daily001', 'Cleartext-Password', ':=', 'Cafe@Daily001');
INSERT INTO radusergroup (username, groupname, priority) VALUES
('cafe_daily001', 'cafe_customer', 1);
-- ============================================
-- VERIFICATION
-- ============================================
SELECT '=== NAS DEVICES ===' as info;
SELECT nasname, shortname, LEFT(secret, 10) as secret_preview, description FROM nas;
SELECT '' as '';
SELECT '=== USERS ===' as info;
SELECT c.username, LEFT(c.value, 10) as pass_preview, g.groupname
FROM radcheck c
LEFT JOIN radusergroup g ON c.username = g.username
WHERE c.attribute = 'Cleartext-Password'
ORDER BY g.groupname, c.username;
Testing Script
#!/bin/bash
# test_multi_location.sh
echo "=== Testing Multi-Location RADIUS Setup ==="
echo ""
# Test company admin on different routers
echo "1. Testing CEO on HQ Router:"
radtest ceo 'CEO@Secure2025!' localhost 0 'HQ@Secure!2025' | grep -E "Access-Accept|Access-Reject"
echo ""
echo "2. Testing CEO on Region 1 Router (different secret):"
radtest ceo 'CEO@Secure2025!' localhost 0 'Region1@Secure!2025' | grep -E "Access-Accept|Access-Reject"
echo ""
echo "3. Testing Staff on Branch 1:"
radtest staff_alice 'Staff@Alice2025' localhost 0 'Branch1@Secure!2025' | grep -E "Access-Accept|Access-Reject"
echo ""
echo "4. Testing Staff on Branch 2 (different secret):"
radtest staff_alice 'Staff@Alice2025' localhost 0 'Branch2@Secure!2025' | grep -E "Access-Accept|Access-Reject"
echo ""
echo "5. Testing Hotel Guest on Bangkok Hotel:"
radtest room101 'Room-101-WiFi' localhost 0 'HotelBKK@2025' | grep -E "Access-Accept|Access-Reject"
echo ""
echo "6. Testing Hotel Guest on Phuket Hotel (different secret):"
radtest room101 'Room-101-WiFi' localhost 0 'HotelPhuket@2025' | grep -E "Access-Accept|Access-Reject"
echo ""
echo "7. Testing Cafe Customer on Central Cafe:"
radtest cafe_daily001 'Cafe@Daily001' localhost 0 'CafeCentral@2025' | grep -E "Access-Accept|Access-Reject"
echo ""
echo "8. Testing Cafe Customer on Airport Cafe (different secret):"
radtest cafe_daily001 'Cafe@Daily001' localhost 0 'CafeAirport@2025' | grep -E "Access-Accept|Access-Reject"
echo ""
echo "=== All Tests Complete ==="
Benefits of This Architecture
✅ Centralized User Management
- Add user ONCE → Works everywhere
- Change password ONCE → Updated everywhere
- Disable user ONCE → Blocked everywhere
✅ Security Per Location
- Each location has unique secret
- If one secret is compromised, others are safe
- Can revoke access per location by removing NAS entry
✅ Flexibility
- Roaming users (staff travel between branches)
- Same credentials everywhere
- Easy to add new locations
✅ Simplified Management
-- Add new location (just add NAS)
INSERT INTO nas (nasname, shortname, type, secret, description) VALUES
('10.50.1.1', 'new-branch', 'mikrotik', 'NewBranch@2025', 'New Branch Office');
-- All existing users automatically work there!
Location-Specific Users (If Needed)
Sometimes you want users that ONLY work at specific locations:
-- Create location-specific user
INSERT INTO radcheck (username, attribute, op, value) VALUES
('guest_bangkok_only', 'Cleartext-Password', ':=', 'Bangkok@Guest'),
('guest_bangkok_only', 'NAS-IP-Address', '==', '172.16.1.1'); -- Only this NAS
-- This user can ONLY login from Bangkok hotel (172.16.1.1)
Query to See Where User Can Login
-- See which routers a user can access
SELECT
c.username,
'ALL LOCATIONS' as access,
GROUP_CONCAT(n.shortname SEPARATOR ', ') as available_routers
FROM radcheck c
CROSS JOIN nas n
WHERE c.username = 'staff_alice'
AND c.attribute = 'Cleartext-Password'
GROUP BY c.username;
Summary
Component | Uniqueness | Shared? |
---|---|---|
NAS Secret | Different per router | ❌ NO (unique) |
User Credentials | Same everywhere | ✅ YES (shared) |
User Groups | Same everywhere | ✅ YES (shared) |
Group Attributes | Same everywhere | ✅ YES (shared) |
The Power:
10 Routers × 1000 Users = Only 1000 user accounts to manage!
(Not 10,000 separate accounts)
This is centralized authentication at its best! 🎉
Does this clarify the relationship? Any other questions about how the tables work together?