วิธีค้นหาการเชื่อมต่อซ็อกเก็ตปลายอีกด้าน


44

ฉันมีกระบวนการ (dbus-daemon) ซึ่งมีการเชื่อมต่อแบบเปิดมากมายผ่านซ็อกเก็ต UNIX หนึ่งในการเชื่อมต่อเหล่านี้คือ fd # 36:

=$ ps uw -p 23284
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
depesz   23284  0.0  0.0  24680  1772 ?        Ss   15:25   0:00 /bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session

=$ ls -l /proc/23284/fd/36 
lrwx------ 1 depesz depesz 64 2011-03-28 15:32 /proc/23284/fd/36 -> socket:[1013410]

=$ netstat -nxp | grep 1013410
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
unix  3      [ ]         STREAM     CONNECTED     1013410  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD

=$ netstat -nxp | grep dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013953  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013825  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013726  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013471  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013410  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012325  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012302  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012289  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012151  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011957  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011937  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011900  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011775  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011771  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011769  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011766  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011663  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011635  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011627  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011540  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011480  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011349  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011312  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011284  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011250  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011231  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011155  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011061  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011049  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011035  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011013  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1010961  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1010945  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD

จากการเชื่อมต่อตัวเลขฉันคิดว่า dbus-daemon เป็นเซิร์ฟเวอร์จริง ซึ่งก็โอเค แต่ฉันจะหากระบวนการที่เชื่อมต่อกับมันได้อย่างไร - ใช้การเชื่อมต่อที่จัดการไฟล์ที่ 36 ใน dbus-launcher? ลองใช้ lsof และ greps บน / proc / net / unix แต่ฉันไม่สามารถหาวิธีในการค้นหากระบวนการไคลเอนต์


คำตอบ:


25

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

บน Linux ตัวอย่างเช่นที่ lsof ต้องใช้ / proc / net / unix ซ็อกเก็ตโดเมน UNIX ทั้งหมดมีเส้นทางที่ถูกผูกไว้ แต่ไม่มีข้อมูลปลายทาง บ่อยครั้งที่ไม่มีเส้นทางที่ถูกผูกไว้ บ่อยครั้งที่ทำให้ไม่สามารถกำหนดจุดสิ้นสุดอื่น ๆ ได้ แต่เป็นผลมาจากการใช้งานระบบไฟล์ Linux / proc

ถ้าคุณดูที่ / proc / net / unix คุณสามารถเห็นตัวเองได้ว่า (อย่างน้อยในระบบของฉัน) เขาจะถูกต้องแน่นอน ฉันยังคงตกใจเพราะฉันพบว่าคุณสมบัติดังกล่าวมีความสำคัญในขณะที่ติดตามปัญหาเซิร์ฟเวอร์



โปรดทราบว่าจะบอกคุณแฟ้มเป้าหมายของการอ้างอิงซ็อกเก็ตโดเมนสุ่มคุณได้ขุดออกมาจาก/proc/net/unix /proc/.../fd/
i336_

26

คำตอบนี้สำหรับ Linux เท่านั้น ขึ้นอยู่กับคำตอบจาก Unix และ Linux Stack แลกเปลี่ยนผมประสบความสำเร็จในการระบุส่วนอื่น ๆ ของซ็อกเก็ตโดเมนยูนิกซ์ใช้ในเคอร์เนลโครงสร้างข้อมูลเข้าถึงได้โดยใช้และgdb /proc/kcoreคุณต้องเปิดใช้งานCONFIG_DEBUG_INFOและCONFIG_PROC_KCOREตัวเลือกเคอร์เนล

คุณสามารถใช้เพื่อให้ได้อยู่เคอร์เนลของซ็อกเก็ตซึ่งใช้รูปแบบของตัวชี้เช่นlsof 0xffff8803e256d9c0หมายเลขนั้นเป็นที่อยู่ของโครงสร้างหน่วยความจำในเคอร์เนลหรือชนิดที่struct unix_sockเกี่ยวข้อง โครงสร้างนั้นมีเขตข้อมูลที่เรียกว่าpeerซึ่งจุดที่ปลายอีกด้านของซ็อกเก็ต ดังนั้นคำสั่ง

