El lenguaje de programación Go se destaca por su potente librería estándar, razón por la cual es muy popular entre los desarrolladores. En esta guía, exploraremos el paquete net de Go para generar conexiones TCP a diferentes servidores y escanear los puertos disponibles. Esto te permitirá determinar cuáles puertos están abiertos y cuáles no, un conocimiento esencial si te dedicas a la ciberseguridad.
¿Qué pasos seguir en la codificación para el escaneo de puertos?
Para comenzar, debes crear una nueva carpeta llamada "net" y un archivo nuevo denominado port.go. Este será el esqueleto de tu programa. El paquete main será utilizado para este ejercicio, ya que es el punto de entrada del programa. A continuación, se detalla el proceso para crear el escaneo de puertos.
package main
import("fmt""net")funcmain(){for i :=0; i <100; i++{ address := fmt.Sprintf("scanme.nmap.org:%d", i) conn, err := net.Dial("tcp", address)if err !=nil{continue} conn.Close() fmt.Printf("Puerto %d está abierto\n", i)}}
Crear un ciclo para escanear puertos: El ciclo se inicializa en cero y continúa hasta llegar al puerto 99.
Conexiones TCP: Se establece una conexión TCP a cada puerto posible. Si la conexión es exitosa, el puerto se considera abierto.
Manejo de errores: Si no se puede conectar a un puerto, se omite el error para continuar explorando los siguientes puertos.
Cierre de conexiones: Es vital cerrar la conexión una vez verificada la apertura del puerto, similar a cerrar archivos abiertos.
¿Qué consideraciones tener al escanear puertos de un servidor?
Cuando se escanean puertos, es crucial entender que esta técnica puede ser vista como un ciberataque si no se lleva a cabo de manera adecuada. Por lo tanto, te ofrecemos algunas recomendaciones clave:
Utilizar sitios de prueba: Escanea sitios específicamente diseñados para pruebas, como scanme.nmap.org.
Usar con fines didácticos: Esto debería hacerse en tu propio entorno o en servidores de prueba, nunca en servidores ajenos sin permiso.
Educación continua: Considera inscribirte en cursos de seguridad informática para entender mejor las implicaciones éticas y legales de estas técnicas.
¿Cuál es el problema del escaneo de puertos de este ejemplo?
Una de las principales limitaciones del primer método de escaneo de puertos es su lentitud. En este caso, se limitaron a escanear 100 puertos, pero el internet abarca hasta 65,535 puertos posibles. Debido a que este proceso es secuencial, puede ser extremadamente ineficiente y demorado.
En futuras sesiones, se puede mejorar la eficiencia al implementar el escaneo de puertos concurrente utilizando 'Gorutinas'. Esto permitirá realizar múltiples escaneos simultáneamente, reduciendo el tiempo total.
Recuerda siempre que el uso ético y responsable del conocimiento es fundamental, así que aprovecha estas técnicas de manera segura y legal.
Una recomendación para la vida real, no utilicéis como nombre de variable "i" cuando se hace referencia a puerto, mejor utilizar el nombre "port". Cuanto más explícito sea el código, más fácil será de leer y entender para el resto del mundo :)
package main
import (
"fmt"
"net"
"sync"
)
func scanPort(wg *sync.WaitGroup, port int) {
defer wg.Done()
address := fmt.Sprintf("scanme.nmap.org:%d", port)
conn, err := net.Dial("tcp", address)
if err != nil {
return
}
conn.Close()
fmt.Println("Port", port, "is open")
}
func main() {
var wg sync.WaitGroup
for port := 0; port < 100; port++ {
wg.Add(1)
go scanPort(&wg, port)
}
wg.Wait()
}
Comparto mi solución aplicando concurrencia
package main
import("fmt""net")func main(){// Escanear cada puerto y hacer una conexiónfori:=0; i <100; i++{ conn,err:= net.Dial("tcp", fmt.Sprintf("%s:%d","scanme.nmap.org", i))if err != nil {continue} conn.Close() fmt.Println("Port", i,"is open")}}
Escanear puertos es fundamental para identificar qué servicios están disponibles en un servidor y evaluar su seguridad. Al saber qué puertos están abiertos, puedes determinar vulnerabilidades potenciales que podrían ser explotadas por atacantes. Además, esta práctica es útil para configurar firewalls y optimizar el rendimiento de redes y aplicaciones. Tener este conocimiento te permitirá desarrollar sistemas más seguros y eficientes, lo cual es esencial en el desarrollo de software y la administración de redes.
Comparto mi solución aplicando la concurrencia
package main
import ( "fmt" "net" "sync")
func scanPort(wg *sync.WaitGroup, port int) { defer wg.Done() address := fmt.Sprintf("scanme.nmap.org:%d", port) conn, err := net.Dial("tcp", address) if err != nil { return } conn.Close() fmt.Println("Port", port, "is open")}
func main() { var wg sync.WaitGroup for port := 0; port < 100; port++ { wg.Add(1) go scanPort(&wg, port) } wg.Wait()}
Por alguna razón cuando intento conectarme al puerto 0 queda cargando, sin tirarme ningún timeout. Para omitir este puerto sin cambiar mucho el código, simplemente arranqué el bucle for desde el indice 1.