TCP source port incremented by 2, always even for curl / wget

When using curl and wget, when source port is not set manually (like with --local-port in curl), the source TCP port is always even, and will increment by 2, instead of 1.

EG: in tcpdump when I make a connection I see source port 45080 used, and then the next connection will use 45082, rather than 45801. Using local-port I can force it to use odd ports, and tcpdump confirms these are succesfully being used.

This is causing me problems in a network test bed, and I can't for the life of me figure out what is controlling the implicit tcp port selection. I can change the range, but I cant change the "incrementation".

Using centos7 and "3.10.0-514.el7.x86_64" kernel.

in tcpdump I see the same behavior using wget and curl, which leads me to believe this is not a curl specific problem, but rather whatever under the hood mechanism is being used to select ports.

Also, if I I see curl using port 45080 for example, I know the next port it will use is 45082. If I force a --local-port of 50000, then curl once more without the --local-port, it will be 45082, like a separate counter is increment it, that is not affected by whatever the "last" used port was.

Alternatively, if do the same thing as the above step, but instead of force port 50000, I force it to use 45082, the port it was presumebly going to pick, then i use curl again without forcing a local port, it will pick 45083, then if again it will pick 45084, then 45086...

The only other way I could get it to naturally pick an odd one is if I limited the range to an odd number of ports.

is there a sys call, or some kind of kernel operation for picking source ports, and is there a way to change it?

Thanks!

0
задан 26 September 2017 в 00:10
1 ответ

أعتقد أنني تمكنت من إثبات أن النواة نفسها تزيد المنافذ بهذه الطريقة.

أظهر Strace كلاً من استدعاء wget و curl connect () بدون استدعاء bind () لتعيين منفذ المصدر بشكل صريح.

كتبت نصًا بلغة بيثون لمحاكاة نفس الشيء ، ويبدو أن الزيادات 3.1 kernel بمقدار 2 ، و 2.6 kernel لا تفعل ذلك.

من المثير للاهتمام ، أن هذا صحيح فقط عند استخدام connect () ، إذا قمت بالربط على المنفذ 0 ، وبالتالي تركت kernel يختار المنفذ التالي المتاح ، فسيكون عشوائيًا إلى حد كبير.

البرنامج النصي الخاص بي:

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
0
ответ дан 5 December 2019 в 07:26

Теги

Похожие вопросы