Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python check udp port open

Tags:

I'm trying to check using Python 3.6 if a remote DNS server is listening on port 53 UDP.

This is what I tried:

def check_port(host, port):
    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.settimeout(1)
    try:
        result = s.connect_ex((host, port))
    except socket.gaierror:
        s.close()
        return 1
    s.close()
    return result  # 0 == Port is open

But I get 0 all the time even if the port is close. Trying TCP using SOCK_STREAM works like a charm.

I also tried:

def check_port_udp(host, port):
    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.settimeout(1)
    try:
        s.sendto('ping'.encode(), (host, port))
        s.recvfrom(1024)
    except socket.timeout:
        s.close()
        print(1)
        return 1
    s.close()
    print(0)
    return 0  # 0 == Port is open

But I get 1 all then time even if the port it's open

like image 413
Adrian Gherasim Avatar asked Mar 17 '17 21:03

Adrian Gherasim


2 Answers

Basic idea: send a DNS query to that port.If there is a response, the port is open.

import random
import socket
import struct


class SendDNSPkt:
    def __init__(self,url,serverIP,port=53):
        self.url=url
        self.serverIP = serverIP
        self.port=port
    def sendPkt(self):
        pkt=self._build_packet()
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.settimeout(1)
        sock.sendto(bytes(pkt), (self.serverIP, self.port))
        data, addr = sock.recvfrom(1024)
        sock.close()
        return data

    def _build_packet(self):
        randint = random.randint(0, 65535)
        packet = struct.pack(">H", randint)  # Query Ids (Just 1 for now)
        packet += struct.pack(">H", 0x0100)  # Flags
        packet += struct.pack(">H", 1)  # Questions
        packet += struct.pack(">H", 0)  # Answers
        packet += struct.pack(">H", 0)  # Authorities
        packet += struct.pack(">H", 0)  # Additional
        split_url = self.url.split(".")
        for part in split_url:
            packet += struct.pack("B", len(part))
            for s in part:
                packet += struct.pack('c',s.encode())
        packet += struct.pack("B", 0)  # End of String
        packet += struct.pack(">H", 1)  # Query Type
        packet += struct.pack(">H", 1)  # Query Class
        return packet

def checkDNSPortOpen():
    # replace 8.8.8.8 with your server IP!
    s = SendDNSPkt('www.google.com', '8.8.8.8')
    portOpen = False
    for _ in range(5): # udp is unreliable.Packet loss may occur
        try:
            s.sendPkt()
            portOpen = True
            break
        except socket.timeout:
            pass
    if portOpen:
        print('port open!')
    else:
        print('port closed!')

if __name__ == '__main__':
    checkDNSPortOpen()

Inspired by this post

like image 150
XX 吕 Avatar answered Sep 23 '22 11:09

XX 吕


I have had no luck using sockets for this purpose. The port response is based on the target application and is not standard like TCP. I always use netcat for this:

import os
ip = "127.0.0.1"
port = "<some_udp_port>"
''' send to /dev/null 2>&1 to suppress terminal output '''
res = os.system("nc -vnzu "+ip+" "+port+" > /dev/null 2>&1")
if res == 0:
    print("port alive")
else:
    print("port dead")

This, obviously, requires running on a Linux system. However if you have nmap installed on your Windows system you can try the following:

import os
ip = "127.0.0.1"
port = "<some_udp_port>"
res = os.system("ncat -vnzu "+ip+" "+port)
if res == 0:
    print("port alive")
else:
    print("port dead")
like image 21
corporateWhore Avatar answered Sep 21 '22 11:09

corporateWhore