0

I am trying to get the TCP port number which is used by a remote user's telnet connection.

In case of ssh connection, I am able to get it from SSH_CLIENT env variable, but how to get it in case of telnet connection. Are there any C/Unix APIs to get it.

I tried following code:

u_int32_t 
port_session_connected (void)
{
    struct sockaddr_storage from;
    char *ssh_client;
    char *remote_port;
    char *temp;
    static char remoteport[1024];
    int socklen;
    int rv = 0, err; 

    if ((ssh_client = getenv("SSH_CLIENT")) != NULL) {
        syslog("(%s): Have SSH_CLIENT: %s", __func__, ssh_client);
        if ((temp = strtok(ssh_client, " \t")) != NULL) {
            remote_port = strtok(NULL, " \t");
            syslog("(%s): Remote port: %s", __func__, remote_port);
            if (remote_port) rv = atoi(remote_port);
            return rv;
        }
    } /* For ssh sessions */

    socklen = sizeof(from);
    if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &socklen) == 0) { 
        struct sockaddr_in *sck;
        sck = (struct sockaddr_in *)&from;
        syslog("(%s): getpeername() success", __func__);
        syslog("(%s): Remote IP: %s\n", __func__, inet_ntoa(sck->sin_addr));
        syslog("(%s): Remote Port: %d\n", __func__,  (int)ntohs(sck->sin_port));
        syslog("(%s): Family: %d\n", __func__,  (int)(sck->sin_family));

        err = getnameinfo((struct sockaddr *)&from, socklen, NULL, 0, 
                          remoteport, sizeof(remoteport),NI_NUMERICSERV);
        syslog("(%s): getnameinfo() return: %d", __func__, err);
        if (err == 0) { 
            syslog(LOG_NOTICE, "(%s): getnameinfo() success", __func__);
            syslog(LOG_NOTICE, "(%s): Remote port: %s", __func__, remoteport);
            rv = atoi(remoteport);
            return rv;
        }
    } /* For telnet session*/

    return 0;
}

Function works fine for ssh connections. But For telnet connections, I am not able to get the remote port number used in a session.

Log Telnet case:

(port_session_connected): getpeername() success (port_session_connected): Remote IP: 0.0.0.0 (port_session_connected): Remote Port: 0 (port_session_connected): Family: 1 (port_session_connected): getnameinfo() return: 5

getnameinfo() fails with err=5 which is EAI_FAMILY /* ai_family not supported */ Family is 1 which is AF_UNIX.

Yes, getnameinfo() works only for AF_INET and AF_INET6.

Is there any API or anyway to get the telnet remote port.

Thanks

Ram
  • 1,153
  • 4
  • 16
  • 34
  • 1
    probably nmap command if you are in linux might help you – Romaan Nov 23 '12 at 05:58
  • Looks like it is a tool, is n't there any freebsd/unix API to get the required port? – Ram Nov 23 '12 at 06:00
  • Out of curiosity: Why does it matter? –  Nov 23 '12 at 06:05
  • This can help to close a particular user's connection in case of multiple sessions are established. ( Along with port number there are other fields saved like username, remote IP etc). – Ram Nov 23 '12 at 06:09
  • You have to use the connected socket in the call to `getpeername`, not the standard in descriptor. And also, all telnet or SSH connections _are_ `AF_INET` of `AF_INET6` connections. – Some programmer dude Nov 23 '12 at 06:11
  • After reading a little more, I'm guessing this program is supposed to be run on the remote system? You can then try to find the process id of the server program (telnet or ssh daemon) and the check `/proc//fd/` to find the sockets. – Some programmer dude Nov 23 '12 at 06:16
  • It doesn't work for STDIN_FILENO because stdin is a pty connected to telnetd, not the network connection. Who still uses telnet these days, anyway? Why not just use SSH for everything? – Barmar Nov 23 '12 at 06:26

1 Answers1

1

The address of the peer is return by the accept() call on the server side. As this is done by the telnet daemon, it is not accessable from your code (see Stevens, Vol.1 p.118).

So a possible approach would be to write some sort of proxy, which accepts the incoming connections, logs the peer address information, then sets up a connection to the real telnet daemon and passes the connection along to it.

alk
  • 69,737
  • 10
  • 105
  • 255