W jaki sposób określa się porty źródłowe i jak mogę zmusić go do używania określonego portu

26

Gdy połączę się z https://www.google.co.uk, zmienia się to na 216.58.198.228:443. Następnie połączenie ze mną otwiera się na [Mój adres IP]: 63998.

Moje pytanie brzmi: w jaki sposób wybierany jest port 63998 i czy istnieje sposób na zmuszenie go do 63999.

TheGathron
źródło
9
czy istnieje sposób na zmuszenie go do 63999 Czy masz jakiś powód, aby to zrobić?
AL,
1
Jeśli piszesz aplikację, możesz otworzyć dowolny (nieużywany) port źródłowy, jaki chcesz. Ale to nie jest dobry pomysł i nie jest jasne, dlaczego tego chcesz?
pjc50,
6
@ pjc50 Rzeczywiście, to pytanie wydaje się mieć problem z XY .
Dev
1
Przesłałem zmianę, aby zmienić tytuł na „źródłowy” zamiast „lokalny”, ponieważ numery portów docelowych są „lokalne” na maszynie docelowej, ale źródło początkowego pakietu TCP SYN jest jednoznacznie źródłem inicjatora połączenie
Monty Harder

Odpowiedzi:

39

W jaki sposób określane są porty lokalne

Numer portu jest wybierany przez oprogramowanie implementujące TCP z zakresu numerów portów zwanych portami efemerycznymi .

Dokładny mechanizm wyboru numeru portu i zakresu, który należy zastosować, zależy od systemu operacyjnego.


Czy istnieje sposób na zmuszenie go do 63999.

Można to zrobić, zmieniając konfigurację oprogramowania implementacyjnego TCP.

Instrukcje dotyczące konfigurowania zakresu portów efemerycznych dla różnych systemów operacyjnych można znaleźć w części Zmiana zakresu portów efemerycznych .

  • Instrukcje dla systemu Linux i Windows znajdują się w poniższej odpowiedzi w celach informacyjnych.

Ograniczenie zasięgu do jednego portu nie jest jednak na przykład dobrym pomysłem 63999.

  • W systemie Windows nie jest to możliwe, ponieważ:

    Minimalny zakres portów, jaki można ustawić, to 255.


Zakres portów efemerycznych

Połączenie TCP / IPv4 składa się z dwóch punktów końcowych, a każdy punkt końcowy składa się z adresu IP i numeru portu. Dlatego, gdy użytkownik klienta łączy się z komputerem serwera, ustanowione połączenie może być traktowane jako 4-krotnie (adres IP serwera, port serwera, adres IP klienta, port klienta).

Zazwyczaj trzy z czterech są dobrze znane - komputer kliencki używa własnego adresu IP, a podczas łączenia się ze zdalną usługą wymagany jest adres IP i numer portu usługi serwera.

Nie jest od razu oczywiste, że po ustanowieniu połączenia strona kliencka połączenia używa numeru portu. O ile program kliencki nie zażąda wyraźnie określonego numeru portu, użyty numer portu jest efemerycznym numerem portu.

Porty efemeryczne to porty tymczasowe przypisane przez stos IP komputera i do tego celu są przypisane z wyznaczonego zakresu portów. Po zakończeniu połączenia port efemeryczny jest dostępny do ponownego użycia, chociaż większość stosów adresów IP nie użyje ponownie tego numeru portu, dopóki cała pula portów efemerycznych nie zostanie wykorzystana.

Tak więc, jeśli program kliencki ponownie się połączy, zostanie mu przypisany inny efemeryczny numer portu dla jego strony nowego połączenia.

Źródło Zakres przejściowy portów


Zmiana zakresu portów efemerycznych

Linux:

Linux pozwala przeglądać i zmieniać efemeryczny zakres portów za pomocą pliku /proc/sys/net/ipv4/ip_local_port_range. Na przykład pokazuje domyślną konfigurację w systemie jądra 2.2:

$ cat /proc/sys/net/ipv4/ip_local_port_range 
1024 4999

Aby zmienić to na preferowany zakres, możesz (jako administrator):

# echo "49152 65535" > /proc/sys/net/ipv4/ip_local_port_range 

Pamiętaj, że musisz to zrobić przy każdym uruchomieniu systemu, więc dodaj wiersz do skryptu uruchamiania systemu, tak /etc/rc.local aby twój zakres był zawsze używany.

Zauważ też, że jądro Linuksa 2.4 ustawi domyślnie zakres od 32768 do 61000, jeśli dostępna jest wystarczająca pamięć jądra, więc zmiana zakresu może nie być konieczna w nowszych systemach Linux.

Na koniec zauważ również, że możesz być w stanie użyć sysctlinterfejsu do zmiany ustawień zamiast używać /procsystemu plików. Nazwa sysctlparametru to „net.ipv4.ip_local_port_range”. Edytuj /etc/sysctl.confplik, jeśli go masz, lub poproś o uruchomienie skryptu uruchamiania sysctlręcznie, jeśli chcesz zmienić ten parametr za pomocą sysctl.

