CLI Tools

A collection of high-performance security & network tools.

TCP Port Scanner

A lightweight, command-line TCP port scanner written in C. This tool efficiently scans a specified range of ports on a target IP address using non-blocking sockets and the select() system call for configurable timeouts.

Features

[!CAUTION] This tool is intended for educational purposes only. Port scanning can violate network policies or laws. Use responsibly and only on systems you own or have explicit permission to test.

Installation

Prerequisites

Build Instructions

Clone the repository and compile the source code:

git clone https://github.com/gab-dev-7/port-scanner.git
cd port-scanner
gcc -o scanner scanner.c

This command produces an executable named scanner.

Usage

Execute the scanner with three required arguments: target IP address, starting port number, and ending port number.

./scanner <IP_ADDRESS> <START_PORT> <END_PORT>

Example

Scan ports 1 through 100 on the local host (127.0.0.1):

./scanner 127.0.0.1 1 100

Sample Output:

--- Starting Port Scan ---
Target: 127.0.0.1 | Range: 1 to 100 | Timeout: 1 second(s)
--------------------------
[TIMEOUT] 127.0.0.1:22
[OPEN] 127.0.0.1:80
--- Scan Complete ---

Arguments

Argument Description Constraints
<IP_ADDRESS> The target IPv4 address (e.g., 192.168.1.1) Must be a valid IPv4 address.
<START_PORT> The starting TCP port number. Must be between 1 and 65535.
<END_PORT> The ending TCP port number. Must be between 1 and 65535, and greater than or equal to <START_PORT>.

Timeout Configuration: The default timeout is 1 second per port. To modify this, adjust the TIMEOUT variable defined in the main() function within the source code.

How It Works

The scanner performs a TCP connect scan across the specified port range:

  1. Socket Initialization: Creates a new TCP socket (AF_INET, SOCK_STREAM).
  2. Non-Blocking Mode: Sets the socket to non-blocking mode using fcntl() with O_NONBLOCK. This allows the connect() call to return immediately, even if the connection is still in progress.
  3. Connection Attempt: Initiates an asynchronous connection attempt with connect(). If the call returns immediately and errno is set to EINPROGRESS, the connection attempt is ongoing.
  4. Timeout Enforcement: Uses select() on the socket’s write file descriptor set, paired with a struct timeval specifying the timeout duration. This waits for the socket to become writable, which indicates the connection attempt has completed (either successfully or with an error).
  5. Status Determination: After select() returns, the scanner queries the socket’s SO_ERROR option using getsockopt():
    • If the retrieved error value is 0, the connection was successful, and the port is reported as OPEN.
    • If the retrieved error value is non-zero (e.g., ECONNREFUSED), the connection failed, and the port is considered CLOSED or resulted in another error (which might be reported as a timeout depending on the specific error).
  6. Cleanup: The socket is closed after each scan attempt.

This methodology is effective against firewalls and unresponsive hosts and does not require root privileges, as it uses standard connect() calls.

Limitations

Potential Improvements