# gdb /usr/src/linux/vmlinux /proc/kcore
(gdb) p ((struct unix_sock*)0xffff8803e256d9c0)->peer

จะพิมพ์ที่อยู่ของปลายอีกด้านของการเชื่อมต่อ คุณสามารถ grep ผลลัพธ์ของlsof -Uหมายเลขนั้นเพื่อระบุกระบวนการและหมายเลขตัวอธิบายไฟล์ของส่วนอื่น ๆ

การแจกแจงบางอย่างดูเหมือนจะให้สัญลักษณ์เคอร์เนลดีบักเป็นแพ็กเกจแยกต่างหากซึ่งจะแทนที่vmlinuxไฟล์ในคำสั่งด้านบน


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

3
@depesz สิ่งที่คุณต้องรู้คือออฟเซ็ตของpeerสมาชิกในunix_sockโครงสร้าง บนระบบ x86_64 ของฉันออฟเซ็ตนั้นคือ 656 ไบต์ดังนั้นฉันจึงสามารถใช้ปลายอีกด้านp ((void**)0xffff8803e256d9c0)[0x52]ได้ คุณยังคงต้องการCONFIG_PROC_KCOREแน่นอน
MvG

11

ที่จริงแล้วssจากiproute2(แทนที่ netstat, ifconfig เป็นต้น) สามารถแสดงข้อมูลนี้ได้

นี่คือตัวอย่างที่แสดงซ็อกเก็ต unix โดเมน ssh-agent ซึ่งsshกระบวนการเชื่อมต่ออยู่:

$ sudo ss -a --unix -p
Netid  State      Recv-Q Send-Q Local                             Address:Port          Peer    Address:Port
u_str  ESTAB      0      0      /tmp/ssh-XxnMh2MdLBxo/agent.27402 651026                *       651642                users:(("ssh-agent",pid=27403,fd=4)
u_str  ESTAB      0      0       *                                651642                *       651026                users:(("ssh",pid=2019,fd=4))

อืมมม ที่น่าสนใจ ... ฉันพลาดว่าคอลัมน์ "ที่อยู่: พอร์ต" สามารถจับคู่ได้แม้ว่าคอลัมน์ "เพียร์" จะไร้ประโยชน์โดยสิ้นเชิงสำหรับซ็อกเก็ตโดเมนยูนิกซ์
SamB

9

ซ็อกเก็ต Unix มักจะถูกกำหนดหมายเลขเป็นคู่ ดังนั้นคู่ของคุณน่าจะเท่ากับ 1013410 +/- 1 ดูว่ามีสองสิ่งใดที่อยู่และคาดเดาได้ที่ผู้ร้าย


8

ฉันเขียนเครื่องมือที่ใช้วิธี gdbของ MvG เพื่อรับข้อมูลเพียร์ซ็อกเก็ตอย่างเชื่อถือได้สัญลักษณ์การดีบักเคอร์เนลไม่จำเป็น

เพื่อให้กระบวนการเชื่อมต่อกับซ็อกเก็ตที่กำหนดให้ส่งผ่านหมายเลขไอโหนด:

# socket_peer 1013410
3703 thunderbird 

ในการค้นหากระบวนการทั้งหมดในครั้งเดียวnetstat_unixจะเพิ่มคอลัมน์ไปยังเอาต์พุตของ netstat:

# netstat_unix
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Peer PID/Program name  Path
unix  3      [ ]         STREAM     CONNECTED     6825     982/Xorg             1497/compiz            /tmp/.X11-unix/X0
unix  3      [ ]         STREAM     CONNECTED     6824     1497/compiz          982/Xorg                 
unix  3      [ ]         SEQPACKET  CONNECTED     207142   3770/chromium-brows  17783/UMA-Session-R       
unix  3      [ ]         STREAM     CONNECTED     204903   1523/pulseaudio      3703/thunderbird       
unix  3      [ ]         STREAM     CONNECTED     204902   3703/thunderbird     1523/pulseaudio           
unix  3      [ ]         STREAM     CONNECTED     204666   1523/pulseaudio      3703/thunderbird       
...

ลองnetstat_unix --dumpถ้าคุณต้องการเอาต์พุตที่ง่ายต่อการแยกวิเคราะห์
ดูhttps://github.com/lemonsqueeze/unix_sockets_peersสำหรับรายละเอียด

สำหรับข้อมูลแฮ็ก inode + 1 / -1นั้นไม่น่าเชื่อถือ มันใช้งานได้ตลอดเวลา แต่จะล้มเหลวหรือ (แย่กว่า) คืนซ็อกเก็ตผิดถ้าคุณโชคไม่ดี


1

แก้ไข system.conf ของคุณ

ในไฟล์นี้คุณสามารถเพิ่มสิ่งต่าง ๆ เพิ่มเติมเพื่อจุดประสงค์ในการดีบั๊ก

ตำแหน่งไฟล์: /etc/dbus-1/system.conf

สำหรับวัตถุประสงค์ในการดีบั๊กคุณสามารถแก้ไข system.conf เพื่อให้สามารถทำการดักฟังได้:

  1. แทนที่ส่วนนโยบายโดย:

    <policy context="default">

    <!-- Allow everything to be sent -->

    <allow send_destination="*" eavesdrop="true"/>

    <!-- Allow everything to be received -->

    <allow eavesdrop="true"/>

    <!-- Allow anyone to own anything -->

    <allow own="*"/>

    <!-- XXX: Allow all users to connect -->

    <allow user="*"/> </policy>

  2. ลบบรรทัด includeir: system.d

    <includedir>system.d</includedir>

ที่มา: http://old.nabble.com/dbus-send-error-td29893862.html


สิ่งที่มีประโยชน์อื่น ๆ เกี่ยวกับซ็อกเก็ตยูนิกซ์

วิธีที่ง่ายที่สุดในการค้นหาว่าเกิดอะไรขึ้นบนบัสคือการเรียกใช้dbus-monitorโปรแกรมซึ่งมาพร้อมกับแพ็คเกจ D-Bus

นอกจากนี้คุณสามารถลองใช้dbus-cleanup-socketsทำความสะอาดซ็อกเก็ตที่เหลือ

คำสั่งดังต่อไปนี้จะแสดงให้คุณเห็นว่ากระบวนการใดที่เชื่อมต่อกับซ็อกเก็ต dbus กี่ครั้งตามnetstatเอาต์พุต:

sudo netstat -nap | grep dbus | grep CONNECTED | awk '{print $8}' | sort | uniq -c

(ทดสอบบน Ubuntu)

วิธีที่ไม่ยอมใครง่ายๆ: คำสั่งนี้จะค้นหากระบวนการด้วยตนเองจาก / proc และแสดงว่ากำลังใช้การเชื่อมต่อมากที่สุด (ซ็อกเก็ตทุกประเภท):

ls -lR */fd/* | grep socket | sed -r "s@([0-9{1}]+)/fd/@_\1_@g" | awk -F_ '{print $2}' | uniq -c | sort -n | awk '{print $1" "$2; print system("ps "$2"|tail -n1")}'

ตัวอย่างผลลัพธ์:

(นับ, PID และบรรทัดถัดไปมีรายละเอียดเกี่ยวกับกระบวนการ)

25 3732
 3732 ?        Ss     0:38 /usr/bin/wineserver
89 1970
 1970 ?        Ss     0:02 //bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session

(ทดสอบบน Ubuntu)

มีความสุข.


ดูบทความที่เกี่ยวข้องสำหรับการอ้างอิง:

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