มีการกำหนดพอร์ตต้นทางอย่างไรและฉันจะบังคับให้ใช้พอร์ตเฉพาะได้อย่างไร


26

เมื่อฉันเชื่อมต่อกับhttps://www.google.co.ukการเปลี่ยนแปลงนี้จะเป็น 216.58.198.228:443 จากนั้นการเชื่อมต่อกับฉันจะเปิดใน [ที่อยู่ IP ของฉัน]: 63998

คำถามของฉันคือวิธีเลือกพอร์ต 63998 และมีวิธีบังคับให้เป็น 63999


9
มีวิธีบังคับให้เป็น 63,999คุณมีเหตุผลอะไรบ้างที่พยายามทำเช่นนี้?
อัล

1
หากคุณกำลังเขียนแอปพลิเคชันคุณสามารถเปิดพอร์ตต้นทางใด ๆ (ไม่ได้ใช้) ที่คุณต้องการ แต่ไม่ใช่ความคิดที่ดีและไม่ชัดเจนว่าทำไมคุณต้องการสิ่งนี้
pjc50

6
@ pjc50 อันที่จริงคำถามนี้ดูเหมือนว่ามันอาจจะมีปัญหา XY
Dev

1
ฉัน "ได้ส่งการแก้ไขเพื่อเปลี่ยนชื่อให้พูดว่า" source "แทนที่จะเป็น" local "เนื่องจากหมายเลขพอร์ตปลายทางคือ" local "ไปยังเครื่องปลายทาง แต่แหล่งที่มาของแพ็กเก็ต TCP SYN เริ่มต้นนั้นไม่น่าสงสัยเลยว่าเป็นผู้ริเริ่ม การเชื่อมต่อ
Monty Harder

คำตอบ:


39

พอร์ตท้องถิ่นถูกกำหนดอย่างไร

หมายเลขพอร์ตที่ถูกเลือกโดยซอฟแวร์การดำเนินงานของ TCP จากช่วงของหมายเลขพอร์ตที่เรียกว่าพอร์ตชั่วคราว

กลไกที่แน่นอนสำหรับการเลือกหมายเลขพอร์ตและช่วงที่จะใช้นั้นขึ้นอยู่กับระบบปฏิบัติการ


มีวิธีการบังคับให้เป็น 63999

สิ่งนี้สามารถทำได้โดยการเปลี่ยนการกำหนดค่าของซอฟต์แวร์การใช้ TCP

คำแนะนำเกี่ยวกับการกำหนดค่าพอร์ตชั่วคราวช่วงสำหรับความหลากหลายของระบบปฏิบัติการที่แตกต่างกันสามารถพบได้ที่เปลี่ยนชั่วคราวช่วงพอร์ต

  • คำแนะนำสำหรับ Linux และ Windows รวมอยู่ในคำตอบด้านล่างนี้เพื่อการอ้างอิง

แต่ก็ไม่ได้เป็นความคิดที่ดีที่จะ จำกัด 63999ช่วงที่จะพอร์ตเดียวตัวอย่างเช่น

  • ในความเป็นจริงบน Windows นี่เป็นไปไม่ได้เช่น

    ช่วงต่ำสุดของพอร์ตที่สามารถตั้งค่าได้คือ 255


ช่วงพอร์ตชั่วคราว

การเชื่อมต่อ TCP / IPv4 ประกอบด้วยสองปลายทางและแต่ละปลายทางประกอบด้วยที่อยู่ IP และหมายเลขพอร์ต ดังนั้นเมื่อผู้ใช้ไคลเอนต์เชื่อมต่อกับคอมพิวเตอร์เซิร์ฟเวอร์การเชื่อมต่อที่สร้างไว้สามารถถูกคิดเป็น 4-tuple ของ (IP เซิร์ฟเวอร์, พอร์ตเซิร์ฟเวอร์, IP ไคลเอ็นต์, พอร์ตไคลเอ็นต์)

