0

It's easy to test for TCP, but how about UDP? Here: Check if OpenVPN UDP Port is open I read that it is impossible to do this. However, here: How to retrieve both TCP and UDP ports with Nmap? it was proved that nmap can do this, so its possible I think.

I wrote a very simple code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    char * ip_addr;
    int port;

    int sockfd;
    struct sockaddr_in server_addr;

    if (argc != 3)
    {
        fprintf(stderr,"Usage: %s IP port \n", argv[0]);
        exit(1);
    }

    ip_addr = argv[1];
    port = atoi(argv[2]);

    if (port <= 0)
    {
        fprintf(stderr,"error: invalid port\n");
        exit(1);
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(1);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    inet_aton(ip_addr, &server_addr.sin_addr);

    char msg[] = "Just a text\n";
    char buffer[255];
    int recv_size, send_size;

    if ((send_size = sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*) &server_addr, sizeof(server_addr))) < 0)
    {
        close(sockfd);
        if (errno != 0)
        {
            perror("send");
            exit(1);
        }
    }else if(send_size == 0)
    {
        printf("sent\n");
    }
    else if (send_size > 0)
    {
        printf("sent\n");
    }

    if ((recv_size = recvfrom(sockfd, buffer, 255, 0, NULL, NULL)) == 0)
    {
        close(sockfd);
        if (errno != 0)
        {
            perror("recv");
            exit(1);
        }
    }

    buffer[recv_size] = '\0';

    close(sockfd);


    return 0;
}

But it prints nothing, just ends. So its hard to say what happend, if the port is opened or not. Is there a simple way, using sockets, to test whether the remote UDP port is opened?

Community
  • 1
  • 1
mirx
  • 606
  • 1
  • 9
  • 21
  • 1
    without looking at your code, there isn't a definitive way to do this that I've ever heard of. As I'm sure you know, UDP is a connectionless, spray-and-pray protocol. No handshake, no acknowledgement. If I send a packet to a host at UDP port x, and hear nothing back, that could mean a variety of things. You can only definitively tell a UDP port is closed if a host responds with an ICMP message telling you so, and for security reasons they shouldn't do this. Port scanning for UDP ports isn't exact. – yano Mar 01 '17 at 19:18
  • actually, you could imagine a scenario where, even if a UDP port was open, if the data you delivered to it wasn't in the correct format or your IP didn't match a whitelist or what have you, the host could respond with an ICMP port closed message,, so I have to walk back on what I said... even ICMP port closed messages won't definitively tell you whether a port is closed or not. Security through obfuscation won't deter a determined hacker, but it can certainly weed out the riffraff and be part of an overall security strategy. – yano Mar 01 '17 at 19:48
  • 1
    Assuming ICMP is not being blocked, if a UDP packet cannot be routed to a given target host then an ICMP Host Unreachable packet is sent back, otherwise if the host is reachable but the port is not open then an ICMP Port Unreachable packet is sent back. There is no ICMP Port Closed packet. – Remy Lebeau Mar 01 '17 at 21:15
  • Also see: [How does UDP port scanning and service detection work?](https://community.qualys.com/docs/DOC-1185) – Remy Lebeau Mar 01 '17 at 21:18

2 Answers2

3

It's easy to test for TCP [ports being open], but how about UDP?

It's not possible to reliably detect that a remote port of either flavor is closed. It is not even possible to reliably detect that a remote TCP port is open -- the best you can do is determine whether that port is open to you, by successfully connecting to it. The remote machine may affirmatively reject your connection attempt even though it would accept connections from a different machine, and it may silently ignore the attempt whether the port is open (to other machines) or closed.

All of that applies to UDP as well, except that you cannot rely on a response from the remote machine even if it accepts your packet. You may get an affirmative rejection, but if you don't, you learn nothing from the attempt. You can scan for a particular UDP service running and serving request from your machine on the remote port, but you can't count more generally on being able to determine whether the port is open.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

Your socket is created with SOC_STREAM, but never connected. In such situation sendto fails with ENOTCONN. The code prints nothing because close(sockfd) succeeds and resets errno to 0.

Notice also that you don't need to test errno; it is guaranteed to be non-zero once sendto fails:

    if ((send_size = ....) < 0) {
        perror("send");
        close(sockfd);
        ....
    }
user58697
  • 7,808
  • 1
  • 14
  • 28