{"id":26040623,"url":"https://github.com/chutrunganh/simple-port-scanner","last_synced_at":"2026-04-21T06:33:18.572Z","repository":{"id":222339271,"uuid":"756859643","full_name":"chutrunganh/Simple-Port-Scanner","owner":"chutrunganh","description":" 📡 A basic CLI port scanner uses Python's socket module.","archived":false,"fork":false,"pushed_at":"2024-03-02T03:14:24.000Z","size":153,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-07T12:46:27.314Z","etag":null,"topics":["multithreading","network-tools","nmap","port-scanner","port-scanner-in-python","port-scanning","simple-port-scanner"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chutrunganh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-13T13:00:29.000Z","updated_at":"2024-02-17T16:35:31.000Z","dependencies_parsed_at":"2024-03-02T04:24:36.428Z","dependency_job_id":"e6d72bad-dfd6-46cc-bd46-bfdb3bad49fb","html_url":"https://github.com/chutrunganh/Simple-Port-Scanner","commit_stats":null,"previous_names":["chutrunganh/simple-port-scanner"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chutrunganh/Simple-Port-Scanner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chutrunganh%2FSimple-Port-Scanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chutrunganh%2FSimple-Port-Scanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chutrunganh%2FSimple-Port-Scanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chutrunganh%2FSimple-Port-Scanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chutrunganh","download_url":"https://codeload.github.com/chutrunganh/Simple-Port-Scanner/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chutrunganh%2FSimple-Port-Scanner/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32080380,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T06:27:27.065Z","status":"ssl_error","status_checked_at":"2026-04-21T06:27:21.250Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["multithreading","network-tools","nmap","port-scanner","port-scanner-in-python","port-scanning","simple-port-scanner"],"created_at":"2025-03-07T12:46:30.348Z","updated_at":"2026-04-21T06:33:18.557Z","avatar_url":"https://github.com/chutrunganh.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Intro\n I created a simple port scanner named **Lmap**, inspired by famous tool Nmap. Utilizing the ```socket``` library in Python, I crafted this project in just a few days during my vacation. Here's a quick look:\n\n![Alt text](Image/Image1.png)\n\n## Main Features\n- **h** option: Prints the help menu.\n- **n** option: Performs a normal scan, checking the 20 most popular ports defined in myList.\n```python\nmylist = [21, 22, 23, 25, 53, 80, 110, 111, 135, 139, 143, 443, 445, 993, 995, 1723, 3306, 3389, 5900, 8080]\n```\nExample: ```./Lmap -n scanme.org```\n![Alt text](Image/Image2.png)\n- **r** option: Allows users to specify a port range to scan.\nExample: ```./Lmap.py -r 50-100 scanme.org```\n![Alt text](Image/Image3.png)\n- Save scan data to a text file with a filename based on the target and the time the scan was taken.\n\n![Alt text](Image/Image4.png)\n\nBefore running ./Lmap.py, make sure the main code file has permission to execute by:\n```bash\n chmod +x Lmap.py\n```\n### Note\nYou can use http://scanme.org/ as a practice target, a website provided by Nmap for experimentation. Avoid performing port scans on arbitrary servers, as this action may be considered illegal in some countries. Otherwhile, for experimental purposes in this project, I've created ```server.py``` that listens for requests on specified ports we can set.\n```python\nimport socket\nimport threading\n\ndef start_server(port):\n    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    server_socket.bind(('localhost', port))\n    server_socket.listen(1)\n\n    print(f\"Server listening on port {port}\")\n\n    while True:\n        client_socket, client_address = server_socket.accept()\n        print(f\"Connection from {client_address}\")\n        client_socket.send(b\"Welcome to the server!\")\n        client_socket.close()\n\nif __name__ == \"__main__\":\n    ports = [21, 22, 23, 25, 53, 80, 110,]  # Add more ports as needed\n\n    threads = []\n\n    for port in ports:\n        thread = threading.Thread(target=start_server, args=(port,))\n        threads.append(thread)\n        thread.start()\n\n    for thread in threads:\n        thread.join()\n```\n\nRun the server with: \n```bash\nsudo python3 server.py\n```\nAnd it will listen on the set ports, receiving incoming requests.\n```plaintext\nServer listening on port 23\nServer listening on port 22\nServer listening on port 21\nServer listening on port 53\nServer listening on port 25\nServer listening on port 80\nServer listening on port 110\nConnection from ('127.0.0.1', 36938)\nConnection from ('127.0.0.1', 49454)\nConnection from ('127.0.0.1', 41208)\nConnection from ('127.0.0.1', 33612)\nConnection from ('127.0.0.1', 51322)\nConnection from ('127.0.0.1', 54824)\nConnection from ('127.0.0.1', 60342)\n```\n\n## Details how it work\nTo begin with, the program reads parameters from the command line, for example: `./Lmap.py -n localhost`. We extract the value for the `options` from the input using `sys.argv`:\n\n```python\noptions = sys.argv[1] if len(sys.argv) \u003e 1 else None\n```\nBased on the chosen option, the main program calls relevant functions. In the example, the normal scan mode is used.\n\nIn this mode, the initial step is to read the target parameter. The target should ideally be an IP address. Therefore, I check whether it is an IP address. If it is still a name, I convert it back to an IP using ```socket.gethostbyname()``` inside ```check_target()``` function:\n\n```python\n#the last argument in the command line is the target\ntarget = sys.argv[-1] if len(sys.argv) \u003e 2 else None\ntarget = check_target(target)\n```\n\nOnce we have the target IP, we can initiate the scan process by calling the ```normal_scan``` function. This function takes the target IP as a parameter and performs the following tasks:\n\n- Determine the server location based on that IP address. Here, I use the geocoder library:\n```python\ndef print_location(target):\n    # When working with localhost, the geocoder library only returns results if I use the target IP as 'me' instead of '127.0.0.1'\n    if target == '127.0.0.1':\n        target = 'me'\n\n    if geocoder.ip(target).city is not None:\n        print('Based on the IP address, the location of the server might be: ' + str(geocoder.ip(target).city) + ' city, at coordinates: ' + str(geocoder.ip(target).latlng[0]) + ', ' + str(geocoder.ip(target).latlng[1]) + '\\n')\n```\n**Note**: I've observed that the geocoder library takes a considerable amount of time to process, potentially slowing down the program. Additionally, its accuracy may vary. In my location, the coordinate deviation is approximately 3-4 km. Hence, you may want to comment out this feature if it's not particularly useful for you.\n\n- Based on the provided ports, attempt to connect to each of them:\n```python\ndef check_port_is_open(target, port):\n    # Create a socket object\n    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) \n    # AF_INET: Address Family, IPv4\n    # SOCK_STREAM: TCP protocol\n    s.settimeout(1) # Set timeout to 1 second\n\n    # Connect to the port\n    result = s.connect_ex((target, port))\n    if result == 0:\n        print(GREEN + \"[*]\" + RESET + 'Port ' + str(port) + ': ' + str(lookup_port_name(port)))\n    # else:\n    #     print(RED + \"[*]\" + RESET + 'Port', port, ':', lookup_port_name(port))\n    s.close()\n```\nI use a socket to establish a connection to each port, specifying the parameters for the TCP three-way handshake connection. Based on the returned result, we determine the state of the port. Once we identify an open port, we look up the port number in ```portlist.csv``` to find the corresponding name or service with ```lookup_port_name()``` function.\n\n\nHowever, if we use a for loop to sequentially scan each port, it could significantly slow down the scanning process. Therefore, I employ multi-threading from the ```thread``` library to scan ports simultaneously.\n```python\nthreads = []\n    for port in mylist:\n        thread = threading.Thread(target=check_port_is_open, args=(target, port))\n        thread.start()\n        threads.append(thread)\n    for thread in threads:\n        thread.join()\n```\nTo create a new thread, we create an object of the Thread class. It takes the **‘target’** and **‘args’** as the parameters. The target is the function to be executed by the thread whereas the args is the arguments to be passed to the target function as I did in this line: ```thread = threading.Thread(target=check_port_is_open, args=(target, port))``` \n We wait for all ports to be scanned completely before moving on to the next part using the ```.join()``` method.\n\n## Reference:\nI find this website explain quite comprehensive about socket in Python:\n\n https://www.datacamp.com/tutorial/a-complete-guide-to-socket-programming-in-python\n\nand some usefull tutorial videos on Youtube:\n1. https://m.youtube.com/watch?v=DmrZyNiE6M\n2. https://m.youtube.com/watch?v=XGFDXGyd7Uw\n3. https://youtu.be/vRhPOE2uTGA?si=r97YYCAOd_64G1mV\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchutrunganh%2Fsimple-port-scanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchutrunganh%2Fsimple-port-scanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchutrunganh%2Fsimple-port-scanner/lists"}