โดยปกติแล้วสามในสี่นั้นเป็นที่รู้จักกันดี - เครื่องไคลเอนต์ใช้ที่อยู่ IP ของตัวเองและเมื่อเชื่อมต่อกับบริการระยะไกลต้องใช้ที่อยู่ IP ของเครื่องเซิร์ฟเวอร์และหมายเลขพอร์ตบริการ

สิ่งที่ไม่ชัดเจนในทันทีคือเมื่อการเชื่อมต่อถูกสร้างขึ้นที่ฝั่งไคลเอ็นต์ของการเชื่อมต่อจะใช้หมายเลขพอร์ต หากโปรแกรมไคลเอนต์ร้องขอหมายเลขพอร์ตเฉพาะอย่างชัดเจนหมายเลขพอร์ตที่ใช้คือหมายเลขพอร์ตชั่วคราว

พอร์ตชั่วคราวเป็นพอร์ตชั่วคราวที่กำหนดโดยสแต็ค IP ของเครื่องและได้รับมอบหมายจากช่วงของพอร์ตที่กำหนดสำหรับจุดประสงค์นี้ เมื่อการเชื่อมต่อสิ้นสุดลงพอร์ตชั่วคราวจะพร้อมใช้งานเพื่อนำมาใช้ใหม่แม้ว่าสแต็ค IP ส่วนใหญ่จะไม่นำหมายเลขพอร์ตนั้นมาใช้ซ้ำจนกว่าจะใช้พูลทั้งหมดของพอร์ตชั่วคราวเท่านั้น

ดังนั้นหากโปรแกรมไคลเอนต์เชื่อมต่ออีกครั้งจะมีการกำหนดหมายเลขพอร์ตชั่วคราวสำหรับการเชื่อมต่อใหม่

แหล่งที่มาช่วงพอร์ตชั่วคราว


การเปลี่ยนช่วงพอร์ตชั่วคราว

ลินุกซ์:

/proc/sys/net/ipv4/ip_local_port_rangeลินุกซ์ช่วยให้คุณสามารถดูและเปลี่ยนช่วงพอร์ตชั่วคราวโดยเพียงแค่ใช้ไฟล์ ตัวอย่างเช่นสิ่งนี้แสดงการกำหนดค่าเริ่มต้นบนระบบเคอร์เนล 2.2:

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

หากต้องการเปลี่ยนเป็นช่วงที่ต้องการคุณสามารถทำได้ (ในฐานะ superuser):

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

โปรดทราบว่าคุณจะต้องทำสิ่งนี้ทุกครั้งที่บูทระบบดังนั้นโปรดเพิ่มบรรทัดลงในสคริปต์เริ่มต้นระบบเช่น/etc/rc.local เพื่อให้ช่วงของคุณถูกใช้เสมอ

นอกจากนี้โปรดทราบว่าเคอร์เนล 2.4 ของ Linux จะเริ่มต้นช่วงของ 32768 ถึง 61000 หากมีหน่วยความจำเคอร์เนลเพียงพอดังนั้นการเปลี่ยนช่วงอาจไม่จำเป็นสำหรับระบบ Linux รุ่นใหม่

สุดท้ายโปรดทราบว่าคุณอาจใช้sysctlอินเทอร์เฟซเพื่อเปลี่ยนการตั้งค่าแทนการใช้/procระบบไฟล์ ชื่อของsysctlพารามิเตอร์คือ "net.ipv4.ip_local_port_range" แก้ไข/etc/sysctl.confไฟล์ถ้าคุณมีมันหรือมีสคริปต์เริ่มต้นเรียกใช้คำสั่งด้วยตนเองถ้าคุณต้องการที่จะเปลี่ยนพารามิเตอร์นี้ใช้sysctlsysctl

Windows Vista / Windows Server 2008 และใหม่กว่า:

ในฐานะของ Windows Vista และ Windows Server 2008, Windows ตอนนี้ใช้ช่วงขนาดใหญ่ (49,152-65,535) โดยค่าเริ่มต้นตามที่ไมโครซอฟท์คลังความรู้บทความ929851 บทความเดียวกันนั้นยังแสดงวิธีที่คุณสามารถเปลี่ยนช่วงได้หากต้องการ แต่ช่วงเริ่มต้นก็เพียงพอแล้วสำหรับเซิร์ฟเวอร์ส่วนใหญ่

