AWS VPN MTU IPsec throughput networking GCP

AWS Site-to-Site VPN przepustowość poniżej 1 Gbps: MSS clamping i fragmentacja IPsec

Naprawa degradacji przepustowości AWS Site-to-Site VPN spowodowanej fragmentacją MTU na tunelach IPsec łączących się z GCP Cloud VPN.

·
Twój tunel AWS Site-to-Site VPN działa i routing jest poprawny, ale przepustowość utknęła na 400-800 Mbps zamiast oczekiwanych 1.25 Gbps. Transfery dużych plików się zacinają, podczas gdy małe pakiety przechodzą bez problemu. Jest to prawie zawsze problem MTU/fragmentacji. Poniższy runbook przeprowadzi Cię przez diagnostykę i naprawę.

Objawy

Testy iperf3 pokazują przepustowość znacznie poniżej nominalnej wartości 1.25 Gbps:

iperf3 -c 10.128.0.2 -t 30 -P 1
[  5]   0.00-30.00  sec  1.42 GBytes   407 Mbits/sec    sender
[  5]   0.00-30.00  sec  1.40 GBytes   401 Mbits/sec    receiver

Transfery dużych plików (SCP, rsync) zacinają się okresowo lub kończą znacznie wolniej niż oczekiwano. Retransmisje TCP gwałtownie rosną podczas transferów masowych:

ss -ti | grep -A 5 "10.128.0.2"
cubic wscale:7,7 rto:204 rtt:25.3/2.1 ato:40 mss:1360 pmtu:1500
retrans:0/847 rcv_space:65536

Wysoka liczba retransmisji (847 w tym przykładzie) potwierdza odrzucanie pakietów związane z fragmentacją.

Małe pakiety działają idealnie - sesje SSH są responsywne, wywołania API zwracają szybko, DNS rozwiązuje bez opóźnień. Tylko masowe transfery danych cierpią.

Metryki CloudWatch VPN potwierdzają, że tunel jest aktywny, ale transfer danych jest nieoptymalny:

aws cloudwatch get-metric-statistics \
  --namespace "AWS/VPN" \
  --metric-name TunnelDataOut \
  --dimensions Name=VpnId,Value=vpn-0abc123def456 \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%S) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
  --period 300 \
  --statistics Sum

Przyczyna

Degradacja przepustowości na tunelach IPsec wynika z rozmiaru pakietów i fragmentacji:

  1. Za wysoki Path MTU - narzut IPsec powoduje fragmentację. Standardowy MTU Ethernet to 1500 bajtów. Enkapsulacja IPsec dodaje 50-73 bajty narzutu (nagłówek ESP, IV, padding, tag uwierzytelniający). Gdy instancje wysyłają pakiety o rozmiarze 1500 bajtów, gateway VPN musi je fragmentować, aby zmieścić je w tunelu. Fragmentacja na endpoincie tunelu jest kosztowna obliczeniowo i zmniejsza efektywną przepustowość o połowę, ponieważ każdy oryginalny pakiet staje się dwoma.

  2. Brak konfiguracji MSS clamping na gateway VPN. Bez MSS clamping endpointy TCP negocjują maksymalny rozmiar segmentu na podstawie lokalnego MTU interfejsu (1460 bajtów dla MTU 1500). Wysyłają segmenty zbyt duże dla tunelu, powodując fragmentację na gateway VPN zamiast mniejszych segmentów od źródła.

  3. Ustawiony bit DF (Don’t Fragment) powodujący ciche odrzucanie. Wiele aplikacji ustawia bit DF na pakietach. Gdy te pakiety są zbyt duże dla tunelu i fragmentacja nie jest dozwolona, są po cichu odrzucane. Host wysyłający dowiaduje się o tym dopiero gdy komunikaty ICMP “Fragmentation Needed” dotrą z powrotem - co może być blokowane przez zapory sieciowe.

  4. Wyłączone TCP window scaling. Bez window scaling TCP nie jest w stanie dorównać iloczynowi przepustowości i opóźnienia tunelu. Nawet przy poprawnych ustawieniach MTU przepustowość pozostaje niska, ponieważ nadawca pauzuje czekając na potwierdzenia ACK.

  5. Ograniczenie pojedynczego przepływu. AWS VPN używa ECMP per-flow między ścieżkami tunelu. Pojedynczy strumień TCP jest przypięty do jednego tunelu i nie może przekroczyć około 1.25 Gbps. Jeśli testujesz jednym strumieniem iperf3 i oczekujesz więcej - to jest maksimum.

