我正在尝试编写一个检查远程服务器上的开放端口的C程序。
重要提示:我知道有像nmap这样的解决方案,但这里的关键是我自己学习如何编写这样的东西。
我编写了以下代码,它会提示您提示IP和端口。
现在有两种解决方案:
a)已输入端口号 - >将测试与此端口的连接
b)将进入“扫描” - >将检查从1到5000的每个端口是否成功连接。
所以我的问题是,每当我进入“扫描”时,只有端口21会被列为“打开”。
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz){
int ch, extra;
if (prmpt != NULL) {
printf("%s", prmpt);
fflush(stdout);
}
if (fgets(buff, sz, stdin) == NULL)
return NO_INPUT;
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF)){
extra = 1;
}
return (extra == 1) ? TOO_LONG : OK;
}
buff[strlen(buff) - 1] = '\0';
return OK;
}
int main (int argc, char *argv[])
{
int socket_desc;
struct sockaddr_in server;
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1){
printf("Could not open socket\n");
}
char ip[30];
char port[5];
getLine("IP> ", ip, sizeof(ip));
getLine("Port> ", port, sizeof(port));
if (strcmp("scan", port) == 0){
puts("scanning....");
server.sin_addr.s_addr = inet_addr(ip);
server.sin_family = AF_INET;
for (int i = 1; i < 5000; i++){
server.sin_port = htons(i);
if (connect(socket_desc, (struct sockaddr * )&server, sizeof(server)) < 0 ) {
}
else {
printf("Open port: %d\n", i);
}
}
}
else {
int iport = atoi(port);
server.sin_addr.s_addr = inet_addr(ip);
server.sin_family = AF_INET;
server.sin_port = htons(iport);
if (connect(socket_desc, (struct sockaddr * )&server, sizeof(server)) < 0 )
{
puts("connect error");
return 1;
}
puts("Connected");
}
return 0;
}
为什么只有端口21(FTP)列为开放?是否由于我使用的功能的性质,那些仅用于数据连接(然后是端口21)。我应该使用不同的功能,甚至可能使用不同的方法(从我的头脑中,可能ping一个端口(如果可能)而不是尝试连接)
我的最终目标是编写一个扫描服务器的程序,列出打开的端口以及在那里运行的内容(SSH,SMTP等)
感谢您的帮助!!
答案 0 :(得分:1)
连接套接字后,connect
的进一步尝试将保证EISCONN
失败。您需要在每次迭代中创建一个新套接字(并且不要忘记关闭它)。