การตั้งค่า tcp_tw_recycle / นำกลับมาใช้ใหม่เป็น 1 มีอะไรบ้าง


10

ฉันตั้งค่าทั้ง tcp_tw_recycle / reuse เป็น 1 ในไฟล์กำหนดค่าของฉัน

สิ่งที่เป็นประโยชน์ในการทำเช่นนี้?

หากใช้ซ็อกเก็ต tcp อีกครั้งนั่นจะมีความเสี่ยงด้านความปลอดภัยหรือไม่? ie 2 การเชื่อมต่อที่แตกต่างกันทั้งที่อาจสามารถส่งข้อมูลได้

เหมาะสำหรับการเชื่อมต่อช่วงสั้น ๆ ที่มีโอกาสน้อยในการเชื่อมต่อใหม่หรือไม่?


คำถามที่ชัดเจนคือคุณคาดหวังอะไรจากการเปลี่ยนแปลงนี้
Robert Munteanu

1
@RobertMunteanu เกี่ยวข้องกับ: serverfault.com/questions/342501/…
codecompleting

คำตอบ:


24

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

เมื่อคุณเปิดใช้งานสามารถใช้tcp_tw_reuseซ็อกเก็ตในTIME_WAITสถานะก่อนที่จะหมดอายุและเคอร์เนลจะพยายามตรวจสอบให้แน่ใจว่าไม่มีการชนกันของหมายเลขลำดับ TCP หากคุณเปิดใช้งานtcp_timestamps(aka PAWS สำหรับการป้องกันหมายเลขลำดับที่ล้อมรอบ) จะทำให้แน่ใจว่าการชนเหล่านั้นจะไม่เกิดขึ้น อย่างไรก็ตามคุณต้องเปิดใช้งานการประทับเวลา TCP ที่ปลายทั้งสองด้าน (อย่างน้อยนั่นก็คือความเข้าใจของฉัน) ดูคำจำกัดความของ tcp_twsk_uniqueสำหรับรายละเอียดเต็มไปด้วยเลือด

เมื่อคุณเปิดใช้tcp_tw_recycleงานเคอร์เนลจะกลายเป็นก้าวร้าวมากขึ้นและจะทำให้สมมติฐานเกี่ยวกับการประทับเวลาที่ใช้โดยโฮสต์ระยะไกล มันจะติดตามการประทับเวลาครั้งสุดท้ายที่ใช้โดยแต่ละโฮสต์ระยะไกลที่มีการเชื่อมต่ออยู่ในTIME_WAITสถานะ) และอนุญาตให้ใช้ซ็อกเก็ตอีกครั้งหากการประทับเวลาเพิ่มขึ้นอย่างถูกต้อง อย่างไรก็ตามหากการประทับเวลาที่ใช้โดยโฮสต์เปลี่ยนแปลง (เช่นแปรปรวนย้อนเวลากลับไป) SYNแพ็คเก็ตจะลดลงอย่างเงียบ ๆ และการเชื่อมต่อจะไม่สร้างขึ้น (คุณจะเห็นข้อผิดพลาดคล้ายกับ "หมดเวลาเชื่อมต่อ") หากคุณต้องการดำน้ำในรหัสเคอร์เนลนิยามของ tcp_timewait_state_processอาจเป็นจุดเริ่มต้นที่ดี

ตอนนี้การประทับเวลาไม่ควรย้อนเวลากลับไป เว้นแต่:

  • โฮสต์ถูกรีบู๊ต (แต่เมื่อถึงเวลาสำรองข้อมูลTIME_WAITซ็อกเก็ตอาจหมดอายุแล้วดังนั้นจึงไม่ใช่ปัญหา)
  • ที่อยู่ IP นั้นถูกนำกลับมาใช้อย่างรวดเร็วโดยอย่างอื่น ( TIME_WAITการเชื่อมต่อจะยังคงอยู่เล็กน้อย แต่การเชื่อมต่ออื่น ๆ อาจจะถูกรบกวนด้วยTCP RSTและนั่นจะเพิ่มพื้นที่ว่าง)
  • การแปลที่อยู่เครือข่าย (หรือไฟร์วอลล์ smarty-pants) มีส่วนเกี่ยวข้องในระหว่างการเชื่อมต่อ