Rozwiązanie

Krok 1: Ustawienie MTU instancji na 1400

Na instancjach EC2, które komunikują się przez VPN, zmniejsz MTU interfejsu, aby uwzględnić narzut IPsec:

# On Amazon Linux / RHEL
sudo ip link set dev eth0 mtu 1400

# Make persistent via netplan (Ubuntu)
sudo tee /etc/netplan/99-mtu.yaml <<EOF
network:
  version: 2
  ethernets:
    eth0:
      mtu: 1400
EOF
sudo netplan apply

Na instancjach GCP:

# GCP VPC MTU is set at the network level
gcloud compute networks update my-vpc --mtu 1400

Uwaga: Zmiana MTU VPC w GCP wymaga zatrzymania i ponownego uruchomienia instancji w tej sieci.

Alternatywnie, ustaw MTU per-instancja na GCP:

sudo ip link set dev ens4 mtu 1400

Krok 2: Konfiguracja MSS clamping

MSS clamping mówi TCP, aby używał mniejszego rozmiaru segmentu bez zmiany MTU interfejsu. Jest to preferowane podejście, ponieważ wpływa tylko na ruch TCP przechodzący przez tunel.

Na AWS VPN, MSS clamping konfiguruje się w opcjach tunelu:

aws ec2 modify-vpn-tunnel-options \
  --vpn-connection-id vpn-0abc123def456 \
  --vpn-tunnel-outside-ip-address 203.0.113.1 \
  --tunnel-options "TunnelInsideIpVersion=ipv4"

AWS Site-to-Site VPN automatycznie stosuje MSS clamping do 1379 bajtów. Weryfikacja:

aws ec2 describe-vpn-connections \
  --vpn-connection-ids vpn-0abc123def456 \
  --query 'VpnConnections[0].Options.TunnelOptions[0]' \
  --output json | grep -i mss

Na instancjach Linux możesz dodać MSS clamping oparty na iptables jako dodatkowe zabezpieczenie:

sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --set-mss 1360

# Make persistent
sudo iptables-save | sudo tee /etc/iptables/rules.v4

Na GCP Cloud Router MSS clamping nie jest bezpośrednio konfigurowalny, ale gateway VPN obsługuje go automatycznie, gdy MTU tunelu jest ustawione poprawnie.

Krok 3: Weryfikacja działania Path MTU Discovery (PMTUD)

Test, czy komunikaty ICMP “Fragmentation Needed” nie są blokowane:

# From EC2 instance, test PMTUD to GCP instance
tracepath -n 10.128.0.2

Oczekiwany wynik pokazujący wykrywanie MTU:

 1?: [LOCALHOST]                      pmtu 1500
 1:  10.0.1.1                           0.5ms pmtu 1400
 2:  169.254.10.1                       5.2ms pmtu 1400
 3:  10.128.0.2                        25.1ms reached
     Resume: pmtu 1400 hops 3 back 3

Jeśli PMTUD nie działa (brak redukcji pmtu), sprawdź Security Groups i NACLe:

# Ensure ICMP type 3 (Destination Unreachable) is allowed inbound
aws ec2 describe-security-groups \
  --group-ids sg-0abc123 \
  --query 'SecurityGroups[0].IpPermissions[?IpProtocol==`icmp`]'

Dodaj ICMP type 3, jeśli brakuje:

aws ec2 authorize-security-group-ingress \
  --group-id sg-0abc123 \
  --protocol icmp \
  --port -1 \
  --cidr 10.128.0.0/16

Na GCP upewnij się, że reguły firewalla przepuszczają ICMP:

gcloud compute firewall-rules create allow-icmp-pmtud \
  --network my-vpc \
  --allow icmp \
  --source-ranges 10.0.0.0/8 \
  --direction INGRESS

Krok 4: Test z różnymi rozmiarami pakietów

Uruchom iperf3 z jawnym MSS, aby znaleźć optymalny rozmiar segmentu:

# Test with MSS 1360 (accounting for IPsec overhead)
iperf3 -c 10.128.0.2 -t 10 -M 1360

# Compare with default (likely 1460)
iperf3 -c 10.128.0.2 -t 10

# Test UDP to isolate from TCP behavior
iperf3 -c 10.128.0.2 -t 10 -u -b 1G -l 1360

Jeśli MSS 1360 daje znacząco lepszą przepustowość niż domyślna wartość, rozwiązanie jest potwierdzona.

Krok 5: Włączenie TCP window scaling

Sprawdź, czy window scaling jest włączone na instancjach:

sysctl net.ipv4.tcp_window_scaling

Jeśli wyłączone, włącz:

sudo sysctl -w net.ipv4.tcp_window_scaling=1
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

# Make persistent
echo "net.ipv4.tcp_window_scaling = 1" | sudo tee -a /etc/sysctl.d/99-vpn-tuning.conf
echo "net.ipv4.tcp_rmem = 4096 87380 16777216" | sudo tee -a /etc/sysctl.d/99-vpn-tuning.conf
echo "net.ipv4.tcp_wmem = 4096 65536 16777216" | sudo tee -a /etc/sysctl.d/99-vpn-tuning.conf
sudo sysctl --system

Krok 6: Test przepustowości wielowątkowej

Jeśli przepustowość jednego strumienia wynosi około 1.1-1.25 Gbps (limit per-tunel), użyj równoległych przepływów, aby wysycić wiele tuneli:

# 4 parallel streams
iperf3 -c 10.128.0.2 -t 30 -P 4

Jeśli test wielostrumieniowy pokazuje znaczącą poprawę, wąskim gardłem jest ograniczenie ECMP per-flow, a nie fragmentacja. W tym przypadku upewnij się, że Twój workload naturalnie generuje wiele przepływów TCP (co ma miejsce w większości aplikacji produkcyjnych).

Krok 7: Monitoring retransmisji TCP po naprawie

# Watch retransmits in real-time
watch -n 1 'ss -ti dst 10.128.0.0/16 | grep retrans'

Liczby retransmisji powinny pozostać na zero lub bliskie zera podczas masowych transferów.

Walidacja

Przeprowadź kompleksowy test przepustowości po zastosowaniu poprawek:

iperf3 -c 10.128.0.2 -t 60 -P 1 --json | jq '.end.sum_sent.bits_per_second / 1000000'

Oczekiwany wynik: ponad 1100 Mbps dla jednego strumienia.

Weryfikacja, że fragmentacja nie występuje:

# Check for fragmentation on the instance
cat /proc/net/snmp | grep -A 1 "Ip:"

Sprawdź wartości FragCreates i FragFails - nie powinny rosnąć podczas transferów.

Test z rzeczywistym obciążeniem:

# Large file transfer
time scp -o "Compression=no" /tmp/testfile-1G user@10.128.0.2:/tmp/

# Expected: ~8-9 seconds for 1 GB at 1 Gbps+

Uruchom tracepath, aby potwierdzić działanie PMTUD:

tracepath -n 10.128.0.2

Wynik powinien pokazywać pmtu 1400 (lub skonfigurowaną wartość) bez znaczników asymm lub !H.

Sprawdzenie, że retransmisje TCP są znikome podczas długotrwałego transferu:

# Start a transfer in background
iperf3 -c 10.128.0.2 -t 60 &

# Monitor retransmits
ss -ti dst 10.128.0.2 | grep retrans

Oczekiwany wynik: retrans:0/0 lub bardzo niskie jednocyfrowe wartości.

Jerzy Kopaczewski

Potrzebujesz pomocy z łącznością multi-cloud?

Umów darmową 30-minutową rozmowę. Zdiagnozujemy problem z połączeniem i zarekomendujemy właściwe rozwiązanie.