一 摘要
端口是个网络应用中很重要的东西,相当于“门”。
二 什么是端口
端口在计算机网络中是个非常重要的概念,他不是硬件,不同于计算机中的插槽,可以说是个软插槽。如果有需要,一台计算机中可以由上万个端口。
端口是由计算通信协议TCP/IP协议定义的。其中规定,用IP地址和端口作为套接字,它代表TCP链接的一个连接端,一般称为socket,具体来说,就是用[ip:端口]来定位一台主机中的进程。可以做这样的比喻,端口相当于两台计算机进程间的大门,可随便定义,其目的只是为了让两台计算机能找到对方的进程。计算机就想一座大楼,这个大楼有好多入口(端口),进到不同的入口中就可以找到不同的公司(进程)。如果要和远程主机A的程序通信,那么只要把数据发向[A;端口]就可以实现通信了。
三 端口的分类
在Internet上,按照协议类型分类,端口被分为TCP端口和UDP端口两类,虽然他们都用正整数标识,但这并不会引起歧义,比如TCP的80端口和UDP的80端口,因为数据报在标明端口的同时,还将标明端口的类型。
从端口的分配来看,端口被分为固定端口和动态端口两大类(一些教程还将极少被用到的高端口划分为第三类:私有端口):
固定端口(0-1023):
使用集中式管理机制,即服从一个管理机构对端口的指派,这个机构负责发布这些指派。由于这些端口紧绑于一些服务,所以我们会经常扫描这些端口来判断对方 是否开启了这些服务,如TCP的21(ftp),80(http),139(netbios),UDP的7(echo),69(tftp)等等一些大家熟 知的端口;
动态端口(1024-49151):
这些端口并不被固定的捆绑于某一服务,操作系统将这些端口动态的分配给各个进程, 同一进程两次分配有可能分配到不同的端口。不过一些应用程序并不愿意使用操作系统分配的动态端口,他们有其自己的‘商标性’端口,如oicq客户端的 4000端口,木马冰河的7626端口等都是固定而出名的。
四 端口在入侵中的作用
有人曾经把服务器比作房子,而把端口比作通向不同房间(服务)的门,如果不考虑细节的话,这是一个不错的比喻。入侵者要占领这间房子,势必要破门而入(物理入侵另说),那么对于入侵者来说,了解房子开了几扇门,都是什么样的门,门后面有什么东西就显得至关重要。
入侵者通常会用扫描器对目标主机的端口进行扫描,以确定哪些端口是开放的,从开放的端口,入侵者可以知道目标主机大致提供了哪些服务,进而猜测可能存在 的漏洞,因此对端口的扫描可以帮助我们更好的了解目标主机,而对于管理员,扫描本机的开放端口也是做好安全防范的第一步。
五、端口扫描原理:尝试与目标主机建立连接,如果目标主机有回复则说明端口开放。
扫描分类:
1. 全TCP连接,这种方法使用三次握手与目标主机建立标准的tcp连接。但是这种方法跟容易被发现,被目标主机记录。
2. SYN扫描,扫描主机自动向目标主机的指定端口发送SYN数据段,表示发送建立连接请求。
!!如果目标主机的回应报文SYN=1,ACK=1.则说明该端口是活动的,接着扫描主机发送回一个RST给目标主机拒绝连接。导致三次握手失败。
!!如果目标主机回应是RST则端口是“死的”。
3 FIN扫描,发送一个FIN=1的报文到一个关闭的窗口该报文将丢失并返回一个RST,如果该FIN报文发送到活动窗口则报文丢失,不会有任何反应。
4.代理扫描。就是抓鸡啦。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <pthread.h>
#define MAX_THREAD_NUM 100
#define SEG_LEN 655
#define MAX_PORT 65535
typedef struct PortNode
{
char ip[30];
int minPort;
int maxPort;
}PortNode;
pthread_t tid;
void* doit(void* arg)
{
int i, sockfd, connfd;
struct sockaddr_in servaddr;
PortNode* port = (PortNode*)arg;
pthread_detach(pthread_self());//为避免存储器泄漏,每个可结合线程都应该被其他线程显式地收回,要么通过调用pthread_detach函数被分离
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
//inet_pton(AF_INET, port->ip, &servaddr.sin_addr);
servaddr.sin_addr.s_addr = inet_addr(port->ip);
for(i = port->minPort; i <= port->maxPort; i++){
servaddr.sin_port = htons(i);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("socket error");
pthread_exit(NULL);
}
if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)) == 0){
printf("%s:%d\n", port->ip, i);
}
close(sockfd);//注意关闭!!
}
pthread_exit(NULL);
}
int main(int argc, char** argv)
{
int i,j;
for(i = 1; i < argc; i++){
PortNode* port = (PortNode*)malloc(sizeof(PortNode));
for(j = 0; j < MAX_THREAD_NUM; j++){
strcpy(port->ip, argv[i]);
port->minPort = j*SEG_LEN + 1;
if(j == (MAX_THREAD_NUM - 1))port->maxPort = MAX_PORT;
else port->maxPort = port->minPort + SEG_LEN - 1;
if(pthread_create(&tid, NULL, doit, (void*) port) != 0 ){
perror("pthread create error.\n");
free(port);
port=NULL;
exit(1);
}
}
}
sleep(3);
}