DNS Tunneling với iodine trên Linux: Vượt Firewall và Truy Cập Mạng qua Giao Thức DNS

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

Bạn đang ở khách sạn hội nghị, đã trả tiền cho “internet access,” và mọi cổng ngoại trừ 80, 443 và 53 đều bị chặn. SSH qua cổng 22? Không kết nối được. VPN? Cũng không. Nhưng DNS queries vẫn đi qua thoải mái — vì chặn DNS sẽ làm hỏng mọi thứ, nên không ai dám đụng vào.

Đây chính xác là lúc iodine tỏa sáng. Tôi đã gặp tình huống này khi thực hiện kiểm tra mạng được ủy quyền tại một khách hàng và có đầy đủ kết nối trong vòng mười phút sau khi khởi động tunnel. Kể từ đó tôi đã dùng cách tiếp cận này trên nhiều mạng nội bộ doanh nghiệp và captive portal khách sạn — nó hoạt động mọi lần, ngay cả khi Tailscale, OpenVPN và SSH thông thường đều thất bại.

Dưới đây là hướng dẫn đầy đủ: server, client, routing và những lỗi cụ thể sẽ làm bạn vấp ngã lần đầu.

Bắt Đầu Nhanh — Chạy iodine Trong 5 Phút

Những Gì Bạn Cần

  • Một VPS có IP công khai (Ubuntu/Debian/CentOS)
  • Một tên miền bạn quản lý (ví dụ: example.com)
  • Quyền truy cập DNS để tạo NS record

Bước 1: Cài Đặt DNS Record

Tạo hai DNS record tại nhà đăng ký tên miền của bạn:

  • Một A record: vps.example.com → YOUR_VPS_IP
  • Một NS record: tunnel.example.com → vps.example.com

NS record đó là phần quan trọng nhất — nó ủy quyền tất cả queries cho *.tunnel.example.com đến VPS của bạn. iodine mã hóa các IP packet bên trong hostname của DNS query sử dụng không gian subdomain này.

Bước 2: Cài Đặt iodine

Trên VPS của bạn (phía server):

# Ubuntu/Debian
sudo apt update && sudo apt install iodine -y

# CentOS/RHEL
sudo yum install iodine -y

# Từ source (nếu không có trong repos)
git clone https://github.com/yarrick/iodine.git
cd iodine && make && sudo make install

Cài đặt cùng gói phần mềm trên máy client của bạn.

Bước 3: Khởi Động Server (iodined)

sudo iodined -f -c -P yourpassword 10.0.0.1 tunnel.example.com

Giải thích các tham số:

  • -f: Chạy ở foreground (bỏ tham số này để dùng daemon mode)
  • -c: Tắt kiểm tra IP client — hữu ích khi VPS của bạn nằm sau NAT
  • -P yourpassword: Mật khẩu dùng chung để xác thực
  • 10.0.0.1: IP được gán cho TUN interface của server
  • tunnel.example.com: Subdomain được ủy quyền NS của bạn

Bước 4: Kết Nối Từ Client

sudo iodine -f -P yourpassword tunnel.example.com

Kết nối thành công trông như thế này:

Opened dns0
Opened IPv4 UDP socket
Sending DNS queries for tunnel.example.com to 8.8.8.8
Autodetecting DNS query type (use -T to override).
Using EDNS0 extension
...
Server tunnel IP is 10.0.0.1
Sending handshake...
Connection setup complete, transmitting data.

Client của bạn hiện có TUN interface dns0 với IP 10.0.0.2. Xác nhận bằng lệnh ping 10.0.0.1.

Tìm Hiểu Sâu Hơn — DNS Tunneling Thực Sự Hoạt Động Như Thế Nào

Cơ Chế Giao Thức

iodine mã hóa các IP packet thành hostname trong chuỗi DNS query. Một packet rời khỏi client của bạn sẽ được chia nhỏ, mã hóa base32 và gửi đi như một yêu cầu tra cứu:

aabbccddee.tunnel.example.com → DNS type NULL query

VPS của bạn nhận những queries đó qua NS delegation. Nó giải mã dữ liệu, chuyển tiếp IP packet thực tế, mã hóa phản hồi và gửi lại dưới dạng DNS answer. Với bất kỳ firewall nào ở giữa, đây trông giống như DNS traffic thông thường.

Loại Query và Mã Hóa

iodine tự động thương lượng loại DNS record tốt nhất khi khởi động:

  • NULL records: Thông lượng tốt nhất, nhưng một số DNS relay loại bỏ chúng
  • TXT records: Tương thích tốt, kém hiệu quả hơn một chút
  • CNAME/A records: Dự phòng cho môi trường có hạn chế cao

Bạn có thể ép buộc một loại cụ thể nếu tự động phát hiện chọn thứ gì đó không tối ưu:

sudo iodine -f -T TXT -P yourpassword tunnel.example.com

Theo kinh nghiệm của tôi, NULL hoạt động tốt nhất trên mạng doanh nghiệp, trong khi TXT đáng tin cậy hơn trên captive portal khách sạn khi họ proxy DNS traffic qua resolver riêng của họ.

Hiểu về TUN Interface

Sau khi kết nối, kiểm tra những gì iodine đã tạo ra:

ip addr show dns0
# 4: dns0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1130 qdisc fq_codel
#     inet 10.0.0.2/27 scope global dns0

Lưu ý MTU là 1130, không phải 1500 tiêu chuẩn. DNS record có giới hạn kích thước nghiêm ngặt, nên iodine phân mảnh các packet để vừa. Đây là lý do chính khiến DNS tunneling chậm — mỗi IP packet cần nhiều DNS round-trip để lắp ráp lại.

