Назад | Перейти на главную страницу

Порт источника TCP увеличивается на 2, всегда даже для curl / wget

При использовании curl и wget, когда исходный порт не установлен вручную (например, с --local-port в curl), исходный TCP-порт всегда четный и будет увеличиваться на 2 вместо 1.

Например: в tcpdump, когда я устанавливаю соединение, я вижу, что используется исходный порт 45080, а затем следующее соединение будет использовать 45082, а не 45801. Используя локальный порт, я могу заставить его использовать нечетные порты, и tcpdump подтверждает, что они успешно используются. .

Это вызывает у меня проблемы на сетевом испытательном стенде, и я всю жизнь не могу понять, что контролирует неявный выбор порта tcp. Я могу изменить диапазон, но не могу изменить "приращение".

Используется ядро ​​centos7 и "3.10.0-514.el7.x86_64".

в tcpdump я вижу такое же поведение при использовании wget и curl, что заставляет меня думать, что это не проблема, специфичная для curl, а, скорее, то, что скрывается за механизмом, используемым для выбора портов.

Кроме того, если я вижу curl, использующий, например, порт 45080, я знаю, что следующий порт, который он будет использовать, - это 45082. Если я установлю --local-port равным 50000, а затем curl еще раз без --local-port, он будет 45082, как отдельный счетчик, увеличивает его, на который не влияет «последний» использованный порт.

В качестве альтернативы, если сделать то же самое, что и в предыдущем шаге, но вместо принудительного порта 50000, я заставлю его использовать 45082, порт, который он предположительно собирался выбрать, затем я снова использую curl, не форсируя локальный порт, он выберет 45083 , то если снова выберет 45084, то 45086 ...

Единственный другой способ заставить его естественным образом выбрать нечетный - это ограничить диапазон нечетным количеством портов.

есть ли системный вызов или какая-то операция ядра для выбора исходных портов, и есть ли способ изменить это?

Спасибо!

Я считаю, что смог доказать, что само ядро ​​увеличивает порты таким образом.

Strace показал, что как wget, так и curl вызывают connect () без вызова bind (), чтобы явно установить исходный порт.

Я написал сценарий python для имитации того же самого, и кажется, что ядро ​​3.1 увеличивается на 2, а ядро ​​2.6 - нет.

Интересно, что это верно только при использовании connect (), если вы привязываетесь к порту 0, тем самым позволяя ядру выбрать следующий доступный порт, это будет в значительной степени случайным.

Мой сценарий:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('10.28.0.2', 80))
addr = s.getsockname()
print addr[1]
s.close()

вывод:

$ python port_test.py
45008
$ python port_test.py
45010
$ python port_test.py
45012