Tại sao chúng tôi từ bỏ Dual-Stack trên môi trường Staging
Cách đây sáu tháng, đội ngũ hạ tầng của chúng tôi đã quyết định loại bỏ hoàn toàn dual-stack khỏi môi trường staging. Việc duy trì song song hai ngăn xếp giao thức tiêu tốn quá nhiều thời gian kỹ thuật: số lượng firewall rule tăng gấp đôi, phạm vi DHCP bị phân mảnh, và nguồn tài nguyên IPv4 public khan hiếm bị lãng phí. Chúng tôi đã đặt ra mục tiêu rõ ràng: gỡ bỏ hoàn toàn IPv4 trên toàn bộ 85 máy của lập trình viên và CI/CD runner, nhưng vẫn phải đảm bảo kết nối ra ngoài (outbound) tới các kho package mirror, API của bên thứ ba và Docker registry chỉ hỗ trợ IPv4.
Hai công cụ mã nguồn mở đã giúp chúng tôi hiện thực hóa điều này: DNS64 và NAT64.
- DNS64 (qua BIND9): Khi một host IPv6-only truy vấn bản ghi AAAA cho một domain bên ngoài chỉ có bản ghi A, resolver sẽ tự động tổng hợp (synthesize) bản ghi AAAA ngay tức thì. Nó nhúng địa chỉ IPv4 32-bit của máy chủ từ xa vào một prefix được chỉ định—phổ biến nhất là prefix nổi tiếng
64:ff9b::/96theo chuẩn RFC 6052. - NAT64 (qua Tayga): Khi client gửi gói tin tới địa chỉ vừa được tổng hợp đó, bảng định tuyến cục bộ sẽ chuyển tiếp chúng tới Tayga. Tayga là một daemon dịch địa chỉ chạy trên user-space ở chế độ stateless. Nó loại bỏ header IPv6 40-byte, ánh xạ gói tin sang dải địa chỉ IPv4 private, rồi chuyển tiếp cho netfilter của Linux. Từ đó, cơ chế masquerade tiêu chuẩn của iptables sẽ đẩy lưu lượng truy cập ra ngoài internet IPv4.
Kết quả đạt được? Một edge router gọn nhẹ, vận hành êm ái, xử lý trung bình khoảng 45 GB lưu lượng outbound mỗi ngày suốt 180 ngày qua mà không gặp bất kỳ lỗi crash nào, đồng thời chi phí bảo trì gần như bằng không.
Yêu cầu tiên quyết & Mô hình mạng
Chúng tôi đã thử nghiệm và triển khai mô hình này trên một máy ảo 2 core với 2 GB RAM chạy Ubuntu 22.04 LTS. Máy chủ đóng vai trò cầu nối giữa hai interface mạng:
eth0: WAN interface kết nối upstream, sở hữu một địa chỉ IPv4 public có thể định tuyến và một prefix IPv6 được cấp phát (2001:db8:1::2/64).eth1: LAN interface downstream đóng vai trò làm default gateway (2001:db8:100::1/64) cho các máy trạm thuần IPv6 của lập trình viên.
Cài đặt các daemon chuyển đổi địa chỉ cần thiết, công cụ DNS và tiện ích quản lý firewall:
sudo apt update
sudo apt install -y bind9 bind9utils tayga iptables iptables-persistent
Nếu sử dụng RHEL 9 hoặc Rocky Linux 9, bạn hãy cài đặt các package từ EPEL và repository gốc:
sudo dnf install -y epel-release
sudo dnf install -y bind tayga iptables-services
Các bước cấu hình chi tiết
1. Bật tính năng chuyển tiếp gói tin (Packet Forwarding) trong Linux Kernel
Gateway cần chuyển tiếp các gói tin giữa các giao thức và interface khác nhau. Hãy bật IP forwarding trong sysctl:
sudo bash -c 'cat >> /etc/sysctl.d/99-nat64.conf <<EOF
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
EOF'
sudo sysctl --system
2. Cấu hình Tayga cho Stateless NAT64
Tayga đảm nhiệm việc chuyển đổi stateless giữa IPv6 và dải địa chỉ IPv4 staging nội bộ. Chỉnh sửa file /etc/tayga.conf để khai báo interface tun chuyển đổi, pool động và prefix mục tiêu:
sudo bash -c 'cat > /etc/tayga.conf <<EOF
tun-device nat64
ipv4-addr 192.168.255.1
prefix 64:ff9b::/96
dynamic-pool 192.168.255.0/24
data-dir /var/spool/tayga
EOF'
Khởi chạy interface tun và liên kết bảng định tuyến với nó. Để duy trì các route sau khi reboot, hãy thêm các lệnh này vào script network dispatcher hoặc systemd override:
# Khởi tạo thiết bị tun ảo
sudo tayga --mktun
# Bật thiết bị và gán địa chỉ endpoint cục bộ
sudo ip link set nat64 up
sudo ip addr add 192.168.255.1 dev nat64
sudo ip addr add 2001:db8:100::ffff dev nat64
# Định tuyến các prefix cần chuyển đổi vào Tayga
sudo ip route add 192.168.255.0/24 dev nat64
sudo ip route add 64:ff9b::/96 dev nat64
3. Masquerade gói tin IPv4 gửi ra ngoài bằng iptables
Tayga ánh xạ lưu lượng IPv6 đi vào thành subnet private 192.168.255.0/24. Do các địa chỉ này không thể định tuyến trên internet public, bạn cần dùng iptables để masquerade chúng qua interface WAN (eth0):
# Cấu hình NAT cho dynamic pool của Tayga
sudo iptables -t nat -A POSTROUTING -s 192.168.255.0/24 -o eth0 -j MASQUERADE
# Quy tắc chuyển tiếp giữa các interface
sudo iptables -A FORWARD -i nat64 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o nat64 -m state --state RELATED,ESTABLISHED -j ACCEPT
# Lưu lại cấu hình quy tắc sau khi khởi động lại
sudo netfilter-persistent save
4. Cấu hình BIND9 làm bộ tổng hợp DNS64
Khi một máy trạm nội bộ truy vấn một dịch vụ bên ngoài không có bản ghi IPv6, BIND9 sẽ tự động tổng hợp ra một bản ghi. Cập nhật file /etc/bind/named.conf.options với danh sách kiểm soát truy cập (ACL) và khối cấu hình DNS64:
acl "trusted_clients" {
127.0.0.1;
::1;
2001:db8:100::/64;
};
options {
directory "/var/cache/bind";
recursion yes;
allow-query { trusted_clients; };
allow-recursion { trusted_clients; };
listen-on { any; };
listen-on-v6 { any; };
forwarders {
1.1.1.1;
8.8.8.8;
};
dnssec-validation auto;
dns64 64:ff9b::/96 {
clients { trusted_clients; };
mapped { any; };
exclude { 64:ff9b::/96; };
suffix ::;
};
};
Kiểm tra cú pháp cấu hình và khởi động cả hai dịch vụ:
sudo named-checkconf
sudo systemctl restart bind9 tayga
sudo systemctl enable bind9 tayga
Kiểm thử và những lưu ý thực tế khi vận hành
1. Kiểm tra phản hồi DNS tổng hợp
Đăng nhập vào một máy trạm IPv6-only đã trỏ DNS resolver về gateway (2001:db8:100::1). Truy vấn một đích đến chỉ có IPv4 như ipv4.google.com:
dig AAAA ipv4.google.com +short
BIND trả về bản ghi AAAA tổng hợp: 64:ff9b::d83a:ce6e. Hãy chú ý phần giá trị thập lục phân ở cuối (d8.3a.ce.6e). Khi chuyển đổi sang hệ thập phân, chúng tương đương với 216.58.206.110—chính là địa chỉ IPv4 đích của Google.
2. Kiểm tra thông lượng và khả năng kết nối
Kiểm tra bắt tay ICMP và HTTPS đầu cuối hoàn toàn qua IPv6:
ping -6 -c 3 64:ff9b::d83a:ce6e
curl -6 -I https://ipv4.google.com
Client của bạn hoàn tất quá trình bắt tay TLS qua IPv6 mà không hề nhận biết được rằng server đích thực tế đang chạy trên IPv4.
3. Những bài học đắt giá từ môi trường production
Quá trình vận hành hệ thống này trên production đã mang lại ba bài học then chốt:
- Bắt buộc phải cấu hình TCP MSS Clamping: Header của gói tin IPv6 chiếm 40 byte, trong khi header IPv4 chỉ chiếm 20 byte. Một số CDN bên ngoài drop các gói ICMP Packet Too Big, dẫn đến hiện tượng Path MTU blackhole (hố đen MTU). Quá trình chạy
npm installcủa chúng tôi từng bị treo ở mức 99% cho đến khi áp dụng MSS clamping trong iptables:
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu - Bộ dịch Stateless mở rộng hiệu quả với chi phí thấp: Tayga duy trì tốc độ cao vì không cần quản lý session table. Nó đẩy toàn bộ việc theo dõi kết nối (connection tracking) cho module conntrack của kernel. Trong môi trường của chúng tôi, Tayga chỉ tiêu tốn dưới 18 MB RAM ngay cả dưới tải thử nghiệm lên đến 12.000 socket hoạt động đồng thời.
- Truy cập trực tiếp bằng địa chỉ IPv4 thô (IPv4 Literal) sẽ bị lỗi: DNS64 bắt buộc phải thông qua bước phân giải DNS. Nếu lập trình viên dùng công cụ gọi trực tiếp địa chỉ IPv4 dạng hardcoded (ví dụ:
curl http://198.51.100.4), request sẽ bỏ qua BIND và thất bại. Đối với các trường hợp ngoại lệ này, bạn có thể triển khai daemon CLAT phía client (như clatd) hoặc cấu hình cho họ đi qua một SOCKS5 proxy nội bộ.