Sử Dụng Nâng Cao

Chuyển Hướng Toàn Bộ Traffic Qua Tunnel

Ở giai đoạn này bạn đã có tunnel hoạt động, nhưng route mặc định của bạn vẫn đi qua mạng bị hạn chế. Để chuyển toàn bộ traffic qua iodine:

# Lưu gateway hiện tại và địa chỉ IP DNS server
CURRENT_GW=$(ip route show default | awk '/default/ {print $3}')
DNS_SERVER="8.8.8.8"  # thay bằng DNS của mạng bị hạn chế

# Quan trọng: giữ DNS queries đi qua interface local
# để iodine không bị loop
sudo ip route add $DNS_SERVER/32 via $CURRENT_GW

# Chuyển hướng toàn bộ traffic còn lại qua tunnel
sudo ip route del default
sudo ip route add default via 10.0.0.1 dev dns0

Ở phía server, bật NAT để chuyển tiếp traffic của client ra internet:

# Bật IP forwarding
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

# NAT tunnel clients ra internet (thay eth0 bằng interface của bạn)
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/27 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i dns0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o dns0 -m state --state RELATED,ESTABLISHED -j ACCEPT

SOCKS Proxy Qua Tunnel

Nếu bạn chỉ cần truy cập ở cấp độ trình duyệt hoặc ứng dụng, SSH SOCKS proxying qua tunnel hiệu quả hơn routing đầy đủ:

# Mở SOCKS5 proxy qua tunnel server
ssh -D 1080 -N [email protected]

# Sau đó sử dụng
curl --socks5 127.0.0.1:1080 https://example.com

Chạy iodined như systemd Service

Trong môi trường production — hoặc bất kỳ nơi nào bạn cần điều này tồn tại sau khi khởi động lại — cài đặt iodined như systemd service:

sudo nano /etc/systemd/system/iodined.service
[Unit]
Description=iodine DNS Tunnel Server
After=network.target

[Service]
ExecStart=/usr/sbin/iodined -c -P yourpassword 10.0.0.1 tunnel.example.com
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl enable iodined
sudo systemctl start iodined
sudo systemctl status iodined

Mẹo Thực Tế

Kỳ Vọng Hiệu Suất Thực Tế

DNS tunneling vốn chậm theo thiết kế — hãy đặt kỳ vọng trước khi triển khai:

  • Upstream (client → server): 3–10 KB/s
  • Downstream (server → client): 5–20 KB/s
  • Độ trễ: 200–800ms mỗi DNS round-trip

Phiên SSH, Git qua HTTPS và các API call nhẹ hoạt động tốt. Streaming video hoặc truyền file lớn sẽ rất chậm. Đối với quyền truy cập khẩn cấp khi mọi tùy chọn khác bị chặn, thông lượng này hoàn toàn xứng đáng.

Xử Lý Sự Cố Thường Gặp

“Không nhận được dữ liệu downstream” — DNS relay của bạn có thể đang lọc hoặc làm hỏng các phản hồi. Chuyển sang loại query khác:

sudo iodine -f -T TXT -P yourpassword tunnel.example.com

Kết nối được thiết lập nhưng ping thất bại — IP forwarding hoặc NAT rules bị thiếu trên server:

cat /proc/sys/net/ipv4/ip_forward       # Kết quả mong đợi: 1
sudo iptables -t nat -L POSTROUTING    # Kiểm tra rule MASQUERADE tồn tại

NS delegation không phân giải được — Lan truyền DNS có thể mất tới 48 giờ. Xác nhận record đã hoạt động:

dig NS tunnel.example.com
# Kết quả mong đợi: tunnel.example.com. IN NS vps.example.com.

Cải Thiện Hiệu Suất TCP với MSS Clamping

MTU thấp gây ra phân mảnh TCP âm thầm làm giảm thông lượng. Một rule iptables trên server sẽ khắc phục:

sudo iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --clamp-mss-to-pmtu

Nó yêu cầu TCP giới hạn kích thước segment theo những gì thực sự vừa qua tunnel. Thêm rule này vào và SSH bắt đầu phản hồi nhanh hơn — HTTP transfer cũng tăng tốc đáng kể.

Lưu Ý Bảo Mật

iodine xác thực bằng mật khẩu dùng chung, nhưng traffic được mã hóa (encode), không phải được mã hóa bảo mật (encrypt). Đối với bất kỳ thứ gì nhạy cảm, hãy thêm lớp SSH hoặc WireGuard lên trên — DNS tunnel cho bạn kết nối, còn mã hóa là mối quan tâm riêng biệt.

Đáng lưu ý: DNS tunneling tạo ra các mẫu traffic đặc trưng — khối lượng query bất thường cao, chuỗi subdomain dài — mà các công cụ giám sát mạng sẽ phát hiện. Chỉ sử dụng trên các mạng bạn được ủy quyền kiểm tra.

Server iodined của tôi đã chạy hơn một năm, âm thầm chờ đợi như phương thức truy cập dự phòng. Khi VPN chính của khách hàng ngừng hoạt động giữa maintenance-window và nhóm mất quyền truy cập vào máy chủ của họ, đây chính là tunnel đã đưa họ trở lại — trong vài phút, không phải vài giờ. Cấu hình sẵn có nghĩa là bạn không bao giờ bị khóa hoàn toàn. Sự an tâm đó xứng đáng với mười lăm phút cài đặt.

Share: