Vấn đề gặp phải khi mạng có nhiều VLAN
Mình từng gặp tình huống này không ít lần: setup môi trường với nhiều VLAN — VLAN 10 cho server, VLAN 20 cho workstation, VLAN 30 cho IoT device. DHCP server chạy tập trung ở VLAN 10. Mọi thứ ổn cho đến khi máy tính ở VLAN 20 bật lên… chờ mãi không có IP.
Restart network interface, khởi động lại DHCP server, kiểm tra cáp — vẫn không ra gì. Sau đó mới vỡ ra: DHCP hoạt động dựa trên broadcast, mà broadcast thì không đi qua router hoặc layer-3 switch được. VLAN 20 và VLAN 10 là hai broadcast domain hoàn toàn tách biệt nhau.
Tại sao DHCP không tự vượt qua subnet?
DHCP Discovery packet mà client gửi ra là broadcast đến địa chỉ 255.255.255.255. Router nhận được thì bỏ qua luôn vì đó là broadcast — router không forward broadcast theo mặc định.
Cụ thể, khi client ở 192.168.20.0/24 gửi DHCP Discover:
Source IP: 0.0.0.0
Destination: 255.255.255.255
Protocol: UDP 68 (client) → UDP 67 (server)
Packet này chỉ tồn tại trong broadcast domain của VLAN 20. Router không chuyển nó sang VLAN 10 — nơi DHCP server đang chạy. Client đợi khoảng 60 giây không có ai trả lời, cuối cùng tự gán IP 169.254.x.x (APIPA) và mạng thì… không dùng được.
Ba cách giải quyết — và cái nào thực sự nên dùng
Cách 1: Chạy DHCP server riêng cho từng subnet
Cách đơn giản nhất khi nhìn bề ngoài: mỗi subnet một DHCP server. Nhưng vận hành thực tế sẽ gặp ngay:
- Quản lý phân tán, không biết IP nào đã cấp cho ai
- Thay đổi cấu hình phải sửa nhiều chỗ
- Khi có vấn đề thì debug khó gấp đôi
Cách 2: Proxy ARP hoặc unnumbered interface
Cấu hình router giả lập ARP thay cho DHCP server. Về lý thuyết hoạt động được, nhưng ARP cache timeout không đồng bộ với DHCP lease renewal sẽ gây ra những lỗi ngẫu nhiên cực kỳ khó reproduce.
Cách 3: DHCP Relay Agent — giải pháp chuẩn theo RFC
RFC 3046 ra đời chính xác để giải quyết bài toán này. DHCP Relay Agent đặt tại mỗi subnet, nhận broadcast từ client rồi chuyển thành unicast gửi thẳng đến DHCP server tập trung. Server trả lời, relay chuyển ngược lại cho client.
Luồng hoạt động:
Client (VLAN 20) --[broadcast]--> Relay Agent (192.168.20.1)
Relay Agent ------[unicast]-----> DHCP Server (192.168.10.10)
DHCP Server ------[unicast]-----> Relay Agent
Relay Agent ------[unicast]-----> Client
Cài đặt và cấu hình DHCP Relay Agent trên Linux
Bước 1: Cài isc-dhcp-relay
# Ubuntu/Debian
sudo apt update && sudo apt install isc-dhcp-relay -y
# CentOS/RHEL/Rocky Linux
sudo dnf install dhcp-relay -y
Trên Debian/Ubuntu, installer sẽ hỏi địa chỉ DHCP server và interface cần relay. Mình thường bỏ qua bước đó và cấu hình tay trong file config cho chắc ăn.
Bước 2: Xác định topology mạng
Trước khi gõ lệnh gì, cần biết rõ mình đang làm việc với dải IP nào. Mình hay dùng toolcraft.app/vi/tools/developer/ip-subnet-calculator — nhập CIDR là ra ngay network range, broadcast address, số host khả dụng. Tính tay /26 hay /27 không khó, nhưng khi có 5-6 subnet cùng lúc thì khả năng nhầm rất cao.
Topology ví dụ trong bài:
VLAN 10 (Server): 192.168.10.0/24 — interface eth0.10 (IP: 192.168.10.1)
VLAN 20 (Workstation): 192.168.20.0/24 — interface eth0.20 (IP: 192.168.20.1)
VLAN 30 (IoT): 192.168.30.0/24 — interface eth0.30 (IP: 192.168.30.1)
DHCP Server: 192.168.10.10
Linux Router/Relay: có IP trên cả 3 VLAN
Bước 3: Cấu hình isc-dhcp-relay
sudo nano /etc/default/isc-dhcp-relay
# Địa chỉ DHCP server (nhiều server cách nhau bằng dấu cách)
SERVERS="192.168.10.10"
# Interface relay lắng nghe (tất cả VLAN liên quan)
INTERFACES="eth0.10 eth0.20 eth0.30"
# -a: append agent information option (circuit-id)
OPTIONS="-a"
Option -a quan trọng hơn mình nghĩ ban đầu — nó thêm vào packet thông tin về interface nào nhận request. DHCP server dựa vào đó để phân biệt client đến từ subnet nào và cấp đúng dải IP.
Bước 4: Khai báo subnet trên DHCP server
Phía DHCP server (cũng chạy isc-dhcp-server), phải khai báo pool cho từng subnet:
sudo nano /etc/dhcp/dhcpd.conf
authoritative;
default-lease-time 86400;
max-lease-time 172800;
# VLAN 10 — server network, không cần pool nếu dùng IP tĩnh
subnet 192.168.10.0 netmask 255.255.255.0 {
option routers 192.168.10.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
# VLAN 20 — workstations
subnet 192.168.20.0 netmask 255.255.255.0 {
range 192.168.20.100 192.168.20.200;
option routers 192.168.20.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
option broadcast-address 192.168.20.255;
default-lease-time 43200;
}
# VLAN 30 — IoT devices (lease ngắn hơn)
subnet 192.168.30.0 netmask 255.255.255.0 {
range 192.168.30.50 192.168.30.150;
option routers 192.168.30.1;
option domain-name-servers 8.8.8.8;
default-lease-time 3600;
max-lease-time 7200;
}
Mẹo quan trọng: DHCP server bắt buộc phải có khai báo subnet cho tất cả mạng — kể cả mạng mà server đang nằm trên đó (VLAN 10). Nếu thiếu, dhcpd sẽ báo lỗi và từ chối khởi động.
Bước 5: Bật dịch vụ
# Trên máy relay agent (Linux router)
sudo systemctl enable --now isc-dhcp-relay
sudo systemctl status isc-dhcp-relay
# Trên DHCP server
sudo systemctl enable --now isc-dhcp-server
sudo systemctl status isc-dhcp-server
Debug khi client vẫn không lấy được IP
Lần đầu setup, mình mất gần 2 tiếng chỉ để debug phần này. Dưới đây là những lỗi thường xuyên nhất:
Kiểm tra relay agent có nhận được request không
# Xem log real-time
sudo journalctl -u isc-dhcp-relay -f
# Bắt packet trực tiếp trên interface
sudo tcpdump -i eth0.20 port 67 or port 68 -n -v
Kiểm tra DHCP server có thấy forwarded request không
sudo journalctl -u isc-dhcp-server -f
# Kiểm tra lease đã được cấp
cat /var/lib/dhcp/dhcpd.leases
Các lỗi thường gặp
“No subnet declaration for eth0.20” — Thiếu khai báo subnet trong dhcpd.conf. Thêm block subnet tương ứng vào là xong.
Relay chạy nhưng không forward — Firewall trên DHCP server có thể chặn. Kiểm tra:
# UFW
sudo ufw allow 67/udp
# iptables
sudo iptables -A INPUT -p udp --dport 67 -j ACCEPT
Client lấy được IP nhưng sai subnet — Thiếu option -a trong config relay. Server không biết phân biệt request đến từ VLAN nào, cấp đại IP đầu tiên tìm được. Thêm -a vào OPTIONS rồi restart relay.
Khi nào dùng relay trên Linux, khi nào dùng trên switch?
Nếu hạ tầng có switch layer-3 (Cisco, Juniper, MikroTik RouterOS), nên cấu hình ip helper-address thẳng trên interface VLAN của switch — gọn hơn, ít điểm lỗi hơn.
# Ví dụ Cisco IOS
interface Vlan20
ip address 192.168.20.1 255.255.255.0
ip helper-address 192.168.10.10
Nhưng trong môi trường homelab, VPS dùng làm router, hoặc hạ tầng thuần Linux, isc-dhcp-relay hoạt động ổn định và đủ dùng cho production quy mô vừa. Mình đang chạy cách này cho một mạng văn phòng nhỏ khoảng 60 thiết bị qua 4 VLAN, vài tháng nay không có vấn đề gì.

