Vấn đề mình gặp khi chuyển datacenter sang IPv6-only
Khoảng 8 tháng trước, nhà cung cấp VPS mình đang dùng thông báo sẽ tính thêm phí cho IPv4 public và roadmap rõ ràng là hướng đến IPv6-only. Mình quản lý cụm khoảng 15 server — phần lớn chỉ cần giao tiếp nội bộ — nên quyết định thử chuyển sang IPv6-only để tiết kiệm chi phí.
Vấn đề nổ ra ngay tuần đầu: một đống dịch vụ bên ngoài không có IPv6. Repository apt mirror của distro cũ chỉ có IPv4. Payment gateway khách hàng đang dùng cũng IPv4-only. License server phần mềm thương mại? IPv4. Mình ngồi nhìn danh sách lỗi kết nối mà cảm giác như mình đã nhảy quá sớm.
Mua thêm IPv4 cho từng máy thì chi phí tăng tuyến tính. Quay lại dual-stack cho toàn bộ cluster thì mất luôn mục tiêu ban đầu. Sau một tuần tìm hiểu, mình tìm ra giải pháp đúng nghĩa: NAT64 kết hợp DNS64 — cho phép máy chủ IPv6-only kết nối đến dịch vụ IPv4-only hoàn toàn transparent, không cần sửa một dòng code nào của ứng dụng.
Tại sao IPv6-only không tự kết nối được đến IPv4?
IPv6 và IPv4 không nói chuyện trực tiếp được với nhau — khác hoàn toàn về cấu trúc địa chỉ và packet header. Khi máy chủ IPv6-only muốn kết nối đến 203.0.113.5 (IPv4), nó cần giải quyết hai bài toán:
- Routing: Cần một cách “mã hóa” địa chỉ IPv4 thành dạng IPv6 để packet biết đi đâu — đây là việc của NAT64
- DNS: Khi resolve domain, nếu đích chỉ có A record (IPv4), DNS resolver phải trả về AAAA record tổng hợp — đây là DNS64
Về mặt kỹ thuật: DNS64 tạo AAAA record giả bằng cách ghép NAT64 prefix (thường là 64:ff9b::/96 theo RFC 6052) với địa chỉ IPv4. Khi client gửi packet đến địa chỉ IPv6 synthesized đó, NAT64 gateway nhận packet, bóc tách IPv4 original rồi forward đến đích thật bằng IPv4 của gateway. Toàn bộ quá trình này xảy ra transparent với application.
Ba cách giải quyết và lý do mình chọn NAT64
Option 1: Dual-stack — đơn giản nhưng không scale
Gắn thêm IPv4 public cho mỗi máy. Không cần cấu hình gì thêm, nhưng chi phí tăng theo số máy. Với 15-20 server thì ổn, còn khi scale lên 50-100 máy thì không khả thi về tài chính.
Option 2: Application-level proxy (Squid, SOCKS5)
Dùng một máy dual-stack làm HTTP proxy hoặc SOCKS5 gateway. Mình đã thử — nó hoạt động cho HTTP/HTTPS, nhưng với binary protocol, gRPC, custom TCP thì phải cấu hình riêng từng ứng dụng. Khi có hàng chục service khác nhau, việc maintain trở nên rất rườm rà.
Option 3: NAT64 + DNS64 — transparent ở tầng network
Giải pháp này hoạt động hoàn toàn dưới tầng application. Chỉ cần trỏ DNS của máy IPv6-only về DNS64 server, mọi kết nối TCP/UDP ra ngoài tự động được xử lý. Đây là cách mình đang dùng trên production từ 6 tháng nay.
Hướng dẫn triển khai Tayga (NAT64) và BIND9 (DNS64)
Kiến trúc
Mình dùng một máy Linux có cả IPv4 lẫn IPv6 làm gateway — đây sẽ chạy cả Tayga và BIND9:
- Tayga: stateful NAT64 translator chạy userspace
- BIND9: DNS64 — synthesize AAAA record từ A record
- NAT64 prefix:
64:ff9b::/96(well-known prefix) - IPv4 pool cho Tayga:
192.168.255.0/24(private range)
Bước 1: Cài đặt và cấu hình Tayga
Trên Ubuntu/Debian:
sudo apt update && sudo apt install tayga
Tạo file cấu hình /etc/tayga.conf:
tun-device nat64
ipv4-addr 192.168.255.1
prefix 64:ff9b::/96
dynamic-pool 192.168.255.0/24
data-dir /var/db/tayga
Khởi động Tayga và cấu hình interface:
sudo mkdir -p /var/db/tayga
sudo tayga --mktun
sudo ip link set nat64 up
sudo ip addr add 192.168.255.1/24 dev nat64
sudo ip -6 route add 64:ff9b::/96 dev nat64
sudo tayga
Bước 2: Bật forwarding và cấu hình iptables
# Bật IP forwarding
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# NAT traffic IPv4 từ Tayga pool ra internet
sudo iptables -t nat -A POSTROUTING -s 192.168.255.0/24 -j MASQUERADE
# Cho phép forward qua interface nat64
sudo ip6tables -A FORWARD -i nat64 -j ACCEPT
sudo ip6tables -A FORWARD -o nat64 -j ACCEPT
Bước 3: Cấu hình DNS64 trên BIND9
sudo apt install bind9
Thêm block dns64 vào /etc/bind/named.conf.options:
options {
directory "/var/cache/bind";
# DNS64: synthesize AAAA từ A record với NAT64 prefix
dns64 64:ff9b::/96 {
clients { any; };
# Không synthesize cho RFC1918 (private IPv4) — chỉ public
mapped { !rfc1918; any; };
exclude { 64:ff9b::/96; ::ffff:0:0/96; };
};
allow-query { localhost; 2001:db8::/48; };
recursion yes;
forwarders {
8.8.8.8;
1.1.1.1;
};
# DNS64 phá DNSSEC validation — cần disable
dnssec-validation no;
};
sudo systemctl restart bind9 && sudo systemctl enable bind9
Bước 4: Systemd service cho Tayga
Tayga không tự tạo systemd service — mình phải viết tay:
# /etc/systemd/system/tayga.service
[Unit]
Description=Tayga NAT64 daemon
After=network.target
[Service]
Type=forking
ExecStartPre=/usr/sbin/tayga --mktun
ExecStartPre=/bin/ip link set nat64 up
ExecStartPre=/bin/ip addr add 192.168.255.1/24 dev nat64
ExecStartPre=/bin/ip -6 route add 64:ff9b::/96 dev nat64
ExecStart=/usr/sbin/tayga --pidfile /run/tayga.pid
PIDFile=/run/tayga.pid
ExecStopPost=/usr/sbin/tayga --rmtun
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now tayga
Bước 5: Cấu hình máy chủ IPv6-only
Trên các máy chủ IPv6-only, trỏ DNS về gateway (giả sử gateway IPv6 là 2001:db8::1):
# /etc/resolv.conf
nameserver 2001:db8::1
# Thêm route cho NAT64 prefix qua gateway
sudo ip -6 route add 64:ff9b::/96 via 2001:db8::1
Kiểm tra hoạt động
# Test DNS64 — nên trả AAAA dạng 64:ff9b::x.x.x.x
dig AAAA example.com @2001:db8::1
# Ping trực tiếp đến IPv4 qua NAT64
ping6 64:ff9b::8.8.8.8
# Test kết nối thực tế từ máy IPv6-only
curl -6v https://example.com
# Xem mapping table của Tayga
sudo tayga --list
Những bẫy mình đã rơi vào — ghi lại để bạn tránh
DNSSEC phải tắt trên DNS64 resolver: Vì DNS64 tổng hợp AAAA record không có trong authoritative server, DNSSEC validation sẽ fail toàn bộ. Đây là trade-off cần cân nhắc kỹ — mình chấp nhận vì DNS64 chỉ serve traffic nội bộ, không expose ra internet.
Tayga chạy userspace — không phải kernel: Hiệu năng thấp hơn giải pháp kernel như SIIT. Với workload HTTP API call hay database query thông thường thì không cảm nhận được, nhưng nếu cần throughput vài Gbps thì nên xem xét thêm.
Traceroute không hoạt động hoàn hảo: NAT64 không xử lý được ICMP embedded address nên traceroute qua NAT64 sẽ thiếu hop. Debug mạng khó hơn một chút — mình thường debug từ phía gateway thay vì từ máy IPv6-only.
iptables rules không persist sau reboot: Cần cài iptables-persistent hoặc thêm vào systemd service:
sudo apt install iptables-persistent
sudo netfilter-persistent save
Kết quả sau 6 tháng chạy production
Setup này đang chạy stable trên cụm server văn phòng mình. Chi phí giảm rõ rệt so với mua thêm IPv4 public cho từng máy. Quan trọng hơn — team dev không cần thay đổi bất cứ gì, mọi kết nối TCP/UDP đến dịch vụ IPv4-only đều hoạt động bình thường, kể cả apt update, curl, database connection hay license server.
NAT64 + DNS64 không phải giải pháp vĩnh viễn — khi các dịch vụ legacy dần migrate sang IPv6, bạn có thể dần loại bỏ setup này. Nhưng trong giai đoạn chuyển đổi hiện tại, đây là cách thực tế và hiệu quả nhất để tiến về phía IPv6 mà không bị kéo lùi bởi hạ tầng cũ.