แหล่งที่มาการเปลี่ยนช่วงพอร์ตชั่วคราว

คุณสามารถดูช่วงพอร์ตแบบไดนามิกบนคอมพิวเตอร์ที่ใช้ Windows Vista หรือคอมพิวเตอร์ Windows Server 2008 โดยใช้netshคำสั่งต่อไปนี้ :

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

หมายเหตุ:

  • ช่วงถูกตั้งค่าแยกกันสำหรับการขนส่งแต่ละครั้งและสำหรับ IP แต่ละรุ่น
  • ช่วงของพอร์ตเป็นช่วงที่มีจุดเริ่มต้นและจุดสิ้นสุดอย่างแท้จริง
  • ลูกค้าของ Microsoft ที่ปรับใช้เซิร์ฟเวอร์ที่ใช้ Windows Server 2008 อาจมีปัญหากับการสื่อสาร RPC ระหว่างเซิร์ฟเวอร์หากมีการใช้ไฟร์วอลล์ในเครือข่ายภายใน
  • ในกรณีนี้เราขอแนะนำให้คุณกำหนดค่าไฟร์วอลล์เพื่อให้การจราจรระหว่างเซิร์ฟเวอร์ในช่วงพอร์ตแบบไดนามิกของผ่าน49152 65535
  • ช่วงนี้นอกเหนือจากพอร์ตที่รู้จักกันดีที่ใช้โดยบริการและแอปพลิเคชัน
  • หรือช่วงพอร์ตที่ใช้โดยเซิร์ฟเวอร์สามารถแก้ไขได้ในแต่ละเซิร์ฟเวอร์

คุณปรับช่วงนี้โดยใช้netshคำสั่งดังต่อไปนี้:

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

คำสั่งนี้ตั้งค่าช่วงไดนามิกพอร์ตสำหรับ TCP พอร์ตเริ่มต้นคือหมายเลขและจำนวนพอร์ตทั้งหมดคือช่วง ต่อไปนี้เป็นคำสั่งตัวอย่าง:

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

คำสั่งตัวอย่างเหล่านี้ตั้งค่าช่วงพอร์ตแบบไดนามิกเพื่อเริ่มต้นที่พอร์ต 10000 และสิ้นสุดที่พอร์ต10999(1,000 พอร์ต)

หมายเหตุ:

  • 255ช่วงต่ำสุดของพอร์ตที่สามารถตั้งค่าได้
  • 1025พอร์ตเริ่มต้นขั้นต่ำที่สามารถตั้งค่าเป็น
  • พอร์ตสิ้นสุดสูงสุด (ขึ้นอยู่กับความเป็นอยู่ช่วงกำหนดค่า) 65535จะต้องไม่เกิน
  • เมื่อต้องการทำซ้ำการทำงานเริ่มต้นของ Windows Server 2003 ให้ใช้1025เป็นพอร์ตเริ่มต้นจากนั้นใช้3976เป็นช่วงสำหรับทั้ง TCP และ UDP ผลนี้ในพอร์ตเริ่มต้นของและพอร์ตท้ายของ10255000

แหล่งบทความ Microsoft Knowledgebase 929851 :

Windows XP และรุ่นเก่ากว่า:

สำหรับระบบปฏิบัติการ Windows รุ่นเก่า (Windows XP และเก่ากว่า) Windows ใช้ช่วง BSD ดั้งเดิมที่ 1024 ถึง 4999 สำหรับช่วงพอร์ตชั่วคราว น่าเสียดายที่คุณสามารถกำหนดขอบเขตบนของช่วงพอร์ตชั่วคราวได้เท่านั้น นี่คือข้อมูลที่คัดลอกมาจาก Microsoft Knowledgebase Article 196271 :

  • เริ่มตัวแก้ไขรีจิสทรี ( Regedt32.exe)
  • ค้นหาคีย์ต่อไปนี้ในรีจิสตรี:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

  • ในเมนู "แก้ไข" คลิก "เพิ่มค่า" แล้วเพิ่มค่ารีจิสทรีต่อไปนี้:

    ชื่อค่า: MaxUserPortชนิดข้อมูล: REG_DWORDค่า: 65534(ตัวอย่าง)

    ช่วงที่ถูกต้อง: 5000-65534(ทศนิยม) ค่าเริ่มต้น: 0x1388(ทศนิยม 5000)

    คำอธิบาย: พารามิเตอร์นี้ควบคุมหมายเลขพอร์ตสูงสุดที่ใช้เมื่อแอปพลิเคชันร้องขอพอร์ตผู้ใช้ที่มีอยู่จากระบบ โดยปกติพอร์ตชั่วคราว (นั่นคือช่วงสั้น ๆ ) จะถูกจัดสรรระหว่างค่าของ1024และ5000รวม

  • ออกจาก Registry Editor

