Golang中如何检测UDP端口

Golang中如何检测UDP端口 我的代码显示所有UDP协议的端口都是开放的 请帮我修复这个问题

for i := 1; i <= 65535; i++ {
	
	go func(j int) {

		address := net.JoinHostPort(ip, strconv.Itoa(j))
		// 3 second timeout
		//fmt.Println(j)
		conn, err := net.DialTimeout("udp", address, 60*time.Second)

		//fmt.Println(err)
		if err != nil {
			faildcount++
			//m2 := Message{j, "Closed"}
			//list2 = append(list2, m2)
		} else {
			count++
			conn.Close()
			m := Message{j, "open"}
			list = append(list, m)

		}
		
	}(i)
}

更多关于Golang中如何检测UDP端口的实战教程也可以访问 https://www.itying.com/category-94-b0.html

15 回复

请回答这个问题

更多关于Golang中如何检测UDP端口的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题是什么?

请帮助并提供示例代码

exec.Command("nmap", ...)

这段代码显示所有打开的UDP端口 但并未打开

例如,您可以使用 nmap -sU 127.0.0.1 -p 1-65500

正如我所说,我从未做过这件事;这很可能是一个底层的网络主题,并且与编程语言无关。

也许你可以看看ICMP;不知道它是否能帮上忙

netstat 显示的是本地信息。 我需要显示远程 IP 端口。 nmap 的源码非常复杂。 如果你有任何可以帮到我的源码,请发给我。

抱歉,我确实没理解。

  1. 你期望发生什么?
  2. 实际发生了什么?
  3. 你能展示你程序的输出或你用来观察行为的工具的输出,并解释这些输出与你期望的有何不同吗?

NobbZ:

在移动设备上,你必须通过文本字段右上角的汉堡菜单来切换这些控件。

谢谢。 但是我如何在 Go 语言中发送有效载荷并检查 UDP 端口的响应呢?

NobbZ:

  • 你期望发生什么?
  • 实际发生了什么?
  • 你能展示你程序的输出或你用来观察行为的工具的输出,并解释该输出与你期望的有何不同吗?

本应只显示打开的 UDP 端口,但却显示了所有打开的端口。

ICMP 无法告知你 UDP 是否正在被监听。

坦白说,直接调用 nmap 并解析其输出,会比基于对 UDP 工作原理及其与偶发 ICMP“事件”关系的片面理解,去实现一个半成品要简单得多。

我并不声称自己完全理解这一点,因此我会使用一个已经存在且经过实战检验的扫描器。

主要区别在于,nmap 会发送一个载荷,然后只检查响应。仅仅“拨号”并不会建立连接。UDP 是无状态的。

我希望这能解答你的疑问。

另外,请确保使用 Markdown 来正确格式化你的帖子。

在桌面端,你还会看到文本框上方有一些用于格式化的控制选项。

在移动端,你需要通过文本框右上角的汉堡菜单来切换这些控制选项。

如何在 Go 语言中发送负载并检查 UDP 端口响应?

为此,你可以在许多教程和官方的 net 包文档中找到相关资料。 但一般来说,对于 UDP 协议,你需要深入到更底层的操作,因为 UDP 没有已连接的状态。

老实说,我从未有过这种需求,所以不知道具体怎么做,我可以建议:

  • 使用 netstat
  • 查看 nmap 的源代码

你的代码显示所有UDP端口都显示为开放,这是因为UDP是无连接协议。net.DialTimeout("udp", ...)实际上只是创建了一个本地UDP套接字并尝试解析目标地址,并不会真正验证远程端口是否开放。要检测UDP端口,你需要发送探测数据包并等待响应。

以下是修复后的代码示例:

package main

import (
	"fmt"
	"net"
	"strconv"
	"sync"
	"time"
)

func scanUDPPort(host string, port int, timeout time.Duration) bool {
	target := net.JoinHostPort(host, strconv.Itoa(port))
	
	conn, err := net.DialTimeout("udp", target, timeout)
	if err != nil {
		return false
	}
	defer conn.Close()
	
	// 设置读写超时
	conn.SetDeadline(time.Now().Add(timeout))
	
	// 发送探测数据包
	probe := []byte("ping")
	if _, err := conn.Write(probe); err != nil {
		return false
	}
	
	// 尝试接收响应
	buffer := make([]byte, 1024)
	n, err := conn.Read(buffer)
	if err != nil {
		// 超时或连接错误通常表示端口过滤或关闭
		if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
			return false // 超时,端口可能过滤或关闭
		}
		return false
	}
	
	// 收到响应,端口开放
	fmt.Printf("Port %d open, response: %s\n", port, string(buffer[:n]))
	return true
}

func main() {
	host := "127.0.0.1"
	timeout := 2 * time.Second
	var wg sync.WaitGroup
	var mu sync.Mutex
	openPorts := []int{}
	
	for port := 1; port <= 1024; port++ {
		wg.Add(1)
		go func(p int) {
			defer wg.Done()
			if scanUDPPort(host, p, timeout) {
				mu.Lock()
				openPorts = append(openPorts, p)
				mu.Unlock()
			}
		}(port)
	}
	
	wg.Wait()
	fmt.Printf("Open UDP ports: %v\n", openPorts)
}

对于更准确的UDP端口扫描,你可以考虑使用特定协议的数据包进行探测:

func scanDNS(host string, port int, timeout time.Duration) bool {
	conn, err := net.DialTimeout("udp", net.JoinHostPort(host, strconv.Itoa(port)), timeout)
	if err != nil {
		return false
	}
	defer conn.Close()
	conn.SetDeadline(time.Now().Add(timeout))
	
	// DNS查询数据包
	dnsQuery := []byte{
		0xAA, 0xAA, // ID
		0x01, 0x00, // Flags: Standard query
		0x00, 0x01, // Questions: 1
		0x00, 0x00, // Answer RRs: 0
		0x00, 0x00, // Authority RRs: 0
		0x00, 0x00, // Additional RRs: 0
		0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
		0x03, 'c', 'o', 'm',
		0x00,       // null terminator
		0x00, 0x01, // Type A
		0x00, 0x01, // Class IN
	}
	
	if _, err := conn.Write(dnsQuery); err != nil {
		return false
	}
	
	buffer := make([]byte, 1024)
	_, err = conn.Read(buffer)
	return err == nil
}

注意:UDP端口扫描本质上不可靠,因为:

  1. UDP是无连接的,没有类似TCP的三次握手
  2. 许多UDP服务需要特定格式的数据包才会响应
  3. 防火墙可能丢弃UDP数据包而不发送响应
  4. ICMP端口不可达消息可能被过滤

建议使用专门的扫描工具如nmap进行生产环境扫描,它包含各种UDP探测技术和指纹识别功能。

回到顶部