Khi bạn thêm một tiền tố IPv6 vào đường hầm site-to-site, gói tin không đi theo cách sơ đồ gợi ý. Cổng cục bộ lấy toàn bộ gói IPv6, mã hóa nó và đặt phía trước một tiêu đề IP ngoài mà họ địa chỉ của nó do địa chỉ hai đầu quyết định, chứ không phải do nội dung bên trong. Cổng ở xa bóc tiêu đề ngoài đó và chuyển gói gốc vào LAN của nó, nơi nó lại là một gói IPv6 bình thường. Đường hầm ngoài và lưu lượng bên trong là hai cuộc trò chuyện riêng biệt, chỉ chia sẻ một khóa, một cặp đầu mút và không gì khác.

Hai tiêu đề, hai họ địa chỉ

Trong chế độ đường hầm IPsec, gói IPv6 bên trong trở thành tải trọng nằm sau tiêu đề ESP. Tiêu đề ngoài mang gói ESP đó có thể là IPv4 hoặc IPv6, và nó tuân theo local_addrs và remote_addrs. WireGuard làm điều tương tự với ít nghi thức hơn: gói bên trong là tải trọng của một datagram UDP tới đầu mút của đối tác. Cả hai đều để tiêu đề bên trong nguyên vẹn, nhờ đó phía xa có thể định tuyến nó sau khi giải bọc.

Đường đi giữa hai site chỉ thấy UDP 4500 khi IPsec dùng NAT traversal, hoặc UDP 51820 cho một trình lắng nghe WireGuard mặc định. Bất kỳ bộ định tuyến nào trên đường đều có thể chỉ là IPv4 và lưu lượng IPv6 vẫn đi qua, vì nó không bao giờ xuất hiện như một gói IPv6 trên đường đó. Điều đó cho một phân tách đầu tiên rõ ràng: tcpdump -ni eth0 udp port 51820 cho thấy đường đã mã hóa, tcpdump -ni wg0 ip6 cho thấy lưu lượng bên trong. Một bản bắt gói ngoài sôi động với bản bên trong im lặng nghĩa là kernel không đưa IPv6 vào đường hầm; đó là định tuyến hoặc chính sách, không phải trạng thái liên kết.

Cổng cũng giảm Hop Limit bên trong khi chuyển tiếp, nên các đầu mút được tính là bộ định tuyến trên đường IPv6. Số hop ngoài và Hop Limit bên trong chuyển động độc lập, và một gói chết ở cổng xa đã chết trong khâu chuyển tiếp, không phải khâu mã hóa.

Selector và AllowedIPs là danh sách quyền

IKEv2 thương lượng những tiền tố bên trong nào mà child SA có thể mang. Trên strongSwan 5.9 và mới hơn, việc ghi chúng trong swanctl.conf trông như sau:

children {
  net6 {
    local_ts  = 2001:db8:aa::/48
    remote_ts = 2001:db8:bb::/48
    mode = tunnel
    esp_proposals = aes256gcm16-prfsha384-ecp384
    start_action = trap
  }
}

Bỏ qua local_ts và remote_ts thì strongSwan suy ra chúng từ các subnet của giao diện mà nó chọn. Trên một máy dual-stack, lối tắt đó thường cho ra một cặp chỉ IPv4: SA dựng lên và IPv6 bị từ chối trước khi chạm tới mã ESP. Ghi cả hai tiền tố khiến SA có thể mang chúng, và start_action = trap dựng nó lên ở gói khớp đầu tiên.

WireGuard có một danh sách làm hai việc. Trong khối đối tác, AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48 vừa là tuyến được cài khi gửi vừa là bộ lọc áp dụng khi nhận: một gói đã giải mã có nguồn bên trong nằm ngoài danh sách của đối tác đó sẽ bị bỏ âm thầm. wg-quick thêm một tuyến cho mỗi mục, nên khối đối tác bên dưới không cần lệnh ip -6 route riêng.

[Interface]
Address = 2001:db8:aa:ff::1/64, fd00:aa:ff::1/64
ListenPort = 51820

[Peer]
PublicKey = <site-b-public-key>
Endpoint = 203.0.113.20:51820
AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48

Cả hai danh sách phải soi gương nhau: site B chấp nhận tiền tố của site A làm selector từ xa và định tuyến nó trở lại, và đường hầm chỉ hoạt động khi hai chiều khớp nhau. Một danh sách bất đối xứng cho ra triệu chứng tốn thời gian nhất — một cái bắt tay khỏe mạnh, các bộ đếm chạy ở một phía, và một ping từ A tới B thành công trong khi không gì từ B tới được A.

Chuyển tiếp, tuyến và tiền tố trả về

Linux không chuyển tiếp IPv6 cho tới khi bạn bảo, và thiết lập này tính theo namespace chứ không theo giao diện:

