Skip to content

Instantly share code, notes, and snippets.

@mtward
Created March 10, 2025 22:34
Show Gist options
  • Save mtward/675417e84f4e924f9b8144a8b4ad8d36 to your computer and use it in GitHub Desktop.
Save mtward/675417e84f4e924f9b8144a8b4ad8d36 to your computer and use it in GitHub Desktop.
portchecker
#!/usr/libexec/platform-python
import socket
import sys
import select
import http.client
import ssl
def print_help():
"""Prints command-line usage help."""
print("""
Usage: portcheck <host> <port> [options]
Options:
-http Force an HTTP connection, even on non-standard ports.
-https Force an HTTPS connection, even on non-standard ports (ignores certificate verification).
-h Show this help message and exit.
Examples:
portcheck example.com 22
portcheck example.com 80
portcheck example.com 443
portcheck example.com 8443 -https # Force HTTPS connection, ignoring cert errors
portcheck example.com 8080 -http # Force HTTP connection on port 8080
""")
sys.exit(0)
def check_connection(host, port, timeout=5, force_http=False, force_https=False):
print(f"Resolving hostname...")
try:
ip = socket.gethostbyname(host)
print(f"Resolved {host} to {ip}")
print(f"Trying to connect...")
except socket.gaierror:
print(f"Error: Unable to resolve hostname {host}")
return
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
try:
s.connect((ip, port))
local_ip, local_port = s.getsockname()
print(f"Successfully connected to {host} ({ip}) on port {port}")
print(f"Connected from: {local_ip}:{local_port}")
# Force HTTPS connection if -https flag is used or if port is 443
if force_https or port == 443:
print(f"Establishing HTTPS connection to {host} (ignoring certificate verification)...")
try:
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE # Ignore certificate verification
with context.wrap_socket(s, server_hostname=host) as secure_socket:
secure_socket.sendall(b"HEAD / HTTP/1.1\r\nHost: " + host.encode() + b"\r\nConnection: close\r\n\r\n")
response = secure_socket.recv(1024)
if response:
print(f"Response from HTTPS server:\n{response.decode('utf-8', 'ignore')}")
else:
print("No response received from HTTPS server.")
except ssl.SSLError as e:
print(f"SSL error (ignored if CERTIFICATE_VERIFY_FAILED): {e}")
except Exception as e:
print(f"Error making HTTPS request: {e}")
# Force HTTP connection if -http flag is used or if port is 80
elif force_http or port == 80:
print(f"Sending HTTP GET request to {host}...")
try:
connection = http.client.HTTPConnection(host, port, timeout=timeout)
connection.request("HEAD", "/")
response = connection.getresponse()
print(f"HTTP Status: {response.status} {response.reason}")
connection.close()
except Exception as e:
print(f"Error making HTTP request: {e}")
# Handle non-HTTP/HTTPS connections
else:
s.sendall(b'GET /')
# Use select to check if data is available
ready = select.select([s], [], [], 1)
if ready[0]:
response = s.recv(1024)
if response:
print(f"Header returned: {response.decode('utf-8', 'ignore')}")
else:
print("No data received from the host.")
except socket.error as e:
local_ip, local_port = s.getsockname()
print(f"Error: Unable to connect to {host} ({ip}) on port {port}: {e}")
print(f"Tried to connect from: {local_ip}:{local_port}")
if __name__ == "__main__":
if "-h" in sys.argv:
print_help()
force_http = "-http" in sys.argv
force_https = "-https" in sys.argv
# Remove flags from arguments
args = [arg for arg in sys.argv[1:] if arg not in ["-http", "-https"]]
if len(args) >= 2:
host, port = args[0], int(args[1])
else:
host = input("Host: ")
port = int(input("Port: "))
check_connection(host, port, force_http=force_http, force_https=force_https)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment