Sửa lỗi "connect: No route to host" Khi Kết Nối Đến Remote Server

intermediate🌐 Networking2026-03-24| Linux (Ubuntu, CentOS, RHEL, Debian) — ảnh hưởng đến SSH, curl, wget, TCP clients

Error Message

connect: No route to host
#networking#routing#firewall#iptables

Chuyện gì đang xảy ra

Bạn chạy ssh user@192.168.1.50 hoặc curl http://10.0.0.5:8080 và nhận được lỗi:

connect: No route to host

Lỗi này khác với hai lỗi hay bị nhầm lẫn. Connection refused nghĩa là dịch vụ đang chạy nhưng chủ động từ chối kết nối. Connection timed out nghĩa là gói tin bị âm thầm loại bỏ ở đâu đó. "No route to host" thì khác — network stack dừng sớm, hoặc vì không tìm thấy đường đến đích, hoặc vì có thứ gì đó trên đường đã gửi lại thông báo ICMP "host unreachable".

Bốn nguyên nhân phổ biến nhất: quy tắc REJECT của firewall, mục nhập thiếu hoặc sai trong bảng định tuyến, máy đích bị tắt hoàn toàn, hoặc network interface cấu hình sai.

Quy trình debug

Bước 1 — Máy đích có thể ping được không?

Bắt đầu ở tầng IP trước khi đụng vào bất cứ thứ gì khác:

# ICMP ping
ping -c 4 192.168.1.50

# Nếu ping bị chặn, thử TCP trên cổng đã biết là mở
nc -zv 192.168.1.50 22
nc -zv 192.168.1.50 80

Ping thành công nhưng TCP thất bại? Vấn đề nằm ở cổng cụ thể — bỏ qua sang Bước 3. Cả hai đều thất bại? Máy đích không thể truy cập ở tầng IP — tiếp tục đọc bên dưới.

Bước 2 — Kiểm tra bảng định tuyến

ip route get 192.168.1.50

Kết quả bình thường trông như sau:

192.168.1.50 via 192.168.1.1 dev eth0 src 192.168.1.100 uid 1000

Nếu thay vào đó bạn thấy RTNETLINK answers: Network is unreachable, máy của bạn không có route đến subnet đó. Hãy xem toàn bộ bảng định tuyến:

ip route show
# hoặc
netstat -rn

Tìm mục default gateway (0.0.0.0/0 hoặc default). Không có? Thêm vào:

# Default gateway tạm thời
ip route add default via 192.168.1.1 dev eth0

# Hoặc route cụ thể đến subnet đích
ip route add 10.0.0.0/24 via 192.168.1.1 dev eth0

Bước 3 — Kiểm tra quy tắc firewall trên cả hai máy

Chín trên mười trường hợp, đây là thủ phạm. Trên máy chủ đích, chạy:

# iptables
sudo iptables -L -n -v

# nftables (các distro mới hơn)
sudo nft list ruleset

# firewalld (CentOS/RHEL)
sudo firewall-cmd --list-all

Quy tắc REJECT — không phải DROP — kích hoạt ngay lập tức lỗi No route to host phía client. Dấu hiệu trong kết quả iptables trông như sau:

REJECT  tcp  --  0.0.0.0/0  0.0.0.0/0  tcp dpt:22  reject-with icmp-host-prohibited

Để mở cổng:

# iptables: cho phép SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# firewalld: mở vĩnh viễn
sudo firewall-cmd --permanent --add-port=22/tcp
sudo firewall-cmd --reload

# UFW (Ubuntu)
sudo ufw allow 22/tcp

Bước 4 — Kiểm tra interface có đang hoạt động không

ip link show
ip addr show

Interface hiển thị state DOWN cần được bật lên:

sudo ip link set eth0 up

Cũng kiểm tra lại địa chỉ IP được gán và subnet mask. Prefix sai — ví dụ /25 thay vì /24 — sẽ âm thầm cắt đôi dải địa chỉ có thể truy cập, khiến một nửa subnet nội bộ trở nên không thể kết nối.

Bước 5 — Traceroute để tìm điểm đứt

traceroute 192.168.1.50
# hoặc trên các hệ thống cũ hơn
tracert 192.168.1.50