sysctl -w net.ipv6.conf.all.forwarding=1
ip -6 route add 2001:db8:bb::/48 dev wg0
ip -6 route get 2001:db8:bb::10 from 2001:db8:aa::10

Dòng thứ hai là dòng người ta quên trong các thiết kế dựa trên tuyến. IPsec dựa trên chính sách cài một chính sách XFRM khớp với các tiền tố, nhưng một cấu hình dựa trên tuyến với vti6 hoặc WireGuard cần một tuyến IPv6 thật trỏ tới thiết bị đó. Hãy lưu bền sysctl dưới /etc/sysctl.d/; nếu không, khởi động lại sẽ âm thầm đặt chuyển tiếp về trạng thái tắt.

Chuyển tiếp có một tác dụng phụ đáng biết: kernel khi đó bỏ qua các thông báo router trừ khi net.ipv6.conf.<wan>.accept_ra là 2, nên một cổng có địa chỉ WAN đến qua SLAAC có thể mất tuyến mặc định ngay khi bạn bật chuyển tiếp. Đặt accept_ra = 2 trên giao diện đó trong cùng tệp và tuyến sẽ sống sót. Nhân của site B cũng phải học 2001:db8:aa::/48 từ cổng đường hầm, bằng tuyến tĩnh hoặc một giao thức định tuyến trên đường hầm, nếu không phản hồi sẽ chết bên trong chính mạng của B.

Một bước kiểm tra bốn bước để khoanh vùng chỗ đứt

Hãy làm theo thứ tự này và dừng ở bước đầu tiên thất bại, vì mỗi bước sau đều phụ thuộc vào các bước trước.

  1. Selector: swanctl --list-sas phải cho thấy cặp tiền tố IPv6 trên child SA, hoặc wg show wg0 allowed-ips tiền tố từ xa với một latest-handshakes gần đây.
  2. Tuyến của kernel: ip -6 route get 2001:db8:bb::10 phải trả lời bằng thiết bị đường hầm, không phải giao diện WAN.
  3. Bản bắt gói bên trong: tcpdump -ni wg0 ip6 trong khi ping giữa các máy LAN thật. Gói đi ra mà không có gói nào quay về chỉ vào tuyến hoặc tường lửa của B; hoàn toàn không có gói nào chỉ ngược về bước 1 hoặc 2.
  4. Đích: trên máy B, ss -6 -ltn xác nhận dịch vụ lắng nghe trên IPv6, và các bộ đếm tường lửa cục bộ cho thấy gói đã được chấp nhận hay bị bỏ.

MTU thuộc cùng lượt. Bộ định tuyến IPv6 không phân mảnh, nên một gói quá lớn bị bỏ và Packet Too Big quay về người gửi. Nếu các cái bắt tay và ping nhỏ hoạt động nhưng truyền tệp bị kẹt, hãy giảm tải trọng cho tới khi nó đi qua: ping -6 -s 1400 -c 3 2001:db8:bb::10. Giao diện WireGuard mặc định có MTU 1420 byte và IPsec trên IPv4 trừ nhiều hơn, nên đặt MTU bên trong tốt hơn là hy vọng phát hiện MTU đường đi xuyên qua một tường lửa bỏ ICMPv6.

Các kiểu hỏng trông giống vấn đề tường lửa

Kiểu phổ biến nhất hoàn toàn không phải tường lửa: dịch vụ gắn vào 0.0.0.0 thay vì ::, bản ghi AAAA tồn tại, và ứng dụng nhận một từ chối nhanh qua IPv6 mà trình duyệt dual-stack che đi bằng cách lùi về IPv4. Nếu chỉ một số ứng dụng hỏng, hãy kiểm tra họ giao thức đang lắng nghe trước khi chạm vào bộ quy tắc.

Kiểu thứ hai là lọc ICMPv6. Neighbor Discovery và Packet Too Big là một phần của vận hành bình thường, không phải chẩn đoán, và một chính sách bỏ toàn bộ ICMPv6 tạo ra đường hầm kết nối, xác thực rồi kẹt ở mọi thứ lớn hơn một gói nhỏ. Hãy cho phép các loại mà đường đi phụ thuộc vào và để bộ đếm bật để thấy được việc bỏ gói.

Kiểu thứ ba là một tiền tố được thêm vào đường hầm nhưng không bao giờ được thêm vào kế hoạch địa chỉ của site sở hữu nó, nên không bộ định tuyến nào quảng cáo nó và không máy nào trả lời được từ nó. Hãy bắt đầu với một tiền tố và một cặp máy, chứng minh cả hai chiều bằng bốn bước, rồi thêm phần còn lại; một tiền tố hỏng vẫn là một dòng trong cấu hình thay vì một lần thiết kế lại. Nguồn tham chiếu chính thức duy nhất đáng để mở là RFC 8200, nguồn định nghĩa tiêu đề mà đường hầm mang.

Bài viết liên quan