v-byte-cpu/sx

how can I scan udp port in go code

00LT00 opened this issue · 4 comments

I want to try to check a UDP port of a server without using cmd. How can I do? Do you have some examples?

Hi @00LT00 ! As described in README https://github.com/v-byte-cpu/sx#udp-scan, according to the RFC1122 If an UDP packet arrives to a closed UDP port, then server SHOULD send an ICMP Port Unreachable message. It is worth noting that if the server does not respond in any way, the port is either open or the firewall is blocking ICMP reply packets. Thus, to check if the udp port is open you need to send an udp packet to the desired port, if the host sent ICMP reply packet with Destination Unreachable type (3) and Port Unreachable code (3), then port is closed. Otherwise, the port is open or firewall blocks replies.

You can see an example of UDP packet generation in the Fill method of udp.PacketFiller struct:

func (f *PacketFiller) Fill(packet gopacket.SerializeBuffer, r *scan.Request) (err error) {

and ICMP reply packet processing here
func (p *PacketProcessor) ProcessPacketData(data []byte, _ *gopacket.CaptureInfo) (err error) {

Hello @v-byte-cpu . I've seen it. These are how to generate udp packets. They are very helpful. However, I find it difficult to separate the parts that send udp and accept icmp from the whole application. So I'm going to rewrite this part myself
Can you ask me how to send udp and receive icmp in one connection.
Or create an icmp listening at the same time as establishing a udp sending connection.
Or?
Thank you for reply

Or create an icmp listening at the same time as establishing a udp sending connection.

To listen for incoming packets you can see https://github.com/v-byte-cpu/sx/blob/master/pkg/packet/receiver.go#L55 or use https://pkg.go.dev/github.com/google/gopacket#PacketSource.Packets

To send a paket you can just use https://pkg.go.dev/github.com/google/gopacket@v1.1.19/afpacket#TPacket.WritePacketData

Can you ask me how to send udp and receive icmp in one connection.

So you want to send udp packet and block until icmp reply, right ? Sending and listening for reply packets are in any case asynchronous operations. So to emulate this I would write something like this:

func checkPort(port uint16) (bool, error) {
	results := make(chan bool, 1)
	defer close(results)
	go func() {
		result := true // here listen for incoming packets in loop and process
		results <- result
	}()
       //send udp packet here
	select {
	case result := <-results:
		return result, nil
	case <-time.After(5 * time.Second): // your timeout here
		return false, errors.New("timeout")
	}
}

Thank you very much @v-byte-cpu . I think I should learn about gopacket to listen icmp package. I will reference your code. If I have some new questions I will reopen this issue. Thank you again.