ในกรณีหลังคุณสามารถมีโฮสต์หลายหลังที่อยู่ IP เดียวกันดังนั้นลำดับเวลาที่แตกต่างกัน (หรือกล่าวว่าการประทับเวลาจะถูกสุ่มในแต่ละการเชื่อมต่อโดยไฟร์วอลล์) ในกรณีดังกล่าวบางโฮสต์จะไม่สามารถเชื่อมต่อแบบสุ่มได้เนื่องจากมีการแมปกับพอร์ตที่ที่TIME_WAITฝากข้อมูลของเซิร์ฟเวอร์มีการประทับเวลาที่ใหม่กว่า นั่นเป็นสาเหตุที่เอกสารบอกคุณว่า "อุปกรณ์ NAT หรือโหลดบาลานเซอร์อาจเริ่มปล่อยเฟรมเนื่องจากการตั้งค่า"

บางคนแนะนำให้ออกtcp_tw_recycleเพียงอย่างเดียว แต่เปิดใช้งานtcp_tw_reusetcp_timewait_lenและลด ฉันเห็นด้วย :-)


คำอธิบายที่ดี
yanglei

6

ฉันเพิ่งกัดฉันดังนั้นบางคนอาจได้รับประโยชน์จากความเจ็บปวดและความทุกข์ทรมานของฉัน ก่อนอื่นลิงก์ที่เกี่ยวข้องพร้อมข้อมูลมากมาย: http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html

โดยเฉพาะอย่างยิ่ง:

ผลที่ตามมาของการขาดเอกสารนี้คือเราพบคำแนะนำในการปรับแต่งมากมายที่แนะนำให้ตั้งค่าทั้งสองเป็น 1 เพื่อลดจำนวนรายการในสถานะ TIME-WAIT อย่างไรก็ตามตามที่ระบุไว้โดยหน้าคู่มือ tcp (7) ตัวเลือก net.ipv4.tcp_tw_recycle ค่อนข้างเป็นปัญหาสำหรับเซิร์ฟเวอร์สาธารณะเนื่องจากจะไม่จัดการการเชื่อมต่อจากคอมพิวเตอร์สองเครื่องหลังอุปกรณ์ NAT เดียวกันซึ่งเป็นปัญหาที่ยากต่อการ ตรวจจับและรอที่จะกัดคุณ:

ฉันใช้การเปิดใช้งานผู้ที่ประสบความสำเร็จอย่างมากเพื่อให้ latency ต่ำที่สุดเท่าที่จะทำได้การเชื่อมต่อ haproxy จากไคลเอนต์ไปยังคลัสเตอร์ MySql NDB นี่คือในระบบคลาวด์ส่วนตัวและไม่มีการเชื่อมต่อใด ๆ จากที่ใดไปยังที่ใด ๆ มี NAT ใด ๆ ในการผสม กรณีการใช้งานนั้นสมเหตุสมผลลดเวลาในการตอบสนองสำหรับผู้ใช้งานรัศมีที่กดปุ่ม NDB ผ่าน haproxy ให้มากที่สุด มันทำเช่นนั้น

ฉันทำมันซ้ำอีกครั้งในระบบสาธารณะที่หันหน้าไปทาง haproxy, ปรับสมดุลการรับส่งข้อมูลทางเว็บโดยไม่ต้องศึกษาผลกระทบ (โง่ใช่มั้ย?!) และค้นพบหลังจากการแก้ปัญหาและไล่ผีที่:

  • มันจะสร้างความโกลาหลสำหรับลูกค้าที่เชื่อมต่อผ่าน NAT
  • แทบเป็นไปไม่ได้ที่จะระบุเพราะมันสุ่มสมบูรณ์เป็นระยะและอาการจะกระทบลูกค้า A ในเวลาที่แตกต่างกันอย่างสมบูรณ์ (หรือไม่) กว่าลูกค้า B เป็นต้น