Quan sát xem các hop dừng phản hồi ở đâu. Đó chính là thủ phạm — hoặc route bị hỏng, hoặc firewall đang nuốt traffic.

Các cách sửa phổ biến

Cách sửa 1 — Firewall từ xa có quy tắc REJECT

Trên các hệ thống CentOS/RHEL chạy firewalld (mặc định từ RHEL 7), mọi cổng đều bị chặn cho đến khi bạn mở tường minh. Đó là chính sách zone mặc định:

# Mở cổng bạn cần
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# Xác nhận đã mở
sudo firewall-cmd --list-ports

Cách sửa 2 — Default gateway biến mất sau khi khởi động lại

Các bản cài đặt tối giản và máy chủ vừa cấu hình lại đôi khi mất default route sau khi reboot. Lệnh ip route add tạm thời sẽ không tồn tại sau khi khởi động lại — hãy làm cho nó vĩnh viễn:

# Ubuntu/Debian — chỉnh sửa netplan
sudo nano /etc/netplan/00-installer-config.yaml
# Thêm vào phần interface:
#   routes:
#     - to: default
#       via: 192.168.1.1
sudo netplan apply

# CentOS/RHEL — chỉnh sửa file ifcfg
sudo nano /etc/sysconfig/network-scripts/ifcfg-eth0
# Thêm: GATEWAY=192.168.1.1
sudo systemctl restart NetworkManager

Cách sửa 3 — Subnet mask sai (CIDR không khớp)

Interface được cấu hình là 192.168.1.100/25 chỉ có thể kết nối đến các host trong dải 192.168.1.1–126. Bất kỳ địa chỉ nào từ .128 trở lên đều trông như không thể truy cập, dù thực tế chúng nằm trên cùng switch vật lý. Kiểm tra prefix thực tế của bạn:

ip addr show eth0
# inet 192.168.1.100/25 → dải host khả dụng: 192.168.1.1 đến 192.168.1.126

Không chắc CIDR của bạn cần bao phủ dải nào? Nhập IP và prefix vào Subnet Calculator của ToolCraft — công cụ hiển thị ngay dải host chính xác, địa chỉ broadcast và địa chỉ mạng, không cần đăng ký.

Cách sửa 4 — SELinux chặn kết nối

RHEL/CentOS có thêm một lớp bảo vệ. SELinux có thể âm thầm cản trở mà không đưa ra lỗi rõ ràng. Kiểm tra audit log trước:

sudo ausearch -m avc -ts recent
sudo sealert -a /var/log/audit/audit.log

Nếu SELinux đang chặn kết nối, hãy sửa label hoặc policy. Tắt hoàn toàn SELinux nghe có vẻ hấp dẫn nhưng là sai lầm — nó loại bỏ bảo vệ trên toàn hệ thống.

Xác nhận sau khi sửa

# Xác nhận kết nối TCP hoạt động
nc -zv 192.168.1.50 22
# Kết quả mong đợi: Connection to 192.168.1.50 22 port [tcp/ssh] succeeded!

# Sau đó thử lại lệnh gốc
ssh user@192.168.1.50
curl -v http://192.168.1.50:8080/health

nc thành công nhưng ứng dụng của bạn vẫn thất bại? Tin tốt: mạng đã ổn. Vấn đề đã chuyển sang tầng ứng dụng — sai thông tin đăng nhập, TLS không khớp, hoặc hostname sai. Đó là phạm vi vấn đề hẹp hơn nhiều để giải quyết.

Tóm tắt quan trọng

  • "No route to host" hầu như luôn là do quy tắc REJECT của firewall hoặc route bị thiếu — không phải máy đích chết (trường hợp đó sẽ hiện timeout).
  • Kiểm tra cả hai đầu: bảng định tuyến cục bộ quy tắc firewall trên máy chủ từ xa.
  • Trên CentOS/RHEL, firewalld chặn mọi thứ theo mặc định từ RHEL 7. Các cổng mới phải được mở tường minh bằng firewall-cmd --permanent.
  • Sau bất kỳ lần reboot hoặc cấu hình lại mạng nào, chạy ip route show để xác nhận default gateway vẫn còn đó.
  • Dùng nc -zv host port để kiểm tra cổng TCP nhanh chóng — nhanh hơn việc debug ứng dụng trước và loại trừ mạng như một biến số.

Related Error Notes