Windows Vista / Windows Server 2008 i nowsze:

Począwszy od systemów Windows Vista i Windows Server 2008, system Windows domyślnie korzysta z dużego zakresu (49152-65535), zgodnie z art . 929851 bazy wiedzy Microsoft Knowledge Base . Ten sam artykuł pokazuje również, jak możesz zmienić zakres, jeśli to konieczne, ale domyślny zakres jest teraz wystarczający dla większości serwerów.

Źródło Zmiana zakresu portów efemerycznych

Można wyświetlić zakres portów dynamicznych na komputerze z systemem Windows Vista lub Windows Server 2008, używając następujących netshpoleceń:

netsh int ipv4 show dynamicport tcp
netsh int ipv4 show dynamicport udp
netsh int ipv6 show dynamicport tcp
netsh int ipv6 show dynamicport udp 

Uwagi:

  • Zakres jest ustawiany osobno dla każdego transportu i każdej wersji adresu IP.
  • Zakres portów jest teraz naprawdę zasięgiem z punktem początkowym i końcowym.
  • Klienci Microsoft, którzy wdrażają serwery z systemem Windows Server 2008, mogą mieć problemy z komunikacją RPC między serwerami, jeśli zapory są używane w sieci wewnętrznej.
  • W takich przypadkach zalecamy zmianę konfiguracji zapór ogniowych w celu umożliwienia ruchu między serwerami w zakresie dynamicznych portów 49152 przelotowych 65535.
  • Zakres ten jest uzupełnieniem dobrze znanych portów używanych przez usługi i aplikacje.
  • Lub zakres portów używanych przez serwery można zmodyfikować na każdym serwerze.

Dostosuj ten zakres za pomocą netshpolecenia w następujący sposób:

netsh int <ipv4|ipv6> set dynamic <tcp|udp> start=number num=range

To polecenie ustawia dynamiczny zakres portów dla TCP. Port początkowy to liczba, a łączna liczba portów to zakres. Oto przykładowe polecenia:

netsh int ipv4 set dynamicport tcp start=10000 num=1000
netsh int ipv4 set dynamicport udp start=10000 num=1000
netsh int ipv6 set dynamicport tcp start=10000 num=1000
netsh int ipv6 set dynamicport udp start=10000 num=1000

Te przykładowe polecenia ustawiają dynamiczny zakres portów, aby zaczynały się od portu 10000 i kończyły na porcie 10999(1000 portów).

Uwagi:

  • Minimalny zakres portów, jaki można ustawić, to 255.
  • Minimalny port początkowy, jaki można ustawić, to 1025.
  • Maksymalny port końcowy (na podstawie konfigurowanego zakresu) nie może przekroczyć 65535.
  • Aby powielić domyślne zachowanie systemu Windows Server 2003, użyj 1025jako portu początkowego, a następnie użyj 3976jako zakresu zarówno dla TCP, jak i UDP. Powoduje to port początkowy 1025i port końcowy 5000.

Źródło artykułu 929851 Microsoft Knowledgebase :

Windows XP i starszy:

W przypadku starszych systemów operacyjnych Windows (Windows XP i starszych), Windows używa tradycyjnego zakresu BSD od 1024 do 4999 dla efemerycznego zakresu portów. Niestety wydaje się, że można ustawić tylko górną granicę efemerycznego zakresu portów. Oto informacje zaczerpnięte z artykułu 196271 bazy wiedzy Microsoft Knowledge Base :

  • Uruchom Edytor rejestru ( Regedt32.exe).
  • Zlokalizuj następujący klucz w rejestrze:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

  • W menu „Edycja” kliknij „Dodaj wartość”, a następnie dodaj następującą wartość rejestru:

    Nazwa wartości: MaxUserPortTyp danych: REG_DWORDWartość: 65534(na przykład)

    Prawidłowy zakres: 5000-65534(dziesiętny) Domyślnie: 0x1388(5000 dziesiętny)

    Opis: ten parametr kontroluje maksymalny numer portu używany, gdy aplikacja żąda od systemu dowolnego dostępnego portu użytkownika. Normalnie, efemeryczne (czyli krótkotrwałe) porty są rozdzielane pomiędzy wartościami 1024i 5000integracyjnych.

  • Zamknij Edytor rejestru.

Uwaga: istnieje inny odpowiedni artykuł z bazy wiedzy ( 812873 ), który twierdzi, że umożliwia ustawienie zakresu wykluczeń, co może oznaczać, że można wykluczyć porty 1024-9999(na przykład), aby mieć zakres portów efemerycznych 10000-65534. Nie udało nam się jednak uruchomić tego (od października 2004 r.).

Źródło Zmiana zakresu portów efemerycznych

