Añade el capability group `recon` (dominio cybersecurity + pipelines, Python),
con la política de archivado OSINT y página madre docs/capabilities/recon.md.
Lookups y sondeo (wrappers de CLI):
- whois_lookup, rdap_lookup, dns_records, ping_host, traceroute_host, nmap_scan
- save_scan_to_osint (sink común) + recon_osint (pipeline one-shot scan+archivado)
Escaneo de puertos/servicios nativo (stdlib, sin nmap ni sudo):
- scan_tcp_ports: connect-scan TCP concurrente (open/closed/filtered)
- grab_service_banner: banner grab + identificación de servicio/versión real
- identify_port_service: puro, puerto -> servicio IANA esperado (~120 puertos)
- scan_port_services: pipeline one-shot (scan -> identify + banner por puerto abierto)
Fingerprint de tecnología web (estilo Wappalyzer), patrón pura/impura:
- fetch_http_fingerprint: GET stdlib, recoge headers/html/cookies (solo nombres)
- detect_web_tech: puro, matchea ~50 firmas regex -> tecnologías por categoría
- fingerprint_web_stack: pipeline one-shot url -> tecnologías
Todas devuelven dict {status} sin lanzar. Tests: 43 verdes, sin red externa.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.2 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| scan_port_services | pipeline | py | pipelines | 1.0.0 | impure | def scan_port_services(host: str, ports: str | list[int] = 'common', timeout_s: float = 1.0, workers: int = 100, grab_banners: bool = True, banner_timeout_s: float = 3.0, save: bool = True) -> dict | One-shot que escanea los servicios de los puertos de un host: hace un connect-scan TCP y, por cada puerto abierto, devuelve el servicio esperado por convencion IANA (identify_port_service) y el servicio/version REAL leido del banner en vivo (grab_service_banner). Reemplaza el patron scan_tcp_ports -> identify -> grab repetido (1 scan + 2*K por puerto abierto) por una sola llamada. Opcionalmente archiva la evidencia (tabla PORT/EXPECTED/ACTUAL/BANNER) en OSINT. No requiere nmap. Util para fingerprint de servicios, auditoria de superficie de ataque y reconocimiento de puertos de un host. |
|
|
false | error_py_core |
|
dict con status ('ok'|'error'), host, ip (resuelta), open_ports (lista de ints), services (lista de dicts con port, expected_service, expected_desc, actual_service, product, version, banner, match), saved (dict de save_scan_to_osint con note_path/registered/scan_id, o None si save=False) y raw (tabla legible PORT/EXPECTED/ACTUAL/BANNER). Si el escaneo de puertos falla (host no resuelve, spec invalida) -> {status:error, stage:scan, scan:<dict>}. Cuando grab_banners=False, actual_service/product/version/banner quedan None/'' y match=None. Nunca lanza. | true |
|
python/functions/pipelines/scan_port_services_test.py | python/functions/pipelines/scan_port_services.py |
Ejemplo
from pipelines.scan_port_services import scan_port_services
# Escaneo + fingerprint de servicios de un host, archivado en OSINT (1 paso).
r = scan_port_services("127.0.0.1", ports="common")
print(r["status"]) # "ok"
print(r["open_ports"]) # [22, 5432, 6379]
for s in r["services"]:
print(s["port"], s["expected_service"], "->", s["actual_service"], s["version"])
# 22 ssh -> ssh 9.6p1
print(r["saved"]["note_path"]) # ruta de la nota creada en el vault osint
from pipelines.scan_port_services import scan_port_services
# Solo servicio esperado por convencion (sin tocar el servicio en vivo), sin archivar.
r = scan_port_services("10.0.0.5", ports=[22, 80, 443, 3306], grab_banners=False, save=False)
print(r["raw"]) # tabla PORT/EXPECTED/ACTUAL/BANNER (ACTUAL vacio)
# Por CLI: escanea los puertos comunes de un host.
./fn run scan_port_services 127.0.0.1 common
# Flags: --no-banners (solo servicio esperado), --no-save (no archiva OSINT).
./fn run scan_port_services scanme.nmap.org 22,80,443 --no-save
Cuando usarla
Cuando quieras en UN solo paso saber que puertos estan abiertos en un host Y
que servicio/version corre en cada uno, sin nmap. Reemplaza el patron repetido
scan_tcp_ports -> identify_port_service -> grab_service_banner (una ronda
de scan + dos llamadas por cada puerto abierto). Tipico para: fingerprint de
servicios de un objetivo, auditoria de superficie de ataque, validar que un
puerto abierto corre el servicio esperado (campo match), o reconocimiento
inicial de un host autorizado.
Gotchas
- Ruidoso/detectable: es un connect-scan (handshake TCP completo) seguido,
si
grab_banners=True, de una segunda conexion por puerto para leer el banner. Deja rastro en logs del objetivo. Usagrab_banners=Falsepara un paso menos invasivo (sin segunda ronda). - Servicios sobre TLS no dan banner plano: puertos como 443/993/995/8443
hablan TLS, no emiten un banner texto al conectar, asi que
actual_servicequedara"unknown"ahi (no hay handshake TLS engrab_service_banner). Elexpected_service(https/imaps/...) si lo identifica por convencion. - match es heuristico:
match=Truesolo cuando expected y actual son ambos concretos (no "unknown") y coinciden. Unmatch=Falsepuede significar "no coinciden" o "no se pudo determinar el real"; miraactual_service. - save=True escribe en el vault OSINT (
~/Obsidian/osint) y hace POST al serviceosint_db(http://127.0.0.1:8771). Si el service esta caido,save_scan_to_osintdegrada a solo-nota (saved.registered=Falseconregister_warning); el pipeline no falla por eso. - Autorizacion legal: escanear puertos y leer banners de hosts ajenos sin permiso puede ser ilegal. Solo objetivos propios o con autorizacion explicita.
- Pipeline impuro: hace red (scan + banners) y FS/HTTP (vault + service). No es determinista entre ejecuciones.
- Si el escaneo de puertos falla (
status != "ok": host no resuelve, spec invalida), el pipeline devuelve{"status":"error","stage":"scan",...}y no intenta identificar servicios ni archivar nada.
Notas
Pipeline que compone 4 funciones atomicas del dominio cybersecurity. No
reimplementa logica de escaneo, identificacion ni persistencia: solo orquesta
scan_tcp_ports (puertos abiertos) + identify_port_service (servicio esperado,
puro) + grab_service_banner (servicio real, por puerto abierto) y delega el
guardado en save_scan_to_osint. El grab de banners es secuencial por KISS (los
puertos abiertos suelen ser pocos y cada grab ya tiene timeout acotado). Nunca
lanza excepciones: todo fallo se refleja en la clave status del dict devuelto.