หมายเหตุ: มีบทความ KB อื่นที่เกี่ยวข้องคือ ( 812,873 ) ซึ่งอ้างว่าเพื่อให้คุณสามารถตั้งค่าช่วงการยกเว้นซึ่งอาจหมายความว่าคุณสามารถยกเว้นพอร์ต1024-9999(ตัวอย่าง) 10000-65534จะมีพอร์ตชั่วคราวช่วงเป็น อย่างไรก็ตามเราไม่สามารถใช้งานได้ (จนถึงเดือนตุลาคม 2547)

แหล่งที่มาการเปลี่ยนช่วงพอร์ตชั่วคราว


1
ดูเหมือนว่าอย่างน้อย windows ก็เป็นไปได้ที่จะ จำกัด ระบบช่วงพอร์ต ในกรณีส่วนใหญ่นี่อาจเป็นความคิดที่ไม่ดีโดยเฉพาะอย่างยิ่งการ จำกัด ให้พอร์ตหนึ่งพอร์ต: ดู KB 929851คำสั่งที่แสดงรายการอย่างน้อยใช้งานได้กับ Windows 7
Seth

@ เซทใช่ ฉันลังเลที่จะพูดถึงเรื่องนี้เนื่องจาก OP ไม่ได้พูดถึงระบบปฏิบัติการของเขาและฉันไม่ต้องการขยายคำตอบเพื่อให้ครอบคลุมระบบปฏิบัติการ N ...
DavidPostill

คุณพูดถูก หลังจากทั้งหมดมีระบบปฏิบัติการมากมาย มันเป็นสิ่งที่ฉันสะดุดในขณะที่พยายามตอบคำถามนี้ เมื่อคำตอบของคุณเร็วขึ้นฉันแค่คิดว่าฉันจะเพิ่ม มันเป็นคำตอบที่เขียนได้ดีมาก! :) เพิ่งเพิ่มมันเป็นคำใบ้ที่บางครั้งการเปลี่ยนการตั้งค่านั้นเพียงพอมากกว่าการเขียนโปรแกรมซ้ำ (บางทีความเข้าใจของฉันอาจแตกต่างกัน - สำหรับฉันที่ฟังดูเหมือนจะคอมไพล์ใหม่)
เซท

1
ในความเป็นจริงใน Linux เกินไปมันเป็นเรื่องง่ายมาก: เพียงแค่ทำecho "49152 65535"> proc / มันจึงเป็นเรื่องง่ายที่จะสามารถทำได้บนต่อคำสั่งพื้นฐาน
MariusMatutiae

2
แทนที่จะเปลี่ยนช่วงพอร์ตชั่วคราวมันจะดีกว่ามากที่จะมีแอพลิเคชันโทรสายระบบก่อนที่มันจะสายbind connectแอปพลิเคชั่นบางตัวมีตัวเลือกในการทำเช่นนั้น
kasperd

9

คำตอบของ David Postill นั้นถูกต้องสมบูรณ์ ฉันต้องการเพียงเพิ่มเข้าไปโดยเน้นว่าการเปลี่ยนช่วงพอร์ตชั่วคราวในLinuxนั้นง่ายมาก OP จึงมีคำตอบยืนยัน

คุณเปลี่ยน EPR ดังนี้:

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

และคุณสามารถเลือกพอร์ต 50000 (เป็นตัวอย่าง) ด้วยสคริปต์ต่อไปนี้:

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 

หนึ่งข้อแม้ที่นี่: เนื่องจากมีพอร์ตเดียวในช่วงแอปพลิเคชันอื่นอาจแย่งออกไปจากคุณระหว่างการดำเนินการของบรรทัดที่สามและสี่ด้านบน นอกจากนี้แม้ว่าจะไม่มีสภาพการแข่งขันคุณจะทำให้เป็นอัมพาตแอปพลิเคชันอื่น ๆ ทั้งหมดจนกว่าคุณจะเรียกคืน EPR ขนาดใหญ่ซึ่งเป็นสาเหตุที่ฉันกู้คืนช่วงดั้งเดิมโดยเร็วที่สุด

ดังนั้นหากระบบปฏิบัติการของ OPs เป็น Linux คำตอบก็น่าจะทำได้ง่าย

น่าแปลกใจที่สิ่งนี้ไม่ตรงไปตรงมากับ BSD บางแห่งไม่มีการตั้งค่าเคอร์เนลรันไทม์สำหรับ EPR MacOS X, FreeBSD และ OpenBSD ต้องการการแก้ไขไฟล์/etc/sysctl.confแต่มีตัวเลือกต่าง ๆ สำหรับ EPR

โดยไม่คำนึงถึงข้างต้นและของ OS ความจริงที่ว่าสิ่งที่สามารถทำได้ไม่ได้หมายความว่ามันควรจะทำ: ทำไมบนโลกนี้คุณต้องการสิ่งนี้? ฉันไม่สามารถนึกถึงกรณีการใช้งานเพียงครั้งเดียว


สำหรับ Linux ตัวอย่าง +1
DavidPostill

ฮิฮิ. BSD / OS ต้องการการคอมไพล์เคอร์เนลใหม่ :)
DavidPostill

1
@DavidPostill นั่นเป็นคนเกียจคร้านที่สำคัญ
MariusMatutiae

มีข้อบกพร่องในตัวอย่างโค้ดของคุณ นักแสดงประเภทของคุณถูกใส่ผิดที่มาก นอกจากนี้จะเป็นการดีBIND_PORTถ้าคุณเลือกทำเช่นนั้นรหัสยังคงสามารถใช้งานได้ในลักษณะเดียวกับต้นฉบับ ฉันคิดว่าhtons(bind_port_env ? atoi(bind_port_env) : 0)จะทำในสิ่งที่ถูกต้อง
kasperd

1

เป็นมูลค่าเพิ่มที่เคอร์เนลลินุกซ์ยังมี

net.ipv4.ip_local_reserved_ports

ลูกบิดที่ค่อนข้างตรงข้าม แต่อย่างไรก็ตามมันอาจมีประโยชน์มากเพราะวิธีนี้คุณสามารถ "punch a hole" สำหรับบริการที่เปิดพอร์ตเฉพาะ (s) ในช่วงอื่น ๆ ของพอร์ตชั่วคราว

ข้อความที่ตัดตอนมาสั้น ๆ จากเอกสาร :

ระบุพอร์ตที่สงวนไว้สำหรับแอปพลิเคชันบุคคลที่สามที่รู้จัก พอร์ตเหล่านี้จะไม่ถูกใช้โดยการกำหนดพอร์ตอัตโนมัติ (เช่นเมื่อโทรเชื่อมต่อ () หรือผูก () ด้วยหมายเลขพอร์ต 0) พฤติกรรมการจัดสรรพอร์ตอย่างชัดเจนไม่เปลี่ยนแปลง

รูปแบบที่ใช้สำหรับทั้งอินพุตและเอาต์พุตเป็นรายการของช่วงที่คั่นด้วยเครื่องหมายจุลภาค (เช่น "1,2-4,10-10" สำหรับพอร์ต 1, 2, 3, 4 และ 10) การเขียนไฟล์จะล้างพอร์ตที่สงวนไว้ก่อนหน้านี้ทั้งหมดและอัปเดตรายการปัจจุบันด้วยพอร์ตที่ให้ไว้ในอินพุต

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.