python 3.5 ICMP socket not working on Windows

ghz 昨天 ⋅ 2 views

I'm trying to make traceroute implementation in python 3.5. On linux this code works fine. On Windows 10 I have infinity waiting of ICMP packet. Wireshark see ICMP packet in Windows.

import socket

Create a UDP and ICMP sockets

receiver = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('ICMP'))

sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sender.setsockopt(socket.SOL_IP, socket.IP_TTL, 1)

server_address = (socket.gethostbyname('google.com'), 33434)

try: # Send data receiver.bind(("", 33434)) sent = sender.sendto(b"", server_address) data, server = receiver.recvfrom(512) print('received "%s"\n"%s"' % (data, server[0])) finally: print('closing socket') sender.close() receiver.close()

Answer

The issue you're encountering is likely related to the handling of raw sockets and the way Windows 10 treats ICMP packets. Windows has stricter rules when it comes to raw socket access, especially when it comes to sending and receiving ICMP packets, and this might be causing the infinite wait you're experiencing. Additionally, the use of raw sockets often requires administrative privileges on Windows, which could also be contributing to the issue.

Here's a breakdown of what might be happening and how to resolve it:

Problem Breakdown:

  1. Windows and Raw Sockets: In Windows, raw sockets are restricted to users with administrative privileges, and even then, they may behave differently compared to Linux. The issue might be that Windows is silently dropping the ICMP packets or that the TTL value isn't being handled correctly by the system.

  2. ICMP and UDP: You're sending a UDP packet with socket.SOCK_DGRAM, and you're trying to listen for ICMP (which is typically used for responses to a ping or traceroute). However, there might be confusion around how these packets are being handled by the system, especially with respect to the ICMP response.

Recommendations:

  1. Administrative Privileges: Ensure you're running your Python script with administrative privileges on Windows. Raw sockets require elevated privileges on Windows, so you may need to run your Python environment (e.g., command prompt, or IDE) as an administrator.

  2. ICMP Socket: You're using a raw socket to listen for ICMP packets. Make sure that Windows is allowing raw socket access. You might also want to ensure that the system's firewall is not blocking the ICMP packets.

  3. Timeout Handling: It might be helpful to implement a timeout for the recvfrom call to prevent it from hanging indefinitely if no ICMP response is received.

Modified Code with Timeout Handling:

import socket
import time

# Create a UDP socket and ICMP raw socket
receiver = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('ICMP'))
sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Set TTL to 1 to begin traceroute
sender.setsockopt(socket.SOL_IP, socket.IP_TTL, 1)

server_address = (socket.gethostbyname('google.com'), 33434)

try:
    # Bind receiver socket
    receiver.bind(("", 33434))
    sender.sendto(b"", server_address)

    # Set timeout for recvfrom to avoid infinite wait
    receiver.settimeout(2)  # Timeout after 2 seconds

    try:
        # Wait for the ICMP response
        data, server = receiver.recvfrom(512)
        print('Received "%s" from %s' % (data, server[0]))

    except socket.timeout:
        print("No response received within timeout.")

finally:
    print('Closing sockets.')
    sender.close()
    receiver.close()

Key Changes:

  1. Timeout for recvfrom: I added a timeout of 2 seconds for the recvfrom call to prevent the script from waiting forever if the ICMP response isn't received. You can adjust the timeout as needed.

  2. Error Handling: I wrapped the recvfrom call in a try-except block to catch timeouts and print a more informative message if no response is received.

Further Troubleshooting:

  • Firewall: Make sure the Windows firewall isn't blocking ICMP requests. You might need to temporarily disable it or add an exception for your Python program.

  • WinPcap / Npcap: On Windows, tools like Wireshark use WinPcap or Npcap to capture raw packets. While this works fine for tools like Wireshark, it may not be enough for your Python program to capture the raw ICMP responses. You can install Npcap (which is more updated) and ensure that it's configured to allow raw socket access.

  • Running as Administrator: Ensure that you're running your Python script as an administrator, as raw socket usage requires elevated privileges on Windows.

If the issue persists after applying these changes, it's likely a combination of Windows' restrictions on raw socket access and the way you're sending and receiving ICMP packets.