В результате мониторинга и изучения проблем с рабочими VPN за последний 1.5 месяца стала примерно ясна суть еще одной проблемы.
Судя по всему вносятся потери во входящий трафик, весьма приблизительно по такой схеме: if (hash(src_ip, src_port, dst_ip, dst_port) % koef == 0) → drop packets with 3% probability.
При этом без разницы, что за трафик там идет - хоть даже Iperf3. То видно, что пока не меняются src_ip, dst_ip, dst_port, набор проблемных портов src_port не меняется в выборке из 100 портов (сейчас в такой выборке - около 5-6 проблемных портов).
Вероятность того что порт плохой (koef) - иногда больше, иногда меньше становится.
Отсюда следует, что при установке соединения - когда src_port выбирается рандомный, то с некоторой вероятностью мы получаем потерю пакетов и тормоза.
Наблюдается такое на TCP и на UDP, в связках (hetzner, leaseweb, other) ↔ (ростелеком, транстелеком).
Схема выглядит достаточно странно.
Находятся эти проблемные порты через Iperf, 3 секунды гоняем на порту, смотрим потери UDP или ретрансмиты TCP.
Вот к примеру график потерь пакетов из Гонконга на наборе из 1000 src портов от 1300 до 65000 с шагом 65:
А по вертикальной оси что отложено? Процент потерь?
Да, по вертикали процент потерь.
Интересно, значит пора начать повсеместно использовать UDPspeeder и udp2raw.
Если кто-то объединит функции этих программ с, например, TunSafe с автоматическим слежением качества связи дайте мне знать — мобильные процессоры не особо справляются с такой нагрузкой.
У меня есть такая проблема, но только в связке с одним провайдером на моей стороне (РФ) и одним зарубежным провайдером: не доходит значимая часть TCP SYN’ов, в обе стороны (ни я не могу установить соединение, ни они ко мне), на определённых портах.
Это обычный HTTP-вебсайт, не VPN.
Я пока не уверен, что это блокировки. Больше похоже либо на роутер с битой памятью где-то ближе к РФ (думал, что у моего провайдера, вы говорите, что разные каналы подвержены проблеме), либо как-то забавно настроенные фильтры BCP38.
Если я отправляю себе TCP SYN’ы от любого IP-адреса с определённой площадки (которая позволяет подменять IP-адрес источника), вижу 100% потерей при определённых портах.
Например, ни один TCP SYN-пакет из 10 от 8.8.8.8:65248 до меня:2233 не дошел, а от 8.8.8.8:55945 — никаких проблем, все дошли.
Вот еще аналогичный график потерь снятый с hetzner в сторону ростелеком. Не очень похоже на нормальный random / hash, либо используется плохая функция хэша.
Сегодня, после 3 ночи MSK, раскладка проблемных портов сменилась, хотя более суток была неизменной, с начала наблюдения.
Ранее также была зафиксирована зависимость потерь от размеров пакетов iperf (внутри vpn):
20 bytes - 0.37%
50 bytes - 0.5%
200 bytes - 0.76%
1350 bytes - 2.8%
А вообще эта байда длится уже не менее 1.5 месяцев.
А с помощью долбёжки с TTL можно ли выяснить проблемный маршрутизатор?
Наверное можно, но mtr под линукс не поддерживает --localport, а --port работает только в tcp режиме, судя по мануалу.
Рабочий исходящий порт:
% sudo tcptraceroute 94.100.24.67 80 -P 10016 -q 6
Selected device enp2s0, address 192.168.69.10, port 10016 for outgoing packets
Tracing the path to 94.100.24.67 on TCP port 80 (http), 30 hops max
1 192.168.69.1 1.975 ms 0.749 ms 1.166 ms 2.423 ms 2.253 ms *
2 95-161-156-121.obit.ru (95.161.156.121) 1.421 ms 2.675 ms 1.134 ms 4.958 ms 1.556 ms 1.889 ms
3 172.29.194.72 1.304 ms 2.454 ms 18.128 ms 9.192 ms 16.138 ms 14.347 ms
4 172.29.192.121 16.369 ms 12.064 ms 12.735 ms 9.513 ms 6.279 ms 3.141 ms
5 172.29.194.77 1.159 ms 0.963 ms 5.978 ms 1.091 ms 0.903 ms 0.936 ms
6 172.29.194.94 1.131 ms 2.890 ms 1.372 ms 1.941 ms 1.015 ms 1.064 ms
7 172.29.255.197 2.567 ms 1.537 ms 1.179 ms 1.031 ms 1.103 ms 1.136 ms
8 172.29.194.113 2.176 ms 1.925 ms 1.586 ms 1.224 ms 1.151 ms 1.352 ms
9 172.29.194.37 5.130 ms 1.498 ms 0.911 ms 1.154 ms 1.973 ms 1.570 ms
10 vi-xx-0150.brc2.obit.ru (85.114.1.13) 1.974 ms 2.378 ms 3.236 ms 1.887 ms 1.976 ms 7.417 ms
11 * 109.239.136.155 15.394 ms * * * *
12 100ge0-42.core2.ams1.he.net (184.105.65.125) 33.066 ms * * 112.909 ms * *
13 100ge0-29.core1.ams7.he.net (184.105.213.197) 60.557 ms 58.424 ms 64.578 ms 67.975 ms 83.675 ms 35.377 ms
14 hivelocity-ventures-corp.e0-1.switch1.ams7.he.net (184.105.27.106) 34.104 ms 48.390 ms 57.888 ms 64.501 ms 84.650 ms 105.816 ms
15 * * * * * *
16 * * * * * *
17 * * * * * *
18 94-100-24-67.static.hvvc.us (94.100.24.67) [open] 34.051 ms 35.087 ms 34.208 ms 34.867 ms 35.691 ms 34.678 ms
Нерабочий исходящий порт:
% sudo tcptraceroute 94.100.24.67 80 -P 10009 -q 6
Selected device enp2s0, address 192.168.69.10, port 10009 for outgoing packets
Tracing the path to 94.100.24.67 on TCP port 80 (http), 30 hops max
1 192.168.69.1 15.789 ms 2.220 ms 0.463 ms 0.513 ms 0.291 ms 0.852 ms
2 95-161-156-121.obit.ru (95.161.156.121) 1.104 ms 1.795 ms 0.810 ms 2.062 ms 0.843 ms 0.860 ms
3 172.29.194.72 1.588 ms 0.786 ms 0.857 ms 0.939 ms 0.791 ms 1.152 ms
4 172.29.192.121 1.264 ms 4.696 ms 4.347 ms 8.515 ms 9.309 ms 5.530 ms
5 172.29.194.77 1.583 ms 6.602 ms 0.909 ms 1.458 ms 2.957 ms 7.076 ms
6 172.29.194.94 0.853 ms 1.583 ms 1.364 ms 2.193 ms 0.903 ms 0.938 ms
7 172.29.255.197 2.833 ms 0.885 ms 1.057 ms 2.617 ms 1.297 ms 0.862 ms
8 172.29.194.113 1.736 ms 0.908 ms 4.144 ms 5.369 ms 4.128 ms 1.041 ms
9 172.29.194.37 1.459 ms 1.075 ms 2.203 ms 1.252 ms 1.298 ms 2.697 ms
10 vi-xx-0150.brc2.obit.ru (85.114.1.13) 1.359 ms 4.076 ms 3.059 ms 3.332 ms 1.875 ms 1.474 ms
11 * * * * * 109.239.136.155 70.226 ms
12 100ge0-42.core2.ams1.he.net (184.105.65.125) 39.163 ms * * 33.007 ms * 35.631 ms
13 100ge0-29.core1.ams7.he.net (184.105.213.197) 31.363 ms 33.058 ms 31.488 ms 32.445 ms 31.278 ms 31.369 ms
14 hivelocity-ventures-corp.e0-1.switch1.ams7.he.net (184.105.27.106) 35.329 ms 33.458 ms 33.483 ms 34.554 ms 39.352 ms 42.495 ms
15 * * * * * *
16 * * * * * *
17 * * * * * *
18 * * * * * *
19 * * * * * *
20 * * * * * *
21 * * * * * *
22 * * * * * *
23 * * * * * *
24 * * * * * *
25 * * * * * *
26 * * * * * *
27 * * * * * *
В трёх случах из трёх проблема появляется при транзите трафика через Мегафон Поволжье/Волга.
Последние хопы с трёх каналов: 83.169.204.90 и 85.26.205.119.
Не удается с помощью tcptraceroute что то толковое определить. Тут также то доходит, то не доходит, в зависимости от порта, но прямой связи с теми портами где потери по iperf - нет.
Но в ходе дальнейшего изучения также было выявлено что один хост, который сначала не давал потерь - вдруг стал давать небольшие потери на портах (0.2%), после нескольких тестов. Возможно спровоцировали это сканом.
А также в процессе скана iperf-ом, другой хост перешел из состояния малых потерь (0.2%) на некоторых портах в состояние больших потерь (3%), прямо посередине процесса скана.
Учитывая то, что iperf гонит случайный трафик, возможно мы идем по китайскому сценарию, когда в нераспознаваемый трафик вносятся потери с некоторой вероятностью.
График начался с малых потерь, а потом потери стали большими. Причем есть фаза когда есть и малые и большие одновременно. Конфиги на железо может распространяются так.
Серверы подконтрольны вам? Сделайте с них traceroute, вдруг там тоже Мегафон.
Да, подконтрольные. Но мегафона там никогда не было в трейсах, там либо ростелеком (в основном), либо трансттелеком (реже). По поводу наличия потерь на транстелекоме возможно я ошибся, проверил, там в трейсах почти везде ростелеком сейчас.
Возможно всё банально, и так проявляется криво работающий trunk.
Только вот проблема эта наблюдается с трафиком из разных частей света - гонконг, сша, европа, япония. Врядли везде транк криво работает.
У меня такое вышло , также проверял с 1300 до 65000 порта с шагом 65 по 3 секунды на UDP.
Использовал такой скрипт на питоне из под винды
import paramiko
import subprocess
import json
# Задайте здесь значения переменных
hostname = 'address' # Имя или IP-адрес сервера
port = 22 # Порт для SSH
username = 'username' # Имя пользователя
private_key_path = 'path-to-file' # Путь к файлу с приватным ключом SSH
iperf3_duration = 3 # Длительность теста iperf3 в секундах
output_file = "data.txt" # Файл для записи результатов
results_file = "results.txt" # Файл для записи отфильтрованных результатов
# Создание SSH-соединения
private_key = paramiko.RSAKey(filename=private_key_path)
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname, port=port, username=username, pkey=private_key)
for iperf3_port in range(1300, 65001, 65): # Цикл по портам
# Установка правил ufw и запуск iperf3 на сервере
commands = [
f'sudo ufw allow {iperf3_port}',
f'iperf3 -s -p {iperf3_port} -D'
]
for command in commands:
stdin, stdout, stderr = client.exec_command(command)
print(stdout.read().decode())
print(stderr.read().decode())
# Запуск iperf3 локально. iperf3 должен быть в PATH
subprocess.run(f'iperf3 -c {hostname} -p {iperf3_port} -u -t {iperf3_duration} -J > {output_file}', shell=True)
# Чтение результатов из файла и запись нужных значений в другой файл
with open(output_file, "r") as file:
data = json.load(file)
results = {
"port": iperf3_port,
"lost_percent": data["end"]["sum"]["lost_percent"]
}
with open(results_file, "a") as results_file_obj:
results_file_obj.write(json.dumps(results) + "\n") # Запись результатов в новую строку файла
# Остановка iperf3 на сервере и удаление правил ufw
commands = [
'pkill iperf3',
f'sudo ufw delete allow {iperf3_port}',
]
for command in commands:
stdin, stdout, stderr = client.exec_command(command)
print(stdout.read().decode())
print(stderr.read().decode())
# Закрытие SSH-соединения
client.close()
Может я что-то не так проверяю
А так живу за двумя натами, на дальнем востоке, проверял на серваке с нидерландов
За натом наверное будет проблематично задать source port, потому что NAT назначит свой.
Если же менять порт сервера, как в вашем случае, то source port все равно будет рандомным, и воспроизводимотси результатов не будет.
А так скрипт которым я проверял под линуксом, выглядит так: \
#!/usr/bin/bash
echo . > outfile.txt
for i in {20..1000}
do
SPORT=$((i*65))
echo $SPORT
iperf3 -c X.X.X.X -u -b 10m -t 2 --bind src.white.ip.addr --cport $SPORT >> outfile.txt
done
А на стороне сервера - iperf3 -s
Далее вывод в outfile.txt анализировал grep-ом на предмет потерь.
Под винду там iperf3 потребует больше опций, иначе он работает просто неадекватно.
Для UDP корректно сработает такой вариант опций клиента iperf3: -u -b 10m -l 1350 -w 2m -t 15
(это при условии что сервер - на линуксе или freebsd).
Обязательно чтобы было -l 1350 -w 2m
, иначе он просто меряет какую-то ерунду.
Для tcp iperf3 под винду обязательно чтобы было -w 2m
, иначе результаты тоже будут неакдекватные.
P.S. я тоже мерял на Дальнем Востоке
виндовый iperf где брали? на iperf.fr старая версия, вот тут https://files.budman.pw/ самый последний файл ver3.13, вроде адекватно работает