2

哪些选项可用于枚举 Linux 上特定 IP 的所有侦听端口?

我正在寻找的函数原型是这样的:

enumerateListeners : IP -> [Port]

内核 API 或 C 库都会非常有趣。

4

3 回答 3

3

/proc文件系统是您可以用来获取此信息的内核接口。特别是 TCP 套接字列在/proc/net/tcp和 中/proc/net/tcp6。第二列以 IP:port 对的形式给出本地地址。要选择那些处于 LISTEN 状态的套接字,您必须查看那些0Ast(socket state) 列中的套接字。这是我所拥有的一个例子:

  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:3E81 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 18064 1 0000000000000000 100 0 0 10 0                     
   1: 00000000:1269 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 18056 1 0000000000000000 100 0 0 10 0                     
   2: 0100007F:0CEA 00000000:0000 0A 00000000:00000000 00:00000000 00000000   117        0 13084 1 0000000000000000 100 0 0 10 0                     
   3: 00000000:008B 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 9097 1 0000000000000000 100 0 0 10 0                      
   4: 0100007F:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 14349 1 0000000000000000 100 0 0 10 0                     

在 C 中读取这个文件很简单:打开它并用fscanf.

如果还有其他方法可以获取此信息,我不知道;这也是netstat使用的接口,您可以使用strace.

于 2013-07-02T16:35:26.380 回答
1

更新

#include <stdio.h>          // printf, fopen, fclose
#include <stdlib.h>         // free
#include <arpa/inet.h>      // in_addr*

#define OK(x) ((x) > -1)
#define LISTENING (0x0A)
#define port u_int16_t

int listening(in_addr_t addr, port* ports, size_t nPorts) {

  char* line = NULL; size_t n = 0;
  u_int32_t locaddr; u_int32_t locport; u_int32_t state; int i = 0;
  FILE* tcp = fopen("/proc/net/tcp", "r");

  if   (!OK(getline(&line, &n, tcp))) goto f;
  while (OK(getline(&line, &n, tcp)) && i < nPorts) {
    int r = sscanf(line, "%*d: %8x:%4x %*8x:%*4x %2x", &locaddr, &locport, &state);
    if (r == 3 && addr == locaddr && state == LISTENING) ports[i++] = (port)locport;
  }

  f: fclose(tcp); free(line); return i;
}

int main(int c, char* a[]) {
  struct in_addr ipv4; inet_pton(AF_INET, a[1], &ipv4);     printf("%i = ", ipv4.s_addr);
  char str[512];       inet_ntop(AF_INET, &ipv4, str, 512); printf("%s\n" , str);

  port pts[65536]; printf("{ listening: [ "); c = listening(ipv4.s_addr, pts, 65536);
  int i; for (i = 0; i < c; i++) printf("%i, ", pts[i]); printf("] }\n");
}
于 2013-07-02T16:43:58.120 回答
0

那么,您是否要求使用 PortScanner?我知道的最好的 PortScanner 是 Nmap

您可以查看它的源代码,否则编写一个简单的函数来枚举为特定 IP 打开的 TCP 端口不是一个难题,您可以将connect函数与 for 循环一起使用。

于 2013-07-02T14:21:24.927 回答