a1a17e81a1
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
291 lines
11 KiB
Bash
291 lines
11 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
#########################################################################################
|
|
#### port-checker.sh — Check host:port pairs and report open/closed/timeout status ####
|
|
#### Accepts targets from CLI args, a file, or stdin ####
|
|
#### ####
|
|
#### Author: Phil Connor ####
|
|
#### Contact: contact@mylinux.work ####
|
|
#### License: MIT ####
|
|
#### Version 1.00 ####
|
|
#### ####
|
|
#### Usage: ####
|
|
#### ./port-checker.sh host1:port1 host2:port2 ####
|
|
#### ./port-checker.sh --file targets.txt ####
|
|
#### echo "host:port" | ./port-checker.sh ####
|
|
#### ####
|
|
#### See --help for all options. ####
|
|
#########################################################################################
|
|
|
|
set -euo pipefail
|
|
|
|
# ── Defaults ──────────────────────────────────────────────────────────
|
|
TIMEOUT="${PORT_CHECK_TIMEOUT:-3}"
|
|
VERBOSE="${VERBOSE:-false}"
|
|
COLOR="${COLOR:-auto}"
|
|
JSON_OUTPUT="${JSON_OUTPUT:-false}"
|
|
INPUT_FILE=""
|
|
|
|
# ── State ─────────────────────────────────────────────────────────────
|
|
SCRIPT_NAME="$(basename "$0")"
|
|
readonly SCRIPT_NAME
|
|
TARGETS=()
|
|
COUNT_OPEN=0
|
|
COUNT_CLOSED=0
|
|
COUNT_TIMEOUT=0
|
|
COUNT_TOTAL=0
|
|
|
|
# ── Colors ────────────────────────────────────────────────────────────
|
|
setup_colors() {
|
|
if [[ "$COLOR" == "never" ]]; then
|
|
RED="" GREEN="" YELLOW="" BOLD="" DIM="" RESET=""
|
|
return
|
|
fi
|
|
if [[ "$COLOR" == "always" ]] || [[ -t 1 ]]; then
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
BOLD='\033[1m'
|
|
DIM='\033[2m'
|
|
RESET='\033[0m'
|
|
else
|
|
RED="" GREEN="" YELLOW="" BOLD="" DIM="" RESET=""
|
|
fi
|
|
}
|
|
|
|
# ── Logging ───────────────────────────────────────────────────────────
|
|
log() { echo -e "${DIM}[INFO]${RESET} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${RESET} $*" >&2; }
|
|
err() { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
|
|
verbose() { if [[ "$VERBOSE" == "true" ]]; then echo -e "${DIM}[DEBUG]${RESET} $*"; fi; }
|
|
|
|
# ── Helpers ───────────────────────────────────────────────────────────
|
|
check_port() {
|
|
local host="$1"
|
|
local port="$2"
|
|
local status="closed"
|
|
local latency="-"
|
|
|
|
verbose "Checking ${host}:${port} (timeout ${TIMEOUT}s)"
|
|
|
|
local start_ns end_ns elapsed_ms
|
|
start_ns=$(date +%s%N)
|
|
|
|
if command -v nc &>/dev/null; then
|
|
if nc -z -w "$TIMEOUT" "$host" "$port" &>/dev/null; then
|
|
status="open"
|
|
fi
|
|
elif command -v ncat &>/dev/null; then
|
|
if ncat -z -w "$TIMEOUT" "$host" "$port" &>/dev/null; then
|
|
status="open"
|
|
fi
|
|
else
|
|
if (echo >/dev/tcp/"$host"/"$port") 2>/dev/null; then
|
|
status="open"
|
|
fi
|
|
fi
|
|
|
|
end_ns=$(date +%s%N)
|
|
elapsed_ms=$(( (end_ns - start_ns) / 1000000 ))
|
|
|
|
if [[ "$status" == "closed" && "$elapsed_ms" -ge $(( TIMEOUT * 1000 )) ]]; then
|
|
status="timeout"
|
|
fi
|
|
|
|
if [[ "$status" != "closed" || "$elapsed_ms" -lt $(( TIMEOUT * 1000 )) ]]; then
|
|
latency="${elapsed_ms}ms"
|
|
fi
|
|
|
|
COUNT_TOTAL=$((COUNT_TOTAL + 1))
|
|
case "$status" in
|
|
open) COUNT_OPEN=$((COUNT_OPEN + 1)) ;;
|
|
closed) COUNT_CLOSED=$((COUNT_CLOSED + 1)) ;;
|
|
timeout) COUNT_TIMEOUT=$((COUNT_TIMEOUT + 1)) ;;
|
|
esac
|
|
|
|
if [[ "$JSON_OUTPUT" == "true" ]]; then
|
|
local json_comma=""
|
|
if [[ "$COUNT_TOTAL" -gt 1 ]]; then
|
|
json_comma=","
|
|
fi
|
|
printf '%s{"host":"%s","port":%s,"status":"%s","latency":"%s"}' \
|
|
"$json_comma" "$host" "$port" "$status" "$latency"
|
|
else
|
|
local color
|
|
case "$status" in
|
|
open) color="$GREEN" ;;
|
|
closed) color="$RED" ;;
|
|
timeout) color="$YELLOW" ;;
|
|
*) color="" ;;
|
|
esac
|
|
printf " %-30s %-8s %b%-10s%b %s\n" "$host" "$port" "$color" "$status" "$RESET" "$latency"
|
|
fi
|
|
}
|
|
|
|
load_targets_from_file() {
|
|
local file="$1"
|
|
if [[ ! -f "$file" ]]; then
|
|
err "File not found: $file"
|
|
exit 1
|
|
fi
|
|
while IFS= read -r line; do
|
|
line="${line%%#*}"
|
|
line="${line// /}"
|
|
[[ -z "$line" ]] && continue
|
|
TARGETS+=("$line")
|
|
done < "$file"
|
|
}
|
|
|
|
load_targets_from_stdin() {
|
|
while IFS= read -r line; do
|
|
line="${line%%#*}"
|
|
line="${line// /}"
|
|
[[ -z "$line" ]] && continue
|
|
TARGETS+=("$line")
|
|
done
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# USAGE
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
${SCRIPT_NAME} — Check host:port pairs and report open/closed/timeout status
|
|
|
|
USAGE:
|
|
${SCRIPT_NAME} [OPTIONS] host1:port1 [host2:port2 ...]
|
|
${SCRIPT_NAME} --file targets.txt
|
|
echo "host:port" | ${SCRIPT_NAME}
|
|
|
|
OPTIONS:
|
|
--file FILE Read targets from file (one host:port per line)
|
|
--timeout SECONDS Connection timeout (default: ${TIMEOUT})
|
|
--json Output results in JSON format
|
|
--verbose Enable debug output
|
|
--no-color Disable colored output
|
|
--help Show this help
|
|
|
|
ENVIRONMENT VARIABLES:
|
|
PORT_CHECK_TIMEOUT Connection timeout in seconds (default: 3)
|
|
COLOR Color mode: auto, always, never (default: auto)
|
|
|
|
EXAMPLES:
|
|
# Check specific hosts
|
|
./port-checker.sh google.com:443 github.com:22
|
|
|
|
# Read from file
|
|
./port-checker.sh --file targets.txt
|
|
|
|
# From stdin
|
|
echo -e "google.com:443\ngithub.com:22" | ./port-checker.sh
|
|
|
|
# JSON output with custom timeout
|
|
./port-checker.sh --json --timeout 5 myhost:8080
|
|
|
|
# Pipe-friendly
|
|
./port-checker.sh --no-color myhost:80 myhost:443
|
|
EOF
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# ARGUMENT PARSING
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
|
|
parse_args() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--file)
|
|
INPUT_FILE="$2"; shift 2 ;;
|
|
--timeout)
|
|
TIMEOUT="$2"; shift 2 ;;
|
|
--json)
|
|
JSON_OUTPUT="true"; shift ;;
|
|
--verbose)
|
|
VERBOSE="true"; shift ;;
|
|
--no-color)
|
|
COLOR="never"; shift ;;
|
|
--help|-h)
|
|
setup_colors
|
|
usage
|
|
exit 0 ;;
|
|
-*)
|
|
err "Unknown option: $1"
|
|
echo "Run ${SCRIPT_NAME} --help for usage" >&2
|
|
exit 1 ;;
|
|
*)
|
|
TARGETS+=("$1"); shift ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# MAIN
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
|
|
main() {
|
|
parse_args "$@"
|
|
setup_colors
|
|
|
|
# Load targets from file if specified
|
|
if [[ -n "$INPUT_FILE" ]]; then
|
|
load_targets_from_file "$INPUT_FILE"
|
|
fi
|
|
|
|
# Load from stdin if no targets yet and stdin is not a terminal
|
|
if [[ ${#TARGETS[@]} -eq 0 ]] && ! [[ -t 0 ]]; then
|
|
load_targets_from_stdin
|
|
fi
|
|
|
|
# Validate we have targets
|
|
if [[ ${#TARGETS[@]} -eq 0 ]]; then
|
|
err "No targets specified"
|
|
echo "Run ${SCRIPT_NAME} --help for usage" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$JSON_OUTPUT" == "true" ]]; then
|
|
printf '{"results":['
|
|
else
|
|
echo ""
|
|
echo -e "${BOLD}Port Checker${RESET}"
|
|
echo -e "${DIM}Timeout: ${TIMEOUT}s${RESET}"
|
|
echo ""
|
|
printf " ${BOLD}%-30s %-8s %-10s %s${RESET}\n" "HOST" "PORT" "STATUS" "LATENCY"
|
|
printf " %s\n" "$(printf '%.0s─' {1..62})"
|
|
fi
|
|
|
|
for target in "${TARGETS[@]}"; do
|
|
local host port
|
|
if [[ "$target" == *:* ]]; then
|
|
host="${target%%:*}"
|
|
port="${target##*:}"
|
|
else
|
|
warn "Invalid format (expected host:port): $target"
|
|
continue
|
|
fi
|
|
|
|
if [[ -z "$host" || -z "$port" ]]; then
|
|
warn "Invalid target: $target"
|
|
continue
|
|
fi
|
|
|
|
check_port "$host" "$port"
|
|
done
|
|
|
|
if [[ "$JSON_OUTPUT" == "true" ]]; then
|
|
printf '],"summary":{"total":%d,"open":%d,"closed":%d,"timeout":%d}}\n' \
|
|
"$COUNT_TOTAL" "$COUNT_OPEN" "$COUNT_CLOSED" "$COUNT_TIMEOUT"
|
|
else
|
|
echo ""
|
|
echo -e " ${BOLD}Summary${RESET}"
|
|
printf " %-14s %d\n" "Total checked:" "$COUNT_TOTAL"
|
|
printf " %-14s %b%d%b\n" "Open:" "$GREEN" "$COUNT_OPEN" "$RESET"
|
|
printf " %-14s %b%d%b\n" "Closed:" "$RED" "$COUNT_CLOSED" "$RESET"
|
|
printf " %-14s %b%d%b\n" "Timeout:" "$YELLOW" "$COUNT_TIMEOUT" "$RESET"
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
main "$@"
|