ในด้านลูกค้าพวกเขาจะเห็นช่วงเวลาที่พวกเขาไม่ได้รับการตอบสนองต่อแพ็คเก็ต SYN บางครั้งที่นี่และที่นั่นและบางครั้งเป็นระยะเวลานาน สุ่มอีกครั้ง

เรื่องสั้นที่นี่จากประสบการณ์ที่เจ็บปวดและเจ็บปวดเมื่อเร็ว ๆ นี้ของฉันคือปล่อยให้อยู่คนเดียว / ไม่สามารถใช้งานได้บนเซิร์ฟเวอร์สาธารณะที่เปิดใช้งานโดยไม่คำนึงถึงบทบาท!


4

จาก 'man 7 tcp' คุณจะเห็นสิ่งนี้:

   tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
          Enable fast recycling of TIME_WAIT sockets.  Enabling this option is not recommended since this causes problems when working with NAT
          (Network Address Translation).

   tcp_tw_reuse (Boolean; default: disabled; since Linux 2.4.19/2.6)
          Allow  to  reuse  TIME_WAIT  sockets  for  new connections when it is safe from protocol viewpoint.  It should not be changed without
          advice/request of technical experts.

ช่วยไม่มากที่นั่น การทดสอบนี้มีข้อมูลเชิงลึกที่ดีเช่นกัน:

/programming/6426253/tcp-tw-reuse-vs-tcp-tw-recycle-which-to-use-or-both

แต่ไม่ใช่ข้อมูลที่เฉพาะเจาะจงว่าทำไมการใช้ซ้ำอย่างปลอดภัยกว่าการรีไซเคิล คำตอบพื้นฐานคือ tcp_tw_reuse จะอนุญาตให้หนึ่งใช้ซ็อกเก็ตเดียวกันหากมีหนึ่งใน TIME_WAIT พร้อมกับพารามิเตอร์ TCP เดียวกันและอยู่ในสถานะที่คาดว่าจะไม่มีการรับส่งข้อมูลเพิ่มเติม (ฉันเชื่อว่าเมื่อ FIN ถูกส่ง ) tcp_tw_recycle ในทางกลับกันเพียงแค่จะใช้ซ็อกเก็ตที่อยู่ใน TIME_WAIT ด้วยพารามิเตอร์เดียวกันโดยไม่คำนึงถึงสถานะซึ่งสามารถสร้างความสับสนให้กับไฟร์วอลล์ของรัฐซึ่งอาจคาดว่าแพ็กเก็ตที่แตกต่างกัน

tcp_tw_reuse สามารถทำได้ในการเลือกรหัสโดยการตั้งค่าตัวเลือกซ็อกเก็ต SO_REUSEADDR เอกสารในman 7 socketเช่นนี้:

   SO_REUSEADDR
          Indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses.  For  AF_INET
          sockets  this means that a socket may bind, except when there is an active listening socket bound to the address.  When the listening
          socket is bound to INADDR_ANY with a specific port then it is not possible to bind to this port for any local address.   Argument  is
          an integer boolean flag.

1
คุณแน่ใจหรือว่าSO_REUSEADDRมีการเชื่อมโยงกับtcp_tw_reuse? เท่าที่ฉันรู้SO_REUSEADDRจะใช้เฉพาะเมื่อคุณต้องการbind()ในขณะที่tcp_tw_reuseจะแนะนำเคอร์เนลเพื่อใช้พอร์ตของซ็อกเก็ตท้องถิ่นในTIME_WAITสถานะถ้ามันต้องการที่จะสร้างการเชื่อมต่อขาออกใหม่
jpetazzo

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