DavidPostill
źródło
1
Przynajmniej wydaje się, że system Windows może ograniczyć zakres portów w całym systemie. W większości przypadków jest to prawdopodobnie zły pomysł, szczególnie ograniczenie go do jednego portu to: Patrz KB 929851 , wymienione polecenia przynajmniej działają w systemie Windows 7.
Seth
@Seth Yes. Nie chciałem o tym wspominać, ponieważ OP nie wspomniał o swoim systemie operacyjnym i nie chciałem rozszerzać odpowiedzi na systemy operacyjne N ...
DavidPostill
Masz rację co do tego. W końcu istnieje wiele systemów operacyjnych. To tylko coś, na co natknąłem się, próbując pierwotnie odpowiedzieć na to pytanie. Ponieważ odpowiedź była szybsza, pomyślałem, że ją dodam. To naprawdę dobrze napisana odpowiedź! :) Właśnie dodałem to jako wskazówkę, że czasem zmiana konfiguracji jest wystarczająca zamiast przeprogramowywania (może moje rozumienie jest po prostu inne - dla mnie brzmi to jak rekompilacja).
Seth
1
W rzeczywistości także w Linuksie jest to bardzo proste: po prostu zrób echo „49152 65535”> / proc / sys / net / ipv4 / ip_local_port_range . Jest to tak proste, że można to zrobić dla poszczególnych poleceń .
MariusMatutiae
2
Zamiast zmieniać efemeryczny zakres portów, znacznie lepiej byłoby, gdyby aplikacja wywołała wywołanie bindsystemowe przed wywołaniem connect. Niektóre aplikacje mają taką opcję, inne nie.
kasperd
9

Odpowiedź Davida Postilla jest całkowicie słuszna. Chciałbym tylko dodać do tego, podkreślając, że zmiana efemerycznego zakresu portów w Linuksie jest tak prosta, że ​​OP ma twierdzącą odpowiedź.

Zmieniasz EPR w następujący sposób:

echo "40000 60000" > /proc/sys/net/ipv4/ip_local_port_range 

i możesz wybrać port 50000 (jako przykład) za pomocą następującego skryptu:

OLD_RANGE=$(cat /proc/sys/net/ipv4/ip_local_port_range)
MY_PORT=50000
echo "$MY_PORT $MY_PORT" > /proc/sys/net/ipv4/ip_local_port_range
sudo -u SomeUser SomeApplication  & 
echo $OLD_RANGE" > /proc/sys/net/ipv4/ip_local_port_range 

Jedno zastrzeżenie tutaj: ponieważ w zasięgu znajduje się jeden port, inna aplikacja może go oderwać od wykonania trzeciej i czwartej linii powyżej; również, nawet jeśli nie ma warunków wyścigu, sparaliżujesz wszystkie inne aplikacje, dopóki nie przywrócisz dużego EPR, dlatego przywróciłem pierwotny zakres tak szybko, jak to możliwe.

Tak więc, jeśli systemem operacyjnym PO byłby Linux, odpowiedzią byłoby, że można to łatwo zrobić.

O dziwo, nie jest to takie proste w przypadku BSD, z których niektóre nie mają nawet ustawień jądra środowiska uruchomieniowego dla EPR. MacOS X, FreeBSD i OpenBSD wymagają modyfikacji pliku /etc/sysctl.conf , ale mają różne opcje dla EPR.

Niezależnie od powyższego i systemu operacyjnego fakt, że coś można zrobić, nie oznacza, że należy to zrobić: dlaczego, u licha, potrzebujesz tego? Nie mogę wymyślić jednego przypadku użycia.

MariusMatutiae
źródło
Dla Linuksa przykład +1.
DavidPostill
Hehe BSD / OS wymaga ponownej kompilacji jądra :)
DavidPostill
1
@DavidPostill To poważny problem.
MariusMatutiae
W twoim kodzie jest błąd. Twój typ obsady jest bardzo niewłaściwy. Ponadto dobrym pomysłem byłoby ustawienie BIND_PORTopcjonalne, aby kod mógł być nadal używany dokładnie tak samo jak oryginał. Myślę, htons(bind_port_env ? atoi(bind_port_env) : 0)że postąpiłby właściwie.
kasperd
1

Warto dodać, że jądro Linuksa również ma

net.ipv4.ip_local_reserved_ports

pokrętło działa nieco przeciwnie, ale mimo to może być bardzo przydatne, ponieważ w ten sposób można „wykopać dziurę” w przypadku usług, które otwierają określone porty w efemerycznym zakresie portów.

Krótki fragment dokumentacji :

Określ porty zarezerwowane dla znanych aplikacji innych firm. Porty te nie będą używane przez automatyczne przypisywanie portów (np. Podczas wywoływania connect () lub bind () z numerem portu 0). Jawne zachowanie przydziału portów pozostaje niezmienione.

Format stosowany zarówno dla danych wejściowych, jak i wyjściowych jest oddzieloną przecinkami listą zakresów (np. „1,2–4,10–10” dla portów 1, 2, 3, 4 i 10). Zapis do pliku wyczyści wszystkie wcześniej zarezerwowane porty i zaktualizuje bieżącą listę o tę podaną na wejściu.

poige
źródło